@intlayer/react-intl 9.3.0 → 9.3.2
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.
- package/README.md +24 -24
- package/dist/esm/FormattedComponents.mjs +12 -6
- package/dist/esm/FormattedComponents.mjs.map +1 -1
- package/dist/esm/createIntlObject.mjs +2 -1
- package/dist/esm/createIntlObject.mjs.map +1 -1
- package/dist/esm/plugin/index.mjs +1 -1
- package/dist/esm/plugin/index.mjs.map +1 -1
- package/dist/esm/useDictionary.mjs +2 -1
- package/dist/esm/useDictionary.mjs.map +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -47,27 +47,27 @@ With **per-locale content files**, **TypeScript autocompletion**, **tree-shakabl
|
|
|
47
47
|
|
|
48
48
|
## Keys benefits of Intlayer:
|
|
49
49
|
|
|
50
|
-
| Feature | Description
|
|
51
|
-
| --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
52
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/frameworks.png?raw=true" alt="Feature" width="700"> | **Cross-Frameworks Support**<br><br>Intlayer is compatible with all major frameworks and libraries, including Next.js, React, Vite, Vue.js, Nuxt, Preact, Express, and more.
|
|
53
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/javascript_content_management.jpg?raw=true" alt="Feature" width="700"> | **JavaScript-Powered Content Management**<br><br>Harness the flexibility of JavaScript to define and manage your content efficiently. <br><br> - [Content declaration](https://intlayer.org/doc/concept/content)
|
|
54
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/per_locale_content_declaration_file.png?raw=true" alt="Feature" width="700"> | **Per-Locale Content Declaration File**<br><br>Speed up your development by declaring your content once, before auto generation.<br><br> - [Per-Locale Content Declaration File](https://intlayer.org/doc/concept/per-locale-file)
|
|
55
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/compiler.jpg?raw=true" alt="Feature" width="700"> | **Compiler**<br><br>The Intlayer Compiler extract automatically the content from the components and generate the dictionary files.<br><br> - [Compiler](https://intlayer.org/doc/compiler)
|
|
56
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/autocompletion.png?raw=true" alt="Feature" width="700"> | **Type-Safe Environment**<br><br>Leverage TypeScript to ensure your content definitions and code are error-free, while also benefiting from IDE autocompletion.<br><br> - [TypeScript configuration](https://intlayer.org/doc/environment/vite-and-react#configure-typescript)
|
|
57
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/config_file.png?raw=true" alt="Feature" width="700"> | **Simplified Setup**<br><br>Get up and running quickly with minimal configuration. Adjust settings for internationalization, routing, AI, build, and content handling with ease. <br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs)
|
|
58
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/content_retrieval.png?raw=true" alt="Feature" width="700"> | **Simplified Content Retrieval**<br><br>No need to call your `t` function for each piece of content. Retrieve all your content directly using a single hook.<br><br> - [React integration](https://intlayer.org/doc/environment/create-react-app)
|
|
59
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/server_component.png?raw=true" alt="Feature" width="700"> | **Consistent Server Component Implementation**<br><br>Perfectly suited for Next.js server components, use the same implementation for both client and server components, no need to pass your `t` function across each server component. <br><br> - [Server Components](https://intlayer.org/doc/environment/nextjs#step-7-utilize-content-in-your-code)
|
|
60
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/file_tree.png?raw=true" alt="Feature" width="700"> | **Organized Codebase**<br><br>Keep your codebase more organized: 1 component = 1 dictionary in the same folder. Translations close to their respective components, enhance maintainability and clarity. <br><br> - [How Intlayer works](https://intlayer.org/doc/concept/how-works-intlayer)
|
|
61
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/url_routing.png?raw=true" alt="Feature" width="700"> | **Enhanced Routing**<br><br>Full support of app routing, adapting seamlessly to complex application structures, for Next.js, React, Vite, Vue.js, etc.<br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs)
|
|
62
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/markdown.png?raw=true" alt="Feature" width="700"> | **Markdown Support**<br><br>Import and interpret, locale files and remote Markdown for multilingual content like privacy policies, documentation, etc. Interpret and make Markdown metadata accessible in your code.<br><br> - [Content files](https://intlayer.org/doc/concept/content/file)
|
|
63
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/visual_editor.png?raw=true" alt="Feature" width="700"> | **Free Visual Editor & CMS**<br><br>A free visual editor and CMS are available for content writers, removing the need for a localization platform. Keep your content synchronized using Git, or externalize it totally or partially with the CMS.<br><br> - [Intlayer Editor](https://intlayer.org/doc/concept/editor) <br> - [Intlayer CMS](https://intlayer.org/doc/concept/cms)
|
|
64
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png?raw=true" alt="Feature" width="700"> | **Tree-shakable Content**<br><br>Tree-shakable content, reducing the size of the final bundle. Loads content per component, excluding any unused content from your bundle. Supports lazy loading to enhance app loading efficiency. <br><br> - [App build optimization](https://intlayer.org/doc/concept/how-works-intlayer#app-build-optimization)
|
|
65
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/static_rendering.png?raw=true" alt="Feature" width="700"> | **Static Rendering**<br><br>Doesn't block Static Rendering. <br><br> - [Next.js integration](https://intlayer.org/doc/environment/nextjs)
|
|
66
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/AI_translation.png?raw=true" alt="Feature" width="700"> | **AI-Powered Translation**<br><br>Transform your website into 231 languages with just one click using Intlayer's advanced AI-powered translation tools using your own AI provider / API key. <br><br> - [CI/CD integration](https://intlayer.org/doc/concept/ci-cd) <br> - [Intlayer CLI](https://intlayer.org/doc/concept/cli) <br> - [Auto fill](https://intlayer.org/doc/concept/auto-fill)
|
|
67
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/mcp.png?raw=true" alt="Feature" width="700"> | **MCP Server Integration**<br><br>Provides an MCP (Model Context Protocol) server for IDE automation, enabling seamless content management and i18n workflows directly within your development environment. <br><br> - [MCP Server](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/mcp_server.md)
|
|
68
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/vscode_extension.png?raw=true" alt="Feature" width="700"> | **VSCode Extension**<br><br>Intlayer provides a VSCode extension to help you manage your content and translations, building your dictionaries, translating your content, and more. <br><br> - [VSCode Extension](https://intlayer.org/doc/vs-code-extension)
|
|
69
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/interoperability.png?raw=true" alt="Feature" width="700"> | **Interoperability**<br><br>Allow interoperability with react-i18next, next-i18next, next-intl, react-intl, vue-i18n. <br><br> - [Intlayer and react-intl](https://intlayer.org/blog/intlayer-with-react-intl) <br> - [Intlayer and next-intl](https://intlayer.org/blog/intlayer-with-next-intl) <br> - [Intlayer and next-i18next](https://intlayer.org/blog/intlayer-with-next-i18next) <br> - [Intlayer and vue-i18n](https://intlayer.org/blog/intlayer-with-vue-i18n) |
|
|
70
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/benchmark.png?raw=true" alt="Feature" width="700"> | **Performances & Benchmark**<br><br>Uses advanced tree-shaking and dynamic loading to boost performances and keep the solution as light as possible. <br><br> - [Performances & Benchmark](https://intlayer.org/doc/benchmark)
|
|
50
|
+
| Feature | Description |
|
|
51
|
+
| --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
52
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/frameworks.png?raw=true" alt="Feature" width="700"> | **Cross-Frameworks Support**<br><br>Intlayer is compatible with all major frameworks and libraries, including Next.js, React, Vite, Vue.js, Nuxt, Preact, Express, and more. |
|
|
53
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/javascript_content_management.jpg?raw=true" alt="Feature" width="700"> | **JavaScript-Powered Content Management**<br><br>Harness the flexibility of JavaScript to define and manage your content efficiently. <br><br> - [Content declaration](https://intlayer.org/doc/concept/content) |
|
|
54
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/per_locale_content_declaration_file.png?raw=true" alt="Feature" width="700"> | **Per-Locale Content Declaration File**<br><br>Speed up your development by declaring your content once, before auto generation.<br><br> - [Per-Locale Content Declaration File](https://intlayer.org/doc/concept/per-locale-file) |
|
|
55
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/compiler.jpg?raw=true" alt="Feature" width="700"> | **Compiler**<br><br>The Intlayer Compiler extract automatically the content from the components and generate the dictionary files.<br><br> - [Compiler](https://intlayer.org/doc/compiler) |
|
|
56
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/autocompletion.png?raw=true" alt="Feature" width="700"> | **Type-Safe Environment**<br><br>Leverage TypeScript to ensure your content definitions and code are error-free, while also benefiting from IDE autocompletion.<br><br> - [TypeScript configuration](https://intlayer.org/doc/environment/vite-and-react#configure-typescript) |
|
|
57
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/config_file.png?raw=true" alt="Feature" width="700"> | **Simplified Setup**<br><br>Get up and running quickly with minimal configuration. Adjust settings for internationalization, routing, AI, build, and content handling with ease. <br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
|
|
58
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/content_retrieval.png?raw=true" alt="Feature" width="700"> | **Simplified Content Retrieval**<br><br>No need to call your `t` function for each piece of content. Retrieve all your content directly using a single hook.<br><br> - [React integration](https://intlayer.org/doc/environment/create-react-app) |
|
|
59
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/server_component.png?raw=true" alt="Feature" width="700"> | **Consistent Server Component Implementation**<br><br>Perfectly suited for Next.js server components, use the same implementation for both client and server components, no need to pass your `t` function across each server component. <br><br> - [Server Components](https://intlayer.org/doc/environment/nextjs#step-7-utilize-content-in-your-code) |
|
|
60
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/file_tree.png?raw=true" alt="Feature" width="700"> | **Organized Codebase**<br><br>Keep your codebase more organized: 1 component = 1 dictionary in the same folder. Translations close to their respective components, enhance maintainability and clarity. <br><br> - [How Intlayer works](https://intlayer.org/doc/concept/how-works-intlayer) |
|
|
61
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/url_routing.png?raw=true" alt="Feature" width="700"> | **Enhanced Routing**<br><br>Full support of app routing, adapting seamlessly to complex application structures, for Next.js, React, Vite, Vue.js, etc.<br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
|
|
62
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/markdown.png?raw=true" alt="Feature" width="700"> | **Markdown Support**<br><br>Import and interpret, locale files and remote Markdown for multilingual content like privacy policies, documentation, etc. Interpret and make Markdown metadata accessible in your code.<br><br> - [Content files](https://intlayer.org/doc/concept/content/file) |
|
|
63
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/visual_editor.png?raw=true" alt="Feature" width="700"> | **Free Visual Editor & CMS**<br><br>A free visual editor and CMS are available for content writers, removing the need for a localization platform. Keep your content synchronized using Git, or externalize it totally or partially with the CMS.<br><br> - [Intlayer Editor](https://intlayer.org/doc/concept/editor) <br> - [Intlayer CMS](https://intlayer.org/doc/concept/cms) |
|
|
64
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png?raw=true" alt="Feature" width="700"> | **Tree-shakable Content**<br><br>Tree-shakable content, reducing the size of the final bundle. Loads content per component, excluding any unused content from your bundle. Supports lazy loading to enhance app loading efficiency. <br><br> - [App build optimization](https://intlayer.org/doc/concept/how-works-intlayer#app-build-optimization) |
|
|
65
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/static_rendering.png?raw=true" alt="Feature" width="700"> | **Static Rendering**<br><br>Doesn't block Static Rendering. <br><br> - [Next.js integration](https://intlayer.org/doc/environment/nextjs) |
|
|
66
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/AI_translation.png?raw=true" alt="Feature" width="700"> | **AI-Powered Translation**<br><br>Transform your website into 231 languages with just one click using Intlayer's advanced AI-powered translation tools using your own AI provider / API key. <br><br> - [CI/CD integration](https://intlayer.org/doc/concept/ci-cd) <br> - [Intlayer CLI](https://intlayer.org/doc/concept/cli) <br> - [Auto fill](https://intlayer.org/doc/concept/auto-fill) |
|
|
67
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/mcp.png?raw=true" alt="Feature" width="700"> | **MCP Server Integration**<br><br>Provides an MCP (Model Context Protocol) server for IDE automation, enabling seamless content management and i18n workflows directly within your development environment. <br><br> - [MCP Server](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/mcp_server.md) |
|
|
68
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/vscode_extension.png?raw=true" alt="Feature" width="700"> | **VSCode Extension**<br><br>Intlayer provides a VSCode extension to help you manage your content and translations, building your dictionaries, translating your content, and more. <br><br> - [VSCode Extension](https://intlayer.org/doc/vs-code-extension) |
|
|
69
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/interoperability.png?raw=true" alt="Feature" width="700"> | **Interoperability**<br><br>Allow interoperability with react-i18next, next-i18next, next-intl, react-intl, vue-i18n. <br><br> - [Intlayer and react-intl](https://intlayer.org/blog/intlayer-with-react-intl) <br> - [Intlayer and next-intl](https://intlayer.org/blog/intlayer-with-next-intl) <br> - [Intlayer and next-i18next](https://intlayer.org/blog/intlayer-with-next-i18next) <br> - [Intlayer and vue-i18n](https://intlayer.org/blog/intlayer-with-vue-i18n) <br> - [Intlayer compat adapters](https://intlayer.org/doc/compatibility) |
|
|
70
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/benchmark.png?raw=true" alt="Feature" width="700"> | **Performances & Benchmark**<br><br>Uses advanced tree-shaking and dynamic loading to boost performances and keep the solution as light as possible. <br><br> - [Performances & Benchmark](https://intlayer.org/doc/benchmark) |
|
|
71
71
|
|
|
72
72
|
---
|
|
73
73
|
|
|
@@ -162,7 +162,7 @@ Explore our comprehensive documentation to get started with Intlayer and learn h
|
|
|
162
162
|
<li><a href="https://intlayer.org/doc/concept/cms" rel=''>Intlayer CMS</a></li>
|
|
163
163
|
<li><a href="https://intlayer.org/doc/concept/content" rel=''>Dictionary</a>
|
|
164
164
|
<ul>
|
|
165
|
-
<li><a href="https://intlayer.org/doc/concept/
|
|
165
|
+
<li><a href="https://intlayer.org/doc/concept/per-locale-file" rel=''>Per-Locale Content Declaration File</a></li>
|
|
166
166
|
<li><a href="https://intlayer.org/doc/concept/content/translation" rel=''>Translation</a></li>
|
|
167
167
|
<li><a href="https://intlayer.org/doc/concept/content/enumeration" rel=''>Enumeration</a></li>
|
|
168
168
|
<li><a href="https://intlayer.org/doc/concept/content/condition" rel=''>Condition</a></li>
|
|
@@ -183,7 +183,7 @@ Explore our comprehensive documentation to get started with Intlayer and learn h
|
|
|
183
183
|
<ul>
|
|
184
184
|
<li><a href="https://intlayer.org/doc/environment/nextjs/15" rel=''>Next.js 15</a></li>
|
|
185
185
|
<li><a href="https://intlayer.org/doc/environment/nextjs/14" rel=''>Next.js 14 (App Router)</a></li>
|
|
186
|
-
<li><a href="https://intlayer.org/doc/environment/nextjs/next-with-
|
|
186
|
+
<li><a href="https://intlayer.org/doc/environment/nextjs/next-with-page-router" rel=''>Next.js Page Router</a></li>
|
|
187
187
|
<li><a href="https://intlayer.org/doc/environment/nextjs/compiler" rel=''>Next.js using Compiler</a></li>
|
|
188
188
|
</ul>
|
|
189
189
|
</li>
|
|
@@ -212,7 +212,7 @@ Explore our comprehensive documentation to get started with Intlayer and learn h
|
|
|
212
212
|
<li><a href="https://intlayer.org/doc/environment/sveltekit" rel=''>SvelteKit</a></li>
|
|
213
213
|
<li><a href="https://intlayer.org/doc/environment/vite-and-preact" rel=''>Vite + Preact</a></li>
|
|
214
214
|
<li><a href="https://intlayer.org/doc/environment/vite-and-vue" rel=''>Vite + Vue</a></li>
|
|
215
|
-
<li><a href="https://intlayer.org/doc/environment/
|
|
215
|
+
<li><a href="https://intlayer.org/doc/environment/nuxt-and-vue" rel=''>Vite + Nuxt</a></li>
|
|
216
216
|
<li><a href="https://intlayer.org/doc/environment/vite-and-solid" rel=''>Vite + Solid</a></li>
|
|
217
217
|
<li><a href="https://intlayer.org/doc/environment/angular" rel=''>Angular</a></li>
|
|
218
218
|
<li>
|
|
@@ -38,14 +38,16 @@ const FormattedNumber = ({ value, children, format: _format, ...options }) => {
|
|
|
38
38
|
const FormattedList = ({ value, ...options }) => {
|
|
39
39
|
const intl = useIntl();
|
|
40
40
|
const strings = value.filter((item) => typeof item === "string");
|
|
41
|
-
|
|
41
|
+
const formatted = intl.formatList(strings, options);
|
|
42
|
+
return /* @__PURE__ */ jsx(Fragment, { children: formatted });
|
|
42
43
|
};
|
|
43
44
|
/**
|
|
44
45
|
* Drop-in for react-intl's `<FormattedDisplayName>`.
|
|
45
46
|
* Renders a locale-aware display name using `Intl.DisplayNames`.
|
|
46
47
|
*/
|
|
47
48
|
const FormattedDisplayName = ({ value, ...options }) => {
|
|
48
|
-
|
|
49
|
+
const formatted = useIntl().formatDisplayName(value, options);
|
|
50
|
+
return /* @__PURE__ */ jsx(Fragment, { children: formatted ?? value });
|
|
49
51
|
};
|
|
50
52
|
/**
|
|
51
53
|
* Drop-in for react-intl's `<FormattedRelativeTime>`.
|
|
@@ -88,21 +90,24 @@ const FormattedDateTimeRange = ({ from, to, children, ...options }) => {
|
|
|
88
90
|
* Renders format parts via a `children` render-prop.
|
|
89
91
|
*/
|
|
90
92
|
const FormattedDateParts = ({ value, children, format: _format, ...options }) => {
|
|
91
|
-
|
|
93
|
+
const parts = useIntl().formatDateToParts(value, options);
|
|
94
|
+
return /* @__PURE__ */ jsx(Fragment, { children: children(parts) });
|
|
92
95
|
};
|
|
93
96
|
/**
|
|
94
97
|
* Drop-in for react-intl's `<FormattedTimeParts>`.
|
|
95
98
|
* Renders format parts via a `children` render-prop.
|
|
96
99
|
*/
|
|
97
100
|
const FormattedTimeParts = ({ value, children, format: _format, ...options }) => {
|
|
98
|
-
|
|
101
|
+
const parts = useIntl().formatTimeToParts(value, options);
|
|
102
|
+
return /* @__PURE__ */ jsx(Fragment, { children: children(parts) });
|
|
99
103
|
};
|
|
100
104
|
/**
|
|
101
105
|
* Drop-in for react-intl's `<FormattedNumberParts>`.
|
|
102
106
|
* Renders format parts via a `children` render-prop.
|
|
103
107
|
*/
|
|
104
108
|
const FormattedNumberParts = ({ value, children, format: _format, ...options }) => {
|
|
105
|
-
|
|
109
|
+
const parts = useIntl().formatNumberToParts(value, options);
|
|
110
|
+
return /* @__PURE__ */ jsx(Fragment, { children: children(parts) });
|
|
106
111
|
};
|
|
107
112
|
/**
|
|
108
113
|
* Drop-in for react-intl's `<FormattedListParts>`.
|
|
@@ -111,7 +116,8 @@ const FormattedNumberParts = ({ value, children, format: _format, ...options })
|
|
|
111
116
|
const FormattedListParts = ({ value, children, ...options }) => {
|
|
112
117
|
const intl = useIntl();
|
|
113
118
|
const strings = Array.from(value).filter((item) => typeof item === "string");
|
|
114
|
-
|
|
119
|
+
const parts = intl.formatListToParts(strings, options);
|
|
120
|
+
return /* @__PURE__ */ jsx(Fragment, { children: children(parts) });
|
|
115
121
|
};
|
|
116
122
|
|
|
117
123
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormattedComponents.mjs","names":[],"sources":["../../src/FormattedComponents.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactElement } from 'react';\nimport type {\n FormattedDate as _FormattedDate,\n FormattedDateParts as _FormattedDateParts,\n FormattedDateTimeRange as _FormattedDateTimeRange,\n FormattedDisplayName as _FormattedDisplayName,\n FormattedList as _FormattedList,\n FormattedListParts as _FormattedListParts,\n FormattedNumber as _FormattedNumber,\n FormattedNumberParts as _FormattedNumberParts,\n FormattedPlural as _FormattedPlural,\n FormattedRelativeTime as _FormattedRelativeTime,\n FormattedTime as _FormattedTime,\n FormattedTimeParts as _FormattedTimeParts,\n} from 'react-intl';\nimport { useIntl } from './useIntl';\n\nconst toDate = (value: Date | number | string | undefined): Date =>\n value instanceof Date\n ? value\n : typeof value === 'undefined'\n ? new Date()\n : new Date(value);\n\n/**\n * Drop-in for react-intl's `<FormattedDate>`.\n * Renders a locale-aware date string using `Intl.DateTimeFormat`.\n */\nexport const FormattedDate: typeof _FormattedDate = ({\n value,\n children,\n format: _format,\n ...options\n}) => {\n const intl = useIntl();\n const formatted = intl.formatDate(value, options);\n if (typeof children === 'function') {\n return (children(formatted) ?? null) as ReactElement | null;\n }\n return <>{formatted}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedTime>`.\n * Renders a locale-aware time string using `Intl.DateTimeFormat`.\n */\nexport const FormattedTime: typeof _FormattedTime = ({\n value,\n children,\n format: _format,\n ...options\n}) => {\n const intl = useIntl();\n const formatted = intl.formatTime(value, options);\n if (typeof children === 'function') {\n return (children(formatted) ?? null) as ReactElement | null;\n }\n return <>{formatted}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedNumber>`.\n * Renders a locale-aware number string using `Intl.NumberFormat`.\n */\nexport const FormattedNumber: typeof _FormattedNumber = ({\n value,\n children,\n format: _format,\n ...options\n}) => {\n const intl = useIntl();\n const formatted = intl.formatNumber(value, options);\n if (typeof children === 'function') {\n return (children(formatted) ?? null) as ReactElement | null;\n }\n return <>{formatted}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedList>`.\n * Renders a locale-aware list string using `Intl.ListFormat`.\n */\nexport const FormattedList: typeof _FormattedList = ({ value, ...options }) => {\n const intl = useIntl();\n const strings = (value as unknown[]).filter(\n (item): item is string => typeof item === 'string'\n );\n const formatted = intl.formatList(strings, options);\n return <>{formatted}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedDisplayName>`.\n * Renders a locale-aware display name using `Intl.DisplayNames`.\n */\nexport const FormattedDisplayName: typeof _FormattedDisplayName = ({\n value,\n ...options\n}) => {\n const intl = useIntl();\n const formatted = intl.formatDisplayName(\n value,\n options as Intl.DisplayNamesOptions\n );\n return <>{formatted ?? value}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedRelativeTime>`.\n * Renders a locale-aware relative time string using `Intl.RelativeTimeFormat`.\n * Auto-update (`updateIntervalInSeconds`) is not implemented.\n */\nexport const FormattedRelativeTime: typeof _FormattedRelativeTime = ({\n value = 0,\n unit = 'second',\n children,\n updateIntervalInSeconds: _updateIntervalInSeconds,\n ...options\n}) => {\n const intl = useIntl();\n const formatted = intl.formatRelativeTime(value, unit, options);\n if (typeof children === 'function') {\n return (children(formatted) ?? null) as ReactElement | null;\n }\n return <>{formatted}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedPlural>`.\n * Selects the matching plural slot using `Intl.PluralRules`.\n */\nexport const FormattedPlural: typeof _FormattedPlural = ({\n value,\n other,\n zero,\n one,\n two,\n few,\n many,\n children,\n ...options\n}) => {\n const intl = useIntl();\n const rule = intl.formatPlural(value, options);\n const slots: Record<Intl.LDMLPluralRule, unknown> = {\n zero,\n one,\n two,\n few,\n many,\n other,\n };\n const selected = slots[rule] ?? other;\n\n if (typeof children === 'function') {\n return (children(selected as import('react').ReactNode) ??\n null) as ReactElement | null;\n }\n\n return <>{selected}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedDateTimeRange>`.\n * Renders a locale-aware date range string using `Intl.DateTimeFormat#formatRange`.\n */\nexport const FormattedDateTimeRange: typeof _FormattedDateTimeRange = ({\n from,\n to,\n children,\n ...options\n}) => {\n const intl = useIntl();\n const formatted = intl.formatDateTimeRange(from, to, options);\n if (typeof children === 'function') {\n return (children(formatted) ?? null) as ReactElement | null;\n }\n return <>{formatted}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedDateParts>`.\n * Renders format parts via a `children` render-prop.\n */\nexport const FormattedDateParts: typeof _FormattedDateParts = ({\n value,\n children,\n format: _format,\n ...options\n}) => {\n const intl = useIntl();\n const parts = intl.formatDateToParts(\n value as Parameters<Intl.DateTimeFormat['format']>[0],\n options\n );\n return <>{children(parts)}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedTimeParts>`.\n * Renders format parts via a `children` render-prop.\n */\nexport const FormattedTimeParts: typeof _FormattedTimeParts = ({\n value,\n children,\n format: _format,\n ...options\n}) => {\n const intl = useIntl();\n const parts = intl.formatTimeToParts(\n value as Parameters<Intl.DateTimeFormat['format']>[0],\n options\n );\n return <>{children(parts)}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedNumberParts>`.\n * Renders format parts via a `children` render-prop.\n */\nexport const FormattedNumberParts: typeof _FormattedNumberParts = ({\n value,\n children,\n format: _format,\n ...options\n}) => {\n const intl = useIntl();\n const parts = intl.formatNumberToParts(value, options);\n return <>{children(parts)}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedListParts>`.\n * Renders list format parts via a `children` render-prop.\n */\nexport const FormattedListParts: typeof _FormattedListParts = ({\n value,\n children,\n ...options\n}) => {\n const intl = useIntl();\n const strings = Array.from(value).filter(\n (item): item is string => typeof item === 'string'\n );\n const parts = intl.formatListToParts(strings, options);\n return <>{children(parts)}</>;\n};\n"],"mappings":";;;;;;;;;;AA8BA,MAAa,iBAAwC,EACnD,OACA,UACA,QAAQ,SACR,GAAG,cACC;CAEJ,MAAM,YADO,QACQ,CAAC,CAAC,WAAW,OAAO,OAAO;CAChD,IAAI,OAAO,aAAa,YACtB,OAAQ,SAAS,SAAS,KAAK;CAEjC,OAAO,0CAAG,UAAY;AACxB;;;;;AAMA,MAAa,iBAAwC,EACnD,OACA,UACA,QAAQ,SACR,GAAG,cACC;CAEJ,MAAM,YADO,QACQ,CAAC,CAAC,WAAW,OAAO,OAAO;CAChD,IAAI,OAAO,aAAa,YACtB,OAAQ,SAAS,SAAS,KAAK;CAEjC,OAAO,0CAAG,UAAY;AACxB;;;;;AAMA,MAAa,mBAA4C,EACvD,OACA,UACA,QAAQ,SACR,GAAG,cACC;CAEJ,MAAM,YADO,QACQ,CAAC,CAAC,aAAa,OAAO,OAAO;CAClD,IAAI,OAAO,aAAa,YACtB,OAAQ,SAAS,SAAS,KAAK;CAEjC,OAAO,0CAAG,UAAY;AACxB;;;;;AAMA,MAAa,iBAAwC,EAAE,OAAO,GAAG,cAAc;CAC7E,MAAM,OAAO,QAAQ;CACrB,MAAM,UAAW,MAAoB,QAClC,SAAyB,OAAO,SAAS,QAC5C;
|
|
1
|
+
{"version":3,"file":"FormattedComponents.mjs","names":[],"sources":["../../src/FormattedComponents.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactElement } from 'react';\nimport type {\n FormattedDate as _FormattedDate,\n FormattedDateParts as _FormattedDateParts,\n FormattedDateTimeRange as _FormattedDateTimeRange,\n FormattedDisplayName as _FormattedDisplayName,\n FormattedList as _FormattedList,\n FormattedListParts as _FormattedListParts,\n FormattedNumber as _FormattedNumber,\n FormattedNumberParts as _FormattedNumberParts,\n FormattedPlural as _FormattedPlural,\n FormattedRelativeTime as _FormattedRelativeTime,\n FormattedTime as _FormattedTime,\n FormattedTimeParts as _FormattedTimeParts,\n} from 'react-intl';\nimport { useIntl } from './useIntl';\n\nconst toDate = (value: Date | number | string | undefined): Date =>\n value instanceof Date\n ? value\n : typeof value === 'undefined'\n ? new Date()\n : new Date(value);\n\n/**\n * Drop-in for react-intl's `<FormattedDate>`.\n * Renders a locale-aware date string using `Intl.DateTimeFormat`.\n */\nexport const FormattedDate: typeof _FormattedDate = ({\n value,\n children,\n format: _format,\n ...options\n}) => {\n const intl = useIntl();\n const formatted = intl.formatDate(value, options);\n if (typeof children === 'function') {\n return (children(formatted) ?? null) as ReactElement | null;\n }\n return <>{formatted}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedTime>`.\n * Renders a locale-aware time string using `Intl.DateTimeFormat`.\n */\nexport const FormattedTime: typeof _FormattedTime = ({\n value,\n children,\n format: _format,\n ...options\n}) => {\n const intl = useIntl();\n const formatted = intl.formatTime(value, options);\n if (typeof children === 'function') {\n return (children(formatted) ?? null) as ReactElement | null;\n }\n return <>{formatted}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedNumber>`.\n * Renders a locale-aware number string using `Intl.NumberFormat`.\n */\nexport const FormattedNumber: typeof _FormattedNumber = ({\n value,\n children,\n format: _format,\n ...options\n}) => {\n const intl = useIntl();\n const formatted = intl.formatNumber(value, options);\n if (typeof children === 'function') {\n return (children(formatted) ?? null) as ReactElement | null;\n }\n return <>{formatted}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedList>`.\n * Renders a locale-aware list string using `Intl.ListFormat`.\n */\nexport const FormattedList: typeof _FormattedList = ({ value, ...options }) => {\n const intl = useIntl();\n const strings = (value as unknown[]).filter(\n (item): item is string => typeof item === 'string'\n );\n const formatted = intl.formatList(strings, options);\n return <>{formatted}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedDisplayName>`.\n * Renders a locale-aware display name using `Intl.DisplayNames`.\n */\nexport const FormattedDisplayName: typeof _FormattedDisplayName = ({\n value,\n ...options\n}) => {\n const intl = useIntl();\n const formatted = intl.formatDisplayName(\n value,\n options as Intl.DisplayNamesOptions\n );\n return <>{formatted ?? value}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedRelativeTime>`.\n * Renders a locale-aware relative time string using `Intl.RelativeTimeFormat`.\n * Auto-update (`updateIntervalInSeconds`) is not implemented.\n */\nexport const FormattedRelativeTime: typeof _FormattedRelativeTime = ({\n value = 0,\n unit = 'second',\n children,\n updateIntervalInSeconds: _updateIntervalInSeconds,\n ...options\n}) => {\n const intl = useIntl();\n const formatted = intl.formatRelativeTime(value, unit, options);\n if (typeof children === 'function') {\n return (children(formatted) ?? null) as ReactElement | null;\n }\n return <>{formatted}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedPlural>`.\n * Selects the matching plural slot using `Intl.PluralRules`.\n */\nexport const FormattedPlural: typeof _FormattedPlural = ({\n value,\n other,\n zero,\n one,\n two,\n few,\n many,\n children,\n ...options\n}) => {\n const intl = useIntl();\n const rule = intl.formatPlural(value, options);\n const slots: Record<Intl.LDMLPluralRule, unknown> = {\n zero,\n one,\n two,\n few,\n many,\n other,\n };\n const selected = slots[rule] ?? other;\n\n if (typeof children === 'function') {\n return (children(selected as import('react').ReactNode) ??\n null) as ReactElement | null;\n }\n\n return <>{selected}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedDateTimeRange>`.\n * Renders a locale-aware date range string using `Intl.DateTimeFormat#formatRange`.\n */\nexport const FormattedDateTimeRange: typeof _FormattedDateTimeRange = ({\n from,\n to,\n children,\n ...options\n}) => {\n const intl = useIntl();\n const formatted = intl.formatDateTimeRange(from, to, options);\n if (typeof children === 'function') {\n return (children(formatted) ?? null) as ReactElement | null;\n }\n return <>{formatted}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedDateParts>`.\n * Renders format parts via a `children` render-prop.\n */\nexport const FormattedDateParts: typeof _FormattedDateParts = ({\n value,\n children,\n format: _format,\n ...options\n}) => {\n const intl = useIntl();\n const parts = intl.formatDateToParts(\n value as Parameters<Intl.DateTimeFormat['format']>[0],\n options\n );\n return <>{children(parts)}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedTimeParts>`.\n * Renders format parts via a `children` render-prop.\n */\nexport const FormattedTimeParts: typeof _FormattedTimeParts = ({\n value,\n children,\n format: _format,\n ...options\n}) => {\n const intl = useIntl();\n const parts = intl.formatTimeToParts(\n value as Parameters<Intl.DateTimeFormat['format']>[0],\n options\n );\n return <>{children(parts)}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedNumberParts>`.\n * Renders format parts via a `children` render-prop.\n */\nexport const FormattedNumberParts: typeof _FormattedNumberParts = ({\n value,\n children,\n format: _format,\n ...options\n}) => {\n const intl = useIntl();\n const parts = intl.formatNumberToParts(value, options);\n return <>{children(parts)}</>;\n};\n\n/**\n * Drop-in for react-intl's `<FormattedListParts>`.\n * Renders list format parts via a `children` render-prop.\n */\nexport const FormattedListParts: typeof _FormattedListParts = ({\n value,\n children,\n ...options\n}) => {\n const intl = useIntl();\n const strings = Array.from(value).filter(\n (item): item is string => typeof item === 'string'\n );\n const parts = intl.formatListToParts(strings, options);\n return <>{children(parts)}</>;\n};\n"],"mappings":"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"}
|
|
@@ -21,7 +21,8 @@ const lookupMessage = (id, locale) => {
|
|
|
21
21
|
const { dictionaryKey, path } = splitId(id);
|
|
22
22
|
if (!dictionaryKey) return void 0;
|
|
23
23
|
try {
|
|
24
|
-
|
|
24
|
+
const dictionary = getIntlayer(dictionaryKey, locale);
|
|
25
|
+
return navigatePath(dictionary, path);
|
|
25
26
|
} catch {
|
|
26
27
|
return;
|
|
27
28
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createIntlObject.mjs","names":[],"sources":["../../src/createIntlObject.tsx"],"sourcesContent":["import { getIntlayer } from '@intlayer/core/interpreter';\nimport {\n type MessageValues,\n navigatePath,\n parseTaggedMessage,\n resolveMessage,\n type TaggedMessageToken,\n} from '@intlayer/core/messageFormat';\nimport type {\n DictionaryKeys,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport { Fragment, type ReactNode } from 'react';\nimport type { IntlShape, MessageDescriptor } from 'react-intl';\n\ntype RichRenderer = (chunks: ReactNode) => ReactNode;\n\n/** Splits a full dotted id into the dictionary key and remaining path. */\nconst splitId = (id: string): { dictionaryKey: string; path: string } => {\n const dotIndex = id.indexOf('.');\n if (dotIndex === -1) return { dictionaryKey: id, path: '' };\n return {\n dictionaryKey: id.slice(0, dotIndex),\n path: id.slice(dotIndex + 1),\n };\n};\n\n/** Looks up a message value by full dotted id; first segment = dictionary key. */\nconst lookupMessage = (id: string, locale: LocalesValues): unknown => {\n const { dictionaryKey, path } = splitId(id);\n if (!dictionaryKey) return undefined;\n try {\n const dictionary = getIntlayer(dictionaryKey as DictionaryKeys, locale);\n return navigatePath(dictionary, path);\n } catch {\n return undefined;\n }\n};\n\n/** Maps tagged tokens to React nodes using the provided renderer functions. */\nconst renderRichTokens = (\n tokens: TaggedMessageToken[],\n renderers: Record<string, unknown>\n): ReactNode[] =>\n tokens.map((token, tokenIndex) => {\n if (typeof token === 'string') return token;\n const children = renderRichTokens(token.children, renderers);\n const renderer = renderers[token.tag];\n if (typeof renderer === 'function') {\n return (\n <Fragment key={tokenIndex}>\n {(renderer as RichRenderer)(<>{children}</>)}\n </Fragment>\n );\n }\n return <Fragment key={tokenIndex}>{children}</Fragment>;\n });\n\n/** Partitions values into scalar interpolation params and tag renderers. */\nconst splitRichValues = (\n values: Record<string, unknown>\n): { scalarValues: MessageValues; renderers: Record<string, unknown> } => {\n const scalarValues: MessageValues = {};\n const renderers: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(values)) {\n if (typeof value === 'function') renderers[key] = value;\n else scalarValues[key] = value as MessageValues[string];\n }\n return { scalarValues, renderers };\n};\n\nconst isRichValues = (values: Record<string, unknown>): boolean =>\n Object.values(values).some((value) => typeof value === 'function');\n\n/**\n * Builds an intlayer-backed `IntlShape` object for the given locale.\n *\n * - Translation ids use the first dot-path segment as the dictionary key.\n * - Full ICU MessageFormat syntax is supported via `@intlayer/core/messageFormat`.\n * - Rich text tags (`<b>chunks</b>`) are resolved through render functions in `values`.\n *\n * @param locale - The locale messages are resolved for.\n * @param lookupOverride - Optional message lookup replacing the registry-based\n * id resolution; used by the dictionary-bound `useDictionary` variant.\n */\nexport const createIntlObject = (\n locale: LocalesValues,\n lookupOverride?: (id: string) => unknown\n): IntlShape => {\n const localeString = locale as string;\n\n const formatMessage = (\n descriptor: MessageDescriptor,\n values?: Record<string, unknown>\n ): string | ReactNode[] => {\n const { id = '', defaultMessage } = descriptor;\n const rawValue = lookupOverride\n ? lookupOverride(id)\n : lookupMessage(id, locale);\n const messageTemplate =\n rawValue !== undefined && rawValue !== null\n ? (rawValue as string)\n : typeof defaultMessage === 'string'\n ? defaultMessage\n : id;\n\n if (!values || !isRichValues(values)) {\n return (\n resolveMessage(\n messageTemplate,\n (values ?? {}) as MessageValues,\n locale,\n 'icu'\n ) ?? id\n );\n }\n\n const { scalarValues, renderers } = splitRichValues(values);\n const message =\n resolveMessage(messageTemplate, scalarValues, locale, 'icu') ?? id;\n return renderRichTokens(parseTaggedMessage(message), renderers);\n };\n\n const toDate = (value: Date | number | string): Date =>\n value instanceof Date ? value : new Date(value);\n\n const formatDate = (\n value: string | number | Date | undefined,\n options?: Intl.DateTimeFormatOptions\n ): string => {\n if (value === undefined || value === null) return '';\n return new Intl.DateTimeFormat(localeString, options).format(toDate(value));\n };\n\n const formatNumber = (\n value: number | bigint,\n options?: Intl.NumberFormatOptions\n ): string => new Intl.NumberFormat(localeString, options).format(value);\n\n const formatPlural = (\n value: number,\n options?: Intl.PluralRulesOptions\n ): Intl.LDMLPluralRule =>\n new Intl.PluralRules(localeString, options).select(value);\n\n const formatList = (\n list: Iterable<unknown> | readonly unknown[],\n options?: Intl.ListFormatOptions\n ): string => {\n const strings = Array.from(list).filter(\n (item): item is string => typeof item === 'string'\n );\n return new Intl.ListFormat(localeString, options).format(strings);\n };\n\n const formatListToParts = (\n list: Iterable<unknown> | readonly unknown[],\n options?: Intl.ListFormatOptions\n ): ReturnType<Intl.ListFormat['formatToParts']> => {\n const strings = Array.from(list).filter(\n (item): item is string => typeof item === 'string'\n );\n return new Intl.ListFormat(localeString, options).formatToParts(strings);\n };\n\n const formatDisplayName = (\n value: string,\n options?: Intl.DisplayNamesOptions\n ): string | undefined =>\n new Intl.DisplayNames([localeString], options ?? { type: 'language' }).of(\n value\n );\n\n const formatRelativeTime = (\n value: number,\n unit?: Intl.RelativeTimeFormatUnit,\n options?: Intl.RelativeTimeFormatOptions\n ): string =>\n new Intl.RelativeTimeFormat(localeString, {\n numeric: 'auto',\n ...options,\n }).format(value, unit ?? 'second');\n\n const formatDateTimeRange = (\n from: Date | number,\n to: Date | number,\n options?: Intl.DateTimeFormatOptions\n ): string =>\n new Intl.DateTimeFormat(localeString, options).formatRange(\n toDate(from),\n toDate(to)\n );\n\n const formatDateToParts = (\n value: Parameters<Intl.DateTimeFormat['format']>[0] | string,\n options?: Intl.DateTimeFormatOptions\n ): Intl.DateTimeFormatPart[] =>\n new Intl.DateTimeFormat(localeString, options).formatToParts(\n typeof value === 'string' ? new Date(value) : value\n );\n\n const formatNumberToParts = (\n value: number | bigint,\n options?: Intl.NumberFormatOptions\n ): Intl.NumberFormatPart[] =>\n new Intl.NumberFormat(localeString, options).formatToParts(value);\n\n /** Alias of `formatMessage` — provided for `@formatjs/intl` v4 compatibility. */\n const $t = formatMessage as IntlShape['$t'];\n\n return {\n locale: localeString,\n defaultLocale: localeString,\n messages: {},\n formats: {},\n defaultFormats: {},\n timeZone: undefined,\n textComponent: Fragment,\n wrapRichTextChunksInFragment: false,\n fallbackOnEmptyString: true,\n onError: () => {},\n onWarn: () => {},\n formatters: {} as IntlShape['formatters'],\n formatMessage: formatMessage as IntlShape['formatMessage'],\n $t,\n formatDate,\n formatTime: formatDate,\n formatNumber,\n formatPlural,\n formatList: formatList as IntlShape['formatList'],\n formatListToParts: formatListToParts as IntlShape['formatListToParts'],\n formatDisplayName: formatDisplayName as IntlShape['formatDisplayName'],\n formatRelativeTime,\n formatDateTimeRange,\n formatDateToParts: formatDateToParts as IntlShape['formatDateToParts'],\n formatTimeToParts: formatDateToParts as IntlShape['formatTimeToParts'],\n formatNumberToParts:\n formatNumberToParts as IntlShape['formatNumberToParts'],\n } as unknown as IntlShape;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createIntlObject.mjs","names":[],"sources":["../../src/createIntlObject.tsx"],"sourcesContent":["import { getIntlayer } from '@intlayer/core/interpreter';\nimport {\n type MessageValues,\n navigatePath,\n parseTaggedMessage,\n resolveMessage,\n type TaggedMessageToken,\n} from '@intlayer/core/messageFormat';\nimport type {\n DictionaryKeys,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport { Fragment, type ReactNode } from 'react';\nimport type { IntlShape, MessageDescriptor } from 'react-intl';\n\ntype RichRenderer = (chunks: ReactNode) => ReactNode;\n\n/** Splits a full dotted id into the dictionary key and remaining path. */\nconst splitId = (id: string): { dictionaryKey: string; path: string } => {\n const dotIndex = id.indexOf('.');\n if (dotIndex === -1) return { dictionaryKey: id, path: '' };\n return {\n dictionaryKey: id.slice(0, dotIndex),\n path: id.slice(dotIndex + 1),\n };\n};\n\n/** Looks up a message value by full dotted id; first segment = dictionary key. */\nconst lookupMessage = (id: string, locale: LocalesValues): unknown => {\n const { dictionaryKey, path } = splitId(id);\n if (!dictionaryKey) return undefined;\n try {\n const dictionary = getIntlayer(dictionaryKey as DictionaryKeys, locale);\n return navigatePath(dictionary, path);\n } catch {\n return undefined;\n }\n};\n\n/** Maps tagged tokens to React nodes using the provided renderer functions. */\nconst renderRichTokens = (\n tokens: TaggedMessageToken[],\n renderers: Record<string, unknown>\n): ReactNode[] =>\n tokens.map((token, tokenIndex) => {\n if (typeof token === 'string') return token;\n const children = renderRichTokens(token.children, renderers);\n const renderer = renderers[token.tag];\n if (typeof renderer === 'function') {\n return (\n <Fragment key={tokenIndex}>\n {(renderer as RichRenderer)(<>{children}</>)}\n </Fragment>\n );\n }\n return <Fragment key={tokenIndex}>{children}</Fragment>;\n });\n\n/** Partitions values into scalar interpolation params and tag renderers. */\nconst splitRichValues = (\n values: Record<string, unknown>\n): { scalarValues: MessageValues; renderers: Record<string, unknown> } => {\n const scalarValues: MessageValues = {};\n const renderers: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(values)) {\n if (typeof value === 'function') renderers[key] = value;\n else scalarValues[key] = value as MessageValues[string];\n }\n return { scalarValues, renderers };\n};\n\nconst isRichValues = (values: Record<string, unknown>): boolean =>\n Object.values(values).some((value) => typeof value === 'function');\n\n/**\n * Builds an intlayer-backed `IntlShape` object for the given locale.\n *\n * - Translation ids use the first dot-path segment as the dictionary key.\n * - Full ICU MessageFormat syntax is supported via `@intlayer/core/messageFormat`.\n * - Rich text tags (`<b>chunks</b>`) are resolved through render functions in `values`.\n *\n * @param locale - The locale messages are resolved for.\n * @param lookupOverride - Optional message lookup replacing the registry-based\n * id resolution; used by the dictionary-bound `useDictionary` variant.\n */\nexport const createIntlObject = (\n locale: LocalesValues,\n lookupOverride?: (id: string) => unknown\n): IntlShape => {\n const localeString = locale as string;\n\n const formatMessage = (\n descriptor: MessageDescriptor,\n values?: Record<string, unknown>\n ): string | ReactNode[] => {\n const { id = '', defaultMessage } = descriptor;\n const rawValue = lookupOverride\n ? lookupOverride(id)\n : lookupMessage(id, locale);\n const messageTemplate =\n rawValue !== undefined && rawValue !== null\n ? (rawValue as string)\n : typeof defaultMessage === 'string'\n ? defaultMessage\n : id;\n\n if (!values || !isRichValues(values)) {\n return (\n resolveMessage(\n messageTemplate,\n (values ?? {}) as MessageValues,\n locale,\n 'icu'\n ) ?? id\n );\n }\n\n const { scalarValues, renderers } = splitRichValues(values);\n const message =\n resolveMessage(messageTemplate, scalarValues, locale, 'icu') ?? id;\n return renderRichTokens(parseTaggedMessage(message), renderers);\n };\n\n const toDate = (value: Date | number | string): Date =>\n value instanceof Date ? value : new Date(value);\n\n const formatDate = (\n value: string | number | Date | undefined,\n options?: Intl.DateTimeFormatOptions\n ): string => {\n if (value === undefined || value === null) return '';\n return new Intl.DateTimeFormat(localeString, options).format(toDate(value));\n };\n\n const formatNumber = (\n value: number | bigint,\n options?: Intl.NumberFormatOptions\n ): string => new Intl.NumberFormat(localeString, options).format(value);\n\n const formatPlural = (\n value: number,\n options?: Intl.PluralRulesOptions\n ): Intl.LDMLPluralRule =>\n new Intl.PluralRules(localeString, options).select(value);\n\n const formatList = (\n list: Iterable<unknown> | readonly unknown[],\n options?: Intl.ListFormatOptions\n ): string => {\n const strings = Array.from(list).filter(\n (item): item is string => typeof item === 'string'\n );\n return new Intl.ListFormat(localeString, options).format(strings);\n };\n\n const formatListToParts = (\n list: Iterable<unknown> | readonly unknown[],\n options?: Intl.ListFormatOptions\n ): ReturnType<Intl.ListFormat['formatToParts']> => {\n const strings = Array.from(list).filter(\n (item): item is string => typeof item === 'string'\n );\n return new Intl.ListFormat(localeString, options).formatToParts(strings);\n };\n\n const formatDisplayName = (\n value: string,\n options?: Intl.DisplayNamesOptions\n ): string | undefined =>\n new Intl.DisplayNames([localeString], options ?? { type: 'language' }).of(\n value\n );\n\n const formatRelativeTime = (\n value: number,\n unit?: Intl.RelativeTimeFormatUnit,\n options?: Intl.RelativeTimeFormatOptions\n ): string =>\n new Intl.RelativeTimeFormat(localeString, {\n numeric: 'auto',\n ...options,\n }).format(value, unit ?? 'second');\n\n const formatDateTimeRange = (\n from: Date | number,\n to: Date | number,\n options?: Intl.DateTimeFormatOptions\n ): string =>\n new Intl.DateTimeFormat(localeString, options).formatRange(\n toDate(from),\n toDate(to)\n );\n\n const formatDateToParts = (\n value: Parameters<Intl.DateTimeFormat['format']>[0] | string,\n options?: Intl.DateTimeFormatOptions\n ): Intl.DateTimeFormatPart[] =>\n new Intl.DateTimeFormat(localeString, options).formatToParts(\n typeof value === 'string' ? new Date(value) : value\n );\n\n const formatNumberToParts = (\n value: number | bigint,\n options?: Intl.NumberFormatOptions\n ): Intl.NumberFormatPart[] =>\n new Intl.NumberFormat(localeString, options).formatToParts(value);\n\n /** Alias of `formatMessage` — provided for `@formatjs/intl` v4 compatibility. */\n const $t = formatMessage as IntlShape['$t'];\n\n return {\n locale: localeString,\n defaultLocale: localeString,\n messages: {},\n formats: {},\n defaultFormats: {},\n timeZone: undefined,\n textComponent: Fragment,\n wrapRichTextChunksInFragment: false,\n fallbackOnEmptyString: true,\n onError: () => {},\n onWarn: () => {},\n formatters: {} as IntlShape['formatters'],\n formatMessage: formatMessage as IntlShape['formatMessage'],\n $t,\n formatDate,\n formatTime: formatDate,\n formatNumber,\n formatPlural,\n formatList: formatList as IntlShape['formatList'],\n formatListToParts: formatListToParts as IntlShape['formatListToParts'],\n formatDisplayName: formatDisplayName as IntlShape['formatDisplayName'],\n formatRelativeTime,\n formatDateTimeRange,\n formatDateToParts: formatDateToParts as IntlShape['formatDateToParts'],\n formatTimeToParts: formatDateToParts as IntlShape['formatTimeToParts'],\n formatNumberToParts:\n formatNumberToParts as IntlShape['formatNumberToParts'],\n } as unknown as IntlShape;\n};\n"],"mappings":"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"}
|
|
@@ -27,7 +27,7 @@ const reactIntlVitePlugin = (options) => {
|
|
|
27
27
|
const appLogger = getAppLogger(intlayerConfig);
|
|
28
28
|
runOnce(join(intlayerConfig.system.baseDir, ".intlayer", "cache", "intlayer-issues-invitation.lock"), () => {
|
|
29
29
|
appLogger([colorize("Please report any issues you met on GitHub:", ANSIColors.GREY), colorize("https://github.com/aymericzip/intlayer/issues", ANSIColors.GREY_LIGHT)]);
|
|
30
|
-
}, { cacheTimeoutMs:
|
|
30
|
+
}, { cacheTimeoutMs: 36e5 });
|
|
31
31
|
const basePlugins = intlayer({
|
|
32
32
|
...options,
|
|
33
33
|
compatCallers: [...options?.compatCallers ?? [], ...REACT_INTL_CALLERS]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugin/index.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { REACT_INTL_CALLERS } from '@intlayer/config/callers';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { runOnce } from '@intlayer/engine/utils';\nimport type { PluginOption } from 'vite';\nimport { intlayer } from 'vite-intlayer';\n\n/**\n * A Vite plugin for react-intl compat that wraps vite-intlayer\n * and injects a resolve alias mapping `react-intl` to\n * `@intlayer/react-intl`.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import reactIntlVitePlugin from '@intlayer/react-intl/plugin';\n *\n * export default defineConfig({\n * plugins: [reactIntlVitePlugin()],\n * });\n * ```\n */\nexport const reactIntlVitePlugin = (\n options?: Parameters<typeof intlayer>[0]\n): PluginOption[] => {\n const intlayerConfig = getConfiguration();\n const appLogger = getAppLogger(intlayerConfig);\n\n runOnce(\n join(\n intlayerConfig.system.baseDir,\n '.intlayer',\n 'cache',\n 'intlayer-issues-invitation.lock'\n ),\n () => {\n appLogger([\n colorize(\n 'Please report any issues you met on GitHub:',\n ANSIColors.GREY\n ),\n colorize(\n 'https://github.com/aymericzip/intlayer/issues',\n ANSIColors.GREY_LIGHT\n ),\n ]);\n },\n {\n cacheTimeoutMs: 1000 * 60 * 60, // 1 hour\n }\n );\n\n const basePlugins = intlayer({\n ...options,\n compatCallers: [...(options?.compatCallers ?? []), ...REACT_INTL_CALLERS],\n });\n\n const compatPlugin: PluginOption = {\n name: 'vite-react-intl-compat-plugin',\n config: () => ({\n resolve: {\n alias: {\n 'react-intl': '@intlayer/react-intl',\n },\n },\n }),\n };\n\n return [\n ...(Array.isArray(basePlugins) ? basePlugins : [basePlugins]),\n compatPlugin,\n ];\n};\n\nexport default reactIntlVitePlugin;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,uBACX,YACmB;CACnB,MAAM,iBAAiB,iBAAiB;CACxC,MAAM,YAAY,aAAa,cAAc;CAE7C,QACE,KACE,eAAe,OAAO,SACtB,aACA,SACA,iCACF,SACM;EACJ,UAAU,CACR,SACE,+CACA,WAAW,IACb,GACA,SACE,iDACA,WAAW,UACb,CACF,CAAC;CACH,GACA,EACE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugin/index.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { REACT_INTL_CALLERS } from '@intlayer/config/callers';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { runOnce } from '@intlayer/engine/utils';\nimport type { PluginOption } from 'vite';\nimport { intlayer } from 'vite-intlayer';\n\n/**\n * A Vite plugin for react-intl compat that wraps vite-intlayer\n * and injects a resolve alias mapping `react-intl` to\n * `@intlayer/react-intl`.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import reactIntlVitePlugin from '@intlayer/react-intl/plugin';\n *\n * export default defineConfig({\n * plugins: [reactIntlVitePlugin()],\n * });\n * ```\n */\nexport const reactIntlVitePlugin = (\n options?: Parameters<typeof intlayer>[0]\n): PluginOption[] => {\n const intlayerConfig = getConfiguration();\n const appLogger = getAppLogger(intlayerConfig);\n\n runOnce(\n join(\n intlayerConfig.system.baseDir,\n '.intlayer',\n 'cache',\n 'intlayer-issues-invitation.lock'\n ),\n () => {\n appLogger([\n colorize(\n 'Please report any issues you met on GitHub:',\n ANSIColors.GREY\n ),\n colorize(\n 'https://github.com/aymericzip/intlayer/issues',\n ANSIColors.GREY_LIGHT\n ),\n ]);\n },\n {\n cacheTimeoutMs: 1000 * 60 * 60, // 1 hour\n }\n );\n\n const basePlugins = intlayer({\n ...options,\n compatCallers: [...(options?.compatCallers ?? []), ...REACT_INTL_CALLERS],\n });\n\n const compatPlugin: PluginOption = {\n name: 'vite-react-intl-compat-plugin',\n config: () => ({\n resolve: {\n alias: {\n 'react-intl': '@intlayer/react-intl',\n },\n },\n }),\n };\n\n return [\n ...(Array.isArray(basePlugins) ? basePlugins : [basePlugins]),\n compatPlugin,\n ];\n};\n\nexport default reactIntlVitePlugin;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,uBACX,YACmB;CACnB,MAAM,iBAAiB,iBAAiB;CACxC,MAAM,YAAY,aAAa,cAAc;CAE7C,QACE,KACE,eAAe,OAAO,SACtB,aACA,SACA,iCACF,SACM;EACJ,UAAU,CACR,SACE,+CACA,WAAW,IACb,GACA,SACE,iDACA,WAAW,UACb,CACF,CAAC;CACH,GACA,EACE,gBAAgB,KAClB,CACF;CAEA,MAAM,cAAc,SAAS;EAC3B,GAAG;EACH,eAAe,CAAC,GAAI,SAAS,iBAAiB,CAAC,GAAI,GAAG,kBAAkB;CAC1E,CAAC;CAED,MAAM,eAA6B;EACjC,MAAM;EACN,eAAe,EACb,SAAS,EACP,OAAO,EACL,cAAc,uBAChB,EACF,EACF;CACF;CAEA,OAAO,CACL,GAAI,MAAM,QAAQ,WAAW,IAAI,cAAc,CAAC,WAAW,GAC3D,YACF;AACF"}
|
|
@@ -15,7 +15,8 @@ import { navigatePath } from "@intlayer/core/messageFormat";
|
|
|
15
15
|
* absolute (`'home.title'`) and relative (`'title'`) forms resolve.
|
|
16
16
|
*/
|
|
17
17
|
const createDictionaryLookup = (dictionaryKey, content) => (id) => {
|
|
18
|
-
|
|
18
|
+
const relativePath = id.startsWith(`${dictionaryKey}.`) ? id.slice(dictionaryKey.length + 1) : id === dictionaryKey ? "" : id;
|
|
19
|
+
return navigatePath(content, relativePath);
|
|
19
20
|
};
|
|
20
21
|
/**
|
|
21
22
|
* Dictionary-accepting variant of `useIntl`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDictionary.mjs","names":["useDictionaryBase"],"sources":["../../src/useDictionary.ts"],"sourcesContent":["'use client';\n\nimport { navigatePath } from '@intlayer/core/messageFormat';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type {\n DictionaryKeys,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport { useMemo } from 'react';\nimport { useDictionary as useDictionaryBase, useLocale } from 'react-intlayer';\nimport { createIntlObject } from './createIntlObject';\nimport type { DictionaryIntlShape } from './dictionaryIntlShape';\n\n/**\n * Builds the id lookup of a dictionary-bound intl object.\n *\n * react-intl ids encode the dictionary key as their first dot-segment\n * (`'home.title'` → dictionary `home`, field `title`). When the content is\n * supplied directly, the leading `<dictionaryKey>.` is stripped so both the\n * absolute (`'home.title'`) and relative (`'title'`) forms resolve.\n */\nexport const createDictionaryLookup =\n (dictionaryKey: string, content: unknown) =>\n (id: string): unknown => {\n const relativePath = id.startsWith(`${dictionaryKey}.`)\n ? id.slice(dictionaryKey.length + 1)\n : id === dictionaryKey\n ? ''\n : id;\n return navigatePath(content, relativePath);\n };\n\n/**\n * Dictionary-accepting variant of `useIntl`.\n *\n * Returns an `IntlShape` whose `formatMessage` resolves ids inside the\n * supplied dictionary instead of the runtime registry, enabling tree-shaking\n * of unused locale content. All `Intl`-backed formatters (`formatNumber`,\n * `formatDate`, …) behave exactly like `useIntl()`.\n *\n * @example\n * import _abc from '.intlayer/dictionaries/home.json' with { type: 'json' };\n * const intl = useDictionary(_abc);\n * intl.formatMessage({ id: 'home.title' }); // or { id: 'title' } — both typed\n */\nexport const useDictionary = <T extends Dictionary>(\n dictionary: T\n): DictionaryIntlShape<T['key'] & DictionaryKeys> => {\n const content = useDictionaryBase(dictionary);\n const { locale } = useLocale();\n\n return useMemo(\n () =>\n createIntlObject(\n locale as LocalesValues,\n createDictionaryLookup(dictionary.key, content)\n ) as DictionaryIntlShape<T['key'] & DictionaryKeys>,\n [locale, dictionary.key, content]\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAqBA,MAAa,0BACV,eAAuB,aACvB,OAAwB;
|
|
1
|
+
{"version":3,"file":"useDictionary.mjs","names":["useDictionaryBase"],"sources":["../../src/useDictionary.ts"],"sourcesContent":["'use client';\n\nimport { navigatePath } from '@intlayer/core/messageFormat';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type {\n DictionaryKeys,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport { useMemo } from 'react';\nimport { useDictionary as useDictionaryBase, useLocale } from 'react-intlayer';\nimport { createIntlObject } from './createIntlObject';\nimport type { DictionaryIntlShape } from './dictionaryIntlShape';\n\n/**\n * Builds the id lookup of a dictionary-bound intl object.\n *\n * react-intl ids encode the dictionary key as their first dot-segment\n * (`'home.title'` → dictionary `home`, field `title`). When the content is\n * supplied directly, the leading `<dictionaryKey>.` is stripped so both the\n * absolute (`'home.title'`) and relative (`'title'`) forms resolve.\n */\nexport const createDictionaryLookup =\n (dictionaryKey: string, content: unknown) =>\n (id: string): unknown => {\n const relativePath = id.startsWith(`${dictionaryKey}.`)\n ? id.slice(dictionaryKey.length + 1)\n : id === dictionaryKey\n ? ''\n : id;\n return navigatePath(content, relativePath);\n };\n\n/**\n * Dictionary-accepting variant of `useIntl`.\n *\n * Returns an `IntlShape` whose `formatMessage` resolves ids inside the\n * supplied dictionary instead of the runtime registry, enabling tree-shaking\n * of unused locale content. All `Intl`-backed formatters (`formatNumber`,\n * `formatDate`, …) behave exactly like `useIntl()`.\n *\n * @example\n * import _abc from '.intlayer/dictionaries/home.json' with { type: 'json' };\n * const intl = useDictionary(_abc);\n * intl.formatMessage({ id: 'home.title' }); // or { id: 'title' } — both typed\n */\nexport const useDictionary = <T extends Dictionary>(\n dictionary: T\n): DictionaryIntlShape<T['key'] & DictionaryKeys> => {\n const content = useDictionaryBase(dictionary);\n const { locale } = useLocale();\n\n return useMemo(\n () =>\n createIntlObject(\n locale as LocalesValues,\n createDictionaryLookup(dictionary.key, content)\n ) as DictionaryIntlShape<T['key'] & DictionaryKeys>,\n [locale, dictionary.key, content]\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAqBA,MAAa,0BACV,eAAuB,aACvB,OAAwB;CACvB,MAAM,eAAe,GAAG,WAAW,GAAG,cAAc,EAAE,IAClD,GAAG,MAAM,cAAc,SAAS,CAAC,IACjC,OAAO,gBACL,KACA;CACN,OAAO,aAAa,SAAS,YAAY;AAC3C;;;;;;;;;;;;;;AAeF,MAAa,iBACX,eACmD;CACnD,MAAM,UAAUA,gBAAkB,UAAU;CAC5C,MAAM,EAAE,WAAW,UAAU;CAE7B,OAAO,cAEH,iBACE,QACA,uBAAuB,WAAW,KAAK,OAAO,CAChD,GACF;EAAC;EAAQ,WAAW;EAAK;CAAO,CAClC;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/react-intl",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "react-intl API adapter for intlayer — drop-in compatibility layer",
|
|
6
6
|
"keywords": [
|
|
@@ -74,13 +74,13 @@
|
|
|
74
74
|
"typecheck": "tsc --noEmit --project tsconfig.types.json"
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@intlayer/config": "9.3.
|
|
78
|
-
"@intlayer/core": "9.3.
|
|
79
|
-
"@intlayer/dictionaries-entry": "9.3.
|
|
80
|
-
"@intlayer/engine": "9.3.
|
|
81
|
-
"@intlayer/types": "9.3.
|
|
82
|
-
"react-intlayer": "9.3.
|
|
83
|
-
"vite-intlayer": "9.3.
|
|
77
|
+
"@intlayer/config": "9.3.2",
|
|
78
|
+
"@intlayer/core": "9.3.2",
|
|
79
|
+
"@intlayer/dictionaries-entry": "9.3.2",
|
|
80
|
+
"@intlayer/engine": "9.3.2",
|
|
81
|
+
"@intlayer/types": "9.3.2",
|
|
82
|
+
"react-intlayer": "9.3.2",
|
|
83
|
+
"vite-intlayer": "9.3.2"
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
86
|
"@types/node": "26.2.0",
|