Common i18n patterns in React

Following page describes the most common i18n patterns in React. It’s a followup to tutorial with practical examples. See the API reference for detailed information about all components.

Macros

Using jsx macros is the most straightforward way how to translate your React components.

<Trans> handles translations of messages including variables and other React components:

import { Trans } from "@lingui/macro"

<h1><Trans>LinguiJS example</Trans></h1>

<p><Trans>Hello <a href="/profile">{name}</a>.</Trans></p>

You don’t need anything special to use <Trans> inside out app (except of wrapping your app in <I18nProvider>).

Using generated message as ID

In the examples above, the content of <Trans> is transformed into message in MessageFormat syntax. By default, this message is used as a message ID. In the example above, messages LinguiJS example and Hello <0>{name}</0>. are extracted.

Using custom ID

If you’re using custom IDs in your project, add id prop to i18n components:

import { Trans } from "@lingui/macro"

<h1><Trans id="msg.header">LinguiJS example</Trans></h1>

<p><Trans id="msg.hello">Hello <a href="/profile">{name}</a>.</Trans></p>

Messages msg.header and msg.hello will be extracted with default values LinguiJS example and Hello <0>{name}</0>..

Element attributes and string only translations

Sometimes you can’t use <Trans> component, for example when translating element attributes:

<img src="..." alt="Image caption" />

In such case you need to use <I18n> render prop component to access i18n object and t macro to wrap message:

  1. Use render prop component <I18n> from @lingui/react, to access i18n object.
  2. Call i18n._`() to translate message wrapped in JS macros. t is equivalent for <Trans>, plural is equivalent to <Plural>.
import { I18n } from "@lingui/react"
import { t } from "@lingui/macro"

export default function ImageWithCaption() {
   return (
      <I18n>
         {({ i18n }) => (
            <img src="..." alt={i18n._(t`Image caption`)} />
         )}
      </I18n>
   )
}

Using generated message as ID

You can either use generated messages as IDs or custom ones. This is the same as working for i18n components.

In this example:

import { I18n } from "@lingui/react"
import { t } from "@lingui/macro"

export default function ImageWithCaption() {
   return (
      <I18n>
         {({ i18n }) => (
            <img src="..." alt={i18n._(t`Image caption`)} />
         )}
      </I18n>
   )
}

Message Image caption will be extracted.

Using custom ID

If you’re using custom IDs in your project, call t with ID as a first argument and then use string templates as usual:

import { I18n } from "@lingui/react"
import { t } from "@lingui/macro"

export default function ImageWithCaption() {
   return (
      <I18n>
         {({ i18n }) => (
            <img src="..." alt={i18n._(t('msg.caption')`Image caption`)} />
         )}
      </I18n>
   )
}

Message msg.caption will be extracted with default value Image caption.

For all other js macros (plural, select`, selectOrdinal`), pass ID as object key:

import { I18n } from "@lingui/react"
import { plural } from "@lingui/macro"

export default function ImageWithCaption({ count }) {
   return (
      <I18n>
         {({ i18n }) => (
            <img src="..." alt={i18n._(plural('msg.caption', {
               value: count,
               one: "# image caption",
               other: "# image captions",
            }))} />
         )}
      </I18n>
   )
}

Translations outside React components

Another common pattern is when you need to access translations (i18n object) outside React components, for example inside redux-saga. In such case, you need a bit more setup:

  1. Create your own instance of i18n using setupI18n() form @lingui/core

  2. Pass this instance as i18n prop to <I18nProvider>. This will replace default i18n object initialized inside <I18nProvider>.

    // App.js
    import { setupI18n } from "@lingui/core"
    import { I18nProvider } from "@lingui/react"
    
    export const i18n = setupI18n()
    
    export default function App() {
       return (
          <I18nProvider i18n={i18n}>
             {/* Out app */}
          </I18nProvider>
       )
    }
    
  3. Whenever you are outside React context (i.e. you can’t access props), you can use this i18n object.

    import { i18n } from "./App.js"
    import { t } from "@lingui/macro"
    
    export function alert() {
       // use i18n as you were inside React component
       alert(i18n._(t`...`))
    }
    

Lazy translations

<Trans> can also translate messages from variables. We can use t macro to create a message descriptor and then pass it to <Trans> macro as id prop:

import { t, Trans } from "@lingui/macro"

const languages = [
   t`English`
   t`Czech`
]

function LanguageSwitcher() {
   return (
      <ul>
         {languages.map(lang => <li><Trans id={lang}/></li>}
      </ul>
   )
}

This pattern also work with string-only translations. Just pass the message descriptor to I18n._() method as usual:

import { t } from "@lingui/macro"

const languages = [
   t`English`
   t`Czech`
]

const translatedLanguages = languages.map(
   lang => i18n._(lang)
)