Author:
    Creation:2026-07-30Last update:2026-07-30

    Select Content / Intlayer

    How Select Works

    In Intlayer, select content is achieved through the select function, which maps arbitrary string values to their corresponding content. It is the equivalent of the ICU {value, select, …} message, or similar to a switch statement in your application's code.

    Use select when the discriminant is an arbitrary string: such as a status, a plan, a platform, or a role. For other discriminants, Intlayer provides dedicated nodes:

    Discriminant Node
    Quantity enu()
    Boolean cond()
    Gender gender()
    Any other string select()

    Setting Up Select Content

    To set up select content in your Intlayer project, create a content module that includes your select definitions. Below are examples in different formats.

    **/*.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", // optional
        }),
      },
    } satisfies Dictionary;
    
    export default myPostContent;
    If no fallback is declared, the last declared key is considered as the fallback if the provided value does not match any of the declared cases: exactly the same as for cond() and gender() contracts.

    Type Safety

    The accepted argument is inferred from the declared cases:

    • Without a fallback, only the declared cases are accepted: a typo will result in a type error.
    • With a fallback, any string is accepted (as the fallback covers unmatched values), whilst the declared cases still provide autocomplete.

    Why not use a regular object?

    It could be tempting to declare a regular object and index it with the runtime value:

    tsx
    // ❌ Do not do thisconst { publishStatus } = useIntlayer("my_key");return <p>{publishStatus[publishType]}</p>;

    The Intlayer compiler parses your source code to eliminate unused content and minify the remaining keys. A dynamically computed access (obj[expr]) cannot be resolved statically, hence the entire branch is marked as opaque: it will be kept in the bundle, and its keys will not be minified.

    By using select(), the case resolution happens inside a function call rather than a property access. The compiler sees it as a single, static field access and properly optimises the node exactly as it does for enu(), cond(), or gender():

    tsx
    // ✅ Do thisconst { publishStatus } = useIntlayer("my_key");return <p>{publishStatus(publishType)}</p>;

    Using Select Content

    To utilise select content in a React component, import and use the useIntlayer hook from the react-intlayer package. This hook fetches the content for the specified key and allows you to pass a value to select the appropriate output.

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

    Composing Select with Other Nodes

    Because each case is housing a complete content node, select can be combined with t(), insert(), md(), etc.:

    **/*.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",          "en-GB": "{{name}} saved a draft",          fr: "{{name}} a enregistré un brouillon",        })      ),      published: insert(        t({          en: "{{name}} published the post",          "en-GB": "{{name}} published the post",          fr: "{{name}} a publié l’article",        })      ),      fallback: insert(        t({          en: "{{name}} updated the post",          "en-GB": "{{name}} updated the post",          fr: "{{name}} a mis à jour l’article",        })      ),    }),  },} satisfies Dictionary;export default myPostContent;
    tsx
    publishStatus("draft")({ name: "Alice" }); // Output: Alice saved a draft

    Migrating from ICU select

    Messages using the ICU select argument are imported as a select node:

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

    Will become:

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

    The ICU other case is renamed to fallback, which is the Intlayer canonical name for all catch-all cases. The second argument holds the ICU variable name so that when exported, the message reverts back to the exact same ICU string.

    Please note that ICU select messages where the cases are gender values (male / female / other) are imported as a gender node instead.

    Additional Resources

    For more detailed information on configuration and usage, please refer to the following resources:

    These resources provide further insights into setting up and using Intlayer across various environments and frameworks.