diff --git a/packages/localize/src/LocalizeManager.js b/packages/localize/src/LocalizeManager.js index 6f8038935..4dc730f52 100644 --- a/packages/localize/src/LocalizeManager.js +++ b/packages/localize/src/LocalizeManager.js @@ -16,6 +16,7 @@ export class LocalizeManager extends LionSingleton { } this._autoLoadOnLocaleChange = !!params.autoLoadOnLocaleChange; + this._fallbackLocale = params.fallbackLocale; this.__storage = {}; this.__namespacePatternsMap = new Map(); this.__namespaceLoadersCache = {}; @@ -163,13 +164,24 @@ export class LocalizeManager extends LionSingleton { return loader; } - _getNamespaceLoaderPromise(loader, locale, namespace) { + _getNamespaceLoaderPromise(loader, locale, namespace, fallbackLocale = this._fallbackLocale) { return loader(locale, namespace).catch(() => { const lang = this._getLangFromLocale(locale); return loader(lang, namespace).catch(() => { + if (fallbackLocale) { + return this._getNamespaceLoaderPromise(loader, fallbackLocale, namespace, false).catch( + () => { + const fallbackLang = this._getLangFromLocale(fallbackLocale); + throw new Error( + `Data for namespace "${namespace}" and current locale "${locale}" or fallback locale "${fallbackLocale}" could not be loaded. ` + + `Make sure you have data either for locale "${locale}" (and/or generic language "${lang}") or for fallback "${fallbackLocale}" (and/or "${fallbackLang}").`, + ); + }, + ); + } throw new Error( `Data for namespace "${namespace}" and locale "${locale}" could not be loaded. ` + - `Make sure you have data for locale "${locale}" and/or generic language "${lang}".`, + `Make sure you have data for locale "${locale}" (and/or generic language "${lang}").`, ); }); }); diff --git a/packages/localize/test/LocalizeManager.test.js b/packages/localize/test/LocalizeManager.test.js index 1d0b1b653..fecc2f8d7 100644 --- a/packages/localize/test/LocalizeManager.test.js +++ b/packages/localize/test/LocalizeManager.test.js @@ -213,7 +213,7 @@ describe('LocalizeManager', () => { }); }); - it('fallbacks to language file if locale file is not found', async () => { + it('loads generic language file if locale file is not found', async () => { setupFakeImport('./my-component/en.js', { default: { greeting: 'Hello!' } }); manager = new LocalizeManager(); @@ -240,13 +240,69 @@ describe('LocalizeManager', () => { expect(e).to.be.instanceof(Error); expect(e.message).to.equal( 'Data for namespace "my-component" and locale "en-GB" could not be loaded. ' + - 'Make sure you have data for locale "en-GB" and/or generic language "en".', + 'Make sure you have data for locale "en-GB" (and/or generic language "en").', ); return; } throw new Error('did not throw'); }); + + describe('fallback locale', () => { + it('can load a fallback locale if current one can not be loaded', async () => { + manager = new LocalizeManager({ fallbackLocale: 'en-GB' }); + manager.locale = 'nl-NL'; + + setupFakeImport('./my-component/en-GB.js', { default: { greeting: 'Hello!' } }); + + await manager.loadNamespace({ + 'my-component': locale => fakeImport(`./my-component/${locale}.js`), + }); + + expect(manager.__storage).to.deep.equal({ + 'nl-NL': { + 'my-component': { greeting: 'Hello!' }, + }, + }); + }); + + it('can load fallback generic language file if fallback locale file is not found', async () => { + manager = new LocalizeManager({ fallbackLocale: 'en-GB' }); + manager.locale = 'nl-NL'; + + setupFakeImport('./my-component/en.js', { default: { greeting: 'Hello!' } }); + + await manager.loadNamespace({ + 'my-component': locale => fakeImport(`./my-component/${locale}.js`), + }); + + expect(manager.__storage).to.deep.equal({ + 'nl-NL': { + 'my-component': { greeting: 'Hello!' }, + }, + }); + }); + + it('throws if neither current locale nor fallback locale are found', async () => { + manager = new LocalizeManager({ fallbackLocale: 'en-GB' }); + manager.locale = 'nl-NL'; + + try { + await manager.loadNamespace({ + 'my-component': locale => fakeImport(`./my-component/${locale}.js`), + }); + } catch (e) { + expect(e).to.be.instanceof(Error); + expect(e.message).to.equal( + 'Data for namespace "my-component" and current locale "nl-NL" or fallback locale "en-GB" could not be loaded. ' + + 'Make sure you have data either for locale "nl-NL" (and/or generic language "nl") or for fallback "en-GB" (and/or "en").', + ); + return; + } + + throw new Error('did not throw'); + }); + }); }); describe('loading using routes predefined via setupNamespaceLoader()', () => {