V15: A user cannot switch back to the default language (#18414)

* chore: prettier

* fix: loads all extensions everytime but register only new localizations

this ensures that the browser is updated even if you switch back to a previously loaded language

* test: adds a test to check if we can switch between already loaded languages
This commit is contained in:
Jacob Overgaard
2025-02-21 16:58:23 +01:00
committed by GitHub
parent a0ddaefaa1
commit d5e2efbbaa
3 changed files with 71 additions and 22 deletions

View File

@@ -1261,7 +1261,8 @@ export default {
colorsTitle: 'Colours',
colorsDescription: 'Add, remove or sort colours',
showLabelTitle: 'Include labels?',
showLabelDescription: 'Stores colours as a JSON object containing both the colour hex string and label, rather than just the hex string.',
showLabelDescription:
'Stores colours as a JSON object containing both the colour hex string and label, rather than just the hex string.',
},
contentPicker: {
allowedItemTypes: 'You can only select items of type(s): %0%',

View File

@@ -4,15 +4,30 @@ import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registr
import type { ManifestLocalization } from '../extensions/localization.extension.js';
//#region Localizations
const english: ManifestLocalization = {
const englishUk: ManifestLocalization = {
type: 'localization',
alias: 'test.en',
name: 'Test English',
name: 'Test English (UK)',
meta: {
culture: 'en',
localizations: {
general: {
color: 'Colour',
},
},
},
};
const english: ManifestLocalization = {
type: 'localization',
alias: 'test.en-us',
name: 'Test English (US)',
meta: {
culture: 'en-us',
direction: 'ltr',
localizations: {
general: {
color: 'Color',
close: 'Close',
logout: 'Log out',
withInlineToken: '{0} {1}',
@@ -72,6 +87,7 @@ const danishRegional: ManifestLocalization = {
//#endregion
describe('UmbLocalizeController', () => {
umbExtensionsRegistry.register(englishUk);
umbExtensionsRegistry.register(english);
umbExtensionsRegistry.register(danish);
umbExtensionsRegistry.register(danishRegional);
@@ -111,6 +127,32 @@ describe('UmbLocalizeController', () => {
expect(current).to.have.property('general_logout', 'Log out');
});
it('should be able to switch to the fallback language', async () => {
// Verify that the document language and direction is set correctly to the default language
expect(document.documentElement.lang).to.equal(english.meta.culture);
expect(document.documentElement.dir).to.equal(english.meta.direction);
// Switch to the fallback language, which is the UK version of English
registry.loadLanguage('en');
await aTimeout(0);
expect(document.documentElement.lang).to.equal('en');
expect(document.documentElement.dir).to.equal('ltr');
const current = registry.localizations.get(englishUk.meta.culture);
expect(current).to.have.property('general_color', 'Colour');
// And switch back again
registry.loadLanguage('en-us');
await aTimeout(0);
expect(document.documentElement.lang).to.equal('en-us');
expect(document.documentElement.dir).to.equal('ltr');
const newCurrent = registry.localizations.get(english.meta.culture);
expect(newCurrent).to.have.property('general_color', 'Color');
});
it('should load a new language', async () => {
registry.loadLanguage(danish.meta.culture);

View File

@@ -48,33 +48,39 @@ export class UmbLocalizationRegistry {
combineLatest([this.currentLanguage, extensionRegistry.byType('localization')]).subscribe(
async ([currentLanguage, extensions]) => {
const locale = new Intl.Locale(currentLanguage);
const filteredExt = extensions.filter(
const currentLanguageExtensions = extensions.filter(
(ext) =>
ext.meta.culture.toLowerCase() === locale.baseName.toLowerCase() ||
ext.meta.culture.toLowerCase() === locale.language.toLowerCase(),
);
// Only get the extensions that are not already loading/loaded:
const diff = filteredExt.filter((ext) => !this.#loadedExtAliases.includes(ext.alias));
if (diff.length !== 0) {
// got new localizations to load:
const translations = await Promise.all(diff.map(this.#loadExtension));
// If there are no extensions for the current language, return early
if (!currentLanguageExtensions.length) return;
if (translations.length) {
umbLocalizationManager.registerManyLocalizations(translations);
// Register the new translations only if they have not been registered before
const diff = currentLanguageExtensions.filter((ext) => !this.#loadedExtAliases.includes(ext.alias));
// Set the document language
const newLang = locale.baseName.toLowerCase();
if (document.documentElement.lang.toLowerCase() !== newLang) {
document.documentElement.lang = newLang;
}
// Load all localizations
const translations = await Promise.all(currentLanguageExtensions.map(this.#loadExtension));
// Set the document direction to the direction of the primary language
const newDir = translations[0].$dir ?? 'ltr';
if (document.documentElement.dir !== newDir) {
document.documentElement.dir = newDir;
}
}
// If there are no translations, return early
if (!translations.length) return;
if (diff.length) {
const filteredTranslations = translations.filter((t) => diff.some((ext) => ext.meta.culture === t.$code));
umbLocalizationManager.registerManyLocalizations(filteredTranslations);
}
// Set the document language
const newLang = locale.baseName.toLowerCase();
if (document.documentElement.lang.toLowerCase() !== newLang) {
document.documentElement.lang = newLang;
}
// Set the document direction to the direction of the primary language
const newDir = translations[0].$dir ?? 'ltr';
if (document.documentElement.dir !== newDir) {
document.documentElement.dir = newDir;
}
},
);