or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

date-time-formatting.mddisplay-name-formatting.mdindex.mdintl-instance.mdlist-formatting.mdmessage-formatting.mdnumber-formatting.mdrelative-time-pluralization.mdutility-functions.md
tile.json

utility-functions.mddocs/

Utility Functions

Cache management, configuration utilities, and performance optimization helpers. Provides infrastructure functions for managing formatter instances, configuration processing, and memory optimization.

Capabilities

createIntlCache Function

Creates a cache object for storing formatter instances to prevent memory leaks and improve performance.

/**
 * Create cache for formatter instances to prevent memory leaks
 * @returns Empty cache object with all formatter storage initialized
 */
function createIntlCache(): IntlCache;

interface IntlCache {
  /** DateTimeFormat instances keyed by serialized options */
  dateTime: Record<string, DateTimeFormat>;
  /** NumberFormat instances keyed by serialized options */
  number: Record<string, Intl.NumberFormat>;
  /** IntlMessageFormat instances keyed by serialized options */
  message: Record<string, IntlMessageFormat>;
  /** RelativeTimeFormat instances keyed by serialized options */
  relativeTime: Record<string, Intl.RelativeTimeFormat>;
  /** PluralRules instances keyed by serialized options */
  pluralRules: Record<string, Intl.PluralRules>;
  /** ListFormat instances keyed by serialized options */
  list: Record<string, IntlListFormat>;
  /** DisplayNames instances keyed by serialized options */
  displayNames: Record<string, DisplayNames>;
}

Usage Examples:

import { createIntlCache, createIntl } from "@formatjs/intl";

// Create shared cache for multiple intl instances
const cache = createIntlCache();

const intlEn = createIntl({
  locale: 'en-US',
  messages: { /* ... */ }
}, cache);

const intlEs = createIntl({
  locale: 'es-ES', 
  messages: { /* ... */ }
}, cache);

// Both instances share formatter caches for memory efficiency
// Formatters with same options are reused across instances

// Cache inspection (for debugging)
console.log('Cached formatters:', {
  dateTime: Object.keys(cache.dateTime).length,
  number: Object.keys(cache.number).length,
  message: Object.keys(cache.message).length
});

// Manual cache clearing (rarely needed)
const clearCache = (cache: IntlCache) => {
  cache.dateTime = {};
  cache.number = {};
  cache.message = {};
  cache.relativeTime = {};
  cache.pluralRules = {};
  cache.list = {};
  cache.displayNames = {};
};

createFormatters Function

Creates memoized formatter instances with cache integration for optimal performance.

/**
 * Create intl formatters and populate cache
 * @param cache - Optional explicit cache to prevent leaking memory
 * @returns Formatters object with memoized factory functions
 */
function createFormatters(cache?: IntlCache): Formatters;

interface Formatters {
  /** Memoized DateTimeFormat factory */
  getDateTimeFormat(locale?: string | string[], options?: Intl.DateTimeFormatOptions): DateTimeFormat;
  /** Memoized NumberFormat factory */
  getNumberFormat(locales?: string | string[], opts?: NumberFormatOptions): Intl.NumberFormat;
  /** Memoized MessageFormat factory */
  getMessageFormat(message: string, locales?: string | string[], overrideFormats?: Partial<Formats>, opts?: IntlMessageFormatOptions): IntlMessageFormat;
  /** Memoized RelativeTimeFormat factory */
  getRelativeTimeFormat(locales?: string | string[], options?: Intl.RelativeTimeFormatOptions): Intl.RelativeTimeFormat;
  /** Memoized PluralRules factory */
  getPluralRules(locales?: string | string[], options?: Intl.PluralRulesOptions): Intl.PluralRules;
  /** Memoized ListFormat factory */
  getListFormat(locales?: string | string[], options?: IntlListFormatOptions): IntlListFormat;
  /** Memoized DisplayNames factory */
  getDisplayNames(locales?: string | string[], options?: DisplayNamesOptions): DisplayNames;
}

Usage Examples:

import { createFormatters, createIntlCache } from "@formatjs/intl";

// Create formatters with default cache
const formatters = createFormatters();

// Create formatters with explicit cache
const explicitCache = createIntlCache();
const cachedFormatters = createFormatters(explicitCache);

// Use formatters directly
const numberFormatter = formatters.getNumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
});

const formatted = numberFormatter.format(1234.56);
// Result: "$1,234.56"

// Subsequent calls with same parameters return cached instance
const sameFormatter = formatters.getNumberFormat('en-US', {
  style: 'currency', 
  currency: 'USD'
});
// sameFormatter === numberFormatter (same instance)

// Different parameters create new cached instance
const euroFormatter = formatters.getNumberFormat('en-US', {
  style: 'currency',
  currency: 'EUR'
});
// Different instance, also cached

// Date formatter usage
const dateFormatter = formatters.getDateTimeFormat('en-US', {
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});

const formattedDate = dateFormatter.format(new Date());
// Result: "March 15, 2024"

filterProps Function

Filters object properties based on an allowlist with optional defaults.

/**
 * Filter properties from objects with allowlist and defaults
 * @param props - Source object to filter properties from
 * @param allowlist - Array of allowed property names
 * @param defaults - Optional default values for missing properties
 * @returns New object with only allowed properties
 */
function filterProps<T extends Record<string, any>, K extends string>(
  props: T,
  allowlist: Array<K>,
  defaults?: Partial<T>
): Pick<T, K>;

Usage Examples:

import { filterProps } from "@formatjs/intl";

// Basic property filtering
const sourceObject = {
  locale: 'en-US',
  currency: 'USD',
  style: 'currency',
  unwantedProp: 'remove me',
  anotherBadProp: 123
};

const allowedProps = ['locale', 'currency', 'style'] as const;
const filtered = filterProps(sourceObject, allowedProps);
// Result: { locale: 'en-US', currency: 'USD', style: 'currency' }

// With defaults for missing properties
const incompleteObject = {
  locale: 'en-US',
  currency: 'USD'
  // missing 'style'
};

const withDefaults = filterProps(
  incompleteObject,
  allowedProps,
  { style: 'decimal' }
);
// Result: { locale: 'en-US', currency: 'USD', style: 'decimal' }

// Real-world usage in number formatting options
const NUMBER_FORMAT_OPTIONS = [
  'style', 'currency', 'unit', 'useGrouping',
  'minimumIntegerDigits', 'minimumFractionDigits',
  'maximumFractionDigits', 'minimumSignificantDigits',
  'maximumSignificantDigits'
] as const;

const userOptions = {
  style: 'currency',
  currency: 'USD',
  minimumFractionDigits: 2,
  localeMatcher: 'best fit', // Not in allowlist
  invalidOption: 'remove'    // Not in allowlist
};

const cleanOptions = filterProps(userOptions, NUMBER_FORMAT_OPTIONS);
// Result: { style: 'currency', currency: 'USD', minimumFractionDigits: 2 }

// TypeScript provides type safety
const typedFiltered: Pick<typeof sourceObject, 'locale' | 'currency' | 'style'> = 
  filterProps(sourceObject, allowedProps);

getNamedFormat Function

Retrieves named format configurations from custom formats with error handling.

/**
 * Get named format from configuration with error handling
 * @param formats - Custom formats object
 * @param type - Format type (number, date, time, relative)
 * @param name - Named format identifier
 * @param onError - Error handler for missing formats
 * @returns Format options or undefined if not found
 */
function getNamedFormat<T extends keyof CustomFormats>(
  formats: CustomFormats,
  type: T,
  name: string,
  onError: OnErrorFn
): NumberFormatOptions | Intl.DateTimeFormatOptions | Intl.RelativeTimeFormatOptions | undefined;

Usage Examples:

import { getNamedFormat } from "@formatjs/intl";

// Custom formats configuration
const customFormats = {
  number: {
    currency: { style: 'currency', currency: 'USD' },
    percentage: { style: 'percent', minimumFractionDigits: 1 },
    compact: { notation: 'compact' }
  },
  date: {
    short: { month: 'numeric', day: 'numeric', year: '2-digit' },
    long: { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }
  },
  relative: {
    short: { numeric: 'auto', style: 'short' },
    verbose: { numeric: 'always', style: 'long' }
  }
};

const onError = (error: any) => console.error('Format error:', error);

// Retrieve existing named formats
const currencyFormat = getNamedFormat(customFormats, 'number', 'currency', onError);
// Result: { style: 'currency', currency: 'USD' }

const longDateFormat = getNamedFormat(customFormats, 'date', 'long', onError);
// Result: { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }

const shortRelativeFormat = getNamedFormat(customFormats, 'relative', 'short', onError);
// Result: { numeric: 'auto', style: 'short' }

// Handle missing named formats
const missingFormat = getNamedFormat(customFormats, 'number', 'nonexistent', onError);
// Result: undefined
// Also calls onError with UnsupportedFormatterError

// Real-world usage in formatting functions
const formatWithNamedFormat = (
  value: number,
  formatName: string,
  locale: string = 'en-US'
) => {
  const formatOptions = getNamedFormat(
    customFormats,
    'number',
    formatName,
    onError
  );
  
  if (formatOptions) {
    return new Intl.NumberFormat(locale, formatOptions).format(value);
  }
  
  // Fallback to basic formatting
  return new Intl.NumberFormat(locale).format(value);
};

const price = formatWithNamedFormat(29.99, 'currency');
// Result: "$29.99"

const percentage = formatWithNamedFormat(0.156, 'percentage');
// Result: "15.6%"

DEFAULT_INTL_CONFIG Constant

Default configuration object providing sensible defaults for intl instances.

const DEFAULT_INTL_CONFIG: Pick<
  ResolvedIntlConfig<any>,
  | 'fallbackOnEmptyString'
  | 'formats'
  | 'messages'
  | 'timeZone'
  | 'defaultLocale'
  | 'defaultFormats'
  | 'onError'
  | 'onWarn'
>;

Usage Examples:

import { DEFAULT_INTL_CONFIG, createIntl } from "@formatjs/intl";

// Inspect default configuration
console.log('Default config:', DEFAULT_INTL_CONFIG);
// Result: {
//   formats: {},
//   messages: {},
//   timeZone: undefined,
//   defaultLocale: 'en',
//   defaultFormats: {},
//   fallbackOnEmptyString: true,
//   onError: [Function: defaultErrorHandler],
//   onWarn: [Function: defaultWarnHandler]
// }

// Use defaults with custom overrides
const intl = createIntl({
  ...DEFAULT_INTL_CONFIG,
  locale: 'es-ES',
  messages: {
    greeting: 'Hola {name}'
  },
  // Other defaults are preserved
});

// Override specific defaults
const customIntl = createIntl({
  locale: 'en-US',
  messages: { /* ... */ },
  // Override default error handling
  onError: (error) => {
    // Custom error handling
    console.error('Custom error handler:', error);
    
    // Send to monitoring service
    if (process.env.NODE_ENV === 'production') {
      sendErrorToMonitoring(error);
    }
  },
  // Keep other defaults by not specifying them
});

// Access individual default handlers
const defaultErrorHandler = DEFAULT_INTL_CONFIG.onError;
const defaultWarnHandler = DEFAULT_INTL_CONFIG.onWarn;

// Create wrapper with enhanced defaults
const createIntlWithDefaults = (config: Partial<IntlConfig>) => {
  return createIntl({
    ...DEFAULT_INTL_CONFIG,
    defaultLocale: 'en-US', // Override default
    fallbackOnEmptyString: false, // Override default
    ...config
  });
};

Performance Optimization Utilities

Additional utilities for optimizing intl performance in production applications.

Usage Examples:

// Cache warming for critical formatters
const warmCache = (cache: IntlCache, locales: string[]) => {
  const formatters = createFormatters(cache);
  
  // Pre-warm common formatters
  locales.forEach(locale => {
    // Common number formats
    formatters.getNumberFormat(locale, { style: 'decimal' });
    formatters.getNumberFormat(locale, { style: 'currency', currency: 'USD' });
    formatters.getNumberFormat(locale, { style: 'percent' });
    
    // Common date formats
    formatters.getDateTimeFormat(locale, { dateStyle: 'short' });
    formatters.getDateTimeFormat(locale, { timeStyle: 'short' });
    
    // Common relative time formats
    formatters.getRelativeTimeFormat(locale, { numeric: 'auto' });
    
    // Common plural rules
    formatters.getPluralRules(locale, { type: 'cardinal' });
  });
};

// Usage in app initialization
const appCache = createIntlCache();
warmCache(appCache, ['en-US', 'es-ES', 'fr-FR', 'de-DE']);

// Cache metrics for monitoring
const getCacheMetrics = (cache: IntlCache) => {
  return {
    dateTime: Object.keys(cache.dateTime).length,
    number: Object.keys(cache.number).length,
    message: Object.keys(cache.message).length,
    relativeTime: Object.keys(cache.relativeTime).length,
    pluralRules: Object.keys(cache.pluralRules).length,
    list: Object.keys(cache.list).length,
    displayNames: Object.keys(cache.displayNames).length,
    total: Object.keys(cache.dateTime).length +
           Object.keys(cache.number).length +
           Object.keys(cache.message).length +
           Object.keys(cache.relativeTime).length +
           Object.keys(cache.pluralRules).length +
           Object.keys(cache.list).length +
           Object.keys(cache.displayNames).length
  };
};

// Memory management for long-running applications
const createManagedCache = (maxSize: number = 1000) => {
  const cache = createIntlCache();
  let totalEntries = 0;
  
  const trackingCache = new Proxy(cache, {
    set(target, prop, value) {
      if (typeof prop === 'string' && prop in target) {
        const category = target[prop as keyof IntlCache];
        if (typeof value === 'object' && value !== null) {
          Object.keys(value).forEach(key => {
            if (!(key in category)) {
              totalEntries++;
            }
          });
          
          // Clear oldest entries if over limit
          if (totalEntries > maxSize) {
            const categories = Object.keys(target) as (keyof IntlCache)[];
            categories.forEach(cat => {
              const categoryCache = target[cat];
              const keys = Object.keys(categoryCache);
              if (keys.length > maxSize / categories.length) {
                // Clear half the entries (simple LRU approximation)
                keys.slice(0, Math.floor(keys.length / 2)).forEach(k => {
                  delete categoryCache[k];
                  totalEntries--;
                });
              }
            });
          }
        }
      }
      return Reflect.set(target, prop, value);
    }
  });
  
  return trackingCache;
};

Error Handler Utilities

Utilities for managing error handling in intl operations.

Usage Examples:

// Enhanced error handler with categorization
const createEnhancedErrorHandler: () => OnErrorFn = () => {
  const errorCounts = new Map<string, number>();
  
  return (error) => {
    const errorType = error.constructor.name;
    errorCounts.set(errorType, (errorCounts.get(errorType) || 0) + 1);
    
    // Log with context
    console.error(`[Intl Error ${error.code}] ${errorType}:`, error.message);
    
    // Handle specific error types
    switch (error.code) {
      case 'MISSING_TRANSLATION':
        // Report missing translations to translation management system
        reportMissingTranslation(error);
        break;
        
      case 'MISSING_DATA':
        // Handle missing locale data
        console.warn('Consider adding polyfill for:', error.message);
        break;
        
      case 'FORMAT_ERROR':
        // Handle format errors
        console.error('Format error details:', error);
        break;
    }
    
    // Metrics reporting
    if (errorCounts.get(errorType)! % 100 === 0) {
      console.warn(`${errorType} has occurred ${errorCounts.get(errorType)} times`);
    }
  };
};

// Silent error handler for production
const createSilentErrorHandler = (): OnErrorFn => {
  return (error) => {
    // Only log in development
    if (process.env.NODE_ENV === 'development') {
      console.error('Intl error:', error);
    }
    
    // Send to monitoring in production
    if (process.env.NODE_ENV === 'production') {
      // Send to error monitoring service
      sendToErrorMonitoring({
        type: 'intl_error',
        code: error.code,
        message: error.message,
        stack: error.stack
      });
    }
  };
};

const reportMissingTranslation = (error: any) => {
  // Implementation for reporting to translation management
  console.warn('Missing translation:', error.descriptor?.id);
};

const sendToErrorMonitoring = (errorData: any) => {
  // Implementation for error monitoring service
  console.log('Sending to monitoring:', errorData);
};