Loading...
Loading...
Implement internationalization with Lingui in React and JavaScript applications. Use when adding i18n, translating UI, working with Trans/useLingui/Plural, extracting messages, compiling catalogs, or when the user mentions Lingui, internationalization, i18n, translations, locales, message extraction, ICU MessageFormat, or working with .po files.
npx skill4agent add lingui/skills lingui-best-practicesI18nProviderTranstlingui extractlingui compile// React macros (recommended)
import { Trans, Plural, Select, useLingui } from "@lingui/react/macro";
// Core macros for vanilla JS
import { t, msg, plural, select } from "@lingui/core/macro";
// Runtime (rarely used directly)
import { I18nProvider } from "@lingui/react";
import { i18n } from "@lingui/core";I18nProviderimport { I18nProvider } from "@lingui/react";
import { i18n } from "@lingui/core";
import { messages } from "./locales/en/messages";
i18n.load("en", messages);
i18n.activate("en");
function App() {
return (
<I18nProvider i18n={i18n}>
{/* Your app */}
</I18nProvider>
);
}Transimport { Trans } from "@lingui/react/macro";
// Simple text
<Trans>Hello World</Trans>
// With variables
<Trans>Hello {userName}</Trans>
// With components (rich text)
<Trans>
Read the <a href="/docs">documentation</a> for more info.
</Trans>
// Extracted as: "Read the <0>documentation</0> for more info."import { useLingui } from "@lingui/react/macro";
function MyComponent() {
const { t } = useLingui();
const handleClick = () => {
alert(t`Action completed!`);
};
return (
<div>
<img src="..." alt={t`Image description`} />
<button onClick={handleClick}>{t`Click me`}</button>
</div>
);
}import { msg } from "@lingui/core/macro";
import { useLingui } from "@lingui/react";
// Module-level constants
const STATUSES = {
active: msg`Active`,
inactive: msg`Inactive`,
pending: msg`Pending`,
};
function StatusList() {
const { _ } = useLingui();
return Object.entries(STATUSES).map(([key, message]) => (
<div key={key}>{_(message)}</div>
));
}Pluralimport { Plural } from "@lingui/react/macro";
<Plural
value={messageCount}
one="You have # message"
other="You have # messages"
/>#_N<Plural
value={count}
_0="No messages"
one="One message"
other="# messages"
/>Trans<Plural
value={count}
one={`You have # message, ${userName}`}
other={
<Trans>
You have <strong>#</strong> messages, {userName}
</Trans>
}
/>i18n.date()i18n.number()import { useLingui } from "@lingui/react/macro";
function MyComponent() {
const { i18n } = useLingui();
const lastLogin = new Date();
return (
<Trans>
Last login: {i18n.date(lastLogin)}
</Trans>
);
}Intl<Trans id="header.welcome">Welcome to our app</Trans>context<Trans context="direction">right</Trans>
<Trans context="correctness">right</Trans><Trans comment="Greeting shown on homepage">Hello World</Trans>lingui.config.jsimport { defineConfig } from "@lingui/cli";
export default defineConfig({
sourceLocale: "en",
locales: ["en", "es", "fr", "de"],
catalogs: [
{
path: "<rootDir>/src/locales/{locale}/messages",
include: ["src"],
exclude: ["**/node_modules/**"],
},
],
});// ✅ Good - uses macro
import { Trans } from "@lingui/react/macro";
// ❌ Avoid - runtime only
import { Trans } from "@lingui/react";// ❌ Bad - loses context
<Trans>Hello {user.name.toUpperCase()}</Trans>
// Extracted as: "Hello {0}"
// ✅ Good - clear variable name
const userName = user.name.toUpperCase();
<Trans>Hello {userName}</Trans>
// Extracted as: "Hello {userName}"// ✅ For JSX content
<h1><Trans>Welcome</Trans></h1>
// ✅ For string values
const { t } = useLingui();
<img alt={t`Profile picture`} />msg// ❌ Bad - won't work
import { t } from "@lingui/core/macro";
const LABELS = [t`Red`, t`Green`, t`Blue`];
// ✅ Good - use msg for lazy translation
import { msg } from "@lingui/core/macro";
const LABELS = [msg`Red`, msg`Green`, msg`Blue`];eslint-plugin-linguinpm install --save-dev eslint-plugin-lingui// eslint.config.js
import pluginLingui from "eslint-plugin-lingui";
export default [
pluginLingui.configs["flat/recommended"],
];import { i18n } from "@lingui/core";
async function changeLocale(locale) {
const { messages } = await import(`./locales/${locale}/messages`);
i18n.load(locale, messages);
i18n.activate(locale);
}import { useEffect } from "react";
import { i18n } from "@lingui/core";
function loadCatalog(locale) {
return import(`./locales/${locale}/messages`);
}
function App() {
useEffect(() => {
loadCatalog("en").then(catalog => {
i18n.load("en", catalog.messages);
i18n.activate("en");
});
}, []);
return <I18nProvider i18n={i18n}>{/* ... */}</I18nProvider>;
}timport { useLingui } from "@lingui/react/macro";
import { msg } from "@lingui/core/macro";
import { useMemo } from "react";
const welcomeMessage = msg`Welcome!`;
function MyComponent() {
const { t } = useLingui(); // Macro version - reference changes with locale
// ✅ Safe - t reference updates with locale
const message = useMemo(() => t(welcomeMessage), [t]);
return <div>{message}</div>;
}includelingui.config.jslingui compileI18nProviderlingui compile --typescript