05 / 07

How to render static messages and messages with arguments in next-intl?

next-intl renders static messages as plain strings, while messages with arguments use ICU syntax for interpolation, plurals, and rich text via the t() function's second parameter.

In next-intl, messages are defined in JSON files and rendered using the useTranslations hook (client/server) or getTranslations (async server). Static messages are returned as-is, while dynamic messages use ICU syntax to handle interpolation, plurals, dates, and rich text formatting through the second argument of the translation function.

Message Structure (messages/en.json)

Static messages contain no dynamic placeholders. They are rendered exactly as defined in the JSON file using t('key'). The return value is a plain string that can be used directly in components.

Rendering Static Messages

Dynamic values are inserted into messages using curly braces {placeholder}. The second argument to t() is an object where keys match the placeholders. Value names must be alphanumeric and can contain underscores; dashes are not supported.

Basic Interpolation

Pluralization uses the plural ICU syntax. The # marker inserts the formatted number. Supported plural categories include zero, one, two, few, many, and other (varies by locale). Use selectordinal for ordinal numbers (e.g., 1st, 2nd, 3rd).

Cardinal Pluralization Examples

Dates and numbers can be formatted using ICU syntax within messages. Common formats include date, time, number, and currency. Use useFormatter for complex formatting needs outside messages.

Date Formatting

For messages containing HTML-like tags that should map to React components, use t.rich(). Tags in the message are replaced with component functions. Self-closing tags require a closing tag (e.g., <br></br>) due to ICU parser requirements.

Rich Text Rendering

The select argument works like a switch statement for mapping identifiers to human-readable text. The other case is required as a fallback.

Select Syntax

In async Server Components, use getTranslations() from next-intl/server. For static rendering with output: 'export', include generateStaticParams for the [locale] route and call setRequestLocale before using translations.

Server Component with Static Rendering

Messages can be nested for better organization using dot notation. The namespace passed to useTranslations should be the lowest common denominator containing all messages the component needs. Use useTranslations() without arguments to access the full tree.

Nested Message Structure
Key Points
  1. 1

    Static messages are rendered directly from JSON without placeholders

  2. 2

    Dynamic values use the second argument object: t('key', { arg: value })

  3. 3

    ICU syntax supports pluralization (plural, selectordinal), selection (select), and date/number formatting

  4. 4

    Rich text uses t.rich() to map tags to React components

  5. 5

    Use getTranslations() for async Server Components, useTranslations() for Client Components and shared components

  6. 6

    Enable static rendering with generateStaticParams and setRequestLocale

  7. 7

    Namespace keys cannot contain '.' characters except to express nesting