---
createdAt: 2026-07-30
updatedAt: 2026-07-30
title: Select Content
description: Learn how to use select content in Intlayer to dynamically render content based on an arbitrary string value. Follow this documentation to implement switch-like content efficiently in your project.
keywords:
- Select Content
- Switch Content
- ICU select
- Dynamic rendering
- Documentation
- Intlayer
- Next.js
- JavaScript
- React
slugs:
- doc
- concept
- content
- select
history:
- version: 9.1.0
date: 2026-07-30
changes: "Introduce select content"
author: aymericzip
---
# 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.
```typescript fileName="**/*.content.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
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;
```
```json5 fileName="**/*.content.json" contentDeclarationFormat="json"
{
"$schema": "https://intlayer.org/schema.json",
"key": "my_key",
"content": {
"publishStatus": {
"nodeType": "select",
"select": {
"draft": "This post is a draft",
"published": "This post is live",
"scheduled": "This post is scheduled",
"fallback": "Unknown status", // optional
},
},
},
}
```
> 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 this
const { publishStatus } = useIntlayer("my_key");
return
{publishStatus[publishType]}
;
```
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 this
const { publishStatus } = useIntlayer("my_key");
return {publishStatus(publishType)}
;
```
## 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 fileName="**/*.tsx" codeFormat={["typescript", "esm"]}
import type { FC } from "react";
import { useIntlayer } from "react-intlayer";
const PostStatus: FC = () => {
const { publishStatus } = useIntlayer("my_key");
return (
{
/* Output: This post is a draft */
publishStatus("draft")
}
{
/* Output: This post is live */
publishStatus("published")
}
{
/* Output: Unknown status */
publishStatus("Archived")
}
);
};
export default PostStatus;
```
To utilise select content in Next.js Client Components, fetch the content via the `useIntlayer` hook. Here's an example:
```tsx fileName="**/*.tsx" codeFormat={["typescript", "esm"]}
"use client";
import type { FC } from "react";
import { useIntlayer } from "next-intlayer";
const PostStatus: FC = () => {
const { publishStatus } = useIntlayer("my_key");
return (
{publishStatus("draft")}
{publishStatus("published")}
);
};
export default PostStatus;
```
To utilise select content in Vue components, fetch the content via the `useIntlayer` hook. Here's an example:
```vue fileName="**/*.vue"
{{ publishStatus("draft") }}
{{ publishStatus("published") }}
```
To utilise select content in Svelte components, fetch the content via the `useIntlayer` hook. The store is accessed using `$`. Here's an example:
```svelte fileName="**/*.svelte"
{$content.publishStatus("draft")}
{$content.publishStatus("published")}
```
To utilise select content in Preact components, fetch the content via the `useIntlayer` hook. Here's an example:
```tsx fileName="**/*.tsx" codeFormat={["typescript", "esm"]}
import type { FC } from "preact";
import { useIntlayer } from "preact-intlayer";
const PostStatus: FC = () => {
const { publishStatus } = useIntlayer("my_key");
return (
{publishStatus("draft")}
{publishStatus("published")}
);
};
export default PostStatus;
```
To utilise select content in SolidJS components, fetch the content via the `useIntlayer` hook. Here's an example:
```tsx fileName="**/*.tsx" codeFormat={["typescript", "esm"]}
import type { Component } from "solid-js";
import { useIntlayer } from "solid-intlayer";
const PostStatus: Component = () => {
const { publishStatus } = useIntlayer("my_key");
return (
{publishStatus("draft")}
{publishStatus("published")}
);
};
export default PostStatus;
```
To utilise select content in Angular components, fetch the content via the `useIntlayer` hook. Here's an example:
```typescript fileName="app.component.ts" codeFormat="typescript"
import { Component } from "@angular/core";
import { useIntlayer } from "angular-intlayer";
@Component({
selector: "app-post-status",
template: `
{{ content().publishStatus("draft") }}
{{ content().publishStatus("published") }}
`,
})
export class PostStatusComponent {
content = useIntlayer("my_key");
}
```
To utilise select content with `vanilla-intlayer`, fetch the content via the `useIntlayer` function. Here's an example:
```typescript fileName="**/*.ts" codeFormat={["typescript", "esm"]}
import { installIntlayer, useIntlayer } from "vanilla-intlayer";
installIntlayer();
const content = useIntlayer("my_key").onChange((newContent) => {
document.getElementById("status")!.textContent =
newContent.publishStatus("draft");
});
// Initial render
document.getElementById("status")!.textContent = content.publishStatus("draft");
```
## Composing Select with Other Nodes
Because each case is housing a complete content node, `select` can be combined with `t()`, `insert()`, `md()`, etc.:
```typescript fileName="**/*.content.ts" codeFormat="typescript"
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`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/gender.md) node instead.
## Additional Resources
For more detailed information on configuration and usage, please refer to the following resources:
- [Intlayer CLI Documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/cli/index.md)
- [Intlayer React Documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/intlayer_with_create_react_app.md)
- [Intlayer Next.js Documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/intlayer_with_nextjs_15.md)
These resources provide further insights into setting up and using Intlayer across various environments and frameworks.