CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-intl-messageformat

Formats ICU Message strings with number, date, plural, and select placeholders to create localized messages.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

formatters-types.mddocs/

Formatters and Types

Formatting utilities and type definitions for number, date, time, and custom formatters with extensible configuration.

Capabilities

Formatters Interface

Defines the formatter functions used for number, date/time, and plural formatting.

/**
 * Interface for formatter function providers
 */
interface Formatters {
  /**
   * Get a number formatter instance
   * @param locals - Locale(s) for formatting
   * @param opts - Number formatting options
   * @returns Intl.NumberFormat instance
   */
  getNumberFormat(
    locals?: string | string[],
    opts?: NumberFormatOptions
  ): Intl.NumberFormat;
  
  /**
   * Get a date/time formatter instance
   * @param args - Arguments for Intl.DateTimeFormat constructor
   * @returns Intl.DateTimeFormat instance
   */
  getDateTimeFormat(
    ...args: ConstructorParameters<typeof Intl.DateTimeFormat>
  ): Intl.DateTimeFormat;
  
  /**
   * Get a plural rules instance
   * @param args - Arguments for Intl.PluralRules constructor
   * @returns Intl.PluralRules instance
   */
  getPluralRules(
    ...args: ConstructorParameters<typeof Intl.PluralRules>
  ): Intl.PluralRules;
}

Usage Examples:

import IntlMessageFormat from "intl-messageformat";

// Custom formatters with caching
const customFormatters = {
  getNumberFormat: (locales, opts) => {
    // Custom number formatter with additional logic
    return new Intl.NumberFormat(locales, {
      ...opts,
      notation: 'compact' // Always use compact notation
    });
  },
  getDateTimeFormat: (...args) => new Intl.DateTimeFormat(...args),
  getPluralRules: (...args) => new Intl.PluralRules(...args)
};

const msg = new IntlMessageFormat(
  'You have {count, number} notifications',
  'en-US',
  undefined,
  { formatters: customFormatters }
);

Formats Interface

Configuration object for defining number, date, and time format styles.

/**
 * Format configuration for different formatting types
 */
interface Formats {
  /** Number format configurations */
  number: Record<string, NumberFormatOptions>;
  /** Date format configurations */
  date: Record<string, Intl.DateTimeFormatOptions>;
  /** Time format configurations */
  time: Record<string, Intl.DateTimeFormatOptions>;
}

Default Formats:

// Built-in format configurations
const defaultFormats: Formats = {
  number: {
    integer: { maximumFractionDigits: 0 },
    currency: { style: 'currency' },
    percent: { style: 'percent' }
  },
  date: {
    short: { month: 'numeric', day: 'numeric', year: '2-digit' },
    medium: { month: 'short', day: 'numeric', year: 'numeric' },
    long: { month: 'long', day: 'numeric', year: 'numeric' },
    full: { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' }
  },
  time: {
    short: { hour: 'numeric', minute: 'numeric' },
    medium: { hour: 'numeric', minute: 'numeric', second: 'numeric' },
    long: { hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'short' },
    full: { hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'short' }
  }
};

Usage Examples:

// Custom format configurations
const customFormats = {
  number: {
    currency: { style: 'currency', currency: 'EUR' },
    compact: { notation: 'compact', compactDisplay: 'short' }
  },
  date: {
    monthYear: { month: 'long', year: 'numeric' },
    dayMonth: { day: '2-digit', month: '2-digit' }
  },
  time: {
    hourMinute: { hour: '2-digit', minute: '2-digit', hour12: false }
  }
};

const msg = new IntlMessageFormat(
  'Price: {price, number, currency}, Last updated: {date, date, monthYear}',
  'en-US',
  customFormats
);

FormatterCache Interface

Cache structure for storing formatter instances to improve performance.

/**
 * Cache structure for formatter instances
 */
interface FormatterCache {
  /** Cache for number formatters */
  number: Record<string, NumberFormatOptions>;
  /** Cache for date/time formatters */
  dateTime: Record<string, Intl.DateTimeFormat>;
  /** Cache for plural rules */
  pluralRules: Record<string, Intl.PluralRules>;
}

formatToParts Function

Core formatting function that converts parsed message elements to formatted parts.

/**
 * Format message elements to structured parts
 * @param els - Array of parsed message format elements
 * @param locales - Locale(s) for formatting
 * @param formatters - Formatter function providers
 * @param formats - Format configurations
 * @param values - Values for placeholder substitution
 * @param currentPluralValue - Current plural value for nested contexts
 * @param originalMessage - Original message for error reporting
 * @returns Array of formatted message parts
 */
function formatToParts<T>(
  els: MessageFormatElement[],
  locales: string | string[],
  formatters: Formatters,
  formats: Formats,
  values?: Record<string, PrimitiveType | T | FormatXMLElementFn<T>>,
  currentPluralValue?: number,
  originalMessage?: string
): MessageFormatPart<T>[];

isFormatXMLElementFn Function

Type guard function to check if a value is a formatter function for XML elements.

/**
 * Type guard to check if a value is an XML element formatter function
 * @param el - Value to check
 * @returns True if the value is a formatter function
 */
function isFormatXMLElementFn<T>(
  el: PrimitiveType | T | FormatXMLElementFn<T>
): el is FormatXMLElementFn<T>;

Usage Examples:

const values = {
  name: 'Alice',
  link: (chunks) => `<a href="/profile">${chunks.join('')}</a>`
};

if (isFormatXMLElementFn(values.link)) {
  // TypeScript now knows this is a formatter function
  const result = values.link(['Click here']);
}

Part Types and Enums

PART_TYPE Enum

Defines the types of parts that can be returned by formatting operations.

/**
 * Types for message format parts
 */
enum PART_TYPE {
  /** Literal text part */
  literal = 0,
  /** Object/variable part */
  object = 1
}

MessageFormatPart Types

Structures for representing different types of formatted parts.

/**
 * Literal text part
 */
interface LiteralPart {
  type: PART_TYPE.literal;
  value: string;
}

/**
 * Object value part
 */
interface ObjectPart<T = any> {
  type: PART_TYPE.object;
  value: T;
}

/**
 * Union type for all message format parts
 */
type MessageFormatPart<T> = LiteralPart | ObjectPart<T>;

Type Definitions

PrimitiveType

Basic primitive types that can be used as message values.

/**
 * Basic primitive types for message values
 */
type PrimitiveType = string | number | boolean | null | undefined | Date;

FormatXMLElementFn

Function type for formatting XML/HTML elements in messages.

/**
 * Function type for XML element formatting
 * @param parts - Array of child content (strings or objects)
 * @returns Formatted result (string, object, or array)
 */
type FormatXMLElementFn<T, R = string | T | (string | T)[]> = (
  parts: Array<string | T>
) => R;

Usage Examples:

// Simple string formatter
const boldFormatter: FormatXMLElementFn<never> = (parts) => 
  `<strong>${parts.join('')}</strong>`;

// React component formatter
const LinkFormatter: FormatXMLElementFn<JSX.Element> = (parts) => 
  <a href="/link">{parts.join('')}</a>;

// Custom object formatter
const CustomFormatter: FormatXMLElementFn<{type: string, content: string}> = (parts) => ({
  type: 'custom',
  content: parts.join('')
});

Advanced Formatting Patterns

Custom Number Formatters

// Create a formatter for file sizes
const fileSizeFormatter = {
  getNumberFormat: (locales, opts) => {
    return new Intl.NumberFormat(locales, {
      ...opts,
      notation: 'compact',
      unit: 'byte',
      unitDisplay: 'short'
    });
  },
  getDateTimeFormat: (...args) => new Intl.DateTimeFormat(...args),
  getPluralRules: (...args) => new Intl.PluralRules(...args)
};

const msg = new IntlMessageFormat(
  'File size: {size, number} bytes',
  'en-US',
  undefined,
  { formatters: fileSizeFormatter }
);

Regional Format Customization

// European-style number and date formatting
const europeanFormats = {
  number: {
    currency: { style: 'currency', currency: 'EUR' },
    decimal: { minimumFractionDigits: 2, maximumFractionDigits: 2 }
  },
  date: {
    standard: { day: '2-digit', month: '2-digit', year: 'numeric' }
  },
  time: {
    standard: { hour: '2-digit', minute: '2-digit', hour12: false }
  }
};

const europeanMsg = new IntlMessageFormat(
  'Price: {price, number, currency} on {date, date, standard}',
  'de-DE',
  europeanFormats
);

Performance Optimization with Caching

// Shared cache across multiple message instances
const sharedCache: FormatterCache = {
  number: {},
  dateTime: {},
  pluralRules: {}
};

const createOptimizedFormatters = (cache: FormatterCache): Formatters => ({
  getNumberFormat: memoize(
    (...args) => new Intl.NumberFormat(...args),
    { cache: cache.number }
  ),
  getDateTimeFormat: memoize(
    (...args) => new Intl.DateTimeFormat(...args),
    { cache: cache.dateTime }
  ),
  getPluralRules: memoize(
    (...args) => new Intl.PluralRules(...args),
    { cache: cache.pluralRules }
  )
});

const optimizedFormatters = createOptimizedFormatters(sharedCache);

// Use the same formatters across multiple messages
const msg1 = new IntlMessageFormat('Hello {name}!', 'en-US', undefined, {
  formatters: optimizedFormatters
});
const msg2 = new IntlMessageFormat('Goodbye {name}!', 'en-US', undefined, {
  formatters: optimizedFormatters
});

docs

error-handling.md

formatters-types.md

index.md

message-formatting.md

tile.json