fix(localize): support fallback locale

This commit is contained in:
Mikhail Bashkirov 2019-07-15 14:32:48 +02:00
parent 688fcb6690
commit e7ea9cb6f4
2 changed files with 72 additions and 4 deletions

View file

@ -16,6 +16,7 @@ export class LocalizeManager extends LionSingleton {
} }
this._autoLoadOnLocaleChange = !!params.autoLoadOnLocaleChange; this._autoLoadOnLocaleChange = !!params.autoLoadOnLocaleChange;
this._fallbackLocale = params.fallbackLocale;
this.__storage = {}; this.__storage = {};
this.__namespacePatternsMap = new Map(); this.__namespacePatternsMap = new Map();
this.__namespaceLoadersCache = {}; this.__namespaceLoadersCache = {};
@ -163,13 +164,24 @@ export class LocalizeManager extends LionSingleton {
return loader; return loader;
} }
_getNamespaceLoaderPromise(loader, locale, namespace) { _getNamespaceLoaderPromise(loader, locale, namespace, fallbackLocale = this._fallbackLocale) {
return loader(locale, namespace).catch(() => { return loader(locale, namespace).catch(() => {
const lang = this._getLangFromLocale(locale); const lang = this._getLangFromLocale(locale);
return loader(lang, namespace).catch(() => { 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( throw new Error(
`Data for namespace "${namespace}" and locale "${locale}" could not be loaded. ` + `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}").`,
); );
}); });
}); });

View file

@ -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!' } }); setupFakeImport('./my-component/en.js', { default: { greeting: 'Hello!' } });
manager = new LocalizeManager(); manager = new LocalizeManager();
@ -240,13 +240,69 @@ describe('LocalizeManager', () => {
expect(e).to.be.instanceof(Error); expect(e).to.be.instanceof(Error);
expect(e.message).to.equal( expect(e.message).to.equal(
'Data for namespace "my-component" and locale "en-GB" could not be loaded. ' + '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; return;
} }
throw new Error('did not throw'); 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()', () => { describe('loading using routes predefined via setupNamespaceLoader()', () => {