@intlayer/docs 9.0.2 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/cjs/generated/docs.entry.cjs +20 -0
  2. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  3. package/dist/esm/generated/docs.entry.mjs +20 -0
  4. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  5. package/dist/types/generated/docs.entry.d.ts +1 -0
  6. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  7. package/docs/ar/dictionary/content_file.md +24 -1
  8. package/docs/ar/dictionary/select.md +386 -0
  9. package/docs/de/dictionary/content_file.md +24 -1
  10. package/docs/de/dictionary/select.md +386 -0
  11. package/docs/en/dictionary/content_file.md +24 -1
  12. package/docs/en/dictionary/select.md +382 -0
  13. package/docs/en-GB/dictionary/content_file.md +24 -1
  14. package/docs/en-GB/dictionary/select.md +385 -0
  15. package/docs/es/dictionary/content_file.md +24 -1
  16. package/docs/es/dictionary/select.md +385 -0
  17. package/docs/fr/dictionary/content_file.md +24 -1
  18. package/docs/fr/dictionary/select.md +382 -0
  19. package/docs/hi/dictionary/content_file.md +24 -1
  20. package/docs/hi/dictionary/select.md +386 -0
  21. package/docs/id/dictionary/content_file.md +24 -1
  22. package/docs/id/dictionary/select.md +386 -0
  23. package/docs/it/dictionary/content_file.md +24 -1
  24. package/docs/it/dictionary/select.md +386 -0
  25. package/docs/ja/dictionary/content_file.md +24 -1
  26. package/docs/ja/dictionary/select.md +386 -0
  27. package/docs/ko/dictionary/content_file.md +24 -1
  28. package/docs/ko/dictionary/select.md +386 -0
  29. package/docs/pl/dictionary/content_file.md +24 -1
  30. package/docs/pl/dictionary/select.md +386 -0
  31. package/docs/pt/dictionary/content_file.md +24 -1
  32. package/docs/pt/dictionary/select.md +386 -0
  33. package/docs/ru/dictionary/content_file.md +25 -2
  34. package/docs/ru/dictionary/select.md +386 -0
  35. package/docs/tr/dictionary/content_file.md +24 -1
  36. package/docs/tr/dictionary/select.md +386 -0
  37. package/docs/uk/dictionary/content_file.md +24 -1
  38. package/docs/uk/dictionary/select.md +386 -0
  39. package/docs/vi/dictionary/content_file.md +24 -1
  40. package/docs/vi/dictionary/select.md +386 -0
  41. package/docs/zh/dictionary/content_file.md +24 -1
  42. package/docs/zh/dictionary/select.md +387 -0
  43. package/package.json +7 -7
  44. package/src/generated/docs.entry.ts +20 -0
@@ -0,0 +1,382 @@
1
+ ---
2
+ createdAt: 2026-07-30
3
+ updatedAt: 2026-07-30
4
+ title: Select-Based Content
5
+ description: Learn how to use select-based content in Intlayer to dynamically display content based on an arbitrary string value. Follow this documentation to implement switch-like content efficiently in your project.
6
+ keywords:
7
+ - Select-Based Content
8
+ - Switch Content
9
+ - ICU select
10
+ - Dynamic Rendering
11
+ - Documentation
12
+ - Intlayer
13
+ - Next.js
14
+ - JavaScript
15
+ - React
16
+ slugs:
17
+ - doc
18
+ - concept
19
+ - content
20
+ - select
21
+ history:
22
+ - version: 9.1.0
23
+ date: 2026-07-30
24
+ changes: "Introduce select based content"
25
+ author: aymericzip
26
+ ---
27
+
28
+ # Select-Based Content / Select in Intlayer
29
+
30
+ ## How Select Works
31
+
32
+ In Intlayer, select-based content is achieved through the `select` function, which maps arbitrary string values to their corresponding content. It is the equivalent of an ICU `{value, select, …}` message, or of a `switch` statement in your application code.
33
+
34
+ Use `select` when the discriminant is a free-form string — a status, a plan, a platform, a role. For the other discriminants, Intlayer provides dedicated nodes:
35
+
36
+ | Discriminant | Node |
37
+ | ---------------------- | ---------- |
38
+ | A quantity | `enu()` |
39
+ | A boolean | `cond()` |
40
+ | A gender | `gender()` |
41
+ | Any other string value | `select()` |
42
+
43
+ ## Setting Up Select-Based Content
44
+
45
+ To set up select-based content in your Intlayer project, create a content module that includes your select definitions. Below are examples in various formats.
46
+
47
+ ```typescript fileName="**/*.content.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
48
+ import { select, type Dictionary } from "intlayer";
49
+
50
+ const myPostContent = {
51
+ key: "my_key",
52
+ content: {
53
+ publishStatus: select({
54
+ draft: "This post is a draft",
55
+ published: "This post is live",
56
+ scheduled: "This post is scheduled",
57
+ fallback: "Unknown status", // Optional
58
+ }),
59
+ },
60
+ } satisfies Dictionary;
61
+
62
+ export default myPostContent;
63
+ ```
64
+
65
+ ```json5 fileName="**/*.content.json" contentDeclarationFormat="json"
66
+ {
67
+ "$schema": "https://intlayer.org/schema.json",
68
+ "key": "my_key",
69
+ "content": {
70
+ "publishStatus": {
71
+ "nodeType": "select",
72
+ "select": {
73
+ "draft": "This post is a draft",
74
+ "published": "This post is live",
75
+ "scheduled": "This post is scheduled",
76
+ "fallback": "Unknown status", // Optional
77
+ },
78
+ },
79
+ },
80
+ }
81
+ ```
82
+
83
+ > If no `fallback` is declared, the last key declared will be taken as a fallback when the provided value matches no declared case — the same contract as `cond()` and `gender()`.
84
+
85
+ ### Type safety
86
+
87
+ The accepted argument is inferred from the declared cases:
88
+
89
+ - Without a `fallback`, only the declared cases are accepted — a typo is a type error.
90
+ - With a `fallback`, any string is accepted (the fallback covers the unmatched values) while the declared cases still autocomplete.
91
+
92
+ ## Why not a plain object?
93
+
94
+ It is tempting to declare a plain object and index it with the runtime value:
95
+
96
+ ```tsx
97
+ // ❌ Do not do this
98
+ const { publishStatus } = useIntlayer("my_key");
99
+
100
+ return <p>{publishStatus[publishType]}</p>;
101
+ ```
102
+
103
+ The Intlayer compiler analyses your source to prune unused content and minify the remaining keys. A dynamic computed access (`obj[expr]`) cannot be resolved statically, so the whole branch is marked opaque: it is kept in the bundle and its keys stay un-minified.
104
+
105
+ With `select()`, the case resolution happens inside a function call rather than as a property access. The compiler sees a single static field access and optimises the node exactly like `enu()`, `cond()` or `gender()`:
106
+
107
+ ```tsx
108
+ // ✅ Do this
109
+ const { publishStatus } = useIntlayer("my_key");
110
+
111
+ return <p>{publishStatus(publishType)}</p>;
112
+ ```
113
+
114
+ ## Using Select-Based Content
115
+
116
+ <Tabs group="framework">
117
+ <Tab label="React" value="react">
118
+
119
+ To utilize select-based content within 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 in a value to select the appropriate output.
120
+
121
+ ```tsx fileName="**/*.tsx" codeFormat={["typescript", "esm"]}
122
+ import type { FC } from "react";
123
+ import { useIntlayer } from "react-intlayer";
124
+
125
+ const PostStatus: FC = () => {
126
+ const { publishStatus } = useIntlayer("my_key");
127
+
128
+ return (
129
+ <div>
130
+ <p>
131
+ {
132
+ /* Output: This post is a draft */
133
+ publishStatus("draft")
134
+ }
135
+ </p>
136
+ <p>
137
+ {
138
+ /* Output: This post is live */
139
+ publishStatus("published")
140
+ }
141
+ </p>
142
+ <p>
143
+ {
144
+ /* Output: Unknown status */
145
+ publishStatus("archived")
146
+ }
147
+ </p>
148
+ </div>
149
+ );
150
+ };
151
+
152
+ export default PostStatus;
153
+ ```
154
+
155
+ </Tab>
156
+ <Tab label="Next.js" value="nextjs">
157
+
158
+ To utilize select-based content in Next.js Client Components, retrieve it via the `useIntlayer` hook. Here's an example:
159
+
160
+ ```tsx fileName="**/*.tsx" codeFormat={["typescript", "esm"]}
161
+ "use client";
162
+
163
+ import type { FC } from "react";
164
+ import { useIntlayer } from "next-intlayer";
165
+
166
+ const PostStatus: FC = () => {
167
+ const { publishStatus } = useIntlayer("my_key");
168
+
169
+ return (
170
+ <div>
171
+ <p>{publishStatus("draft")}</p>
172
+ <p>{publishStatus("published")}</p>
173
+ </div>
174
+ );
175
+ };
176
+
177
+ export default PostStatus;
178
+ ```
179
+
180
+ </Tab>
181
+ <Tab label="Vue" value="vue">
182
+
183
+ To utilize select-based content in Vue components, retrieve it via the `useIntlayer` hook. Here's an example:
184
+
185
+ ```vue fileName="**/*.vue"
186
+ <script setup lang="ts">
187
+ import { useIntlayer } from "vue-intlayer";
188
+
189
+ const { publishStatus } = useIntlayer("my_key");
190
+ </script>
191
+
192
+ <template>
193
+ <div>
194
+ <p>{{ publishStatus("draft") }}</p>
195
+ <p>{{ publishStatus("published") }}</p>
196
+ </div>
197
+ </template>
198
+ ```
199
+
200
+ </Tab>
201
+ <Tab label="Svelte" value="svelte">
202
+
203
+ To utilize select-based content in Svelte components, retrieve it via the `useIntlayer` hook. The store is accessed with `$`. Here's an example:
204
+
205
+ ```svelte fileName="**/*.svelte"
206
+ <script lang="ts">
207
+ import { useIntlayer } from "svelte-intlayer";
208
+
209
+ const content = useIntlayer("my_key");
210
+ </script>
211
+
212
+ <div>
213
+ <p>{$content.publishStatus("draft")}</p>
214
+ <p>{$content.publishStatus("published")}</p>
215
+ </div>
216
+ ```
217
+
218
+ </Tab>
219
+ <Tab label="Preact" value="preact">
220
+
221
+ To utilize select-based content in Preact components, retrieve it via the `useIntlayer` hook. Here's an example:
222
+
223
+ ```tsx fileName="**/*.tsx" codeFormat={["typescript", "esm"]}
224
+ import type { FC } from "preact";
225
+ import { useIntlayer } from "preact-intlayer";
226
+
227
+ const PostStatus: FC = () => {
228
+ const { publishStatus } = useIntlayer("my_key");
229
+
230
+ return (
231
+ <div>
232
+ <p>{publishStatus("draft")}</p>
233
+ <p>{publishStatus("published")}</p>
234
+ </div>
235
+ );
236
+ };
237
+
238
+ export default PostStatus;
239
+ ```
240
+
241
+ </Tab>
242
+ <Tab label="Solid" value="solid">
243
+
244
+ To utilize select-based content in SolidJS components, retrieve it via the `useIntlayer` hook. Here's an example:
245
+
246
+ ```tsx fileName="**/*.tsx" codeFormat={["typescript", "esm"]}
247
+ import type { Component } from "solid-js";
248
+ import { useIntlayer } from "solid-intlayer";
249
+
250
+ const PostStatus: Component = () => {
251
+ const { publishStatus } = useIntlayer("my_key");
252
+
253
+ return (
254
+ <div>
255
+ <p>{publishStatus("draft")}</p>
256
+ <p>{publishStatus("published")}</p>
257
+ </div>
258
+ );
259
+ };
260
+
261
+ export default PostStatus;
262
+ ```
263
+
264
+ </Tab>
265
+ <Tab label="Angular" value="angular">
266
+
267
+ To utilize select-based content in Angular components, retrieve it via the `useIntlayer` hook. Here's an example:
268
+
269
+ ```typescript fileName="app.component.ts" codeFormat="typescript"
270
+ import { Component } from "@angular/core";
271
+ import { useIntlayer } from "angular-intlayer";
272
+
273
+ @Component({
274
+ selector: "app-post-status",
275
+ template: `
276
+ <div>
277
+ <p>{{ content().publishStatus("draft") }}</p>
278
+ <p>{{ content().publishStatus("published") }}</p>
279
+ </div>
280
+ `,
281
+ })
282
+ export class PostStatusComponent {
283
+ content = useIntlayer("my_key");
284
+ }
285
+ ```
286
+
287
+ </Tab>
288
+ <Tab label="Vanilla JS" value="vanilla">
289
+
290
+ To utilize select-based content with `vanilla-intlayer`, retrieve it via the `useIntlayer` hook. Here's an example:
291
+
292
+ ```typescript fileName="**/*.ts" codeFormat={["typescript", "esm"]}
293
+ import { installIntlayer, useIntlayer } from "vanilla-intlayer";
294
+
295
+ installIntlayer();
296
+
297
+ const content = useIntlayer("my_key").onChange((newContent) => {
298
+ document.getElementById("status")!.textContent =
299
+ newContent.publishStatus("draft");
300
+ });
301
+
302
+ // Initial render
303
+ document.getElementById("status")!.textContent = content.publishStatus("draft");
304
+ ```
305
+
306
+ </Tab>
307
+ </Tabs>
308
+
309
+ ## Combining Select with Other Nodes
310
+
311
+ Each case holds a full content node, so `select` composes with `t()`, `insert()`, `md()` and the others:
312
+
313
+ ```typescript fileName="**/*.content.ts" codeFormat="typescript"
314
+ import { insert, select, t, type Dictionary } from "intlayer";
315
+
316
+ const myPostContent = {
317
+ key: "my_key",
318
+ content: {
319
+ publishStatus: select({
320
+ draft: insert(
321
+ t({
322
+ en: "{{name}} saved a draft",
323
+ fr: "{{name}} a enregistré un brouillon",
324
+ })
325
+ ),
326
+ published: insert(
327
+ t({
328
+ en: "{{name}} published the post",
329
+ fr: "{{name}} a publié l’article",
330
+ })
331
+ ),
332
+ fallback: insert(
333
+ t({
334
+ en: "{{name}} updated the post",
335
+ fr: "{{name}} a mis à jour l’article",
336
+ })
337
+ ),
338
+ }),
339
+ },
340
+ } satisfies Dictionary;
341
+
342
+ export default myPostContent;
343
+ ```
344
+
345
+ ```tsx
346
+ publishStatus("draft")({ name: "Alice" }); // Output: Alice saved a draft
347
+ ```
348
+
349
+ ## Migrating from ICU `select`
350
+
351
+ Messages using the ICU `select` argument are imported as `select` nodes:
352
+
353
+ ```text
354
+ {publishType, select, draft {draft} published {published} other {Unknown}}
355
+ ```
356
+
357
+ becomes
358
+
359
+ ```typescript
360
+ select(
361
+ {
362
+ draft: "draft",
363
+ published: "published",
364
+ fallback: "Unknown",
365
+ },
366
+ "publishType"
367
+ );
368
+ ```
369
+
370
+ The ICU `other` case is renamed to `fallback`, which is Intlayer's canonical name for a catch-all. The second argument records the ICU variable name so the message round-trips back to the exact same ICU string when exported.
371
+
372
+ > An ICU `select` whose cases are gender values (`male` / `female` / `other`) is imported as a [`gender`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dictionary/gender.md) node instead.
373
+
374
+ ## Additional Resources
375
+
376
+ For more detailed information on configuration and usage, refer to the following resources:
377
+
378
+ - [Intlayer CLI Documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/cli/index.md)
379
+ - [React Intlayer Documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_with_create_react_app.md)
380
+ - [Next Intlayer Documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_with_nextjs_15.md)
381
+
382
+ These resources offer further insights into the setup and usage of Intlayer across various environments and frameworks.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  createdAt: 2025-02-07
3
- updatedAt: 2026-05-12
3
+ updatedAt: 2026-07-30
4
4
  title: Content File
5
5
  description: Learn how to customise the extensions for your content declaration files. Follow this documentation to implement conditions efficiently in your project.
6
6
  keywords:
@@ -12,6 +12,9 @@ slugs:
12
12
  - concept
13
13
  - content
14
14
  history:
15
+ - version: 9.1.0
16
+ date: 2026-07-30
17
+ changes: "Introduce select content"
15
18
  - version: 8.10.0
16
19
  date: 2026-05-19
17
20
  changes: "Add support of YAML and Markdown file formats"
@@ -253,6 +256,7 @@ Intlayer supports various content types through typed nodes:
253
256
  - **HTML Content**: Rich HTML content with optional custom components [see HTML Content](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/html.md)
254
257
  - **Nested Content**: References to other dictionaries [see Nested Content](https://github.com/aymericzip/intlayer/blob/main/docs/docs/{{locale}}/dictionary/nested_content.md)
255
258
  - **Gender Content**: Content that varies based on gender [see Gender Content](https://github.com/aymericzip/intlayer/blob/main/docs/docs/{{locale}}/dictionary/gender_content.md)
259
+ - **Select Content**: Content that varies based on an arbitrary string value [see Select Content](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/select.md)
256
260
  - **File Content**: References to external files [see File Content](https://github.com/aymericzip/intlayer/blob/main/docs/docs/{{locale}}/dictionary/file_content.md)
257
261
 
258
262
  ## Dictionary Structure
@@ -742,6 +746,25 @@ genderContent: gender({
742
746
 
743
747
  > See [Gender Content (`gender`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/gender.md) for more information.
744
748
 
749
+ ### Select Content (`select`)
750
+
751
+ Content that varies based on an arbitrary string value — the equivalent of an ICU `select`:
752
+
753
+ ```typescript
754
+ import { select } from "intlayer";
755
+
756
+ selectContent: select({
757
+ draft: "This post is a draft",
758
+ published: "This post is live",
759
+ scheduled: "This post is scheduled",
760
+ fallback: "Unknown status",
761
+ });
762
+ ```
763
+
764
+ Use `select` when the discriminant is neither a quantity (`enu`), a boolean (`cond`), nor a gender (`gender`). Prefer it over indexing a regular object with a runtime value: the Intlayer compiler cannot statically resolve dynamically computed access.
765
+
766
+ > See [Select Content (`select`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/select.md) for more information.
767
+
745
768
  ### File Content (`file`)
746
769
 
747
770
  References to external files: