do not reset subscription every time a new language is loaded

use combineLatest to get latest of both culture and extensions so that whenever something changes we update the translations
This commit is contained in:
Jacob Overgaard
2023-08-01 10:21:25 +02:00
parent eec8e56763
commit e82d25ac4c

View File

@@ -1,61 +1,56 @@
import { Translation, registerTranslation } from '../manager.js';
import { hasDefaultExport, loadExtension } from '@umbraco-cms/backoffice/extension-api';
import { UmbBackofficeExtensionRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { Subscription } from '@umbraco-cms/backoffice/external/rxjs';
import { Subject, combineLatest } from '@umbraco-cms/backoffice/external/rxjs';
export type UmbTranslationDictionary = Record<string, string>;
export class UmbTranslationRegistry {
#registry;
#subscription?: Subscription;
#currentLanguage = new Subject<string>();
constructor(extensionRegistry: UmbBackofficeExtensionRegistry) {
this.#registry = extensionRegistry;
combineLatest([this.#currentLanguage, this.#registry.extensionsOfType('translations')]).subscribe(
async ([userCulture, extensions]) => {
await Promise.all(
extensions
.filter((x) => x.meta.culture.toLowerCase() === userCulture)
.map(async (extension) => {
const innerDictionary: UmbTranslationDictionary = {};
// If extension contains a dictionary, add it to the inner dictionary.
if (extension.meta.translations) {
for (const [dictionaryName, dictionary] of Object.entries(extension.meta.translations)) {
this.#addOrUpdateDictionary(innerDictionary, dictionaryName, dictionary);
}
}
// If extension contains a js file, load it and add the default dictionary to the inner dictionary.
const loadedExtension = await loadExtension(extension);
if (loadedExtension && hasDefaultExport(loadedExtension)) {
for (const [dictionaryName, dictionary] of Object.entries(loadedExtension.default)) {
this.#addOrUpdateDictionary(innerDictionary, dictionaryName, dictionary);
}
}
// Notify subscribers that the inner dictionary has changed.
const translation: Translation = {
$code: userCulture,
$dir: 'ltr',
...innerDictionary,
};
registerTranslation(translation);
})
);
}
);
}
loadLanguage(userCulture: string) {
// Normalize the culture
userCulture = userCulture.toLowerCase();
// Cancel any previous subscription.
if (this.#subscription) {
this.#subscription.unsubscribe();
}
// Load new translations
this.#subscription = this.#registry.extensionsOfType('translations').subscribe(async (extensions) => {
await Promise.all(
extensions
.filter((x) => x.meta.culture.toLowerCase() === userCulture)
.map(async (extension) => {
const innerDictionary: UmbTranslationDictionary = {};
// If extension contains a dictionary, add it to the inner dictionary.
if (extension.meta.translations) {
for (const [dictionaryName, dictionary] of Object.entries(extension.meta.translations)) {
this.#addOrUpdateDictionary(innerDictionary, dictionaryName, dictionary);
}
}
// If extension contains a js file, load it and add the default dictionary to the inner dictionary.
const loadedExtension = await loadExtension(extension);
if (loadedExtension && hasDefaultExport(loadedExtension)) {
for (const [dictionaryName, dictionary] of Object.entries(loadedExtension.default)) {
this.#addOrUpdateDictionary(innerDictionary, dictionaryName, dictionary);
}
}
// Notify subscribers that the inner dictionary has changed.
const translation: Translation = {
$code: userCulture,
$dir: 'ltr',
...innerDictionary,
};
registerTranslation(translation);
})
);
});
this.#currentLanguage.next(userCulture.toLowerCase());
}
#addOrUpdateDictionary(