core-app-api: add support for explicit configuration of default language

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-09-14 19:53:58 +02:00
parent 8bc4ecf03e
commit d93a3cdd1b
5 changed files with 41 additions and 3 deletions
@@ -25,6 +25,7 @@ export const DEFAULT_LANGUAGE = 'en';
/** @alpha */
export interface AppLanguageSelectorOptions {
defaultLanguage?: string;
availableLanguages?: string[];
}
@@ -47,7 +48,14 @@ export class AppLanguageSelector implements AppLanguageApi {
throw new Error(`Supported languages must include '${DEFAULT_LANGUAGE}'`);
}
return new AppLanguageSelector(languages);
const initialLanguage = options?.defaultLanguage ?? DEFAULT_LANGUAGE;
if (!languages.includes(initialLanguage)) {
throw new Error(
`Initial language must be one of the supported languages, got '${initialLanguage}'`,
);
}
return new AppLanguageSelector(languages, initialLanguage);
}
static createWithStorage(options?: AppLanguageSelectorOptions) {
@@ -85,9 +93,9 @@ export class AppLanguageSelector implements AppLanguageApi {
#language: string;
#subject: BehaviorSubject<{ language: string }>;
private constructor(languages: string[]) {
private constructor(languages: string[], initialLanguage: string) {
this.#languages = languages;
this.#language = languages[0];
this.#language = initialLanguage;
this.#subject = new BehaviorSubject<{ language: string }>({
language: this.#language,
});
@@ -193,6 +193,29 @@ describe('I18nextTranslationApi', () => {
expect(snapshot.t('foo')).toBe('OtherFoo');
});
it('should allow initial language to not be the default one', async () => {
const languageApi = AppLanguageSelector.create({
defaultLanguage: 'sv',
availableLanguages: ['en', 'sv'],
});
const translationApi = I18nextTranslationApi.create({
languageApi,
resources: [
createTranslationResource({
ref: plainRef,
translations: {
sv: () => Promise.resolve({ default: { foo: 'Föö' } }),
},
}),
],
});
const snapshot = assertReady(
await waitForNext(translationApi.translation$(plainRef), s => s.ready),
);
expect(snapshot.t('foo')).toBe('Föö');
});
it('should prefer the last loaded resource', async () => {
const languageApi = AppLanguageSelector.create({
availableLanguages: ['en', 'sv'],
@@ -155,6 +155,11 @@ export class I18nextTranslationApi implements TranslationApi {
i18n.init();
const { language: initialLanguage } = options.languageApi.getLanguage();
if (initialLanguage !== DEFAULT_LANGUAGE) {
i18n.changeLanguage(initialLanguage);
}
const loader = new ResourceLoader(loaded => {
i18n.addResourceBundle(
loaded.language,
@@ -182,6 +182,7 @@ export class AppManager implements BackstageApp {
this.bindRoutes = options.bindRoutes;
this.apiFactoryRegistry = new ApiFactoryRegistry();
this.appLanguageApi = AppLanguageSelector.createWithStorage({
defaultLanguage: options.__experimentalTranslations?.defaultLanguage,
availableLanguages:
options.__experimentalTranslations?.availableLanguages,
});
+1
View File
@@ -284,6 +284,7 @@ export type AppOptions = {
bindRoutes?(context: { bind: AppRouteBinder }): void;
__experimentalTranslations?: {
defaultLanguage?: string;
availableLanguages?: string[];
resources?: Array<TranslationMessages | TranslationResource>;
};