diff --git a/.changeset/witty-geese-exercise.md b/.changeset/witty-geese-exercise.md new file mode 100644 index 000000000..04092df29 --- /dev/null +++ b/.changeset/witty-geese-exercise.md @@ -0,0 +1,5 @@ +--- +'@lion/ui': patch +--- + +fix(input-tel): use full locale to translate country names in dropdown diff --git a/packages/ui/components/input-tel-dropdown/src/LionInputTelDropdown.js b/packages/ui/components/input-tel-dropdown/src/LionInputTelDropdown.js index ca7057b61..82146194c 100644 --- a/packages/ui/components/input-tel-dropdown/src/LionInputTelDropdown.js +++ b/packages/ui/components/input-tel-dropdown/src/LionInputTelDropdown.js @@ -4,6 +4,7 @@ import { ref, createRef } from 'lit/directives/ref.js'; import { LionInputTel } from '@lion/ui/input-tel.js'; import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js'; import { getFlagSymbol } from './getFlagSymbol.js'; +import { regionCodeToLocale } from './regionCodeToLocale.js'; /** * Note: one could consider to implement LionInputTelDropdown as a @@ -193,8 +194,7 @@ export class LionInputTelDropdown extends LionInputTel { onLocaleUpdated() { super.onLocaleUpdated(); - // @ts-expect-error relatively new platform api - this.__namesForLocale = new Intl.DisplayNames([this._langIso], { + this.__namesForLocale = new Intl.DisplayNames([this._localizeManager.locale], { type: 'region', }); this.__createRegionMeta(); @@ -408,7 +408,7 @@ export class LionInputTelDropdown extends LionInputTel { this.__regionMetaListPreferred = []; this._allowedOrAllRegions.forEach(regionCode => { // @ts-ignore relatively new platform api - const namesForRegion = new Intl.DisplayNames([regionCode.toLowerCase()], { + const namesForRegion = new Intl.DisplayNames([regionCodeToLocale(regionCode)], { type: 'region', }); const countryCode = diff --git a/packages/ui/components/input-tel-dropdown/src/regionCodeToLocale.js b/packages/ui/components/input-tel-dropdown/src/regionCodeToLocale.js new file mode 100644 index 000000000..e40b220e6 --- /dev/null +++ b/packages/ui/components/input-tel-dropdown/src/regionCodeToLocale.js @@ -0,0 +1,10 @@ +/** + * Get the full locale for a region. + * As we don't know the language for that region, we first set it as 'und', which stands for 'undetermined'. + * @param {string} regionCode + */ +export function regionCodeToLocale(regionCode) { + const locale = new Intl.Locale('und', { region: regionCode }); // Set language as undetermined. + const maximizedLocale = locale.maximize(); // Determine the most likely full locale for a region with an undetermined language. + return maximizedLocale.baseName; +} diff --git a/packages/ui/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.js b/packages/ui/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.js index 750c7c3f8..30fa6f87e 100644 --- a/packages/ui/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.js +++ b/packages/ui/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.js @@ -133,7 +133,7 @@ export function runInputTelDropdownSuite({ klass } = { klass: LionInputTelDropdo countryCode: 63, flagSymbol: '🇵🇭', nameForLocale: 'Philippines', - nameForRegion: 'Philippines', + nameForRegion: 'Pilipinas', regionCode: 'PH', }, ], @@ -239,6 +239,74 @@ export function runInputTelDropdownSuite({ klass } = { klass: LionInputTelDropdo restorePhoneUtilManager(); spy.restore(); }); + + it('has the correct nameForLocale, based on browser language', async () => { + const el = fixtureSync(html` <${tag} + .modelValue="${'+31612345678'}" + .allowedRegions="${['NL', 'PH']}" + .preferredRegions="${['PH']}" + > `); + const spy = sinon.spy( + /** @type {typeof LionInputTelDropdown} */ (el.constructor).templates, + 'dropdown', + ); + // @ts-ignore + const originalLocale = el._localizeManager.locale; + // @ts-ignore + el._localizeManager.locale = 'fr-BE'; + await el.updateComplete; + const dropdownNode = el.refs.dropdown.value; + const templateDataForDropdown = /** @type {TemplateDataForDropdownInputTel} */ ( + spy.args[0][0] + ); + expect(templateDataForDropdown).to.eql( + /** @type {TemplateDataForDropdownInputTel} */ ({ + data: { + activeRegion: 'NL', + regionMetaList: [ + { + countryCode: 31, + flagSymbol: '🇳🇱', + nameForLocale: 'Pays-Bas', + nameForRegion: 'Nederland', + regionCode: 'NL', + }, + ], + regionMetaListPreferred: [ + { + countryCode: 63, + flagSymbol: '🇵🇭', + nameForLocale: 'Philippines', + nameForRegion: 'Pilipinas', + regionCode: 'PH', + }, + ], + }, + refs: { + dropdown: { + labels: { + allCountries: 'Tous les pays', + preferredCountries: 'Pays suggérés', + selectCountry: 'Sélectionnez un pays', + }, + listeners: { + // @ts-expect-error [allow-protected] + change: el._onDropdownValueChange, + // @ts-expect-error [allow-protected] + 'model-value-changed': el._onDropdownValueChange, + }, + props: { style: 'height: 100%;' }, + ref: { value: dropdownNode }, + }, + // @ts-expect-error [allow-protected] + input: el._inputNode, + }, + }), + ); + spy.restore(); + // @ts-ignore + el._localizeManager.locale = originalLocale; // restore the locale back to original + }); }); describe('On dropdown value change', () => { diff --git a/packages/ui/components/input-tel-dropdown/test/regionCodeToLocale.test.js b/packages/ui/components/input-tel-dropdown/test/regionCodeToLocale.test.js new file mode 100644 index 000000000..bf8bf0c9e --- /dev/null +++ b/packages/ui/components/input-tel-dropdown/test/regionCodeToLocale.test.js @@ -0,0 +1,10 @@ +import { expect } from '@open-wc/testing'; +import { regionCodeToLocale } from '../src/regionCodeToLocale.js'; + +describe('regionCodeToLocale', () => { + it('returns the most likely locale basename for a region', () => { + expect(regionCodeToLocale('NL')).to.equal('nl-Latn-NL'); + expect(regionCodeToLocale('FR')).to.equal('fr-Latn-FR'); + expect(regionCodeToLocale('DE')).to.equal('de-Latn-DE'); + }); +});