Fix #5652 - Runtime i18n Loading for Theme Translations (no build-time merge for i18n files)#5653
Conversation
|
Hi @kanasznagyzoltan, thank you for this PR! Since this would probably qualify as an improvement to build process rather than a new user feature, I added it to the 10.0 project to start. However since we're close to the May 22 code freeze, this will likely go towards a later release unless reviews are very quick for it. |
…18n-Loading-for-Theme-Translations
https://github.com/qultoltd/dspace-angular into QREPO-405-Runtime-i18n-Loading-for-Theme-Translations
Thank you @lgeggleston |
References
Description
Make the i18n
TranslateLoadertheme-aware: instead of relying on the build-timemerge-i18nscript, theme-specific translation overrides are loaded and merged at runtime from each configured theme'sassets/<theme>/i18n/<lang>.json5, following the themeextendschain. This lets a single Docker image serve multiple customers/themes with their own translations.Instructions for Reviewers
Changes in this PR:
src/ngx-translate-loaders/translate-server.loader.ts— After reading the base i18n file (dist/.../assets/i18n/<lang>.<hash>.json), the loader overlays every configured theme'sdist/.../assets/<theme>/i18n/<lang>.json5on top, in inheritance order (ancestor first, descendant last, so child theme keys win). The merged map is stored inNGX_TRANSLATE_STATE, so the browser does not re-fetch theme overrides after SSR.src/ngx-translate-loaders/translate-browser.loader.ts— When the TransferState is empty (CSR / dev mode), the loader fetches the base i18n file plus each configured theme's override.json5over HTTP and merges them client-side. Missing override files are tolerated viacatchError.src/ngx-translate-loaders/theme-i18n.util.ts(new) — SharedresolveThemeLoadOrder()helper used by both loaders. It walks each configured theme'sextendschain up to the root ancestor and emits theme names in ancestor → descendant order, with deduplication and cycle protection. This follows the same themeextendsinheritance DSpace already uses for component resolution (themed.component.ts).theme-i18n.util.spec.tscovers the load-order logic (extends chains, multi-level inheritance, deduplication, cycles);translate-browser.loader.spec.tscovers the browser merge (TransferState short-circuit, base + theme merge precedence, missing-file fallback). The server loader imports Node'sfs/path, which cannot run in the browser-based Karma suite, so its ordering is covered by the shared-util spec and its merge mirrors the browser path.assets/<theme>/i18n/*.json5files are ignored (missing file → empty object → no effect on the merged result). Existing setups that still runmerge-i18nkeep working unchanged.How it works
Given a config like:
…and i18n files at:
…the loader merges them at runtime in the order
base → custom-parent → custom-child, socustom-childkeys overridecustom-parentkeys, which override base keys. Ifcustom-childdoes not define a key, it falls back tocustom-parent's value, then to base.How to test
src/assets/i18n/<lang>.json5contains only base content (no merged theme content), and do not runnpm run merge-i18n.src/themes/<theme>/assets/i18n/<lang>.json5.npm run build:prod) and serve the SSR output. On the home page, verify that theme-specific keys render the override value, that switching language keeps using the theme override, and that non-overridden keys fall back to the base translation./assets/<theme>/i18n/<lang>.json5fires on first navigation (served fromNGX_TRANSLATE_STATE).npm run start:dev(no SSR) and confirm the loader fetches base + theme files over HTTP and merges them in the browser.extendsanother, override a key only in the child and another only in the parent — both should resolve correctly when the child theme is active.Checklist
This checklist provides a reminder of what we are going to look for when reviewing your PR. You do not need to complete this checklist prior creating your PR (draft PRs are always welcome).
However, reviewers may request that you complete any actions in this list if you have not done so. If you are unsure about an item in the checklist, don't hesitate to ask. We're here to help!
mainbranch of code (unless it is a backport or is fixing an issue specific to an older branch).npm run lintnpm run check-circ-deps)package.json), I've made sure their licenses align with the DSpace BSD License based on the Licensing of Contributions documentation.