|
|
|
|
@@ -1,256 +1,240 @@
|
|
|
|
|
import { aTimeout, elementUpdated, expect, fixture, html } from '@open-wc/testing';
|
|
|
|
|
import { umbTranslationRegistry } from '@umbraco-cms/backoffice/localization';
|
|
|
|
|
import { DefaultTranslationSet, TranslationSet, registerTranslation, translations } from './manager.js';
|
|
|
|
|
import { UmbLocalizeController } from './localize.controller.js';
|
|
|
|
|
import { customElement, property } from '@umbraco-cms/backoffice/external/lit';
|
|
|
|
|
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
|
|
|
|
import { ManifestTranslations, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
|
|
|
|
import { LitElement, customElement, property } from '@umbraco-cms/backoffice/external/lit';
|
|
|
|
|
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
|
|
|
|
|
import { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
|
|
|
|
|
|
|
|
|
@customElement('umb-localize-controller-host')
|
|
|
|
|
class UmbLocalizeControllerHostElement extends UmbLitElement {
|
|
|
|
|
@property()
|
|
|
|
|
lang = 'en-us';
|
|
|
|
|
class UmbLocalizeControllerHostElement extends UmbElementMixin(LitElement) {
|
|
|
|
|
@property() lang = 'en-us';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface TestTranslation extends TranslationSet {
|
|
|
|
|
close: string;
|
|
|
|
|
logout: string;
|
|
|
|
|
withInlineToken: string;
|
|
|
|
|
withInlineTokenLegacy: string;
|
|
|
|
|
notOnRegional: string;
|
|
|
|
|
numUsersSelected: (count: number) => string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//#region Translations
|
|
|
|
|
const english: ManifestTranslations = {
|
|
|
|
|
type: 'translations',
|
|
|
|
|
alias: 'test.en',
|
|
|
|
|
name: 'Test English',
|
|
|
|
|
meta: {
|
|
|
|
|
culture: 'en-us',
|
|
|
|
|
direction: 'ltr',
|
|
|
|
|
translations: {
|
|
|
|
|
general: {
|
|
|
|
|
close: 'Close',
|
|
|
|
|
logout: 'Log out',
|
|
|
|
|
withInlineToken: '{0} {1}',
|
|
|
|
|
withInlineTokenLegacy: '%0% %1%',
|
|
|
|
|
numUsersSelected: (count: number) => {
|
|
|
|
|
if (count === 0) return 'No users selected';
|
|
|
|
|
if (count === 1) return 'One user selected';
|
|
|
|
|
return `${count} users selected`;
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
const english: TestTranslation = {
|
|
|
|
|
$code: 'en-us',
|
|
|
|
|
$dir: 'ltr',
|
|
|
|
|
close: 'Close',
|
|
|
|
|
logout: 'Log out',
|
|
|
|
|
withInlineToken: '{0} {1}',
|
|
|
|
|
withInlineTokenLegacy: '%0% %1%',
|
|
|
|
|
notOnRegional: 'Not on regional',
|
|
|
|
|
numUsersSelected: (count: number) => {
|
|
|
|
|
if (count === 0) return 'No users selected';
|
|
|
|
|
if (count === 1) return 'One user selected';
|
|
|
|
|
return `${count} users selected`;
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const englishOverride: ManifestTranslations = {
|
|
|
|
|
type: 'translations',
|
|
|
|
|
alias: 'test.en.override',
|
|
|
|
|
name: 'Test English',
|
|
|
|
|
meta: {
|
|
|
|
|
culture: 'en-us',
|
|
|
|
|
translations: {
|
|
|
|
|
general: {
|
|
|
|
|
close: 'Close 2',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
const englishOverride: DefaultTranslationSet = {
|
|
|
|
|
$code: 'en-us',
|
|
|
|
|
$dir: 'ltr',
|
|
|
|
|
close: 'Close 2',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const danish: ManifestTranslations = {
|
|
|
|
|
type: 'translations',
|
|
|
|
|
alias: 'test.da',
|
|
|
|
|
name: 'Test Danish',
|
|
|
|
|
meta: {
|
|
|
|
|
culture: 'da',
|
|
|
|
|
translations: {
|
|
|
|
|
general: {
|
|
|
|
|
close: 'Luk',
|
|
|
|
|
notOnRegional: 'Not on regional',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
const danish: DefaultTranslationSet = {
|
|
|
|
|
$code: 'da',
|
|
|
|
|
$dir: 'ltr',
|
|
|
|
|
close: 'Luk',
|
|
|
|
|
notOnRegional: 'Not on regional',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const danishRegional: ManifestTranslations = {
|
|
|
|
|
type: 'translations',
|
|
|
|
|
alias: 'test.da-DK',
|
|
|
|
|
name: 'Test Danish (Denmark)',
|
|
|
|
|
meta: {
|
|
|
|
|
culture: 'da-DK',
|
|
|
|
|
translations: {
|
|
|
|
|
general: {
|
|
|
|
|
close: 'Luk',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
const danishRegional: DefaultTranslationSet = {
|
|
|
|
|
$code: 'da-dk',
|
|
|
|
|
$dir: 'ltr',
|
|
|
|
|
close: 'Luk',
|
|
|
|
|
};
|
|
|
|
|
//#endregion
|
|
|
|
|
|
|
|
|
|
describe('UmbLocalizeController', () => {
|
|
|
|
|
umbExtensionsRegistry.register(english);
|
|
|
|
|
umbExtensionsRegistry.register(danish);
|
|
|
|
|
umbExtensionsRegistry.register(danishRegional);
|
|
|
|
|
|
|
|
|
|
let element: UmbLocalizeControllerHostElement;
|
|
|
|
|
let controller: UmbLocalizeController<TestTranslation>;
|
|
|
|
|
|
|
|
|
|
beforeEach(async () => {
|
|
|
|
|
umbTranslationRegistry.loadLanguage(english.meta.culture);
|
|
|
|
|
element = await fixture(html`<umb-localize-controller-host></umb-localize-controller-host>`);
|
|
|
|
|
registerTranslation(english, danish, danishRegional);
|
|
|
|
|
document.documentElement.lang = english.$code;
|
|
|
|
|
document.documentElement.dir = english.$dir;
|
|
|
|
|
await aTimeout(0);
|
|
|
|
|
const host = {
|
|
|
|
|
getHostElement: () => document.createElement('div'),
|
|
|
|
|
addController: () => {},
|
|
|
|
|
removeController: () => {},
|
|
|
|
|
hasController: () => false,
|
|
|
|
|
getControllers: () => [],
|
|
|
|
|
removeControllerByAlias: () => {},
|
|
|
|
|
} satisfies UmbControllerHost;
|
|
|
|
|
controller = new UmbLocalizeController(host);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should have a localize controller', () => {
|
|
|
|
|
expect(element.localize).to.be.instanceOf(UmbLocalizeController);
|
|
|
|
|
afterEach(() => {
|
|
|
|
|
controller.destroy();
|
|
|
|
|
translations.clear();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should have a default language', () => {
|
|
|
|
|
expect(element.localize.lang()).to.equal(english.meta.culture);
|
|
|
|
|
expect(controller.lang()).to.equal(english.$code);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update the language when the language changes', async () => {
|
|
|
|
|
document.documentElement.lang = danishRegional.$code;
|
|
|
|
|
await aTimeout(0);
|
|
|
|
|
expect(controller.lang()).to.equal(danishRegional.$code);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should have a default dir', () => {
|
|
|
|
|
expect(element.localize.dir()).to.equal(english.meta.direction);
|
|
|
|
|
expect(controller.dir()).to.equal(english.$dir);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update the dir when the dir changes', async () => {
|
|
|
|
|
document.documentElement.dir = 'rtl';
|
|
|
|
|
await aTimeout(0);
|
|
|
|
|
expect(controller.dir()).to.equal('rtl');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('term', () => {
|
|
|
|
|
it('should return a term', async () => {
|
|
|
|
|
expect(element.localize.term('general_close')).to.equal('Close');
|
|
|
|
|
expect(controller.term('close')).to.equal('Close');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update the term when the language changes', async () => {
|
|
|
|
|
// Load Danish
|
|
|
|
|
umbTranslationRegistry.loadLanguage(danishRegional.meta.culture);
|
|
|
|
|
await aTimeout(0);
|
|
|
|
|
expect(document.documentElement.lang).to.equal(danishRegional.meta.culture);
|
|
|
|
|
|
|
|
|
|
// Force an element update as well
|
|
|
|
|
element.lang = danishRegional.meta.culture;
|
|
|
|
|
await elementUpdated(element);
|
|
|
|
|
expect(element.localize.term('general_close')).to.equal('Luk');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update the term when the dir changes', async () => {
|
|
|
|
|
expect(element.localize.term('general_close')).to.equal('Close');
|
|
|
|
|
element.dir = 'rtl';
|
|
|
|
|
await elementUpdated(element);
|
|
|
|
|
expect(element.localize.term('general_close')).to.equal('Close');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should provide a secondary term when the term is not found', async () => {
|
|
|
|
|
// Load Danish
|
|
|
|
|
umbTranslationRegistry.loadLanguage(danishRegional.meta.culture);
|
|
|
|
|
// Change language
|
|
|
|
|
document.documentElement.lang = danishRegional.$code;
|
|
|
|
|
await aTimeout(0);
|
|
|
|
|
|
|
|
|
|
element.lang = danishRegional.meta.culture;
|
|
|
|
|
await elementUpdated(element);
|
|
|
|
|
expect(element.localize.term('general_notOnRegional')).to.equal('Not on regional');
|
|
|
|
|
expect(controller.term('close')).to.equal('Luk');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should provide a fallback term when the term is not found', async () => {
|
|
|
|
|
it('should provide a secondary term when the term is not found on the regional language', async () => {
|
|
|
|
|
// Load Danish
|
|
|
|
|
umbTranslationRegistry.loadLanguage(danishRegional.meta.culture);
|
|
|
|
|
document.documentElement.lang = danishRegional.$code;
|
|
|
|
|
await aTimeout(0);
|
|
|
|
|
|
|
|
|
|
element.lang = danishRegional.meta.culture;
|
|
|
|
|
await elementUpdated(element);
|
|
|
|
|
expect(element.localize.term('general_close')).to.equal('Luk');
|
|
|
|
|
expect(element.localize.term('general_logout')).to.equal('Log out');
|
|
|
|
|
expect(controller.term('notOnRegional')).to.equal('Not on regional');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should override a term if new extension is registered', async () => {
|
|
|
|
|
umbExtensionsRegistry.register(englishOverride);
|
|
|
|
|
it('should provide a fallback term from the fallback language when the term is not found on primary or secondary', async () => {
|
|
|
|
|
// Load Danish
|
|
|
|
|
document.documentElement.lang = danishRegional.$code;
|
|
|
|
|
await aTimeout(0);
|
|
|
|
|
|
|
|
|
|
expect(controller.term('close')).to.equal('Luk'); // Primary
|
|
|
|
|
expect(controller.term('logout')).to.equal('Log out'); // Fallback
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should override a term if new translation is registered', () => {
|
|
|
|
|
// Let the registry load the new extension
|
|
|
|
|
await aTimeout(0);
|
|
|
|
|
await elementUpdated(element);
|
|
|
|
|
expect(element.localize.term('general_close')).to.equal('Close 2');
|
|
|
|
|
registerTranslation(englishOverride);
|
|
|
|
|
|
|
|
|
|
expect(controller.term('close')).to.equal('Close 2');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return a term with a custom format', async () => {
|
|
|
|
|
expect(element.localize.term('general_numUsersSelected', 0)).to.equal('No users selected');
|
|
|
|
|
expect(element.localize.term('general_numUsersSelected', 1)).to.equal('One user selected');
|
|
|
|
|
expect(element.localize.term('general_numUsersSelected', 2)).to.equal('2 users selected');
|
|
|
|
|
expect(controller.term('numUsersSelected', 0)).to.equal('No users selected');
|
|
|
|
|
expect(controller.term('numUsersSelected', 1)).to.equal('One user selected');
|
|
|
|
|
expect(controller.term('numUsersSelected', 2)).to.equal('2 users selected');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return a term with a custom format with inline tokens', async () => {
|
|
|
|
|
expect(element.localize.term('general_withInlineToken', 'Hello', 'World')).to.equal('Hello World');
|
|
|
|
|
expect(element.localize.term('general_withInlineTokenLegacy', 'Hello', 'World')).to.equal('Hello World');
|
|
|
|
|
expect(controller.term('withInlineToken', 'Hello', 'World')).to.equal('Hello World');
|
|
|
|
|
expect(controller.term('withInlineTokenLegacy', 'Hello', 'World')).to.equal('Hello World');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return a term with no tokens even though they are provided', async () => {
|
|
|
|
|
expect(element.localize.term('general_logout', 'Hello', 'World')).to.equal('Log out');
|
|
|
|
|
expect(controller.term('logout', 'Hello', 'World')).to.equal('Log out');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('date', () => {
|
|
|
|
|
it('should return a date', async () => {
|
|
|
|
|
expect(element.localize.date(new Date(2020, 0, 1))).to.equal('1/1/2020');
|
|
|
|
|
expect(controller.date(new Date(2020, 0, 1))).to.equal('1/1/2020');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should accept a string input', async () => {
|
|
|
|
|
expect(element.localize.date('2020-01-01')).to.equal('1/1/2020');
|
|
|
|
|
expect(controller.date('2020-01-01')).to.equal('1/1/2020');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update the date when the language changes', async () => {
|
|
|
|
|
expect(element.localize.date(new Date(2020, 11, 31))).to.equal('12/31/2020');
|
|
|
|
|
expect(controller.date(new Date(2020, 11, 31))).to.equal('12/31/2020');
|
|
|
|
|
|
|
|
|
|
// Switch browser to Danish
|
|
|
|
|
element.lang = danish.meta.culture;
|
|
|
|
|
document.documentElement.lang = danishRegional.$code;
|
|
|
|
|
await aTimeout(0);
|
|
|
|
|
|
|
|
|
|
await elementUpdated(element);
|
|
|
|
|
expect(element.localize.date(new Date(2020, 11, 31))).to.equal('31.12.2020');
|
|
|
|
|
expect(controller.date(new Date(2020, 11, 31))).to.equal('31.12.2020');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update the date when the dir changes', async () => {
|
|
|
|
|
expect(element.localize.date(new Date(2020, 11, 31))).to.equal('12/31/2020');
|
|
|
|
|
element.dir = 'rtl';
|
|
|
|
|
await elementUpdated(element);
|
|
|
|
|
expect(element.localize.date(new Date(2020, 11, 31))).to.equal('12/31/2020');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return a date with a custom format', async () => {
|
|
|
|
|
expect(
|
|
|
|
|
element.localize.date(new Date(2020, 11, 31), { month: 'long', day: '2-digit', year: 'numeric' })
|
|
|
|
|
).to.equal('December 31, 2020');
|
|
|
|
|
it('should return a date with a custom format', () => {
|
|
|
|
|
expect(controller.date(new Date(2020, 11, 31), { month: 'long', day: '2-digit', year: 'numeric' })).to.equal(
|
|
|
|
|
'December 31, 2020'
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('number', () => {
|
|
|
|
|
it('should return a number', async () => {
|
|
|
|
|
expect(element.localize.number(123456.789)).to.equal('123,456.789');
|
|
|
|
|
it('should return a number', () => {
|
|
|
|
|
expect(controller.number(123456.789)).to.equal('123,456.789');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should accept a string input', async () => {
|
|
|
|
|
expect(element.localize.number('123456.789')).to.equal('123,456.789');
|
|
|
|
|
it('should accept a string input', () => {
|
|
|
|
|
expect(controller.number('123456.789')).to.equal('123,456.789');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update the number when the language changes', async () => {
|
|
|
|
|
expect(element.localize.number(123456.789)).to.equal('123,456.789');
|
|
|
|
|
|
|
|
|
|
// Switch browser to Danish
|
|
|
|
|
element.lang = danish.meta.culture;
|
|
|
|
|
document.documentElement.lang = danishRegional.$code;
|
|
|
|
|
await aTimeout(0);
|
|
|
|
|
|
|
|
|
|
await elementUpdated(element);
|
|
|
|
|
expect(element.localize.number(123456.789)).to.equal('123.456,789');
|
|
|
|
|
expect(controller.number(123456.789)).to.equal('123.456,789');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update the number when the dir changes', async () => {
|
|
|
|
|
expect(element.localize.number(123456.789)).to.equal('123,456.789');
|
|
|
|
|
element.dir = 'rtl';
|
|
|
|
|
await elementUpdated(element);
|
|
|
|
|
expect(element.localize.number(123456.789)).to.equal('123,456.789');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return a number with a custom format', async () => {
|
|
|
|
|
expect(element.localize.number(123456.789, { minimumFractionDigits: 2, maximumFractionDigits: 2 })).to.equal(
|
|
|
|
|
it('should return a number with a custom format', () => {
|
|
|
|
|
expect(controller.number(123456.789, { minimumFractionDigits: 2, maximumFractionDigits: 2 })).to.equal(
|
|
|
|
|
'123,456.79'
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('relative time', () => {
|
|
|
|
|
it('should return a relative time', async () => {
|
|
|
|
|
expect(element.localize.relativeTime(2, 'days')).to.equal('in 2 days');
|
|
|
|
|
it('should return a relative time', () => {
|
|
|
|
|
expect(controller.relativeTime(2, 'days')).to.equal('in 2 days');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update the relative time when the language changes', async () => {
|
|
|
|
|
expect(element.localize.relativeTime(2, 'days')).to.equal('in 2 days');
|
|
|
|
|
// Switch browser to Danish
|
|
|
|
|
document.documentElement.lang = danishRegional.$code;
|
|
|
|
|
await aTimeout(0);
|
|
|
|
|
|
|
|
|
|
expect(controller.relativeTime(2, 'days')).to.equal('om 2 dage');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('host element', () => {
|
|
|
|
|
let element: UmbLocalizeControllerHostElement;
|
|
|
|
|
|
|
|
|
|
beforeEach(async () => {
|
|
|
|
|
element = await fixture(html`<umb-localize-controller-host></umb-localize-controller-host>`);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should have a localize controller', () => {
|
|
|
|
|
expect(element.localize).to.be.instanceOf(UmbLocalizeController);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update the term when the language changes', async () => {
|
|
|
|
|
expect(element.localize.term('close')).to.equal('Close');
|
|
|
|
|
|
|
|
|
|
// Switch browser to Danish
|
|
|
|
|
element.lang = danish.meta.culture;
|
|
|
|
|
element.lang = danishRegional.$code;
|
|
|
|
|
|
|
|
|
|
await elementUpdated(element);
|
|
|
|
|
expect(element.localize.relativeTime(2, 'days')).to.equal('om 2 dage');
|
|
|
|
|
expect(element.localize.term('close')).to.equal('Luk');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|