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:
Use render prop component <I18n> from
@lingui/react
, to accessi18n
object.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:
Create your own instance of
i18n
usingsetupI18n()
form@lingui/core
Pass this instance as
i18n
prop to <I18nProvider>. This will replace defaulti18n
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> ) }
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¶
Messages don’t have to be declared at the same code location where they’re displayed.
Tag a string with the t macro, and you’ve created a “message descriptor”, which
can then be passed around as a variable, and can be displayed as a translated string by
passing it to <Trans> as its id
prop:
import { t, Trans } from "@lingui/macro"
const favoriteColors = [
t`Red`,
t`Orange`,
t`Yellow`,
t`Green`,
]
export default function ColorList() {
return (
<ul>
{favoriteColors.map(color => (
<li><Trans id={color}/></li>
}
</ul>
)
}
Or to render the message descriptor as a string-only translation, just pass it to
the I18n._()
method as usual:
import { t } from "@lingui/macro"
const favoriteColors = [
t`Red`,
t`Orange`,
t`Yellow`,
t`Green`,
]
const translatedColorNames = favoriteColors.map(
color => i18n._(color)
)
Passing messages as props¶
It’s often convenient to pass messages around as component props, for example as a “label” prop on a button. The easiest way to do this is to pass a <Trans> element as the prop:
import { Trans } from "@lingui/macro"
export default function FancyButton(props) {
return <button>{props.label}</button>
}
export function LoginLogoutButtons(props) {
return <div>
<FancyButton label={<Trans>Log in</Trans>} />
<FancyButton label={<Trans>Log out</Trans>} />
</div>
}
If you need the prop to be displayed as a string-only translation, you can pass a message descriptor (tagged with the t macro), and have the component render it as a string using lazy translation:
import { t } from "@lingui/macro"
import { I18n } from "@lingui/react"
export default function ImageWithCaption(props) {
return (
<I18n>
{({ i18n }) => (
<img src="..." alt={i18n._(props.caption)} />
)}
</I18n>
)
}
export function HappySad(props) {
return <div>
<ImageWithCaption
hoverText={t`I'm so happy!`}
/>
<ImageWithCaption
hoverText={t`I'm so sad.`}
/>
</div>
}
Picking a message based on a variable¶
Sometimes you need to pick between different messages to display, depending on the value of a variable. For example, imagine you have a numeric “status” code that comes from an API, and you need to display a message representing the current status.
A simple way to do this, is to make an object that maps the possible values of “status” to message descriptors (tagged with the t macro), and render them as needed with lazy translation:
import { Trans } from "@lingui/macro";
const STATUS_OPEN = 1,
STATUS_CLOSED = 2,
STATUS_CANCELLED = 4,
STATUS_COMPLETED = 8
const statusMessages = {
[STATUS_OPEN]: t`Open`,
[STATUS_CLOSED]: t`Closed`,
[STATUS_CANCELLED]: t`Cancelled`,
[STATUS_COMPLETED]: t`Completed`,
}
export default function StatusDisplay(statusCode) {
return <div><Trans id={statusMessages[statusCode]} /></div>
}