Add i18n vendor overlays and dynamic bundling
- Add opt-in vendor overlays under src/env/locales/<env>
(and optional variant), merged on top of base locales at runtime.
- Auto-discover and bundle all base locale JSON files
in src/locales/.
- Example: move dump type labels under pageDumps.dumpTypes;
read vendor-only dump labels from overlays.
- Docs: update i18n guidelines and env README (formatting fixes).
- Tests: add focused unit tests for overlays and locale aliases.
Tested:
- Unit: i18n.locale-alias.spec.js, i18n.vendor.spec.js (passing)
- Manual: Verified dynamic locale discovery and overlay merge in UI
Change-Id: I8eae2bfec0e9622bafdafac3168dbf96650e8ae8
Signed-off-by: jason westover <jwestover@nvidia.com>
diff --git a/src/i18n.js b/src/i18n.js
index 2580784..65c7d1f 100644
--- a/src/i18n.js
+++ b/src/i18n.js
@@ -1,29 +1,94 @@
import { createI18n } from 'vue-i18n';
+import { deepMerge } from './utilities/objectUtils';
-import en_us from './locales/en-US.json';
-import ru_ru from './locales/ru-RU.json';
-import ka_ge from './locales/ka-GE.json';
-
-function loadLocaleMessages() {
- const messages = {
- 'en-US': en_us,
- 'ka-GE': ka_ge,
- 'ru-RU': ru_ru,
- };
+export function loadBaseLocaleMessages() {
+ const context = require.context(
+ './locales',
+ true,
+ /[A-Za-z0-9-_,\s]+\.json$/i,
+ );
+ const messages = {};
+ context.keys().forEach((key) => {
+ const match = key.match(/([A-Za-z0-9-_]+)\.json$/i);
+ if (!match) return;
+ const locale = match[1];
+ const mod = context(key);
+ messages[locale] = mod && mod.default ? mod.default : mod;
+ });
return messages;
}
-const i18n = createI18n({
- // Get default locale from local storage
- locale: window.localStorage.getItem('storedLanguage'),
- // Locales that don't exist will fallback to English
- fallbackLocale: 'en-US',
- // Falling back to fallbackLocale generates two console warnings
- // Silent fallback suppresses console warnings when using fallback
- silentFallbackWarn: true,
- messages: loadLocaleMessages(),
- globalInjection: false,
- legacy: false,
-});
+export function loadEnvLocaleMessages(envName) {
+ if (!envName) return {};
+ const envMessages = {};
+ const envLocales = require.context(
+ './env/locales',
+ true,
+ /[A-Za-z0-9-_,\s]+\.json$/i,
+ );
+ const vendorRoot = String(envName).split('-')[0];
+ const candidates =
+ vendorRoot && vendorRoot !== envName ? [vendorRoot, envName] : [envName];
+ candidates.forEach((candidate) => {
+ envLocales.keys().forEach((key) => {
+ if (!key.includes(`/${candidate}/`)) return;
+ const localeMatch = key.match(/([A-Za-z0-9-_]+)\.json$/i);
+ if (!localeMatch) return;
+ const locale = localeMatch[1];
+ const mod = envLocales(key);
+ const bundle = mod && mod.default ? mod.default : mod;
+ envMessages[locale] = deepMerge(envMessages[locale] || {}, bundle);
+ });
+ });
+ return envMessages;
+}
-export default i18n;
+export function createI18nInstance(
+ envName,
+ locale,
+ loadEnv = loadEnvLocaleMessages,
+ loadBase = loadBaseLocaleMessages,
+) {
+ const base = loadBase();
+ const env = loadEnv(envName);
+ const messages = { ...base };
+ Object.keys(env).forEach((loc) => {
+ messages[loc] = deepMerge(base[loc] || {}, env[loc]);
+ });
+
+ const addAlias = (alias, target) => {
+ if (!messages[alias] && messages[target])
+ messages[alias] = messages[target];
+ };
+ addAlias('en', 'en-US');
+ addAlias('ru', 'ru-RU');
+ addAlias('zh', 'zh-CN');
+ addAlias('ka', 'ka-GE');
+
+ const normalize = (val) => {
+ if (!val) return undefined;
+ const s = String(val);
+ if (s === 'en') return 'en-US';
+ if (s === 'ru') return 'ru-RU';
+ if (s === 'zh') return 'zh-CN';
+ if (s === 'ka') return 'ka-GE';
+ return s;
+ };
+
+ return createI18n({
+ locale: normalize(locale),
+ // Locales that don't exist will fallback to English
+ fallbackLocale: 'en-US',
+ // Falling back to fallbackLocale generates two console warnings
+ // Silent fallback suppresses console warnings when using fallback
+ silentFallbackWarn: true,
+ messages,
+ globalInjection: false,
+ legacy: false,
+ });
+}
+
+const envName = process.env.VUE_APP_ENV_NAME;
+// Get default locale from local storage
+const stored = window.localStorage.getItem('storedLanguage');
+export default createI18nInstance(envName, stored);