作者:
    Creation:2026-07-30Last update:2026-07-30

    基于选择的内容 (Select) / Intlayer

    Select 的工作原理

    在 Intlayer 中,基于选择的内容是通过 select 函数实现的,它将任意字符串值映射到相应的内容。这相当于 ICU 的 {value, select, …} 消息,或者应用程序代码中的 switch 语句。

    当判别条件是一个自由格式的字符串时(如状态、计划、平台、角色),请使用 select。对于其他判别条件,Intlayer 提供了专用的节点:

    判别条件 节点
    一个数量 enu()
    一个布尔值 cond()
    一个性别 gender()
    任何其他字符串 select()

    设置基于选择的内容

    要在您的 Intlayer 项目中设置基于选择的内容,请创建一个包含选择定义的内容模块。下面是不同格式的示例。

    **/*.content.ts
    import { select, type Dictionary } from "intlayer";
    
    const myPostContent = {
      key: "my_key",
      content: {
        publishStatus: select({
          draft: "This post is a draft",
          published: "This post is live",
          scheduled: "This post is scheduled",
          fallback: "Unknown status", // 可选
        }),
      },
    } satisfies Dictionary;
    
    export default myPostContent;
    如果未声明 fallback,当提供的值与任何声明的情况不匹配时,最后声明的键将被作为后备项。这与 cond()gender() 的约定相同。

    类型安全

    接受的参数是从声明的情况中推断出来的:

    • 如果没有 fallback,则只接受声明的情况:输入错误将导致类型错误。
    • 如果有 fallback,则接受任何字符串(后备项会处理不匹配的值),同时声明的情况仍然支持自动补全。

    为什么不使用简单对象?

    声明一个简单的对象并使用运行时值进行索引是很诱人的:

    tsx
    // ❌ 不要这样做const { publishStatus } = useIntlayer("my_key");return <p>{publishStatus[publishType]}</p>;

    Intlayer 编译器会分析您的源代码,以丢弃未使用的内容并压缩剩余的键。动态计算访问 (obj[expr]) 无法在静态时解析,因此整个分支会被标记为不透明(opaque):它将保留在包中,且其键保持不被压缩。

    使用 select(),情况解析发生在函数调用内部,而不是属性访问。编译器看到的是单一静态字段访问,并像对待 enu()cond()gender() 一样精确优化该节点:

    tsx
    // ✅ 请这样做const { publishStatus } = useIntlayer("my_key");return <p>{publishStatus(publishType)}</p>;

    使用基于选择的内容

    要在 React 组件中使用基于选择的内容,请导入并使用 react-intlayer 包中的 useIntlayer 钩子。该钩子获取指定键的内容,并允许您传入一个值以选择适当的输出。

    **/*.tsx
    import type { FC } from "react";
    import { useIntlayer } from "react-intlayer";
    
    const PostStatus: FC = () => {
    const { publishStatus } = useIntlayer("my_key");
    
    return (
      <div>
        <p>
          {
            /* 输出: This post is a draft */
            publishStatus("draft")
          }
        </p>
        <p>
          {
            /* 输出: This post is live */
            publishStatus("published")
          }
        </p>
        <p>
          {
            /* 输出: Unknown status */
            publishStatus("Archived")
          }
        </p>
      </div>
    );
    };
    
    export default PostStatus;

    将 Select 与其他节点结合使用

    每个情况都包含一个完整的内容节点,因此 select 可以与 t()insert()md() 等结合使用:

    **/*.content.ts
    import { insert, select, t, type Dictionary } from "intlayer";const myPostContent = {  key: "my_key",  content: {    publishStatus: select({      draft: insert(        t({          en: "{{name}} saved a draft",          fr: "{{name}} a enregistré un brouillon",          zh: "{{name}} 保存了一份草稿",        })      ),      published: insert(        t({          en: "{{name}} published the post",          fr: "{{name}} a publié l’article",          zh: "{{name}} 发布了帖子",        })      ),      fallback: insert(        t({          en: "{{name}} updated the post",          fr: "{{name}} a mis à jour l’article",          zh: "{{name}} 更新了帖子",        })      ),    }),  },} satisfies Dictionary;export default myPostContent;
    tsx
    publishStatus("draft")({ name: "Alice" }); // 输出: Alice 保存了一份草稿

    从 ICU select 迁移

    使用 ICU select 参数的消息将被作为 select 节点导入:

    text
    {publishType, select, draft {draft} published {published} other {Unknown}}

    变为

    typescript
    select(  {    draft: "draft",    published: "published",    fallback: "Unknown",  },  "publishType");

    ICU 中的 other 情况被重命名为 fallback,这是 Intlayer 用于所有未匹配情况的规范名称。第二个参数记录了 ICU 变量的名称,以便在导出时可以将消息完全恢复为原来的 ICU 字符串。

    如果 ICU select 的情况是性别值(male / female / other),它将作为 gender 节点导入。

    其他资源

    有关配置和使用的更多详细信息,请参阅以下资源:

    这些资源深入探讨了在不同环境和框架中配置和使用 Intlayer 的方法。