Skip to content

Commit e7ea9cb

Browse files
author
Mikhail Bashkirov
committed
fix(localize): support fallback locale
1 parent 688fcb6 commit e7ea9cb

File tree

2 files changed

+72
-4
lines changed

2 files changed

+72
-4
lines changed

packages/localize/src/LocalizeManager.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export class LocalizeManager extends LionSingleton {
1616
}
1717

1818
this._autoLoadOnLocaleChange = !!params.autoLoadOnLocaleChange;
19+
this._fallbackLocale = params.fallbackLocale;
1920
this.__storage = {};
2021
this.__namespacePatternsMap = new Map();
2122
this.__namespaceLoadersCache = {};
@@ -163,13 +164,24 @@ export class LocalizeManager extends LionSingleton {
163164
return loader;
164165
}
165166

166-
_getNamespaceLoaderPromise(loader, locale, namespace) {
167+
_getNamespaceLoaderPromise(loader, locale, namespace, fallbackLocale = this._fallbackLocale) {
167168
return loader(locale, namespace).catch(() => {
168169
const lang = this._getLangFromLocale(locale);
169170
return loader(lang, namespace).catch(() => {
171+
if (fallbackLocale) {
172+
return this._getNamespaceLoaderPromise(loader, fallbackLocale, namespace, false).catch(
173+
() => {
174+
const fallbackLang = this._getLangFromLocale(fallbackLocale);
175+
throw new Error(
176+
`Data for namespace "${namespace}" and current locale "${locale}" or fallback locale "${fallbackLocale}" could not be loaded. ` +
177+
`Make sure you have data either for locale "${locale}" (and/or generic language "${lang}") or for fallback "${fallbackLocale}" (and/or "${fallbackLang}").`,
178+
);
179+
},
180+
);
181+
}
170182
throw new Error(
171183
`Data for namespace "${namespace}" and locale "${locale}" could not be loaded. ` +
172-
`Make sure you have data for locale "${locale}" and/or generic language "${lang}".`,
184+
`Make sure you have data for locale "${locale}" (and/or generic language "${lang}").`,
173185
);
174186
});
175187
});

packages/localize/test/LocalizeManager.test.js

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ describe('LocalizeManager', () => {
213213
});
214214
});
215215

216-
it('fallbacks to language file if locale file is not found', async () => {
216+
it('loads generic language file if locale file is not found', async () => {
217217
setupFakeImport('./my-component/en.js', { default: { greeting: 'Hello!' } });
218218

219219
manager = new LocalizeManager();
@@ -240,13 +240,69 @@ describe('LocalizeManager', () => {
240240
expect(e).to.be.instanceof(Error);
241241
expect(e.message).to.equal(
242242
'Data for namespace "my-component" and locale "en-GB" could not be loaded. ' +
243-
'Make sure you have data for locale "en-GB" and/or generic language "en".',
243+
'Make sure you have data for locale "en-GB" (and/or generic language "en").',
244244
);
245245
return;
246246
}
247247

248248
throw new Error('did not throw');
249249
});
250+
251+
describe('fallback locale', () => {
252+
it('can load a fallback locale if current one can not be loaded', async () => {
253+
manager = new LocalizeManager({ fallbackLocale: 'en-GB' });
254+
manager.locale = 'nl-NL';
255+
256+
setupFakeImport('./my-component/en-GB.js', { default: { greeting: 'Hello!' } });
257+
258+
await manager.loadNamespace({
259+
'my-component': locale => fakeImport(`./my-component/${locale}.js`),
260+
});
261+
262+
expect(manager.__storage).to.deep.equal({
263+
'nl-NL': {
264+
'my-component': { greeting: 'Hello!' },
265+
},
266+
});
267+
});
268+
269+
it('can load fallback generic language file if fallback locale file is not found', async () => {
270+
manager = new LocalizeManager({ fallbackLocale: 'en-GB' });
271+
manager.locale = 'nl-NL';
272+
273+
setupFakeImport('./my-component/en.js', { default: { greeting: 'Hello!' } });
274+
275+
await manager.loadNamespace({
276+
'my-component': locale => fakeImport(`./my-component/${locale}.js`),
277+
});
278+
279+
expect(manager.__storage).to.deep.equal({
280+
'nl-NL': {
281+
'my-component': { greeting: 'Hello!' },
282+
},
283+
});
284+
});
285+
286+
it('throws if neither current locale nor fallback locale are found', async () => {
287+
manager = new LocalizeManager({ fallbackLocale: 'en-GB' });
288+
manager.locale = 'nl-NL';
289+
290+
try {
291+
await manager.loadNamespace({
292+
'my-component': locale => fakeImport(`./my-component/${locale}.js`),
293+
});
294+
} catch (e) {
295+
expect(e).to.be.instanceof(Error);
296+
expect(e.message).to.equal(
297+
'Data for namespace "my-component" and current locale "nl-NL" or fallback locale "en-GB" could not be loaded. ' +
298+
'Make sure you have data either for locale "nl-NL" (and/or generic language "nl") or for fallback "en-GB" (and/or "en").',
299+
);
300+
return;
301+
}
302+
303+
throw new Error('did not throw');
304+
});
305+
});
250306
});
251307

252308
describe('loading using routes predefined via setupNamespaceLoader()', () => {

0 commit comments

Comments
 (0)