Skip to content

Commit 2c58c70

Browse files
authored
V16: Localization refinements (#19258)
1 parent 6de255f commit 2c58c70

File tree

32 files changed

+478
-2997
lines changed

32 files changed

+478
-2997
lines changed

src/Umbraco.Web.UI.Client/src/assets/lang/de-ch.ts

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts

Lines changed: 22 additions & 2548 deletions
Large diffs are not rendered by default.

src/Umbraco.Web.UI.Client/src/assets/lang/en.ts

Lines changed: 237 additions & 207 deletions
Large diffs are not rendered by default.

src/Umbraco.Web.UI.Client/src/assets/lang/fr-ch.ts

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/Umbraco.Web.UI.Client/src/assets/lang/it-ch.ts

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/Umbraco.Web.UI.Client/src/assets/lang/pt-br.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
* Creator Link: https://docs.umbraco.com/umbraco-cms/extending/language-files
44
*
55
* Language Alias: pt
6-
* Language Int Name: Portuguese (BR)
7-
* Language Local Name: português (BR)
6+
* Language Int Name: Portuguese (Brazil)
7+
* Language Local Name: Português ()
88
* Language LCID:
99
* Language Culture: pt-BR
1010
*/
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* Creator Name: The Umbraco community
3+
* Creator Link: https://docs.umbraco.com/umbraco-cms/extending/language-files
4+
*
5+
* Language Alias: pt
6+
* Language Int Name: Portuguese
7+
* Language Local Name: Português
8+
* Language LCID:
9+
* Language Culture: pt-PT
10+
*/
11+
import type { UmbLocalizationDictionary } from '@umbraco-cms/backoffice/localization-api';
12+
export default {} as UmbLocalizationDictionary;

src/Umbraco.Web.UI.Client/src/packages/core/localization/components/ui-culture-input/ui-culture-input.element.ts

Lines changed: 75 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,121 @@
1-
import type { ManifestLocalization } from '../../extensions/localization.extension.js';
1+
import { customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit';
22
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
3-
import { css, html, customElement, query, state, property } from '@umbraco-cms/backoffice/external/lit';
4-
import type { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui';
5-
import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui';
63
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
74
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
5+
import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';
6+
import { UMB_DEFAULT_LOCALIZATION_CULTURE } from '@umbraco-cms/backoffice/localization-api';
7+
import type { PropertyValues } from '@umbraco-cms/backoffice/external/lit';
8+
import type { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui';
89

910
interface UmbCultureInputOption {
1011
name: string;
1112
value: string;
1213
}
1314

1415
@customElement('umb-ui-culture-input')
15-
export class UmbUiCultureInputElement extends UUIFormControlMixin(UmbLitElement, '') {
16+
export class UmbUiCultureInputElement extends UmbFormControlMixin<string, typeof UmbLitElement, undefined>(
17+
UmbLitElement,
18+
) {
19+
#invalidCulture?: string;
20+
#invalidBaseCulture?: string;
21+
1622
@state()
1723
private _options: Array<UmbCultureInputOption> = [];
1824

19-
@query('uui-combobox')
20-
private _selectElement!: HTMLInputElement;
21-
2225
@property({ type: String })
23-
override get value() {
24-
return super.value;
25-
}
26-
override set value(value: FormDataEntryValue | FormData) {
27-
if (typeof value === 'string') {
26+
override set value(value: string | undefined) {
27+
if (value && typeof value === 'string') {
2828
const oldValue = super.value;
2929
super.value = value.toLowerCase();
3030
this.requestUpdate('value', oldValue);
3131
}
3232
}
33+
override get value(): string | undefined {
34+
return super.value;
35+
}
3336

3437
constructor() {
3538
super();
36-
this.#observeTranslations();
37-
}
3839

39-
#observeTranslations() {
4040
this.observe(
4141
umbExtensionsRegistry.byType('localization'),
42-
(localizationManifests) => {
43-
this.#mapToOptions(localizationManifests);
42+
(manifests) => {
43+
const options = manifests
44+
.filter((manifest) => !!manifest.meta.culture)
45+
.map((manifest) => {
46+
const culture = manifest.meta.culture.toLowerCase();
47+
return {
48+
name: this.localize.term(`uiCulture_${culture}`),
49+
value: culture,
50+
};
51+
});
52+
53+
const distinct = [...new Map(options.map((item) => [item.value, item])).values()];
54+
55+
this._options = distinct.sort((a, b) => a.name.localeCompare(b.name));
4456
},
4557
'umbObserveLocalizationManifests',
4658
);
47-
}
4859

49-
#mapToOptions(manifests: Array<ManifestLocalization>) {
50-
this._options = manifests
51-
.filter((isoCode) => isoCode !== undefined)
52-
.map((manifest) => ({
53-
name: manifest.name,
54-
value: manifest.meta.culture.toLowerCase(),
55-
}));
60+
this.addValidator(
61+
'customError',
62+
() => this.localize.term('user_languageNotFound', this.#invalidCulture, this.value),
63+
() => !!this.#invalidCulture && !this.#invalidBaseCulture,
64+
);
65+
66+
this.addValidator(
67+
'customError',
68+
() => this.localize.term('user_languageNotFoundFallback', this.#invalidCulture, this.#invalidBaseCulture),
69+
() => !!this.#invalidCulture && !!this.#invalidBaseCulture,
70+
);
5671
}
5772

58-
protected override getFormElement() {
59-
return this._selectElement;
73+
protected override firstUpdated(_changedProperties: PropertyValues): void {
74+
super.firstUpdated(_changedProperties);
75+
76+
if (this.value) {
77+
// Check if the culture can be found.
78+
const found = this._options.find((option) => option.value === this.value);
79+
if (!found) {
80+
this.#invalidCulture = this.value;
81+
82+
// if not found, check for the base culture
83+
const locale = new Intl.Locale(this.value);
84+
if (locale.language) {
85+
const foundBase = this._options.find((option) => option.value === locale.language);
86+
if (foundBase) {
87+
this.value = locale.language;
88+
} else {
89+
// if the base culture is not found, set the value to "en"
90+
this.#invalidBaseCulture = locale.language;
91+
this.value = UMB_DEFAULT_LOCALIZATION_CULTURE;
92+
}
93+
} else {
94+
// if the base culture is not found, set the value to "en"
95+
this.value = UMB_DEFAULT_LOCALIZATION_CULTURE;
96+
}
97+
}
98+
}
99+
100+
this.addFormControlElement(this.shadowRoot!.querySelector('uui-select')!);
101+
this.checkValidity();
60102
}
61103

62104
#onCustomValidationChange(event: UUISelectEvent) {
105+
this.#invalidCulture = undefined;
106+
this.#invalidBaseCulture = undefined;
63107
this.value = event.target.value.toString();
64108
this.dispatchEvent(new UmbChangeEvent());
65109
}
66110

67111
override render() {
68112
return html`
69113
<uui-select
70-
style="margin-top: var(--uui-size-space-1)"
71-
@change=${this.#onCustomValidationChange}
72-
.options=${this._options.map((e) => ({
73-
name: e.name,
74-
value: e.value,
75-
selected: e.value == this.value,
76-
}))}></uui-select>
114+
.options=${this._options.map((e) => ({ ...e, selected: e.value == this.value }))}
115+
@change=${this.#onCustomValidationChange}>
116+
</uui-select>
77117
`;
78118
}
79-
80-
static override styles = [
81-
css`
82-
:host {
83-
display: block;
84-
}
85-
`,
86-
];
87119
}
88120

89121
export default UmbUiCultureInputElement;

0 commit comments

Comments
 (0)