使用您最喜欢的AI助手总结文档,并引用此页面和AI提供商
版本历史
- "变体功能发布"v9.0.02026/6/12
- "`variant` 现在接受字符串或对象 — 以前的 `meta` / 动态记录现在声明为对象变体"v9.1.02026/6/26
- "变体仅声明它覆盖的键;未声明的变体将回退到默认条目"v9.1.12026/7/31
- "提供者接受环境级 `variant` 属性;选择器接受有序的优先级链"v9.1.22026/8/4
此页面的内容已使用 AI 翻译。
查看英文原文的最新版本If you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.
GitHub link to the documentationCopy doc Markdown to clipboard
变体
变体是一组共享相同字典 key、但各自携带不同 variant 值的内容文件。Intlayer 根据传递给 useIntlayer 的选择器提供相应的文件。
variant 的值可以采用两种形式:
- 字符串 — 单个具名替代项(A/B 测试、季节性横幅、功能开关)。
- 对象 — 由一组字段寻址的结构化判别器(CMS 记录、用户特定文案、以不透明 ID 作为键的任何内容)。整个对象即为标识:选择器必须提供一个相等的对象才能解析该条目。
对象形式取代了以前的meta字段。凡是以前写meta: { id, … }的地方,请改写为variant: { id, … },并用{ variant: { id, … } }进行选择。
具名(字符串)变体
每个文件代表一个具名替代项。省略 variant(或将其设置为 "default")会将其标记为回退项。
复制代码到剪贴板
import { t, type Dictionary } from "intlayer";
const dictionary = {
key: "hero-banner",
variant: "default",
content: {
headline: t({
en: "Build faster with Intlayer",
fr: "Développez plus vite avec Intlayer",
}),
cta: t({ en: "Get started", fr: "Commencer" }),
},
} satisfies Dictionary;
export default dictionary;复制代码到剪贴板
import { t, type Dictionary } from "intlayer";
const dictionary = {
key: "hero-banner",
variant: "black_friday",
content: {
headline: t({
en: "50 % off — today only",
fr: "−50 % — aujourd'hui seulement",
}),
cta: t({ en: "Shop now", fr: "Acheter maintenant" }),
},
} satisfies Dictionary;
export default dictionary;部分变体
变体仅声明它覆盖的键;其余部分从默认条目继承。
复制代码到剪贴板
import { t, type Dictionary } from "intlayer";
const dictionary = {
key: "hero-banner",
variant: "summer",
content: {
headline: t({
en: "Build faster all summer",
fr: "Développez plus vite tout l'été",
}),
},
} satisfies Dictionary;
export default dictionary;复制代码到剪贴板
useIntlayer("hero-banner", { variant: "summer" });// → { headline: "Développez plus vite tout l'été", cta: "Commencer" } — 继承了 `cta`useIntlayer("hero-banner", { variant: "never-declared" });// → 默认条目因此,您只需在文本确实不同的地方添加变体文件。只有在声明了变体但没有默认条目的情况下,键才会解析为 null。
使用具名变体
默认变体
复制代码到剪贴板
import { useIntlayer } from "react-intlayer";
export const Hero = () => {
const { headline, cta } = useIntlayer("hero-banner");
// → 默认变体
return (
<section>
<h1>{headline}</h1>
<a>{cta}</a>
</section>
);
};具名变体
复制代码到剪贴板
const { headline, cta } = useIntlayer("hero-banner", { variant: "black_friday",});带显式语言环境的具名变体
复制代码到剪贴板
const content = useIntlayer("hero-banner", { variant: "black_friday", locale: "fr",});对象(结构化)变体
对象变体通过在 variant 字段中声明的任意键值对集合来寻址内容——从而可以建模 CMS 记录、用户特定文案,或键为不透明 ID 的任何内容。整个对象即为标识:选择器必须提供一个相等的对象,该条目才会被解析。
复制代码到剪贴板
import { t, type Dictionary } from "intlayer";
const dictionary = {
key: "product",
variant: { id: "prod_abc", userId: "user_123" },
content: {
name: t({ en: "Widget Pro", fr: "Widget Pro" }),
description: t({ en: "The best widget.", fr: "Le meilleur widget." }),
},
} satisfies Dictionary;
export default dictionary;复制代码到剪贴板
import { t, type Dictionary } from "intlayer";
const dictionary = {
key: "product",
variant: { id: "prod_abcd", userId: "user_123" },
content: {
name: t({ en: "Widget Lite", fr: "Widget Lite" }),
description: t({ en: "A lighter option.", fr: "Une option plus légère." }),
},
} satisfies Dictionary;
export default dictionary;使用对象变体
将匹配的对象传递给 variant。字典上声明的每个字段都必须提供且相等;否则结果为 null。字段顺序无关紧要。
复制代码到剪贴板
import { useIntlayer } from "react-intlayer";
export const Product = ({
productId,
userId,
}: {
productId: string;
userId: string;
}) => {
const content = useIntlayer("product", {
variant: { id: productId, userId },
});
if (!content) return null;
return <p>{content.description}</p>;
};带显式语言环境
复制代码到剪贴板
const content = useIntlayer("product", { variant: { id: "prod_abc", userId: "user_123" }, locale: "fr",});缺少字段 — 无匹配
复制代码到剪贴板
// 返回 null:缺少 `userId`,因此对象与声明的变体不匹配const content = useIntlayer("product", { variant: { id: "prod_abc" } });环境变体
有些变体维度在整个会话中都是固定的——租户、学校类型、套餐等级。它们只需解析一次,任何组件都不应手动传递它们。
不要为了注入它们而把useIntlayer包装进你自己的 Hook。构建期优化只会重写从框架包中导入的字面量useIntlayer("key")调用,因此包装器背后的内容不会被打包。
请改为在提供者上声明一次变体,就像 locale 一样:
复制代码到剪贴板
import { IntlayerProvider } from "react-intlayer";
export const App = ({ locale, schoolType }) => (
<IntlayerProvider locale={locale} variant={schoolType}>
<Hero />
</IntlayerProvider>
);现在提供者下的每次字典读取都会基于该变体解析,而调用处的选择器始终优先:
复制代码到剪贴板
useIntlayer("hero-banner");// → 提供者的变体useIntlayer("hero-banner", { variant: "summer" });// → "summer" —— 替换提供者的变体,而不是扩展它形式
variant 属性接受三种形式:
在弹窗中打开表格以清晰地查看所有数据
| 形式 | 含义 |
|---|---|
variant="school1" | 对所有键使用同一个具名变体 |
variant={["school1", "default"]} | 有序的优先级链 |
variant={{ "hero-banner": "school1", default: "base" }} | 按字典键分别指定变体 |
优先级链
链会针对每个键所声明的条目从左到右依次尝试,第一个已声明的胜出。若都未声明,则使用隐式的默认条目——与单个值的行为完全一致。
复制代码到剪贴板
<IntlayerProvider variant={["school1", "school2"]} />// `hero-banner` 未声明 `school1` 条目,但声明了 `school2` → "school2"// 两者都未声明的键 → 默认条目因此 ["black_friday", "summer"] 可读作「若该键有 black friday 则用它,否则用 summer,再否则用默认」。调用处同样接受链:
复制代码到剪贴板
useIntlayer("hero-banner", { variant: ["black_friday", "summer"] });请注意,这与内容文件中 variant 字段所接受的数组正好相反:在那里,数组为每个元素声明一个条目;而在这里,它按优先级顺序消费这些条目。
按键映射
分别指定每个字典键。保留的 default 条目覆盖所有未列出的键:
复制代码到剪贴板
<IntlayerProvider variant={{ "hero-banner": "school1", product: ["school1", "default"], default: "base", }}/>在提供者上,普通对象始终被解读为按键映射,而绝不会被当作对象变体——两者在结构上完全相同。若要全局指定对象变体,请将其嵌套在某个条目下:variant={{ default: { id: "prod_abc" } }}。
由于映射的键会与你声明的字典键进行校验,拼写错误——或直接写成对象变体,例如 variant={{ id: "prod_abc" }}——都会导致编译期错误。
加载模式
对象变体通常被惰性加载。在字典上设置 importMode 以控制此行为:
复制代码到剪贴板
const dictionary = {
key: "product",
importMode: "fetch", // or "dynamic"
variant: { id: "prod_abc", userId: "user_123" },
content: { … },
} satisfies Dictionary;
export default dictionary;有关 static、dynamic 和 fetch 模式的详细信息,请参阅包优化。
典型用例
- 由实验键驱动的 A/B 文案测试
- 季节性或促销横幅
- 功能开关消息
- 特定语言环境的营销活动
- 在 CMS 中管理的按产品营销文案
- 用户特定或账户特定的内容
- 在运行时以不透明 ID 作为键的任何内容