Lazy Translations
Lazy translation allows you to defer translation of a message until it's rendered, giving you flexibility in how and where you define messages in your code. With lazy translation, you can tag a string with the msg
macro to create a message descriptor that can be saved, passed around as a variable, and rendered later.
Usage Example
To render the message descriptor as a string-only translation, pass it to the i18n._()
method:
import { msg } from "@lingui/core/macro";
import { i18n } from "@lingui/core";
const favoriteColors = [msg`Red`, msg`Orange`, msg`Yellow`, msg`Green`];
export function getTranslatedColorNames() {
return favoriteColors.map((color) => i18n._(color));
}
Usage in React
To render the message descriptor in a React component, pass its id
to the Trans
component as a value of the id
prop:
import { msg } from "@lingui/core/macro";
import { Trans } from "@lingui/react";
const favoriteColors = [msg`Red`, msg`Orange`, msg`Yellow`, msg`Green`];
export default function ColorList() {
return (
<ul>
{favoriteColors.map((color) => (
<li>
<Trans id={color.id} />
</li>
))}
</ul>
);
}
Please note that we import the <Trans>
component from @lingui/react
to use the runtime version, as the message is already defined and we don't need the compile-time macro here.
Picking a Message Based on a Variable
Sometimes you need to choose 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 that represents the current status.
An easy way to do this is to create an object that maps the possible values of "status" to message descriptors (tagged with the msg
macro) and render them as needed with deferred translation:
import { msg } from "@lingui/core/macro";
import { useLingui } from "@lingui/react";
const statusMessages = {
["STATUS_OPEN"]: msg`Open`,
["STATUS_CLOSED"]: msg`Closed`,
["STATUS_CANCELLED"]: msg`Cancelled`,
["STATUS_COMPLETED"]: msg`Completed`,
};
export default function StatusDisplay({ statusCode }) {
const { _ } = useLingui();
return <div>{_(statusMessages[statusCode])}</div>;
}
Memoization Pitfall
In the following contrived example, we document how a welcome message will or will not be updated when locale changes. The documented behavior may not be intuitive at first, but it is expected, because of the way the useMemo
dependencies work.
To avoid bugs with stale translations, use the t
function returned from the useLingui
macro: it is safe to use with memoization because its reference changes whenever the Lingui context updates.
Keep in mind that useMemo
is primarily a performance optimization tool in React. Because of this, there might be no need to memoize your translations. Additionally, this issue is not present when using the Trans
component, which we recommend using whenever possible.
import { i18n } from "@lingui/core";
import { msg } from "@lingui/core/macro";
import { useLingui } from "@lingui/react/macro";
const welcomeMessage = msg`Welcome!`;
// ❌ Bad! This code won't work
export function Welcome() {
const buggyWelcome = useMemo(() => {
return i18n._(welcomeMessage);
}, []);
return <div>{buggyWelcome}</div>;
}
// ❌ Bad! This code won't work either because the reference to i18n does not change
export function Welcome() {
const { i18n } = useLingui();
const buggyWelcome = useMemo(() => {
return i18n._(welcomeMessage);
}, [i18n]);
return <div>{buggyWelcome}</div>;
}
// ✅ Good! `useMemo` consumes the `t` function from the `useLingui` macro
export function Welcome() {
const { t } = useLingui();
const welcome = useMemo(() => {
return t(welcomeMessage);
}, [t]);
return <div>{welcome}</div>;
}