@intlayer/core 9.3.0 → 9.3.1
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/cjs/_virtual/_rolldown/runtime.cjs +1 -2
- package/dist/cjs/deepTransformPlugins/getReplacedValuesContent.cjs +2 -1
- package/dist/cjs/deepTransformPlugins/getReplacedValuesContent.cjs.map +1 -1
- package/dist/cjs/deepTransformPlugins/insertContentInDictionary.cjs +41 -32
- package/dist/cjs/deepTransformPlugins/insertContentInDictionary.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/editDictionaryByKeyPath.cjs +6 -5
- package/dist/cjs/dictionaryManipulator/editDictionaryByKeyPath.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/mergeDictionaries.cjs +4 -3
- package/dist/cjs/dictionaryManipulator/mergeDictionaries.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/mergeQualifiedDictionaries.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/qualifiedDictionary.cjs +0 -1
- package/dist/cjs/dictionaryManipulator/qualifiedDictionary.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/qualifiedDictionary.test-d.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/removeContentNodeByKeyPath.cjs +4 -2
- package/dist/cjs/dictionaryManipulator/removeContentNodeByKeyPath.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/renameContentNodeByKeyPath.cjs +11 -9
- package/dist/cjs/dictionaryManipulator/renameContentNodeByKeyPath.cjs.map +1 -1
- package/dist/cjs/formatters/date.cjs +2 -1
- package/dist/cjs/formatters/date.cjs.map +1 -1
- package/dist/cjs/formatters/relativeTime.cjs +3 -3
- package/dist/cjs/formatters/relativeTime.cjs.map +1 -1
- package/dist/cjs/interpreter/getCondition.cjs +0 -1
- package/dist/cjs/interpreter/getCondition.cjs.map +1 -1
- package/dist/cjs/interpreter/getEnumeration.cjs +0 -1
- package/dist/cjs/interpreter/getEnumeration.cjs.map +1 -1
- package/dist/cjs/interpreter/getGender.cjs +0 -1
- package/dist/cjs/interpreter/getGender.cjs.map +1 -1
- package/dist/cjs/interpreter/getHTML.cjs +0 -1
- package/dist/cjs/interpreter/getHTML.cjs.map +1 -1
- package/dist/cjs/interpreter/getInsertion.cjs +0 -1
- package/dist/cjs/interpreter/getInsertion.cjs.map +1 -1
- package/dist/cjs/interpreter/getIntlayer.cjs.map +1 -1
- package/dist/cjs/interpreter/getIntlayer.test-d.cjs.map +1 -1
- package/dist/cjs/interpreter/getSelect.cjs +0 -1
- package/dist/cjs/interpreter/getSelect.cjs.map +1 -1
- package/dist/cjs/interpreter/getTranslation.cjs +0 -1
- package/dist/cjs/interpreter/getTranslation.cjs.map +1 -1
- package/dist/cjs/interpreter/splitAndJoinInsertion.cjs +0 -1
- package/dist/cjs/interpreter/splitAndJoinInsertion.cjs.map +1 -1
- package/dist/cjs/localization/domainUtils.cjs +0 -1
- package/dist/cjs/localization/domainUtils.cjs.map +1 -1
- package/dist/cjs/localization/getBrowserLocale.cjs +2 -1
- package/dist/cjs/localization/getBrowserLocale.cjs.map +1 -1
- package/dist/cjs/localization/getHTMLTextDir.cjs +0 -1
- package/dist/cjs/localization/getHTMLTextDir.cjs.map +1 -1
- package/dist/cjs/localization/getLocale.cjs +2 -1
- package/dist/cjs/localization/getLocale.cjs.map +1 -1
- package/dist/cjs/localization/getLocaleLang.cjs +0 -1
- package/dist/cjs/localization/getLocaleLang.cjs.map +1 -1
- package/dist/cjs/localization/localeDetector.cjs +2 -1
- package/dist/cjs/localization/localeDetector.cjs.map +1 -1
- package/dist/cjs/localization/proxyMode.cjs.map +1 -1
- package/dist/cjs/localization/rewriteUtils.cjs +0 -1
- package/dist/cjs/localization/rewriteUtils.cjs.map +1 -1
- package/dist/cjs/markdown/compiler.cjs +9 -6
- package/dist/cjs/markdown/compiler.cjs.map +1 -1
- package/dist/cjs/markdown/constants.cjs +0 -1
- package/dist/cjs/markdown/constants.cjs.map +1 -1
- package/dist/cjs/markdown/utils.cjs.map +1 -1
- package/dist/cjs/messageFormat/ICU.cjs +17 -14
- package/dist/cjs/messageFormat/ICU.cjs.map +1 -1
- package/dist/cjs/messageFormat/i18next.cjs +4 -2
- package/dist/cjs/messageFormat/i18next.cjs.map +1 -1
- package/dist/cjs/messageFormat/navigatePath.cjs +0 -1
- package/dist/cjs/messageFormat/navigatePath.cjs.map +1 -1
- package/dist/cjs/messageFormat/resolveMessage.cjs +2 -1
- package/dist/cjs/messageFormat/resolveMessage.cjs.map +1 -1
- package/dist/cjs/messageFormat/verify-icu-format.cjs +3 -2
- package/dist/cjs/messageFormat/verify-icu-format.cjs.map +1 -1
- package/dist/cjs/messageFormat/vue-i18n.cjs +2 -1
- package/dist/cjs/messageFormat/vue-i18n.cjs.map +1 -1
- package/dist/cjs/transpiler/condition/condition.cjs.map +1 -1
- package/dist/cjs/transpiler/enumeration/enumeration.cjs.map +1 -1
- package/dist/cjs/transpiler/file/file.cjs +2 -1
- package/dist/cjs/transpiler/file/file.cjs.map +1 -1
- package/dist/cjs/transpiler/file/fileBrowser.cjs +0 -1
- package/dist/cjs/transpiler/file/fileBrowser.cjs.map +1 -1
- package/dist/cjs/transpiler/gender/gender.cjs.map +1 -1
- package/dist/cjs/transpiler/html/getHTMLCustomComponents.cjs +0 -1
- package/dist/cjs/transpiler/html/getHTMLCustomComponents.cjs.map +1 -1
- package/dist/cjs/transpiler/html/html.cjs.map +1 -1
- package/dist/cjs/transpiler/html/htmlTags.cjs +0 -1
- package/dist/cjs/transpiler/html/htmlTags.cjs.map +1 -1
- package/dist/cjs/transpiler/html/validateHTML.cjs +12 -12
- package/dist/cjs/transpiler/html/validateHTML.cjs.map +1 -1
- package/dist/cjs/transpiler/insertion/getInsertionValues.cjs +0 -1
- package/dist/cjs/transpiler/insertion/getInsertionValues.cjs.map +1 -1
- package/dist/cjs/transpiler/insertion/insertion.cjs.map +1 -1
- package/dist/cjs/transpiler/markdown/getMarkdownMetadata.cjs +2 -1
- package/dist/cjs/transpiler/markdown/getMarkdownMetadata.cjs.map +1 -1
- package/dist/cjs/transpiler/markdown/markdown.cjs +2 -1
- package/dist/cjs/transpiler/markdown/markdown.cjs.map +1 -1
- package/dist/cjs/transpiler/markdown/validateMarkdown.cjs +7 -6
- package/dist/cjs/transpiler/markdown/validateMarkdown.cjs.map +1 -1
- package/dist/cjs/transpiler/nesting/nesting.cjs.map +1 -1
- package/dist/cjs/transpiler/plural/plural.cjs.map +1 -1
- package/dist/cjs/transpiler/select/select.cjs.map +1 -1
- package/dist/cjs/transpiler/translation/translation.cjs.map +1 -1
- package/dist/cjs/utils/checkIsURLAbsolute.cjs +0 -1
- package/dist/cjs/utils/checkIsURLAbsolute.cjs.map +1 -1
- package/dist/cjs/utils/cookieExpiry.cjs +0 -1
- package/dist/cjs/utils/cookieExpiry.cjs.map +1 -1
- package/dist/cjs/utils/getCookie.cjs +0 -1
- package/dist/cjs/utils/getCookie.cjs.map +1 -1
- package/dist/cjs/utils/isSameKeyPath.cjs +0 -1
- package/dist/cjs/utils/isSameKeyPath.cjs.map +1 -1
- package/dist/cjs/utils/isValidReactElement.cjs +0 -1
- package/dist/cjs/utils/isValidReactElement.cjs.map +1 -1
- package/dist/cjs/utils/parseYaml.cjs +0 -1
- package/dist/cjs/utils/parseYaml.cjs.map +1 -1
- package/dist/cjs/utils/stringifyYaml.cjs +0 -1
- package/dist/cjs/utils/stringifyYaml.cjs.map +1 -1
- package/dist/esm/deepTransformPlugins/getReplacedValuesContent.mjs +2 -1
- package/dist/esm/deepTransformPlugins/getReplacedValuesContent.mjs.map +1 -1
- package/dist/esm/deepTransformPlugins/insertContentInDictionary.mjs +41 -32
- package/dist/esm/deepTransformPlugins/insertContentInDictionary.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/editDictionaryByKeyPath.mjs +6 -5
- package/dist/esm/dictionaryManipulator/editDictionaryByKeyPath.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/mergeDictionaries.mjs +4 -3
- package/dist/esm/dictionaryManipulator/mergeDictionaries.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/removeContentNodeByKeyPath.mjs +4 -2
- package/dist/esm/dictionaryManipulator/removeContentNodeByKeyPath.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/renameContentNodeByKeyPath.mjs +11 -9
- package/dist/esm/dictionaryManipulator/renameContentNodeByKeyPath.mjs.map +1 -1
- package/dist/esm/formatters/date.mjs +2 -1
- package/dist/esm/formatters/date.mjs.map +1 -1
- package/dist/esm/formatters/relativeTime.mjs +3 -3
- package/dist/esm/formatters/relativeTime.mjs.map +1 -1
- package/dist/esm/localization/getBrowserLocale.mjs +2 -1
- package/dist/esm/localization/getBrowserLocale.mjs.map +1 -1
- package/dist/esm/localization/getLocale.mjs +2 -1
- package/dist/esm/localization/getLocale.mjs.map +1 -1
- package/dist/esm/localization/localeDetector.mjs +2 -1
- package/dist/esm/localization/localeDetector.mjs.map +1 -1
- package/dist/esm/markdown/compiler.mjs +9 -6
- package/dist/esm/markdown/compiler.mjs.map +1 -1
- package/dist/esm/markdown/utils.mjs.map +1 -1
- package/dist/esm/messageFormat/ICU.mjs +17 -14
- package/dist/esm/messageFormat/ICU.mjs.map +1 -1
- package/dist/esm/messageFormat/i18next.mjs +4 -2
- package/dist/esm/messageFormat/i18next.mjs.map +1 -1
- package/dist/esm/messageFormat/resolveMessage.mjs +2 -1
- package/dist/esm/messageFormat/resolveMessage.mjs.map +1 -1
- package/dist/esm/messageFormat/verify-icu-format.mjs +3 -2
- package/dist/esm/messageFormat/verify-icu-format.mjs.map +1 -1
- package/dist/esm/messageFormat/vue-i18n.mjs +2 -1
- package/dist/esm/messageFormat/vue-i18n.mjs.map +1 -1
- package/dist/esm/transpiler/file/file.mjs +2 -1
- package/dist/esm/transpiler/file/file.mjs.map +1 -1
- package/dist/esm/transpiler/html/validateHTML.mjs +12 -11
- package/dist/esm/transpiler/html/validateHTML.mjs.map +1 -1
- package/dist/esm/transpiler/markdown/getMarkdownMetadata.mjs +2 -1
- package/dist/esm/transpiler/markdown/getMarkdownMetadata.mjs.map +1 -1
- package/dist/esm/transpiler/markdown/markdown.mjs +2 -1
- package/dist/esm/transpiler/markdown/markdown.mjs.map +1 -1
- package/dist/esm/transpiler/markdown/validateMarkdown.mjs +7 -6
- package/dist/esm/transpiler/markdown/validateMarkdown.mjs.map +1 -1
- package/dist/esm/utils/parseYaml.mjs.map +1 -1
- package/package.json +6 -6
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>
|
|
@@ -19,11 +19,10 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
19
19
|
}
|
|
20
20
|
return to;
|
|
21
21
|
};
|
|
22
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
23
23
|
value: mod,
|
|
24
24
|
enumerable: true
|
|
25
25
|
}) : target, mod));
|
|
26
26
|
|
|
27
27
|
//#endregion
|
|
28
|
-
|
|
29
28
|
exports.__toESM = __toESM;
|
|
@@ -50,7 +50,8 @@ const getReplacedValuesContent = (node, value, nodeProps) => {
|
|
|
50
50
|
replaceValuesPlugin(value),
|
|
51
51
|
...nodeProps.plugins ?? []
|
|
52
52
|
];
|
|
53
|
-
|
|
53
|
+
const JSONNode = JSON.parse(JSON.stringify(node));
|
|
54
|
+
return require_interpreter_getContent_deepTransform.deepTransformNode(JSONNode, {
|
|
54
55
|
...nodeProps,
|
|
55
56
|
plugins
|
|
56
57
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getReplacedValuesContent.cjs","names":["deepTransformNode"],"sources":["../../../src/deepTransformPlugins/getReplacedValuesContent.ts"],"sourcesContent":["import type { ContentNode, TypedNode } from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport type { NodeType } from '@intlayer/types/nodeType';\nimport {\n deepTransformNode,\n type NodeProps,\n type Plugins,\n} from '../interpreter';\n\nconst replaceValuesPlugin = (value: string | number | boolean): Plugins => ({\n id: 'replace-values-plugin',\n canHandle: (node) =>\n typeof node === 'string' ||\n typeof node === 'number' ||\n typeof node === 'boolean',\n transform: () => value,\n});\n\nconst skipTypedNodePlugin: Plugins = {\n id: 'skip-typed-node-plugin',\n canHandle: (node) =>\n typeof node === 'object' && typeof node?.nodeType === 'string',\n transform: (node: TypedNode, props, deepTransformNode) => {\n const nodeType = node.nodeType as NodeType;\n const result = structuredClone(\n node[nodeType as unknown as keyof TypedNode] as any\n );\n\n // If the result is a primitive value (string, number, boolean),\n // we need to transform it directly instead of iterating over its properties\n if (typeof result !== 'object' || result === null) {\n const transformedResult = deepTransformNode(result, {\n ...props,\n children: result,\n keyPath: [\n ...props.keyPath,\n { type: nodeType, key: nodeType } as KeyPath,\n ],\n });\n return {\n ...node,\n [nodeType as unknown as keyof TypedNode]: transformedResult,\n };\n }\n\n // For objects and arrays, iterate over their properties\n for (const key in result) {\n const childProps = {\n ...props,\n children: result[key as unknown as keyof typeof result],\n keyPath: [...props.keyPath, { type: nodeType, key } as KeyPath],\n };\n result[key as unknown as keyof typeof result] = deepTransformNode(\n result[key as unknown as keyof typeof result],\n childProps\n );\n }\n\n return { ...node, [nodeType as unknown as keyof TypedNode]: result };\n },\n};\n\nexport const getReplacedValuesContent = (\n node: ContentNode,\n value: string | number | boolean,\n nodeProps: NodeProps\n) => {\n const plugins: Plugins[] = [\n skipTypedNodePlugin,\n replaceValuesPlugin(value),\n ...(nodeProps.plugins ?? []),\n ];\n\n const JSONNode = JSON.parse(JSON.stringify(node));\n\n return deepTransformNode(JSONNode, {\n ...nodeProps,\n plugins,\n });\n};\n"],"mappings":";;;;AASA,MAAM,uBAAuB,WAA+C;CAC1E,IAAI;CACJ,YAAY,SACV,OAAO,SAAS,YAChB,OAAO,SAAS,YAChB,OAAO,SAAS;CAClB,iBAAiB;AACnB;AAEA,MAAM,sBAA+B;CACnC,IAAI;CACJ,YAAY,SACV,OAAO,SAAS,YAAY,OAAO,MAAM,aAAa;CACxD,YAAY,MAAiB,OAAO,sBAAsB;EACxD,MAAM,WAAW,KAAK;EACtB,MAAM,SAAS,gBACb,KAAK,SACP;EAIA,IAAI,OAAO,WAAW,YAAY,WAAW,MAAM;GACjD,MAAM,oBAAoB,kBAAkB,QAAQ;IAClD,GAAG;IACH,UAAU;IACV,SAAS,CACP,GAAG,MAAM,SACT;KAAE,MAAM;KAAU,KAAK;IAAS,CAClC;GACF,CAAC;GACD,OAAO;IACL,GAAG;KACF,WAAyC;GAC5C;EACF;EAGA,KAAK,MAAM,OAAO,QAAQ;GACxB,MAAM,aAAa;IACjB,GAAG;IACH,UAAU,OAAO;IACjB,SAAS,CAAC,GAAG,MAAM,SAAS;KAAE,MAAM;KAAU;IAAI,CAAY;GAChE;GACA,OAAO,OAAyC,kBAC9C,OAAO,MACP,UACF;EACF;EAEA,OAAO;GAAE,GAAG;IAAO,WAAyC;EAAO;CACrE;AACF;AAEA,MAAa,4BACX,MACA,OACA,cACG;CACH,MAAM,UAAqB;EACzB;EACA,oBAAoB,KAAK;EACzB,GAAI,UAAU,WAAW,CAAC;CAC5B;
|
|
1
|
+
{"version":3,"file":"getReplacedValuesContent.cjs","names":["deepTransformNode"],"sources":["../../../src/deepTransformPlugins/getReplacedValuesContent.ts"],"sourcesContent":["import type { ContentNode, TypedNode } from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport type { NodeType } from '@intlayer/types/nodeType';\nimport {\n deepTransformNode,\n type NodeProps,\n type Plugins,\n} from '../interpreter';\n\nconst replaceValuesPlugin = (value: string | number | boolean): Plugins => ({\n id: 'replace-values-plugin',\n canHandle: (node) =>\n typeof node === 'string' ||\n typeof node === 'number' ||\n typeof node === 'boolean',\n transform: () => value,\n});\n\nconst skipTypedNodePlugin: Plugins = {\n id: 'skip-typed-node-plugin',\n canHandle: (node) =>\n typeof node === 'object' && typeof node?.nodeType === 'string',\n transform: (node: TypedNode, props, deepTransformNode) => {\n const nodeType = node.nodeType as NodeType;\n const result = structuredClone(\n node[nodeType as unknown as keyof TypedNode] as any\n );\n\n // If the result is a primitive value (string, number, boolean),\n // we need to transform it directly instead of iterating over its properties\n if (typeof result !== 'object' || result === null) {\n const transformedResult = deepTransformNode(result, {\n ...props,\n children: result,\n keyPath: [\n ...props.keyPath,\n { type: nodeType, key: nodeType } as KeyPath,\n ],\n });\n return {\n ...node,\n [nodeType as unknown as keyof TypedNode]: transformedResult,\n };\n }\n\n // For objects and arrays, iterate over their properties\n for (const key in result) {\n const childProps = {\n ...props,\n children: result[key as unknown as keyof typeof result],\n keyPath: [...props.keyPath, { type: nodeType, key } as KeyPath],\n };\n result[key as unknown as keyof typeof result] = deepTransformNode(\n result[key as unknown as keyof typeof result],\n childProps\n );\n }\n\n return { ...node, [nodeType as unknown as keyof TypedNode]: result };\n },\n};\n\nexport const getReplacedValuesContent = (\n node: ContentNode,\n value: string | number | boolean,\n nodeProps: NodeProps\n) => {\n const plugins: Plugins[] = [\n skipTypedNodePlugin,\n replaceValuesPlugin(value),\n ...(nodeProps.plugins ?? []),\n ];\n\n const JSONNode = JSON.parse(JSON.stringify(node));\n\n return deepTransformNode(JSONNode, {\n ...nodeProps,\n plugins,\n });\n};\n"],"mappings":";;;;AASA,MAAM,uBAAuB,WAA+C;CAC1E,IAAI;CACJ,YAAY,SACV,OAAO,SAAS,YAChB,OAAO,SAAS,YAChB,OAAO,SAAS;CAClB,iBAAiB;AACnB;AAEA,MAAM,sBAA+B;CACnC,IAAI;CACJ,YAAY,SACV,OAAO,SAAS,YAAY,OAAO,MAAM,aAAa;CACxD,YAAY,MAAiB,OAAO,sBAAsB;EACxD,MAAM,WAAW,KAAK;EACtB,MAAM,SAAS,gBACb,KAAK,SACP;EAIA,IAAI,OAAO,WAAW,YAAY,WAAW,MAAM;GACjD,MAAM,oBAAoB,kBAAkB,QAAQ;IAClD,GAAG;IACH,UAAU;IACV,SAAS,CACP,GAAG,MAAM,SACT;KAAE,MAAM;KAAU,KAAK;IAAS,CAClC;GACF,CAAC;GACD,OAAO;IACL,GAAG;KACF,WAAyC;GAC5C;EACF;EAGA,KAAK,MAAM,OAAO,QAAQ;GACxB,MAAM,aAAa;IACjB,GAAG;IACH,UAAU,OAAO;IACjB,SAAS,CAAC,GAAG,MAAM,SAAS;KAAE,MAAM;KAAU;IAAI,CAAY;GAChE;GACA,OAAO,OAAyC,kBAC9C,OAAO,MACP,UACF;EACF;EAEA,OAAO;GAAE,GAAG;IAAO,WAAyC;EAAO;CACrE;AACF;AAEA,MAAa,4BACX,MACA,OACA,cACG;CACH,MAAM,UAAqB;EACzB;EACA,oBAAoB,KAAK;EACzB,GAAI,UAAU,WAAW,CAAC;CAC5B;CAEA,MAAM,WAAW,KAAK,MAAM,KAAK,UAAU,IAAI,CAAC;CAEhD,OAAOA,+DAAkB,UAAU;EACjC,GAAG;EACH;CACF,CAAC;AACH"}
|
|
@@ -13,46 +13,55 @@ _intlayer_types_nodeType = require_runtime.__toESM(_intlayer_types_nodeType);
|
|
|
13
13
|
*/
|
|
14
14
|
const deepMergeContent = (target, source, locale) => {
|
|
15
15
|
if (source === null || source === void 0) return target;
|
|
16
|
-
if (target === null || target === void 0)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
if (target === null || target === void 0) {
|
|
17
|
+
if (Array.isArray(source)) target = [];
|
|
18
|
+
else if (typeof source === "object") target = {};
|
|
19
|
+
else return source;
|
|
20
|
+
}
|
|
21
|
+
if (target && typeof target === "object" && target.nodeType === _intlayer_types_nodeType.TRANSLATION) {
|
|
22
|
+
if (locale) {
|
|
23
|
+
const existingLocaleContent = target[_intlayer_types_nodeType.TRANSLATION][locale];
|
|
24
|
+
let newLocaleContent;
|
|
25
|
+
if (typeof source === "object" && !Array.isArray(source)) newLocaleContent = deepMergeContent(existingLocaleContent, source, void 0);
|
|
26
|
+
else if (Array.isArray(source)) newLocaleContent = source;
|
|
27
|
+
else newLocaleContent = source;
|
|
28
|
+
return {
|
|
29
|
+
...target,
|
|
30
|
+
[_intlayer_types_nodeType.TRANSLATION]: {
|
|
31
|
+
...target[_intlayer_types_nodeType.TRANSLATION],
|
|
32
|
+
[locale]: newLocaleContent
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
} else if (typeof source === "object" && !Array.isArray(source) && source.nodeType === _intlayer_types_nodeType.TRANSLATION) return {
|
|
26
36
|
...target,
|
|
27
37
|
[_intlayer_types_nodeType.TRANSLATION]: {
|
|
28
38
|
...target[_intlayer_types_nodeType.TRANSLATION],
|
|
29
|
-
[
|
|
39
|
+
...source[_intlayer_types_nodeType.TRANSLATION]
|
|
30
40
|
}
|
|
31
41
|
};
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
if (item && typeof item === "object" && item.nodeType === _intlayer_types_nodeType.TRANSLATION) return item;
|
|
49
|
-
return processNewContent(item, locale);
|
|
50
|
-
});
|
|
42
|
+
else return processNewContent(source, locale);
|
|
43
|
+
}
|
|
44
|
+
if (Array.isArray(source)) {
|
|
45
|
+
if (locale && Array.isArray(target)) {
|
|
46
|
+
const result = [];
|
|
47
|
+
const maxLength = Math.max(source.length, target.length);
|
|
48
|
+
for (let i = 0; i < maxLength; i++) if (i < source.length) {
|
|
49
|
+
if (i < target.length && target[i] !== void 0) result[i] = deepMergeContent(target[i], source[i], locale);
|
|
50
|
+
else result[i] = processNewContent(source[i], locale);
|
|
51
|
+
} else result[i] = target[i];
|
|
52
|
+
return result;
|
|
53
|
+
} else return source.map((item) => {
|
|
54
|
+
if (item && typeof item === "object" && item.nodeType === _intlayer_types_nodeType.TRANSLATION) return item;
|
|
55
|
+
return processNewContent(item, locale);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
51
58
|
if (typeof source === "object" && !Array.isArray(source)) {
|
|
52
59
|
if (typeof target !== "object" || Array.isArray(target)) target = {};
|
|
53
60
|
const result = { ...target };
|
|
54
|
-
for (const key in source) if (Object.hasOwn(source, key))
|
|
55
|
-
|
|
61
|
+
for (const key in source) if (Object.hasOwn(source, key)) {
|
|
62
|
+
if (target[key] !== void 0) result[key] = deepMergeContent(target[key], source[key], locale);
|
|
63
|
+
else result[key] = processNewContent(source[key], locale);
|
|
64
|
+
}
|
|
56
65
|
return result;
|
|
57
66
|
}
|
|
58
67
|
return source;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insertContentInDictionary.cjs","names":["NodeTypes"],"sources":["../../../src/deepTransformPlugins/insertContentInDictionary.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport * as NodeTypes from '@intlayer/types/nodeType';\n\n// {\n// {\n// title: 'このページ',\n// linkLabel: 'セクションへ移動',\n// collapseButton: { label: '折りたたむ' }\n// },\n// }\n// {\n// dictionary: {\n// key: 'aside-navigation',\n// content: {\n// title: {\n// nodeType: 'translation',\n// translation: {\n// ar: 'في هذه الصفحة',\n// de: 'Auf dieser Seite',\n// en: 'In this page',\n// 'en-GB': 'On this page',\n// es: 'En esta página',\n// fr: 'Dans cette page',\n// hi: 'इस पृष्ठ में',\n// it: 'In questa pagina',\n// ko: '이 페이지에서',\n// pt: 'Nesta página',\n// ru: 'На этой странице',\n// tr: 'Bu sayfada',\n// zh: '在此页面'\n// }\n// },\n// },\n// localId: 'aside-navigation::local::src/components/AsideNavigation/asideNavigation.content.ts',\n// location: 'local',\n// filePath: 'src/components/AsideNavigation/asideNavigation.content.ts'\n// }\n// }\n\n/**\n * Deep merge helper that handles translation blocks\n * @param target - The target object (dictionary content)\n * @param source - The source object (new content to merge)\n * @param locale - Optional locale to target specific translation\n * @returns Merged content\n */\nconst deepMergeContent = (\n target: any,\n source: any,\n locale?: LocalesValues\n): any => {\n // If source is null or undefined, return target\n if (source === null || source === undefined) return target;\n\n // If target is null or undefined, initialize based on source type\n if (target === null || target === undefined) {\n if (Array.isArray(source)) {\n target = [];\n } else if (typeof source === 'object') {\n target = {};\n } else {\n return source;\n }\n }\n\n // Handle translation nodes FIRST (before arrays) to support arrays within translations\n if (\n target &&\n typeof target === 'object' &&\n target.nodeType === NodeTypes.TRANSLATION\n ) {\n // Target is a translation block\n if (locale) {\n // Update only the specific locale - create new object to preserve order\n const existingLocaleContent = target[NodeTypes.TRANSLATION][locale];\n let newLocaleContent: any;\n\n if (typeof source === 'object' && !Array.isArray(source)) {\n // Source is an object, need to deep merge for this locale\n newLocaleContent = deepMergeContent(\n existingLocaleContent,\n source,\n undefined // Don't pass locale down for nested content\n );\n } else if (Array.isArray(source)) {\n // Source is an array, set it directly for this locale\n newLocaleContent = source;\n } else {\n // Source is a primitive, directly set it\n newLocaleContent = source;\n }\n\n // Return new object with locale appended at the end (preserve insertion order)\n return {\n ...target,\n [NodeTypes.TRANSLATION]: {\n ...target[NodeTypes.TRANSLATION],\n [locale]: newLocaleContent,\n },\n };\n } else {\n // No locale specified, replace/merge the entire translation\n if (\n typeof source === 'object' &&\n !Array.isArray(source) &&\n source.nodeType === NodeTypes.TRANSLATION\n ) {\n // Source is also a translation node, merge translations\n return {\n ...target,\n [NodeTypes.TRANSLATION]: {\n ...target[NodeTypes.TRANSLATION],\n ...source[NodeTypes.TRANSLATION],\n },\n };\n } else {\n // Source is not a translation node, wrap it\n return processNewContent(source, locale);\n }\n }\n }\n\n // Handle arrays\n if (Array.isArray(source)) {\n if (locale && Array.isArray(target)) {\n // When locale is specified and target is also an array, merge element by element\n const result = [];\n const maxLength = Math.max(source.length, target.length);\n\n for (let i = 0; i < maxLength; i++) {\n if (i < source.length) {\n if (i < target.length && target[i] !== undefined) {\n // Both source and target have element at this index - merge them\n result[i] = deepMergeContent(target[i], source[i], locale);\n } else {\n // Only source has element at this index - process new content\n result[i] = processNewContent(source[i], locale);\n }\n } else {\n // Only target has element at this index - keep it\n result[i] = target[i];\n }\n }\n\n return result;\n } else {\n // No locale or target is not an array - replace entirely\n return source.map((item) => {\n // Process each item in case it needs locale wrapping\n if (\n item &&\n typeof item === 'object' &&\n item.nodeType === NodeTypes.TRANSLATION\n ) {\n return item;\n }\n return processNewContent(item, locale);\n });\n }\n }\n\n // Handle objects\n if (typeof source === 'object' && !Array.isArray(source)) {\n if (typeof target !== 'object' || Array.isArray(target)) {\n target = {};\n }\n\n // Create new object to preserve key order and avoid mutation\n const result: any = { ...target };\n\n for (const key in source) {\n if (Object.hasOwn(source, key)) {\n if (target[key] !== undefined) {\n result[key] = deepMergeContent(target[key], source[key], locale);\n } else {\n result[key] = processNewContent(source[key], locale);\n }\n }\n }\n\n return result;\n }\n\n // For primitives, just return the source\n return source;\n};\n\n/**\n * Process new content that doesn't exist in target\n * @param content - New content to process\n * @param locale - Optional locale\n * @returns Processed content\n */\nconst processNewContent = (content: any, locale?: LocalesValues): any => {\n // Handle null and undefined\n if (content === null || content === undefined) {\n return content;\n }\n\n // If content is already a translation node, return as-is\n if (\n content &&\n typeof content === 'object' &&\n content.nodeType === NodeTypes.TRANSLATION\n ) {\n return content;\n }\n\n // Handle arrays\n if (Array.isArray(content)) {\n return content.map((item) => processNewContent(item, locale));\n }\n\n // Handle objects\n if (content && typeof content === 'object') {\n const result: any = {};\n\n for (const key in content) {\n if (Object.hasOwn(content, key)) {\n result[key] = processNewContent(content[key], locale);\n }\n }\n return result;\n }\n\n // Handle primitives\n if (locale) {\n // Wrap in translation node with the specific locale\n return {\n nodeType: NodeTypes.TRANSLATION,\n [NodeTypes.TRANSLATION]: {\n [locale]: content,\n },\n };\n } else {\n // If no locale, just return the content as-is (don't wrap)\n return content;\n }\n};\n\n/**\n * Insert content into a dictionary with deep merge support\n * Handles translation blocks and nested structures\n *\n * @param dictionary - The dictionary to insert content into\n * @param content - The content to insert\n * @param locale - Optional locale to target specific translation\n * @returns Updated dictionary\n *\n * @example\n * // Without locale - deep merge all content\n * insertContentInDictionary(dictionary, { title: 'New Title' })\n *\n * @example\n * // With locale - insert content for specific locale\n * insertContentInDictionary(dictionary, { title: 'このページ' }, 'ja')\n */\nexport const insertContentInDictionary = (\n dictionary: Dictionary,\n content: Dictionary['content'],\n locale?: LocalesValues\n): Dictionary => {\n const mergedContent = deepMergeContent(\n Array.isArray(dictionary.content)\n ? [...dictionary.content]\n : { ...dictionary.content },\n content,\n locale\n );\n\n return {\n ...dictionary,\n content: mergedContent,\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"insertContentInDictionary.cjs","names":["NodeTypes"],"sources":["../../../src/deepTransformPlugins/insertContentInDictionary.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport * as NodeTypes from '@intlayer/types/nodeType';\n\n// {\n// {\n// title: 'このページ',\n// linkLabel: 'セクションへ移動',\n// collapseButton: { label: '折りたたむ' }\n// },\n// }\n// {\n// dictionary: {\n// key: 'aside-navigation',\n// content: {\n// title: {\n// nodeType: 'translation',\n// translation: {\n// ar: 'في هذه الصفحة',\n// de: 'Auf dieser Seite',\n// en: 'In this page',\n// 'en-GB': 'On this page',\n// es: 'En esta página',\n// fr: 'Dans cette page',\n// hi: 'इस पृष्ठ में',\n// it: 'In questa pagina',\n// ko: '이 페이지에서',\n// pt: 'Nesta página',\n// ru: 'На этой странице',\n// tr: 'Bu sayfada',\n// zh: '在此页面'\n// }\n// },\n// },\n// localId: 'aside-navigation::local::src/components/AsideNavigation/asideNavigation.content.ts',\n// location: 'local',\n// filePath: 'src/components/AsideNavigation/asideNavigation.content.ts'\n// }\n// }\n\n/**\n * Deep merge helper that handles translation blocks\n * @param target - The target object (dictionary content)\n * @param source - The source object (new content to merge)\n * @param locale - Optional locale to target specific translation\n * @returns Merged content\n */\nconst deepMergeContent = (\n target: any,\n source: any,\n locale?: LocalesValues\n): any => {\n // If source is null or undefined, return target\n if (source === null || source === undefined) return target;\n\n // If target is null or undefined, initialize based on source type\n if (target === null || target === undefined) {\n if (Array.isArray(source)) {\n target = [];\n } else if (typeof source === 'object') {\n target = {};\n } else {\n return source;\n }\n }\n\n // Handle translation nodes FIRST (before arrays) to support arrays within translations\n if (\n target &&\n typeof target === 'object' &&\n target.nodeType === NodeTypes.TRANSLATION\n ) {\n // Target is a translation block\n if (locale) {\n // Update only the specific locale - create new object to preserve order\n const existingLocaleContent = target[NodeTypes.TRANSLATION][locale];\n let newLocaleContent: any;\n\n if (typeof source === 'object' && !Array.isArray(source)) {\n // Source is an object, need to deep merge for this locale\n newLocaleContent = deepMergeContent(\n existingLocaleContent,\n source,\n undefined // Don't pass locale down for nested content\n );\n } else if (Array.isArray(source)) {\n // Source is an array, set it directly for this locale\n newLocaleContent = source;\n } else {\n // Source is a primitive, directly set it\n newLocaleContent = source;\n }\n\n // Return new object with locale appended at the end (preserve insertion order)\n return {\n ...target,\n [NodeTypes.TRANSLATION]: {\n ...target[NodeTypes.TRANSLATION],\n [locale]: newLocaleContent,\n },\n };\n } else {\n // No locale specified, replace/merge the entire translation\n if (\n typeof source === 'object' &&\n !Array.isArray(source) &&\n source.nodeType === NodeTypes.TRANSLATION\n ) {\n // Source is also a translation node, merge translations\n return {\n ...target,\n [NodeTypes.TRANSLATION]: {\n ...target[NodeTypes.TRANSLATION],\n ...source[NodeTypes.TRANSLATION],\n },\n };\n } else {\n // Source is not a translation node, wrap it\n return processNewContent(source, locale);\n }\n }\n }\n\n // Handle arrays\n if (Array.isArray(source)) {\n if (locale && Array.isArray(target)) {\n // When locale is specified and target is also an array, merge element by element\n const result = [];\n const maxLength = Math.max(source.length, target.length);\n\n for (let i = 0; i < maxLength; i++) {\n if (i < source.length) {\n if (i < target.length && target[i] !== undefined) {\n // Both source and target have element at this index - merge them\n result[i] = deepMergeContent(target[i], source[i], locale);\n } else {\n // Only source has element at this index - process new content\n result[i] = processNewContent(source[i], locale);\n }\n } else {\n // Only target has element at this index - keep it\n result[i] = target[i];\n }\n }\n\n return result;\n } else {\n // No locale or target is not an array - replace entirely\n return source.map((item) => {\n // Process each item in case it needs locale wrapping\n if (\n item &&\n typeof item === 'object' &&\n item.nodeType === NodeTypes.TRANSLATION\n ) {\n return item;\n }\n return processNewContent(item, locale);\n });\n }\n }\n\n // Handle objects\n if (typeof source === 'object' && !Array.isArray(source)) {\n if (typeof target !== 'object' || Array.isArray(target)) {\n target = {};\n }\n\n // Create new object to preserve key order and avoid mutation\n const result: any = { ...target };\n\n for (const key in source) {\n if (Object.hasOwn(source, key)) {\n if (target[key] !== undefined) {\n result[key] = deepMergeContent(target[key], source[key], locale);\n } else {\n result[key] = processNewContent(source[key], locale);\n }\n }\n }\n\n return result;\n }\n\n // For primitives, just return the source\n return source;\n};\n\n/**\n * Process new content that doesn't exist in target\n * @param content - New content to process\n * @param locale - Optional locale\n * @returns Processed content\n */\nconst processNewContent = (content: any, locale?: LocalesValues): any => {\n // Handle null and undefined\n if (content === null || content === undefined) {\n return content;\n }\n\n // If content is already a translation node, return as-is\n if (\n content &&\n typeof content === 'object' &&\n content.nodeType === NodeTypes.TRANSLATION\n ) {\n return content;\n }\n\n // Handle arrays\n if (Array.isArray(content)) {\n return content.map((item) => processNewContent(item, locale));\n }\n\n // Handle objects\n if (content && typeof content === 'object') {\n const result: any = {};\n\n for (const key in content) {\n if (Object.hasOwn(content, key)) {\n result[key] = processNewContent(content[key], locale);\n }\n }\n return result;\n }\n\n // Handle primitives\n if (locale) {\n // Wrap in translation node with the specific locale\n return {\n nodeType: NodeTypes.TRANSLATION,\n [NodeTypes.TRANSLATION]: {\n [locale]: content,\n },\n };\n } else {\n // If no locale, just return the content as-is (don't wrap)\n return content;\n }\n};\n\n/**\n * Insert content into a dictionary with deep merge support\n * Handles translation blocks and nested structures\n *\n * @param dictionary - The dictionary to insert content into\n * @param content - The content to insert\n * @param locale - Optional locale to target specific translation\n * @returns Updated dictionary\n *\n * @example\n * // Without locale - deep merge all content\n * insertContentInDictionary(dictionary, { title: 'New Title' })\n *\n * @example\n * // With locale - insert content for specific locale\n * insertContentInDictionary(dictionary, { title: 'このページ' }, 'ja')\n */\nexport const insertContentInDictionary = (\n dictionary: Dictionary,\n content: Dictionary['content'],\n locale?: LocalesValues\n): Dictionary => {\n const mergedContent = deepMergeContent(\n Array.isArray(dictionary.content)\n ? [...dictionary.content]\n : { ...dictionary.content },\n content,\n locale\n );\n\n return {\n ...dictionary,\n content: mergedContent,\n };\n};\n"],"mappings":"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"}
|
|
@@ -43,11 +43,12 @@ const editDictionaryByKeyPath = (dictionaryContent, keyPath, newValue) => {
|
|
|
43
43
|
let target = parentValue;
|
|
44
44
|
for (const key of lastKeys.slice(0, -1)) target = target[key];
|
|
45
45
|
const finalKey = lastKeys[lastKeys.length - 1];
|
|
46
|
-
if (typeof newValue === "undefined")
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
if (typeof newValue === "undefined") {
|
|
47
|
+
if (Array.isArray(target)) {
|
|
48
|
+
const index = Number(finalKey);
|
|
49
|
+
if (!Number.isNaN(index) && index >= 0 && index < target.length) target.splice(index, 1);
|
|
50
|
+
} else delete target[finalKey];
|
|
51
|
+
} else target[finalKey] = newValue;
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
return dictionaryContent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editDictionaryByKeyPath.cjs","names":["NodeTypes"],"sources":["../../../src/dictionaryManipulator/editDictionaryByKeyPath.ts"],"sourcesContent":["import type { ContentNode } from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport * as NodeTypes from '@intlayer/types/nodeType';\n\ntype LastKeyType = string | number;\n\nexport const editDictionaryByKeyPath = (\n dictionaryContent: ContentNode,\n keyPath: KeyPath[],\n newValue: ContentNode\n): ContentNode => {\n let currentValue: any = dictionaryContent;\n let parentValue: any = null;\n let lastKeys: LastKeyType[] = [];\n\n if (keyPath.length === 0) {\n return newValue;\n }\n\n try {\n for (let i = 0; i < keyPath.length; i++) {\n const keyObj = keyPath[i];\n parentValue = currentValue;\n\n if (\n keyObj?.type === NodeTypes.OBJECT ||\n keyObj?.type === NodeTypes.ARRAY\n ) {\n lastKeys = [keyObj.key];\n\n if (\n !currentValue[keyObj.key] ||\n typeof currentValue[keyObj.key] !== 'object'\n ) {\n currentValue[keyObj.key] = {};\n }\n currentValue = currentValue[keyObj.key];\n }\n\n if (\n keyObj?.type === NodeTypes.TRANSLATION ||\n keyObj?.type === NodeTypes.ENUMERATION ||\n keyObj?.type === NodeTypes.PLURAL ||\n keyObj?.type === NodeTypes.GENDER ||\n keyObj?.type === NodeTypes.SELECT\n ) {\n lastKeys = [keyObj.type, keyObj.key];\n\n if (\n !currentValue[keyObj.type] ||\n typeof currentValue[keyObj.type] !== 'object'\n ) {\n currentValue[keyObj.type] = {};\n }\n\n if (\n !currentValue[keyObj.type][keyObj.key] ||\n typeof currentValue[keyObj.type][keyObj.key] !== 'object'\n ) {\n currentValue[keyObj.type][keyObj.key] = {};\n }\n currentValue = currentValue[keyObj.type][keyObj.key];\n }\n\n if (\n keyObj?.type === NodeTypes.ENUMERATION ||\n keyObj?.type === NodeTypes.PLURAL ||\n keyObj?.type === NodeTypes.CONDITION\n ) {\n // Note: Logic above already handles Enumeration/Plural, ensure no duplication in your actual file\n // or keep the specific block if your logic differs.\n // The important part is below in the final update block.\n\n // Assuming this block runs for Condition/Gender/etc:\n\n if (\n keyObj.type !== NodeTypes.ENUMERATION &&\n keyObj.type !== NodeTypes.PLURAL\n ) {\n lastKeys = [keyObj.type, keyObj.key];\n currentValue = currentValue[keyObj.type][keyObj.key];\n }\n }\n\n if (\n keyObj?.type === NodeTypes.MARKDOWN ||\n keyObj?.type === NodeTypes.HTML ||\n keyObj?.type === NodeTypes.INSERTION\n ) {\n lastKeys = [keyObj.type];\n\n if (currentValue[keyObj.type] == null) {\n currentValue[keyObj.type] = '';\n }\n currentValue = currentValue[keyObj.type];\n }\n\n if (keyObj?.type === NodeTypes.FILE) {\n lastKeys = ['content'];\n currentValue = currentValue.content;\n }\n\n // Only update the value when processing the last key in the keyPath.\n\n if (i === keyPath.length - 1 && parentValue && lastKeys.length > 0) {\n let target = parentValue;\n\n // Drill down to the container holding the value to be changed\n for (const key of lastKeys.slice(0, -1)) {\n target = target[key];\n }\n\n const finalKey = lastKeys[lastKeys.length - 1];\n\n if (typeof newValue === 'undefined') {\n // Use splice for arrays to re-index the list, use delete for objects\n\n if (Array.isArray(target)) {\n const index = Number(finalKey);\n\n if (!Number.isNaN(index) && index >= 0 && index < target.length) {\n target.splice(index, 1);\n }\n } else {\n delete target[finalKey];\n }\n } else {\n target[finalKey] = newValue;\n }\n }\n }\n\n return dictionaryContent;\n } catch (error) {\n console.error(\n 'Cannot edit dictionary by key path',\n { dictionaryContent, keyPath, newValue },\n error\n );\n return dictionaryContent;\n }\n};\n"],"mappings":";;;;;;AAMA,MAAa,2BACX,mBACA,SACA,aACgB;CAChB,IAAI,eAAoB;CACxB,IAAI,cAAmB;CACvB,IAAI,WAA0B,CAAC;CAE/B,IAAI,QAAQ,WAAW,GACrB,OAAO;CAGT,IAAI;EACF,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;GACvC,MAAM,SAAS,QAAQ;GACvB,cAAc;GAEd,IACE,QAAQ,SAASA,yBAAU,UAC3B,QAAQ,SAASA,yBAAU,OAC3B;IACA,WAAW,CAAC,OAAO,GAAG;IAEtB,IACE,CAAC,aAAa,OAAO,QACrB,OAAO,aAAa,OAAO,SAAS,UAEpC,aAAa,OAAO,OAAO,CAAC;IAE9B,eAAe,aAAa,OAAO;GACrC;GAEA,IACE,QAAQ,SAASA,yBAAU,eAC3B,QAAQ,SAASA,yBAAU,eAC3B,QAAQ,SAASA,yBAAU,UAC3B,QAAQ,SAASA,yBAAU,UAC3B,QAAQ,SAASA,yBAAU,QAC3B;IACA,WAAW,CAAC,OAAO,MAAM,OAAO,GAAG;IAEnC,IACE,CAAC,aAAa,OAAO,SACrB,OAAO,aAAa,OAAO,UAAU,UAErC,aAAa,OAAO,QAAQ,CAAC;IAG/B,IACE,CAAC,aAAa,OAAO,KAAK,CAAC,OAAO,QAClC,OAAO,aAAa,OAAO,KAAK,CAAC,OAAO,SAAS,UAEjD,aAAa,OAAO,KAAK,CAAC,OAAO,OAAO,CAAC;IAE3C,eAAe,aAAa,OAAO,KAAK,CAAC,OAAO;GAClD;GAEA,IACE,QAAQ,SAASA,yBAAU,eAC3B,QAAQ,SAASA,yBAAU,UAC3B,QAAQ,SAASA,yBAAU,WAQ3B;QACE,OAAO,SAASA,yBAAU,eAC1B,OAAO,SAASA,yBAAU,QAC1B;KACA,WAAW,CAAC,OAAO,MAAM,OAAO,GAAG;KACnC,eAAe,aAAa,OAAO,KAAK,CAAC,OAAO;IAClD;;GAGF,IACE,QAAQ,SAASA,yBAAU,YAC3B,QAAQ,SAASA,yBAAU,QAC3B,QAAQ,SAASA,yBAAU,WAC3B;IACA,WAAW,CAAC,OAAO,IAAI;IAEvB,IAAI,aAAa,OAAO,SAAS,MAC/B,aAAa,OAAO,QAAQ;IAE9B,eAAe,aAAa,OAAO;GACrC;GAEA,IAAI,QAAQ,SAASA,yBAAU,MAAM;IACnC,WAAW,CAAC,SAAS;IACrB,eAAe,aAAa;GAC9B;GAIA,IAAI,MAAM,QAAQ,SAAS,KAAK,eAAe,SAAS,SAAS,GAAG;IAClE,IAAI,SAAS;IAGb,KAAK,MAAM,OAAO,SAAS,MAAM,GAAG,EAAE,GACpC,SAAS,OAAO;IAGlB,MAAM,WAAW,SAAS,SAAS,SAAS;IAE5C,IAAI,OAAO,aAAa,
|
|
1
|
+
{"version":3,"file":"editDictionaryByKeyPath.cjs","names":["NodeTypes"],"sources":["../../../src/dictionaryManipulator/editDictionaryByKeyPath.ts"],"sourcesContent":["import type { ContentNode } from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport * as NodeTypes from '@intlayer/types/nodeType';\n\ntype LastKeyType = string | number;\n\nexport const editDictionaryByKeyPath = (\n dictionaryContent: ContentNode,\n keyPath: KeyPath[],\n newValue: ContentNode\n): ContentNode => {\n let currentValue: any = dictionaryContent;\n let parentValue: any = null;\n let lastKeys: LastKeyType[] = [];\n\n if (keyPath.length === 0) {\n return newValue;\n }\n\n try {\n for (let i = 0; i < keyPath.length; i++) {\n const keyObj = keyPath[i];\n parentValue = currentValue;\n\n if (\n keyObj?.type === NodeTypes.OBJECT ||\n keyObj?.type === NodeTypes.ARRAY\n ) {\n lastKeys = [keyObj.key];\n\n if (\n !currentValue[keyObj.key] ||\n typeof currentValue[keyObj.key] !== 'object'\n ) {\n currentValue[keyObj.key] = {};\n }\n currentValue = currentValue[keyObj.key];\n }\n\n if (\n keyObj?.type === NodeTypes.TRANSLATION ||\n keyObj?.type === NodeTypes.ENUMERATION ||\n keyObj?.type === NodeTypes.PLURAL ||\n keyObj?.type === NodeTypes.GENDER ||\n keyObj?.type === NodeTypes.SELECT\n ) {\n lastKeys = [keyObj.type, keyObj.key];\n\n if (\n !currentValue[keyObj.type] ||\n typeof currentValue[keyObj.type] !== 'object'\n ) {\n currentValue[keyObj.type] = {};\n }\n\n if (\n !currentValue[keyObj.type][keyObj.key] ||\n typeof currentValue[keyObj.type][keyObj.key] !== 'object'\n ) {\n currentValue[keyObj.type][keyObj.key] = {};\n }\n currentValue = currentValue[keyObj.type][keyObj.key];\n }\n\n if (\n keyObj?.type === NodeTypes.ENUMERATION ||\n keyObj?.type === NodeTypes.PLURAL ||\n keyObj?.type === NodeTypes.CONDITION\n ) {\n // Note: Logic above already handles Enumeration/Plural, ensure no duplication in your actual file\n // or keep the specific block if your logic differs.\n // The important part is below in the final update block.\n\n // Assuming this block runs for Condition/Gender/etc:\n\n if (\n keyObj.type !== NodeTypes.ENUMERATION &&\n keyObj.type !== NodeTypes.PLURAL\n ) {\n lastKeys = [keyObj.type, keyObj.key];\n currentValue = currentValue[keyObj.type][keyObj.key];\n }\n }\n\n if (\n keyObj?.type === NodeTypes.MARKDOWN ||\n keyObj?.type === NodeTypes.HTML ||\n keyObj?.type === NodeTypes.INSERTION\n ) {\n lastKeys = [keyObj.type];\n\n if (currentValue[keyObj.type] == null) {\n currentValue[keyObj.type] = '';\n }\n currentValue = currentValue[keyObj.type];\n }\n\n if (keyObj?.type === NodeTypes.FILE) {\n lastKeys = ['content'];\n currentValue = currentValue.content;\n }\n\n // Only update the value when processing the last key in the keyPath.\n\n if (i === keyPath.length - 1 && parentValue && lastKeys.length > 0) {\n let target = parentValue;\n\n // Drill down to the container holding the value to be changed\n for (const key of lastKeys.slice(0, -1)) {\n target = target[key];\n }\n\n const finalKey = lastKeys[lastKeys.length - 1];\n\n if (typeof newValue === 'undefined') {\n // Use splice for arrays to re-index the list, use delete for objects\n\n if (Array.isArray(target)) {\n const index = Number(finalKey);\n\n if (!Number.isNaN(index) && index >= 0 && index < target.length) {\n target.splice(index, 1);\n }\n } else {\n delete target[finalKey];\n }\n } else {\n target[finalKey] = newValue;\n }\n }\n }\n\n return dictionaryContent;\n } catch (error) {\n console.error(\n 'Cannot edit dictionary by key path',\n { dictionaryContent, keyPath, newValue },\n error\n );\n return dictionaryContent;\n }\n};\n"],"mappings":";;;;;;AAMA,MAAa,2BACX,mBACA,SACA,aACgB;CAChB,IAAI,eAAoB;CACxB,IAAI,cAAmB;CACvB,IAAI,WAA0B,CAAC;CAE/B,IAAI,QAAQ,WAAW,GACrB,OAAO;CAGT,IAAI;EACF,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;GACvC,MAAM,SAAS,QAAQ;GACvB,cAAc;GAEd,IACE,QAAQ,SAASA,yBAAU,UAC3B,QAAQ,SAASA,yBAAU,OAC3B;IACA,WAAW,CAAC,OAAO,GAAG;IAEtB,IACE,CAAC,aAAa,OAAO,QACrB,OAAO,aAAa,OAAO,SAAS,UAEpC,aAAa,OAAO,OAAO,CAAC;IAE9B,eAAe,aAAa,OAAO;GACrC;GAEA,IACE,QAAQ,SAASA,yBAAU,eAC3B,QAAQ,SAASA,yBAAU,eAC3B,QAAQ,SAASA,yBAAU,UAC3B,QAAQ,SAASA,yBAAU,UAC3B,QAAQ,SAASA,yBAAU,QAC3B;IACA,WAAW,CAAC,OAAO,MAAM,OAAO,GAAG;IAEnC,IACE,CAAC,aAAa,OAAO,SACrB,OAAO,aAAa,OAAO,UAAU,UAErC,aAAa,OAAO,QAAQ,CAAC;IAG/B,IACE,CAAC,aAAa,OAAO,KAAK,CAAC,OAAO,QAClC,OAAO,aAAa,OAAO,KAAK,CAAC,OAAO,SAAS,UAEjD,aAAa,OAAO,KAAK,CAAC,OAAO,OAAO,CAAC;IAE3C,eAAe,aAAa,OAAO,KAAK,CAAC,OAAO;GAClD;GAEA,IACE,QAAQ,SAASA,yBAAU,eAC3B,QAAQ,SAASA,yBAAU,UAC3B,QAAQ,SAASA,yBAAU,WAQ3B;QACE,OAAO,SAASA,yBAAU,eAC1B,OAAO,SAASA,yBAAU,QAC1B;KACA,WAAW,CAAC,OAAO,MAAM,OAAO,GAAG;KACnC,eAAe,aAAa,OAAO,KAAK,CAAC,OAAO;IAClD;;GAGF,IACE,QAAQ,SAASA,yBAAU,YAC3B,QAAQ,SAASA,yBAAU,QAC3B,QAAQ,SAASA,yBAAU,WAC3B;IACA,WAAW,CAAC,OAAO,IAAI;IAEvB,IAAI,aAAa,OAAO,SAAS,MAC/B,aAAa,OAAO,QAAQ;IAE9B,eAAe,aAAa,OAAO;GACrC;GAEA,IAAI,QAAQ,SAASA,yBAAU,MAAM;IACnC,WAAW,CAAC,SAAS;IACrB,eAAe,aAAa;GAC9B;GAIA,IAAI,MAAM,QAAQ,SAAS,KAAK,eAAe,SAAS,SAAS,GAAG;IAClE,IAAI,SAAS;IAGb,KAAK,MAAM,OAAO,SAAS,MAAM,GAAG,EAAE,GACpC,SAAS,OAAO;IAGlB,MAAM,WAAW,SAAS,SAAS,SAAS;IAE5C,IAAI,OAAO,aAAa,aAAa;KAGnC,IAAI,MAAM,QAAQ,MAAM,GAAG;MACzB,MAAM,QAAQ,OAAO,QAAQ;MAE7B,IAAI,CAAC,OAAO,MAAM,KAAK,KAAK,SAAS,KAAK,QAAQ,OAAO,QACvD,OAAO,OAAO,OAAO,CAAC;KAE1B,OACE,OAAO,OAAO;IAElB,OACE,OAAO,YAAY;GAEvB;EACF;EAEA,OAAO;CACT,SAAS,OAAO;EACd,QAAQ,MACN,sCACA;GAAE;GAAmB;GAAS;EAAS,GACvC,KACF;EACA,OAAO;CACT;AACF"}
|
|
@@ -40,9 +40,10 @@ const arrayMerge = (destinationArray, sourceArray) => {
|
|
|
40
40
|
const sourceItem = sourceArray[i];
|
|
41
41
|
if (destItem === void 0 && sourceItem === void 0) {} else if (destItem === void 0) result.push(sourceItem);
|
|
42
42
|
else if (sourceItem === void 0) result.push(destItem);
|
|
43
|
-
else if (typeof destItem === "object" && typeof sourceItem === "object" && destItem !== null && sourceItem !== null)
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
else if (typeof destItem === "object" && typeof sourceItem === "object" && destItem !== null && sourceItem !== null) {
|
|
44
|
+
if ("key" in destItem && "key" in sourceItem && destItem.key === sourceItem.key) result.push(customMerge(destItem, sourceItem));
|
|
45
|
+
else result.push(customMerge(destItem, sourceItem));
|
|
46
|
+
} else result.push(destItem);
|
|
46
47
|
}
|
|
47
48
|
return result;
|
|
48
49
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeDictionaries.cjs","names":["getNodeType","getMultilingualDictionary"],"sources":["../../../src/dictionaryManipulator/mergeDictionaries.ts"],"sourcesContent":["import { log } from '@intlayer/config/built';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport type {\n ContentNode,\n Dictionary,\n LocalDictionaryId,\n} from '@intlayer/types/dictionary';\nimport { getMultilingualDictionary } from '../deepTransformPlugins';\nimport { getNodeType } from './getNodeType';\n\n// Extended type that includes arrays for internal merge operations\ntype MergeableContent = ContentNode | ContentNode[];\n\nconst checkTypesMatch = (\n object1: ContentNode,\n object2: ContentNode,\n object2LocalId: LocalDictionaryId | undefined,\n dictionaryKey: string,\n path: string[] = []\n): void => {\n const appLogger = getAppLogger({ log });\n\n // If either side is missing/undefined, allow merge without error\n if (\n object1 === undefined ||\n object1 === null ||\n object2 === undefined ||\n object2 === null\n )\n return;\n\n const type1 = getNodeType(object1);\n const type2 = getNodeType(object2);\n\n // Unknown types are treated as flexible; skip strict mismatch reporting\n if (type1 === 'unknown' || type2 === 'unknown') return;\n\n if (type1 !== type2) {\n appLogger(\n [\n `Error: Dictionary ${colorizeKey(dictionaryKey)} has a multiple content files with type mismatch at path \"${path.join('.')}\": Cannot merge ${type1} with ${type2} while merging ${object2LocalId}`,\n ],\n {\n level: 'error',\n }\n );\n\n return;\n }\n};\n\n// Custom merge function that prefers destination (first dictionary) values\nconst customMerge = (\n destination: ContentNode,\n source: ContentNode\n): MergeableContent => {\n // If destination is undefined/null, use source\n if (destination === undefined || destination === null) {\n return source;\n }\n\n // If source is undefined/null, use destination\n if (source === undefined || source === null) {\n return destination;\n }\n\n // For primitive values, prefer destination (first dictionary)\n if (typeof destination !== 'object' || typeof source !== 'object') {\n return destination;\n }\n\n // For arrays, use our custom array merge\n if (Array.isArray(destination) && Array.isArray(source)) {\n return arrayMerge(\n destination as ContentNode[],\n source as ContentNode[]\n ) as MergeableContent;\n }\n\n // For objects, recursively merge with our custom logic\n if (typeof destination === 'object' && typeof source === 'object') {\n const result: Record<string, MergeableContent> = {};\n const allKeys = new Set([\n ...Object.keys(destination as unknown as Record<string, ContentNode>),\n ...Object.keys(source as unknown as Record<string, ContentNode>),\n ]);\n\n for (const key of allKeys) {\n result[key] = customMerge(\n (destination as unknown as Record<string, ContentNode>)[key],\n (source as unknown as Record<string, ContentNode>)[key]\n );\n }\n\n return result as unknown as MergeableContent;\n }\n\n // Fallback to destination\n return destination;\n};\n\n// Custom array merge strategy that merges arrays by key when present, otherwise by index\nconst arrayMerge = (\n destinationArray: ContentNode[],\n sourceArray: ContentNode[]\n): MergeableContent[] => {\n // Check if both arrays contain only primitives\n const destHasOnlyPrimitives = destinationArray.every(\n (item) => typeof item !== 'object' || item === null\n );\n const sourceHasOnlyPrimitives = sourceArray.every(\n (item) => typeof item !== 'object' || item === null\n );\n\n // If both arrays contain only primitives, use the source array (second dictionary)\n if (destHasOnlyPrimitives && sourceHasOnlyPrimitives) {\n return sourceArray;\n }\n\n // Otherwise, merge by index with object merging logic\n const result: MergeableContent[] = [];\n const maxLength = Math.max(destinationArray.length, sourceArray.length);\n\n for (let i = 0; i < maxLength; i++) {\n const destItem = destinationArray[i];\n const sourceItem = sourceArray[i];\n\n if (destItem === undefined && sourceItem === undefined) {\n } else if (destItem === undefined) {\n // Only source exists, add it\n result.push(sourceItem);\n } else if (sourceItem === undefined) {\n // Only destination exists, add it\n result.push(destItem);\n } else {\n // Both exist, merge them\n if (\n typeof destItem === 'object' &&\n typeof sourceItem === 'object' &&\n destItem !== null &&\n sourceItem !== null\n ) {\n // Check if both objects have a 'key' property for keyed merging\n if (\n 'key' in destItem &&\n 'key' in sourceItem &&\n (destItem as Record<string, string>).key ===\n (sourceItem as Record<string, string>).key\n ) {\n // Merge objects with same key, preferring destination (first dictionary) values\n result.push(customMerge(destItem, sourceItem));\n } else {\n // Merge objects by index, preferring destination (first dictionary) values\n result.push(customMerge(destItem, sourceItem));\n }\n } else {\n // For primitives or non-objects, use destination value (first dictionary)\n result.push(destItem);\n }\n }\n }\n\n return result;\n};\n\nexport const mergeDictionaries = (dictionaries: Dictionary[]): Dictionary => {\n const localIds = Array.from(\n new Set<LocalDictionaryId>(\n dictionaries.filter((dict) => dict.localId).map((dict) => dict.localId!)\n )\n );\n\n if (!dictionaries[0] || dictionaries.length <= 1) {\n return dictionaries[0]!;\n }\n\n const dictionariesKeys = dictionaries.map((dict) => dict.key);\n\n // Check if all dictionaries have the same key\n if (new Set(dictionariesKeys).size !== 1) {\n throw new Error('All dictionaries must have the same key');\n }\n\n let mergedContent: Dictionary['content'] = dictionaries[0].content;\n\n for (let i = 1; i < dictionaries.length; i++) {\n const dict = dictionaries[i];\n\n if (!dict) continue;\n\n // If the dictionary is a per-locale dictionary, transform it to a partial multilingual dictionary\n const currentDictionary = getMultilingualDictionary(dict);\n\n // Check types before merging\n checkTypesMatch(\n mergedContent,\n currentDictionary.content,\n currentDictionary.localId,\n currentDictionary.key,\n []\n );\n\n mergedContent = customMerge(\n mergedContent,\n currentDictionary.content\n ) as ContentNode;\n }\n\n const mergedDictionary: Dictionary = {\n key: dictionaries[0].key,\n content: mergedContent,\n localIds,\n };\n\n return mergedDictionary;\n};\n"],"mappings":";;;;;;;AAaA,MAAM,mBACJ,SACA,SACA,gBACA,eACA,OAAiB,CAAC,MACT;CACT,MAAM,
|
|
1
|
+
{"version":3,"file":"mergeDictionaries.cjs","names":["getAppLogger","getNodeType","colorizeKey","getMultilingualDictionary"],"sources":["../../../src/dictionaryManipulator/mergeDictionaries.ts"],"sourcesContent":["import { log } from '@intlayer/config/built';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport type {\n ContentNode,\n Dictionary,\n LocalDictionaryId,\n} from '@intlayer/types/dictionary';\nimport { getMultilingualDictionary } from '../deepTransformPlugins';\nimport { getNodeType } from './getNodeType';\n\n// Extended type that includes arrays for internal merge operations\ntype MergeableContent = ContentNode | ContentNode[];\n\nconst checkTypesMatch = (\n object1: ContentNode,\n object2: ContentNode,\n object2LocalId: LocalDictionaryId | undefined,\n dictionaryKey: string,\n path: string[] = []\n): void => {\n const appLogger = getAppLogger({ log });\n\n // If either side is missing/undefined, allow merge without error\n if (\n object1 === undefined ||\n object1 === null ||\n object2 === undefined ||\n object2 === null\n )\n return;\n\n const type1 = getNodeType(object1);\n const type2 = getNodeType(object2);\n\n // Unknown types are treated as flexible; skip strict mismatch reporting\n if (type1 === 'unknown' || type2 === 'unknown') return;\n\n if (type1 !== type2) {\n appLogger(\n [\n `Error: Dictionary ${colorizeKey(dictionaryKey)} has a multiple content files with type mismatch at path \"${path.join('.')}\": Cannot merge ${type1} with ${type2} while merging ${object2LocalId}`,\n ],\n {\n level: 'error',\n }\n );\n\n return;\n }\n};\n\n// Custom merge function that prefers destination (first dictionary) values\nconst customMerge = (\n destination: ContentNode,\n source: ContentNode\n): MergeableContent => {\n // If destination is undefined/null, use source\n if (destination === undefined || destination === null) {\n return source;\n }\n\n // If source is undefined/null, use destination\n if (source === undefined || source === null) {\n return destination;\n }\n\n // For primitive values, prefer destination (first dictionary)\n if (typeof destination !== 'object' || typeof source !== 'object') {\n return destination;\n }\n\n // For arrays, use our custom array merge\n if (Array.isArray(destination) && Array.isArray(source)) {\n return arrayMerge(\n destination as ContentNode[],\n source as ContentNode[]\n ) as MergeableContent;\n }\n\n // For objects, recursively merge with our custom logic\n if (typeof destination === 'object' && typeof source === 'object') {\n const result: Record<string, MergeableContent> = {};\n const allKeys = new Set([\n ...Object.keys(destination as unknown as Record<string, ContentNode>),\n ...Object.keys(source as unknown as Record<string, ContentNode>),\n ]);\n\n for (const key of allKeys) {\n result[key] = customMerge(\n (destination as unknown as Record<string, ContentNode>)[key],\n (source as unknown as Record<string, ContentNode>)[key]\n );\n }\n\n return result as unknown as MergeableContent;\n }\n\n // Fallback to destination\n return destination;\n};\n\n// Custom array merge strategy that merges arrays by key when present, otherwise by index\nconst arrayMerge = (\n destinationArray: ContentNode[],\n sourceArray: ContentNode[]\n): MergeableContent[] => {\n // Check if both arrays contain only primitives\n const destHasOnlyPrimitives = destinationArray.every(\n (item) => typeof item !== 'object' || item === null\n );\n const sourceHasOnlyPrimitives = sourceArray.every(\n (item) => typeof item !== 'object' || item === null\n );\n\n // If both arrays contain only primitives, use the source array (second dictionary)\n if (destHasOnlyPrimitives && sourceHasOnlyPrimitives) {\n return sourceArray;\n }\n\n // Otherwise, merge by index with object merging logic\n const result: MergeableContent[] = [];\n const maxLength = Math.max(destinationArray.length, sourceArray.length);\n\n for (let i = 0; i < maxLength; i++) {\n const destItem = destinationArray[i];\n const sourceItem = sourceArray[i];\n\n if (destItem === undefined && sourceItem === undefined) {\n } else if (destItem === undefined) {\n // Only source exists, add it\n result.push(sourceItem);\n } else if (sourceItem === undefined) {\n // Only destination exists, add it\n result.push(destItem);\n } else {\n // Both exist, merge them\n if (\n typeof destItem === 'object' &&\n typeof sourceItem === 'object' &&\n destItem !== null &&\n sourceItem !== null\n ) {\n // Check if both objects have a 'key' property for keyed merging\n if (\n 'key' in destItem &&\n 'key' in sourceItem &&\n (destItem as Record<string, string>).key ===\n (sourceItem as Record<string, string>).key\n ) {\n // Merge objects with same key, preferring destination (first dictionary) values\n result.push(customMerge(destItem, sourceItem));\n } else {\n // Merge objects by index, preferring destination (first dictionary) values\n result.push(customMerge(destItem, sourceItem));\n }\n } else {\n // For primitives or non-objects, use destination value (first dictionary)\n result.push(destItem);\n }\n }\n }\n\n return result;\n};\n\nexport const mergeDictionaries = (dictionaries: Dictionary[]): Dictionary => {\n const localIds = Array.from(\n new Set<LocalDictionaryId>(\n dictionaries.filter((dict) => dict.localId).map((dict) => dict.localId!)\n )\n );\n\n if (!dictionaries[0] || dictionaries.length <= 1) {\n return dictionaries[0]!;\n }\n\n const dictionariesKeys = dictionaries.map((dict) => dict.key);\n\n // Check if all dictionaries have the same key\n if (new Set(dictionariesKeys).size !== 1) {\n throw new Error('All dictionaries must have the same key');\n }\n\n let mergedContent: Dictionary['content'] = dictionaries[0].content;\n\n for (let i = 1; i < dictionaries.length; i++) {\n const dict = dictionaries[i];\n\n if (!dict) continue;\n\n // If the dictionary is a per-locale dictionary, transform it to a partial multilingual dictionary\n const currentDictionary = getMultilingualDictionary(dict);\n\n // Check types before merging\n checkTypesMatch(\n mergedContent,\n currentDictionary.content,\n currentDictionary.localId,\n currentDictionary.key,\n []\n );\n\n mergedContent = customMerge(\n mergedContent,\n currentDictionary.content\n ) as ContentNode;\n }\n\n const mergedDictionary: Dictionary = {\n key: dictionaries[0].key,\n content: mergedContent,\n localIds,\n };\n\n return mergedDictionary;\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeQualifiedDictionaries.cjs","names":["getDictionaryQualifierTypes","QUALIFIER_ORDER","mergeDictionaries","getDictionaryCompositeIds","DEFAULT_VARIANT_ID"],"sources":["../../../src/dictionaryManipulator/mergeQualifiedDictionaries.ts"],"sourcesContent":["import { log } from '@intlayer/config/built';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport type {\n Dictionary,\n DictionaryQualifierType,\n QualifiedDictionaryGroup,\n} from '@intlayer/types/dictionary';\nimport { mergeDictionaries } from './mergeDictionaries';\nimport {\n COMPOSITE_ID_SEPARATOR,\n DEFAULT_VARIANT_ID,\n} from './qualifiedDictionary';\nimport {\n getDictionaryCompositeIds,\n getDictionaryQualifierTypes,\n QUALIFIER_ORDER,\n} from './qualifiedDictionaryDeclaration';\n\n/**\n * Merges sibling dictionaries sharing the same key, honouring qualifiers.\n *\n * - No dictionary declares a qualifier → behaves exactly like\n * `mergeDictionaries` (single merged dictionary).\n * - At least one dictionary declares a qualifier → the group's dimension set is\n * the union of every declared dimension (in canonical order\n * `variant → item`). Dictionaries are grouped by their composite id\n * (one segment per dimension), merged within each group (locale completion /\n * priority overrides preserved), and a `QualifiedDictionaryGroup` is returned.\n * Unqualified siblings act as shared base content merged into every entry —\n * and, on a variant-only key, also materialize the `default` entry when no\n * declaration claims it. Every other variant entry then inherits from that\n * `default` entry, so a variant only declares the fields it overrides.\n *\n * Every qualified entry must declare ALL dimensions of the group; an entry that\n * declares only a subset is ambiguous and is rejected with an error log.\n */\nexport const mergeQualifiedDictionaries = (\n dictionaries: Dictionary[]\n): Dictionary | QualifiedDictionaryGroup => {\n const perDictionaryTypes = dictionaries.map(getDictionaryQualifierTypes);\n\n const declaredDimensions = new Set<DictionaryQualifierType>();\n for (const types of perDictionaryTypes) {\n for (const type of types) declaredDimensions.add(type);\n }\n\n // Canonical order, restricted to the dimensions actually declared.\n const groupQualifierTypes = QUALIFIER_ORDER.filter((qualifierType) =>\n declaredDimensions.has(qualifierType)\n );\n\n if (groupQualifierTypes.length === 0) {\n return mergeDictionaries(dictionaries);\n }\n\n const appLogger = getAppLogger({ log });\n\n const baseDictionaries: Dictionary[] = [];\n const entriesDictionaries = new Map<string, Dictionary[]>();\n\n dictionaries.forEach((dictionary, index) => {\n if (perDictionaryTypes[index]?.length === 0) {\n baseDictionaries.push(dictionary);\n return;\n }\n\n // A dictionary may map to several composite ids (array variant fan-out):\n // its content is registered under every id it lists.\n const compositeIds = getDictionaryCompositeIds(\n dictionary,\n groupQualifierTypes\n );\n\n if (compositeIds === undefined) {\n appLogger(\n `Dictionary ${colorizeKey(dictionary.key)} declares (${perDictionaryTypes[index].join(', ')}) but the key's dimensions are (${groupQualifierTypes.join(', ')}); every entry must declare all of them. Entry ignored${dictionary.filePath ? ` - ${dictionary.filePath}` : ''}.`,\n { level: 'error' }\n );\n return;\n }\n\n for (const compositeId of compositeIds) {\n const existingEntries = entriesDictionaries.get(compositeId) ?? [];\n existingEntries.push(dictionary);\n entriesDictionaries.set(compositeId, existingEntries);\n }\n });\n\n // Unqualified siblings are the key's base content. On a variant key they also\n // materialize the `default` entry when no declaration claims it, so the key\n // still resolves when no variant is selected — and so variants that declare\n // no entry of their own can fall back to it. Registering an empty entry list\n // is enough: the merge loop below appends the base dictionaries to it.\n //\n // Composite (variant × item) keys are excluded: base content carries no item\n // index, so it cannot be placed on the collection axis.\n const isVariantOnlyGroup =\n groupQualifierTypes.length === 1 && groupQualifierTypes[0] === 'variant';\n\n if (\n isVariantOnlyGroup &&\n baseDictionaries.length > 0 &&\n !entriesDictionaries.has(DEFAULT_VARIANT_ID)\n ) {\n entriesDictionaries.set(DEFAULT_VARIANT_ID, []);\n }\n\n // `content` maps each composite id to its resolved content node directly; the\n // qualifier coordinates live in the key, not in a per-entry wrapper. For an\n // object variant the variant segment is the canonical serialization of the\n // object, so it fully identifies the entry — no side-map is needed.\n const content: Record<string, unknown> = {};\n\n let importMode: Dictionary['importMode'];\n\n const variantIndex = groupQualifierTypes.indexOf('variant');\n\n /**\n * The id of the entry a composite id inherits from — itself with its variant\n * segment swapped for `default` (`'promo/2'` → `'default/2'`). `undefined`\n * for the default entries themselves and for keys with no variant dimension.\n */\n const getInheritedEntryId = (compositeId: string): string | undefined => {\n if (variantIndex === -1) return undefined;\n\n const segments = compositeId.split(COMPOSITE_ID_SEPARATOR);\n if (segments[variantIndex] === DEFAULT_VARIANT_ID) return undefined;\n\n segments[variantIndex] = DEFAULT_VARIANT_ID;\n return segments.join(COMPOSITE_ID_SEPARATOR);\n };\n\n for (const [compositeId, qualifiedDictionaries] of entriesDictionaries) {\n // Precedence, highest first: the entry's own declarations, then the\n // `default` variant it inherits from, then the unqualified siblings shared\n // by the whole key (mergeDictionaries prefers the first occurrence).\n //\n // Inheriting from `default` is what makes a variant declaration partial: it\n // only has to declare the fields whose wording actually differs, and every\n // other field is completed from the default entry.\n const inheritedEntryId = getInheritedEntryId(compositeId);\n const inheritedDictionaries = inheritedEntryId\n ? (entriesDictionaries.get(inheritedEntryId) ?? [])\n : [];\n\n const mergedEntry = mergeDictionaries([\n ...qualifiedDictionaries,\n ...inheritedDictionaries,\n ...baseDictionaries,\n ]);\n\n content[compositeId] = mergedEntry.content;\n\n const [firstQualified] = qualifiedDictionaries;\n\n importMode ??= firstQualified?.importMode;\n }\n\n const localIds = Array.from(\n new Set(\n dictionaries\n .filter((dictionary) => dictionary.localId)\n .map((dictionary) => dictionary.localId!)\n )\n );\n\n return {\n key: dictionaries[0]!.key,\n qualifierTypes: groupQualifierTypes,\n content,\n ...(importMode !== undefined && { importMode }),\n localIds,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAa,8BACX,iBAC0C;CAC1C,MAAM,qBAAqB,aAAa,IAAIA,wFAA2B;CAEvE,MAAM,qCAAqB,IAAI,IAA6B;CAC5D,KAAK,MAAM,SAAS,oBAClB,KAAK,MAAM,QAAQ,OAAO,mBAAmB,IAAI,IAAI;CAIvD,MAAM,sBAAsBC,6EAAgB,QAAQ,kBAClD,mBAAmB,IAAI,aAAa,CACtC;CAEA,IAAI,oBAAoB,WAAW,GACjC,OAAOC,kEAAkB,YAAY;CAGvC,MAAM,
|
|
1
|
+
{"version":3,"file":"mergeQualifiedDictionaries.cjs","names":["getDictionaryQualifierTypes","QUALIFIER_ORDER","mergeDictionaries","getAppLogger","getDictionaryCompositeIds","colorizeKey","DEFAULT_VARIANT_ID"],"sources":["../../../src/dictionaryManipulator/mergeQualifiedDictionaries.ts"],"sourcesContent":["import { log } from '@intlayer/config/built';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport type {\n Dictionary,\n DictionaryQualifierType,\n QualifiedDictionaryGroup,\n} from '@intlayer/types/dictionary';\nimport { mergeDictionaries } from './mergeDictionaries';\nimport {\n COMPOSITE_ID_SEPARATOR,\n DEFAULT_VARIANT_ID,\n} from './qualifiedDictionary';\nimport {\n getDictionaryCompositeIds,\n getDictionaryQualifierTypes,\n QUALIFIER_ORDER,\n} from './qualifiedDictionaryDeclaration';\n\n/**\n * Merges sibling dictionaries sharing the same key, honouring qualifiers.\n *\n * - No dictionary declares a qualifier → behaves exactly like\n * `mergeDictionaries` (single merged dictionary).\n * - At least one dictionary declares a qualifier → the group's dimension set is\n * the union of every declared dimension (in canonical order\n * `variant → item`). Dictionaries are grouped by their composite id\n * (one segment per dimension), merged within each group (locale completion /\n * priority overrides preserved), and a `QualifiedDictionaryGroup` is returned.\n * Unqualified siblings act as shared base content merged into every entry —\n * and, on a variant-only key, also materialize the `default` entry when no\n * declaration claims it. Every other variant entry then inherits from that\n * `default` entry, so a variant only declares the fields it overrides.\n *\n * Every qualified entry must declare ALL dimensions of the group; an entry that\n * declares only a subset is ambiguous and is rejected with an error log.\n */\nexport const mergeQualifiedDictionaries = (\n dictionaries: Dictionary[]\n): Dictionary | QualifiedDictionaryGroup => {\n const perDictionaryTypes = dictionaries.map(getDictionaryQualifierTypes);\n\n const declaredDimensions = new Set<DictionaryQualifierType>();\n for (const types of perDictionaryTypes) {\n for (const type of types) declaredDimensions.add(type);\n }\n\n // Canonical order, restricted to the dimensions actually declared.\n const groupQualifierTypes = QUALIFIER_ORDER.filter((qualifierType) =>\n declaredDimensions.has(qualifierType)\n );\n\n if (groupQualifierTypes.length === 0) {\n return mergeDictionaries(dictionaries);\n }\n\n const appLogger = getAppLogger({ log });\n\n const baseDictionaries: Dictionary[] = [];\n const entriesDictionaries = new Map<string, Dictionary[]>();\n\n dictionaries.forEach((dictionary, index) => {\n if (perDictionaryTypes[index]?.length === 0) {\n baseDictionaries.push(dictionary);\n return;\n }\n\n // A dictionary may map to several composite ids (array variant fan-out):\n // its content is registered under every id it lists.\n const compositeIds = getDictionaryCompositeIds(\n dictionary,\n groupQualifierTypes\n );\n\n if (compositeIds === undefined) {\n appLogger(\n `Dictionary ${colorizeKey(dictionary.key)} declares (${perDictionaryTypes[index].join(', ')}) but the key's dimensions are (${groupQualifierTypes.join(', ')}); every entry must declare all of them. Entry ignored${dictionary.filePath ? ` - ${dictionary.filePath}` : ''}.`,\n { level: 'error' }\n );\n return;\n }\n\n for (const compositeId of compositeIds) {\n const existingEntries = entriesDictionaries.get(compositeId) ?? [];\n existingEntries.push(dictionary);\n entriesDictionaries.set(compositeId, existingEntries);\n }\n });\n\n // Unqualified siblings are the key's base content. On a variant key they also\n // materialize the `default` entry when no declaration claims it, so the key\n // still resolves when no variant is selected — and so variants that declare\n // no entry of their own can fall back to it. Registering an empty entry list\n // is enough: the merge loop below appends the base dictionaries to it.\n //\n // Composite (variant × item) keys are excluded: base content carries no item\n // index, so it cannot be placed on the collection axis.\n const isVariantOnlyGroup =\n groupQualifierTypes.length === 1 && groupQualifierTypes[0] === 'variant';\n\n if (\n isVariantOnlyGroup &&\n baseDictionaries.length > 0 &&\n !entriesDictionaries.has(DEFAULT_VARIANT_ID)\n ) {\n entriesDictionaries.set(DEFAULT_VARIANT_ID, []);\n }\n\n // `content` maps each composite id to its resolved content node directly; the\n // qualifier coordinates live in the key, not in a per-entry wrapper. For an\n // object variant the variant segment is the canonical serialization of the\n // object, so it fully identifies the entry — no side-map is needed.\n const content: Record<string, unknown> = {};\n\n let importMode: Dictionary['importMode'];\n\n const variantIndex = groupQualifierTypes.indexOf('variant');\n\n /**\n * The id of the entry a composite id inherits from — itself with its variant\n * segment swapped for `default` (`'promo/2'` → `'default/2'`). `undefined`\n * for the default entries themselves and for keys with no variant dimension.\n */\n const getInheritedEntryId = (compositeId: string): string | undefined => {\n if (variantIndex === -1) return undefined;\n\n const segments = compositeId.split(COMPOSITE_ID_SEPARATOR);\n if (segments[variantIndex] === DEFAULT_VARIANT_ID) return undefined;\n\n segments[variantIndex] = DEFAULT_VARIANT_ID;\n return segments.join(COMPOSITE_ID_SEPARATOR);\n };\n\n for (const [compositeId, qualifiedDictionaries] of entriesDictionaries) {\n // Precedence, highest first: the entry's own declarations, then the\n // `default` variant it inherits from, then the unqualified siblings shared\n // by the whole key (mergeDictionaries prefers the first occurrence).\n //\n // Inheriting from `default` is what makes a variant declaration partial: it\n // only has to declare the fields whose wording actually differs, and every\n // other field is completed from the default entry.\n const inheritedEntryId = getInheritedEntryId(compositeId);\n const inheritedDictionaries = inheritedEntryId\n ? (entriesDictionaries.get(inheritedEntryId) ?? [])\n : [];\n\n const mergedEntry = mergeDictionaries([\n ...qualifiedDictionaries,\n ...inheritedDictionaries,\n ...baseDictionaries,\n ]);\n\n content[compositeId] = mergedEntry.content;\n\n const [firstQualified] = qualifiedDictionaries;\n\n importMode ??= firstQualified?.importMode;\n }\n\n const localIds = Array.from(\n new Set(\n dictionaries\n .filter((dictionary) => dictionary.localId)\n .map((dictionary) => dictionary.localId!)\n )\n );\n\n return {\n key: dictionaries[0]!.key,\n qualifierTypes: groupQualifierTypes,\n content,\n ...(importMode !== undefined && { importMode }),\n localIds,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAa,8BACX,iBAC0C;CAC1C,MAAM,qBAAqB,aAAa,IAAIA,wFAA2B;CAEvE,MAAM,qCAAqB,IAAI,IAA6B;CAC5D,KAAK,MAAM,SAAS,oBAClB,KAAK,MAAM,QAAQ,OAAO,mBAAmB,IAAI,IAAI;CAIvD,MAAM,sBAAsBC,6EAAgB,QAAQ,kBAClD,mBAAmB,IAAI,aAAa,CACtC;CAEA,IAAI,oBAAoB,WAAW,GACjC,OAAOC,kEAAkB,YAAY;CAGvC,MAAM,gBAAYC,sCAAa,EAAE,gCAAI,CAAC;CAEtC,MAAM,mBAAiC,CAAC;CACxC,MAAM,sCAAsB,IAAI,IAA0B;CAE1D,aAAa,SAAS,YAAY,UAAU;EAC1C,IAAI,mBAAmB,MAAM,EAAE,WAAW,GAAG;GAC3C,iBAAiB,KAAK,UAAU;GAChC;EACF;EAIA,MAAM,eAAeC,uFACnB,YACA,mBACF;EAEA,IAAI,iBAAiB,QAAW;GAC9B,UACE,kBAAcC,qCAAY,WAAW,GAAG,EAAE,aAAa,mBAAmB,MAAM,CAAC,KAAK,IAAI,EAAE,kCAAkC,oBAAoB,KAAK,IAAI,EAAE,wDAAwD,WAAW,WAAW,MAAM,WAAW,aAAa,GAAG,IAC5Q,EAAE,OAAO,QAAQ,CACnB;GACA;EACF;EAEA,KAAK,MAAM,eAAe,cAAc;GACtC,MAAM,kBAAkB,oBAAoB,IAAI,WAAW,KAAK,CAAC;GACjE,gBAAgB,KAAK,UAAU;GAC/B,oBAAoB,IAAI,aAAa,eAAe;EACtD;CACF,CAAC;CAaD,IAFE,oBAAoB,WAAW,KAAK,oBAAoB,OAAO,aAI/D,iBAAiB,SAAS,KAC1B,CAAC,oBAAoB,aAAsB,GAE3C,oBAAoB,IAAIC,sEAAoB,CAAC,CAAC;CAOhD,MAAM,UAAmC,CAAC;CAE1C,IAAI;CAEJ,MAAM,eAAe,oBAAoB,QAAQ,SAAS;;;;;;CAO1D,MAAM,uBAAuB,gBAA4C;EACvE,IAAI,iBAAiB,IAAI,OAAO;EAEhC,MAAM,WAAW,YAAY,SAA4B;EACzD,IAAI,SAAS,6BAAsC,OAAO;EAE1D,SAAS,gBAAgBA;EACzB,OAAO,SAAS,QAA2B;CAC7C;CAEA,KAAK,MAAM,CAAC,aAAa,0BAA0B,qBAAqB;EAQtE,MAAM,mBAAmB,oBAAoB,WAAW;EACxD,MAAM,wBAAwB,mBACzB,oBAAoB,IAAI,gBAAgB,KAAK,CAAC,IAC/C,CAAC;EAQL,QAAQ,eANYJ,kEAAkB;GACpC,GAAG;GACH,GAAG;GACH,GAAG;EACL,CAEiC,CAAC,CAAC;EAEnC,MAAM,CAAC,kBAAkB;EAEzB,eAAe,gBAAgB;CACjC;CAEA,MAAM,WAAW,MAAM,KACrB,IAAI,IACF,aACG,QAAQ,eAAe,WAAW,OAAO,CAAC,CAC1C,KAAK,eAAe,WAAW,OAAQ,CAC5C,CACF;CAEA,OAAO;EACL,KAAK,aAAa,EAAE,CAAE;EACtB,gBAAgB;EAChB;EACA,GAAI,eAAe,UAAa,EAAE,WAAW;EAC7C;CACF;AACF"}
|