重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
lingui-best-practices by lingui/skills
npx skills add https://github.com/lingui/skills --skill lingui-best-practicesLingui 是一个强大的 JavaScript 国际化(i18n)框架。本技能涵盖了在 React 和原生 JavaScript 应用中实现 i18n 的最佳实践。
标准的 Lingui 工作流包含以下步骤:
I18nProvider 包装你的应用Trans、t 等)标记待翻译的消息lingui extractlingui compile从以下包中导入:
// React 宏(推荐)
import { Trans, Plural, Select, useLingui } from "@lingui/react/macro";
// 用于原生 JS 的核心宏
import { t, msg, plural, select } from "@lingui/core/macro";
// 运行时(很少直接使用)
import { I18nProvider } from "@lingui/react";
import { i18n } from "@lingui/core";
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
用 I18nProvider 包装你的应用:
import { 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}>
{/* 你的应用 */}
</I18nProvider>
);
}
Trans 宏是翻译 JSX 的主要方式:
import { Trans } from "@lingui/react/macro";
// 简单文本
<Trans>Hello World</Trans>
// 带变量
<Trans>Hello {userName}</Trans>
// 带组件(富文本)
<Trans>
Read the <a href="/docs">documentation</a> for more info.
</Trans>
// 提取为:"Read the <0>documentation</0> for more info."
何时使用:用于 JSX 元素中的任何可翻译文本。
对于 JSX 之外的字符串(属性、警告框、函数调用):
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>
);
}
何时使用:元素属性、警告框、函数参数、任何非 JSX 字符串。
当需要在模块级别或在数组/对象中定义消息时:
import { msg } from "@lingui/core/macro";
import { useLingui } from "@lingui/react";
// 模块级常量
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>
));
}
何时使用:模块级常量、消息数组、条件消息选择。
使用 Plural 宏处理依赖数量的消息:
import { 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 API 进行正确的语言环境格式化。
为稳定的消息键提供自定义 ID:
<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.js:
import { 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/**"],
},
],
});
有关详细的配置模式,请参阅 configuration.md。
优先使用宏而非运行时组件。宏在构建时编译,可减少打包体积:
// ✅ 好 - 使用宏
import { Trans } from "@lingui/react/macro";
// ❌ 避免 - 仅运行时
import { Trans } from "@lingui/react";
避免在消息中使用复杂表达式——它们会被替换为占位符:
// ❌ 不好 - 丢失上下文
<Trans>Hello {user.name.toUpperCase()}</Trans>
// 提取为:"Hello {0}"
// ✅ 好 - 清晰的变量名
const userName = user.name.toUpperCase();
<Trans>Hello {userName}</Trans>
// 提取为:"Hello {userName}"
选择合适的工具:
// ✅ 用于 JSX 内容
<h1><Trans>Welcome</Trans></h1>
// ✅ 用于字符串值
const { t } = useLingui();
<img alt={t`Profile picture`} />
宏需要组件上下文——请改用 msg:
// ❌ 不好 - 无法工作
import { t } from "@lingui/core/macro";
const LABELS = [t`Red`, t`Green`, t`Blue`];
// ✅ 好 - 使用 msg 进行惰性翻译
import { msg } from "@lingui/core/macro";
const LABELS = [msg`Red`, msg`Green`, msg`Blue`];
安装并配置 eslint-plugin-lingui 以自动捕获常见错误:
npm 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>;
}
当使用记忆化时,使用宏版本的 t 函数:
import { useLingui } from "@lingui/react/macro";
import { msg } from "@lingui/core/macro";
import { useMemo } from "react";
const welcomeMessage = msg`Welcome!`;
function MyComponent() {
const { t } = useLingui(); // 宏版本 - 引用随语言环境变化
// ✅ 安全 - t 引用随语言环境更新
const message = useMemo(() => t(welcomeMessage), [t]);
return <div>{message}</div>;
}
如果遇到问题:
lingui.config.js 中的 include 模式lingui compile 编译I18nProvider 包装了你的应用lingui compile --typescript有关详细的常见错误和陷阱,请参阅 common-mistakes.md。
每周安装次数
51
代码仓库
GitHub 星标数
3
首次出现
2026年1月27日
安全审计
已安装于
codex47
gemini-cli46
kimi-cli46
opencode46
github-copilot46
amp46
Lingui is a powerful internationalization (i18n) framework for JavaScript. This skill covers best practices for implementing i18n in React and vanilla JavaScript applications.
The standard Lingui workflow consists of these steps:
I18nProviderTrans, t, etc.)lingui extractlingui compileImport from these packages:
// 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";
Wrap your application with I18nProvider:
import { 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>
);
}
The Trans macro is the primary way to translate JSX:
import { 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."
When to use : For any translatable text in JSX elements.
For strings outside JSX (attributes, alerts, function calls):
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>
);
}
When to use : Element attributes, alerts, function parameters, any non-JSX string.
When you need to define messages at module level or in arrays/objects:
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>
));
}
When to use : Module-level constants, arrays of messages, conditional message selection.
Use the Plural macro for quantity-dependent messages:
import { Plural } from "@lingui/react/macro";
<Plural
value={messageCount}
one="You have # message"
other="You have # messages"
/>
The # placeholder is replaced with the actual value.
Use _N syntax for exact number matches (takes precedence over plural forms):
<Plural
value={count}
_0="No messages"
one="One message"
other="# messages"
/>
Combine with Trans for complex messages:
<Plural
value={count}
one={`You have # message, ${userName}`}
other={
<Trans>
You have <strong>#</strong> messages, {userName}
</Trans>
}
/>
Use i18n.date() and i18n.number() for locale-aware formatting:
import { useLingui } from "@lingui/react/macro";
function MyComponent() {
const { i18n } = useLingui();
const lastLogin = new Date();
return (
<Trans>
Last login: {i18n.date(lastLogin)}
</Trans>
);
}
These use the browser's Intl API for proper locale formatting.
Provide a custom ID for stable message keys:
<Trans id="header.welcome">Welcome to our app</Trans>
When the same text has different meanings, use context:
<Trans context="direction">right</Trans>
<Trans context="correctness">right</Trans>
These create separate catalog entries.
Add context for translators:
<Trans comment="Greeting shown on homepage">Hello World</Trans>
Basic lingui.config.js:
import { 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/**"],
},
],
});
For detailed configuration patterns, see configuration.md.
Prefer macros over runtime components. Macros are compiled at build time, reducing bundle size:
// ✅ Good - uses macro
import { Trans } from "@lingui/react/macro";
// ❌ Avoid - runtime only
import { Trans } from "@lingui/react";
Avoid complex expressions in messages - they'll be replaced with placeholders:
// ❌ 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}"
Choose the right tool:
// ✅ For JSX content
<h1><Trans>Welcome</Trans></h1>
// ✅ For string values
const { t } = useLingui();
<img alt={t`Profile picture`} />
Macros need component context - use msg instead:
// ❌ 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`];
Install and configure eslint-plugin-lingui to catch common mistakes automatically:
npm 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>;
}
When using memoization, use the t function from the macro version:
import { 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>;
}
If you encounter issues:
include patterns in lingui.config.jslingui compileI18nProvider wraps your applingui compile --typescript for TypeScript projectsFor detailed common mistakes and pitfalls, see common-mistakes.md.
Weekly Installs
51
Repository
GitHub Stars
3
First Seen
Jan 27, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex47
gemini-cli46
kimi-cli46
opencode46
github-copilot46
amp46
UI组件模式实战指南:构建可复用React组件库与设计系统
10,700 周安装