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

message-formatting.mddocs/

Message Formatting

ICU MessageFormat integration with pluralization, gender, and rich text element support for comprehensive internationalization. Provides both individual functions and intl instance methods for formatting messages with complex interpolation.

Capabilities

formatMessage Function

Formats messages using ICU MessageFormat syntax with variable interpolation and rich text support.

/**
 * Format messages with ICU MessageFormat syntax
 * @param config - Resolved intl configuration
 * @param formatters - Formatter instances and message format getter
 * @param descriptor - Message descriptor with id and optional default message
 * @param values - Values for message interpolation including rich text elements
 * @param opts - Additional formatting options
 * @returns Formatted message as string or rich text elements
 */
function formatMessage<T>(
  config: ResolvedIntlConfig<T>,
  formatters: Formatters & { getMessageFormat: (...args: any[]) => IntlMessageFormat },
  descriptor: MessageDescriptor,
  values?: Record<string, PrimitiveType | T | FormatXMLElementFn<T>>,
  opts?: IntlMessageFormatOptions
): string | T | Array<string | T>;

Usage Examples:

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

const config = {
  locale: 'en-US',
  messages: {
    greeting: 'Hello {name}!',
    itemCount: 'You have {count, plural, =0 {no items} one {one item} other {# items}}',
    boldText: 'This is <b>bold</b> text'
  },
  // ... other config
};

const formatters = createFormatters();

// Basic message formatting
const greeting = formatMessage(
  config,
  formatters,
  { id: 'greeting' },
  { name: 'Alice' }
);
// Result: "Hello Alice!"

// Pluralization
const count = formatMessage(
  config,
  formatters,
  { id: 'itemCount' },
  { count: 3 }
);
// Result: "You have 3 items"

// Rich text formatting (React example)
const richText = formatMessage(
  config,
  formatters,
  { id: 'boldText' },
  {
    b: (chunks) => <strong>{chunks}</strong>
  }
);
// Result: ["This is ", <strong>bold</strong>, " text"]

$t Alias

The $t method is a convenient alias for formatMessage available on intl instances, providing the same functionality with a shorter syntax.

/**
 * Alias for formatMessage method available on intl instances
 * @param descriptor - Message descriptor with id and optional default message
 * @param values - Values for message interpolation including rich text elements
 * @param opts - Additional formatting options
 * @returns Formatted message as string or rich text elements
 */
$t<T>(
  descriptor: MessageDescriptor,
  values?: Record<string, PrimitiveType | T | FormatXMLElementFn<T>>,
  opts?: IntlMessageFormatOptions
): string | T | Array<string | T>;

Usage Examples:

// Using $t alias for shorter syntax
const intl = createIntl({
  locale: 'en-US',
  messages: {
    greeting: 'Hello {name}!',
    itemCount: 'You have {count, plural, =0 {no items} one {one item} other {# items}}'
  }
});

// Both calls are equivalent
const greeting1 = intl.formatMessage({ id: 'greeting' }, { name: 'Alice' });
const greeting2 = intl.$t({ id: 'greeting' }, { name: 'Alice' });

// Common usage pattern
const welcomeMessage = intl.$t({ 
  id: 'welcome',
  defaultMessage: 'Welcome, {username}!'
}, { 
  username: user.name 
});

defineMessage Function

Defines a single message descriptor with type safety.

/**
 * Define a single message descriptor
 * @param msg - Message descriptor object
 * @returns The same message descriptor for type safety
 */
function defineMessage<T>(msg: T): T;

defineMessages Function

Defines multiple message descriptors with type safety and key preservation.

/**
 * Define multiple message descriptors with type safety
 * @param msgs - Record of message descriptors
 * @returns The same record of message descriptors
 */
function defineMessages<
  K extends keyof any,
  T = MessageDescriptor,
  U extends Record<K, T> = Record<K, T>
>(msgs: U): U;

Usage Examples:

import { defineMessage, defineMessages } from "@formatjs/intl";

// Single message definition
const welcomeMessage = defineMessage({
  id: 'welcome',
  defaultMessage: 'Welcome, {name}!',
  description: 'Greeting message for users'
});

// Multiple message definitions
const messages = defineMessages({
  login: {
    id: 'auth.login',
    defaultMessage: 'Log in',
    description: 'Login button text'
  },
  logout: {
    id: 'auth.logout', 
    defaultMessage: 'Log out',
    description: 'Logout button text'
  },
  profile: {
    id: 'user.profile',
    defaultMessage: 'User Profile',
    description: 'Profile page title'
  }
});

// Type-safe usage
const loginText = intl.formatMessage(messages.login);

MessageDescriptor Interface

Describes a message with identifier, default content, and metadata.

interface MessageDescriptor {
  /** Unique identifier for the message */
  id?: string;
  /** Human-readable description for translators */
  description?: string | object;
  /** Default message text or pre-compiled AST */
  defaultMessage?: string | MessageFormatElement[];
}

Message Values and Rich Text

Support for variable interpolation and rich text elements in messages.

type PrimitiveType = string | number | boolean | null | undefined | Date;

type FormatXMLElementFn<T, R = T | string | (T | string)[]> = (
  chunks: (T | string)[]
) => R;

Usage Examples:

// Variable interpolation
const message = intl.formatMessage(
  { id: 'user.info', defaultMessage: '{name} is {age} years old' },
  { name: 'Alice', age: 25 }
);

// Date and number formatting within messages
const notification = intl.formatMessage(
  { 
    id: 'notification',
    defaultMessage: 'You have {count, number} new messages as of {date, date, short}'
  },
  { 
    count: 5, 
    date: new Date() 
  }
);

// Rich text with React elements
const richMessage = intl.formatMessage(
  {
    id: 'terms',
    defaultMessage: 'I agree to the <link>Terms of Service</link>'
  },
  {
    link: (chunks) => (
      <a href="/terms" className="text-blue-500">
        {chunks}
      </a>
    )
  }
);

// Complex pluralization
const complexPlural = intl.formatMessage(
  {
    id: 'file.status',
    defaultMessage: `{count, plural, 
      =0 {No files} 
      =1 {One file} 
      other {# files}
    } {action, select, 
      upload {uploaded} 
      download {downloaded} 
      other {processed}
    }`
  },
  { count: 3, action: 'upload' }
);
// Result: "3 files uploaded"

Pre-compiled Messages

Support for pre-compiled message formats for better performance.

interface MessageFormatElement {
  type: number;
  value?: string;
  // Additional properties based on element type
}

Usage Examples:

// Pre-compiled messages for production optimization
const precompiledMessages = {
  greeting: [
    { type: 0, value: "Hello " },
    { type: 1, value: "name" },
    { type: 0, value: "!" }
  ]
};

const intl = createIntl({
  locale: 'en-US',
  messages: precompiledMessages
});

// Works the same as string messages
const result = intl.formatMessage(
  { id: 'greeting' },
  { name: 'World' }
);

ICU MessageFormat Syntax

Supported ICU MessageFormat features for complex message patterns.

Pluralization:

{count, plural, =0 {no items} one {one item} other {# items}}

Selection:

{gender, select, male {He} female {She} other {They}} liked this

Number Formatting:

{price, number, currency}
{percentage, number, percent}

Date Formatting:

{date, date, short}
{time, time, medium}

Nested Patterns:

{count, plural, 
  =0 {No {type, select, photo {photos} other {items}}}
  one {One {type, select, photo {photo} other {item}}}
  other {# {type, select, photo {photos} other {items}}}
}

Error Handling

Message formatting includes comprehensive error handling for missing translations and format errors.

class MissingTranslationError extends IntlError<IntlErrorCode.MISSING_TRANSLATION> {
  readonly descriptor?: MessageDescriptor;
  constructor(descriptor: MessageDescriptor, locale: string);
}

class MessageFormatError extends IntlError<IntlErrorCode.FORMAT_ERROR> {
  readonly descriptor?: MessageDescriptor;
  readonly locale: string;
  constructor(message: string, locale: string, descriptor?: MessageDescriptor, exception?: Error);
}