or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

buttons-actions.mdcolor-management.mddata-display.mddata-management.mddate-time.mdform-controls.mdfoundation-layout.mdindex.mdinternationalization.mdoverlays-dialogs.mdprogress-status.mdselection-navigation.md
tile.json

internationalization.mddocs/

Internationalization

Hooks and utilities for formatting, localization, and international text processing with support for multiple languages and regions.

Capabilities

Locale Management

useLocale Hook

Hook for accessing current locale information and text direction.

/**
 * Hook for accessing current locale information
 * @returns Current locale and text direction information
 */
function useLocale(): LocaleInfo;

interface LocaleInfo {
  /** Current locale string (BCP 47 language tag) */
  locale: string;
  /** Text direction for current locale */
  direction: "ltr" | "rtl";
}

Date & Time Formatting

useDateFormatter Hook

Hook for locale-aware date and time formatting with full Intl.DateTimeFormat support.

/**
 * Hook for locale-aware date and time formatting
 * @param options - Date formatting configuration options
 * @returns DateFormatter instance with formatting methods
 */
function useDateFormatter(options?: DateFormatterOptions): DateFormatter;

interface DateFormatterOptions extends Intl.DateTimeFormatOptions {
  /** Calendar system to use */
  calendar?: string;
  /** Override locale */
  locale?: string;
}

interface DateFormatter {
  /** Format single date */
  format: (date: Date) => string;
  /** Format date to parts for custom styling */
  formatToParts: (date: Date) => Intl.DateTimeFormatPart[];
  /** Format date range */
  formatRange: (start: Date, end: Date) => string;
  /** Format date range to parts */
  formatRangeToParts: (start: Date, end: Date) => Intl.DateTimeFormatPart[];
  /** Get resolved formatting options */
  resolvedOptions: () => Intl.DateTimeFormatOptions;
}

Number Formatting

useNumberFormatter Hook

Hook for locale-aware number formatting including currency, percentages, and units.

/**
 * Hook for locale-aware number formatting
 * @param options - Number formatting configuration options
 * @returns Intl.NumberFormat instance for formatting
 */
function useNumberFormatter(options?: Intl.NumberFormatOptions): Intl.NumberFormat;

Text Processing

useCollator Hook

Hook for locale-aware string comparison and sorting.

/**
 * Hook for locale-aware string comparison and sorting
 * @param options - Collation configuration options
 * @returns Intl.Collator instance for string comparison
 */
function useCollator(options?: Intl.CollatorOptions): Intl.Collator;

useFilter Hook

Hook for locale-aware text filtering and searching.

/**
 * Hook for locale-aware text filtering and searching
 * @param options - Filter configuration options
 * @returns Filter function for text matching
 */
function useFilter(options?: FilterOptions): Filter;

interface FilterOptions {
  /** Text matching sensitivity */
  sensitivity?: "base" | "accent" | "case" | "variant";
  /** Whether to ignore case */
  ignorePunctuation?: boolean;
  /** Custom collator options */
  collatorOptions?: Intl.CollatorOptions;
}

interface Filter {
  /** Check if text starts with query */
  startsWith: (text: string, query: string) => boolean;
  /** Check if text ends with query */
  endsWith: (text: string, query: string) => boolean;
  /** Check if text contains query */
  contains: (text: string, query: string) => boolean;
}

Message Formatting

useLocalizedStringFormatter Hook

Hook for accessing localized string resources with interpolation support.

/**
 * Hook for accessing localized string resources
 * @param strings - Localized string dictionary
 * @param deps - Dependencies for re-evaluation
 * @returns String formatter function
 */
function useLocalizedStringFormatter(
  strings: LocalizedStrings, 
  deps?: any[]
): LocalizedStringFormatter;

interface LocalizedStrings {
  [key: string]: string | ((values: any) => string);
}

interface LocalizedStringFormatter {
  /** Format localized string with interpolation */
  format: (key: string, values?: any) => string;
}

useMessageFormatter Hook

Hook for advanced message formatting with ICU MessageFormat support.

/**
 * Hook for advanced message formatting with ICU MessageFormat
 * @param locale - Target locale for formatting
 * @returns Message formatter function
 */
function useMessageFormatter(locale?: string): FormatMessage;

interface FormatMessage {
  /** Format message with ICU MessageFormat syntax */
  (message: string, values?: Record<string, any>): string;
}

Usage Examples

Multi-Language App

function MultiLanguageApp() {
  const { locale, direction } = useLocale();
  const formatDate = useDateFormatter({ 
    dateStyle: 'medium',
    timeStyle: 'short'
  });
  const formatNumber = useNumberFormatter({ 
    style: 'currency',
    currency: locale.startsWith('en-US') ? 'USD' : 'EUR'
  });

  return (
    <div dir={direction}>
      <Text>Current locale: {locale}</Text>
      <Text>Today: {formatDate.format(new Date())}</Text>
      <Text>Price: {formatNumber.format(29.99)}</Text>
    </div>
  );
}

Localized Data Table

function LocalizedDataTable({ data }) {
  const { locale } = useLocale();
  const formatDate = useDateFormatter({
    dateStyle: 'short'
  });
  const formatCurrency = useNumberFormatter({
    style: 'currency',
    currency: 'USD'
  });
  const collator = useCollator({ 
    numeric: true,
    sensitivity: 'base'
  });

  const sortedData = [...data].sort((a, b) => 
    collator.compare(a.name, b.name)
  );

  return (
    <TableView items={sortedData}>
      <TableHeader>
        <Column key="name">Name</Column>
        <Column key="date">Date</Column>
        <Column key="amount">Amount</Column>
      </TableHeader>
      <TableBody>
        {(item) => (
          <Row key={item.id}>
            <Cell>{item.name}</Cell>
            <Cell>{formatDate.format(new Date(item.date))}</Cell>
            <Cell>{formatCurrency.format(item.amount)}</Cell>
          </Row>
        )}
      </TableBody>
    </TableView>
  );
}

Search with Locale-Aware Filtering

function LocalizedSearch({ items, onResults }) {
  const [query, setQuery] = useState('');
  const filter = useFilter({ 
    sensitivity: 'base',
    ignorePunctuation: true 
  });

  const filteredItems = useMemo(() => {
    if (!query.trim()) return items;
    
    return items.filter(item =>
      filter.contains(item.name, query) ||
      filter.contains(item.description, query)
    );
  }, [items, query, filter]);

  useEffect(() => {
    onResults(filteredItems);
  }, [filteredItems, onResults]);

  return (
    <SearchField
      label="Search"
      value={query}
      onChange={setQuery}
      placeholder="Type to search..."
    />
  );
}

Localized Messages

const messages = {
  'en-US': {
    welcome: 'Welcome, {name}!',
    itemCount: '{count, plural, =0 {no items} =1 {one item} other {# items}}',
    lastUpdate: 'Last updated {date, date, medium} at {date, time, short}'
  },
  'es-ES': {
    welcome: '¡Bienvenido, {name}!',
    itemCount: '{count, plural, =0 {sin elementos} =1 {un elemento} other {# elementos}}',
    lastUpdate: 'Última actualización {date, date, medium} a las {date, time, short}'
  }
};

function LocalizedMessages({ userName, itemCount, lastUpdate }) {
  const { locale } = useLocale();
  const strings = useLocalizedStringFormatter(messages[locale] || messages['en-US']);
  const formatMessage = useMessageFormatter(locale);

  return (
    <View>
      <Heading>
        {strings.format('welcome', { name: userName })}
      </Heading>
      
      <Text>
        {formatMessage(strings.format('itemCount'), { count: itemCount })}
      </Text>
      
      <Text>
        {formatMessage(strings.format('lastUpdate'), { date: lastUpdate })}
      </Text>
    </View>
  );
}

Date Range Picker with Localization

function LocalizedDateRangePicker() {
  const [dateRange, setDateRange] = useState({
    start: today(getLocalTimeZone()),
    end: today(getLocalTimeZone()).add({ days: 7 })
  });
  
  const { locale } = useLocale();
  const formatDate = useDateFormatter({
    dateStyle: 'full'
  });

  return (
    <View>
      <DateRangePicker
        label="Select Date Range"
        value={dateRange}
        onChange={setDateRange}
      />
      
      <Text>
        Selected: {formatDate.format(dateRange.start.toDate(getLocalTimeZone()))} 
        {' - '}
        {formatDate.format(dateRange.end.toDate(getLocalTimeZone()))}
      </Text>
      
      <Text>
        Locale: {locale}
      </Text>
    </View>
  );
}

Currency Converter

function CurrencyConverter() {
  const [amount, setAmount] = useState(100);
  const [fromCurrency, setFromCurrency] = useState('USD');
  const [toCurrency, setToCurrency] = useState('EUR');
  
  const formatFrom = useNumberFormatter({
    style: 'currency',
    currency: fromCurrency
  });
  
  const formatTo = useNumberFormatter({
    style: 'currency',
    currency: toCurrency
  });

  // Mock conversion rate - in real app, fetch from API
  const convertedAmount = amount * 0.85;

  return (
    <Form>
      <NumberField
        label="Amount"
        value={amount}
        onChange={setAmount}
        formatOptions={{
          style: 'currency',
          currency: fromCurrency
        }}
      />
      
      <Picker
        label="From Currency"
        selectedKey={fromCurrency}
        onSelectionChange={setFromCurrency}
      >
        <Item key="USD">US Dollar</Item>
        <Item key="EUR">Euro</Item>
        <Item key="GBP">British Pound</Item>
        <Item key="JPY">Japanese Yen</Item>
      </Picker>
      
      <Picker
        label="To Currency"
        selectedKey={toCurrency}
        onSelectionChange={setToCurrency}
      >
        <Item key="USD">US Dollar</Item>
        <Item key="EUR">Euro</Item>
        <Item key="GBP">British Pound</Item>
        <Item key="JPY">Japanese Yen</Item>
      </Picker>
      
      <View backgroundColor="gray-100" padding="size-200">
        <Text>
          {formatFrom.format(amount)} = {formatTo.format(convertedAmount)}
        </Text>
      </View>
    </Form>
  );
}

Types

Locale Types

/** BCP 47 language tag */
type Locale = string;

/** Text direction */
type Direction = "ltr" | "rtl";

/** Locale information */
interface LocaleInfo {
  /** Current locale */
  locale: Locale;
  /** Text direction */
  direction: Direction;
}

Formatting Types

/** Date formatter options extending Intl options */
interface DateFormatterOptions extends Intl.DateTimeFormatOptions {
  /** Calendar system */
  calendar?: string;
  /** Override locale */
  locale?: string;
}

/** Date formatter with additional methods */
interface DateFormatter extends Intl.DateTimeFormat {
  /** Format date range */
  formatRange: (start: Date, end: Date) => string;
  /** Format date range to parts */
  formatRangeToParts: (start: Date, end: Date) => Intl.DateTimeFormatPart[];
}

Filter Types

/** Text filter configuration */
interface FilterOptions {
  /** Case and accent sensitivity */
  sensitivity?: "base" | "accent" | "case" | "variant";
  /** Whether to ignore punctuation */
  ignorePunctuation?: boolean;
  /** Collator options */
  collatorOptions?: Intl.CollatorOptions;
}

/** Text filter function interface */
interface Filter {
  /** Check if text starts with query */
  startsWith: (text: string, query: string) => boolean;
  /** Check if text ends with query */
  endsWith: (text: string, query: string) => boolean;
  /** Check if text contains query */
  contains: (text: string, query: string) => boolean;
}

Message Types

/** Localized string dictionary */
interface LocalizedStrings {
  [key: string]: string | ((values: any) => string);
}

/** String formatter function */
interface LocalizedStringFormatter {
  /** Format string with interpolation */
  format: (key: string, values?: any) => string;
}

/** Message formatter for ICU MessageFormat */
interface FormatMessage {
  /** Format message with values */
  (message: string, values?: Record<string, any>): string;
}