fix(input-tel): use full locale to translate country names in dropdown (#2526)

* fix(input-tel): use full locale to translate country names in dropdown

* test(input-tel): add test for nameForLocale in input tel dropdown

* test(input-tel): update name for locale test suite to fr-BE locale
This commit is contained in:
Stijn Van Asschodt 2025-07-02 09:56:50 +02:00 committed by GitHub
parent e8975f36cf
commit dc5d224e98
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 97 additions and 4 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/ui': patch
---
fix(input-tel): use full locale to translate country names in dropdown

View file

@ -4,6 +4,7 @@ import { ref, createRef } from 'lit/directives/ref.js';
import { LionInputTel } from '@lion/ui/input-tel.js'; import { LionInputTel } from '@lion/ui/input-tel.js';
import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js'; import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js';
import { getFlagSymbol } from './getFlagSymbol.js'; import { getFlagSymbol } from './getFlagSymbol.js';
import { regionCodeToLocale } from './regionCodeToLocale.js';
/** /**
* Note: one could consider to implement LionInputTelDropdown as a * Note: one could consider to implement LionInputTelDropdown as a
@ -193,8 +194,7 @@ export class LionInputTelDropdown extends LionInputTel {
onLocaleUpdated() { onLocaleUpdated() {
super.onLocaleUpdated(); super.onLocaleUpdated();
// @ts-expect-error relatively new platform api this.__namesForLocale = new Intl.DisplayNames([this._localizeManager.locale], {
this.__namesForLocale = new Intl.DisplayNames([this._langIso], {
type: 'region', type: 'region',
}); });
this.__createRegionMeta(); this.__createRegionMeta();
@ -408,7 +408,7 @@ export class LionInputTelDropdown extends LionInputTel {
this.__regionMetaListPreferred = []; this.__regionMetaListPreferred = [];
this._allowedOrAllRegions.forEach(regionCode => { this._allowedOrAllRegions.forEach(regionCode => {
// @ts-ignore relatively new platform api // @ts-ignore relatively new platform api
const namesForRegion = new Intl.DisplayNames([regionCode.toLowerCase()], { const namesForRegion = new Intl.DisplayNames([regionCodeToLocale(regionCode)], {
type: 'region', type: 'region',
}); });
const countryCode = const countryCode =

View file

@ -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;
}

View file

@ -133,7 +133,7 @@ export function runInputTelDropdownSuite({ klass } = { klass: LionInputTelDropdo
countryCode: 63, countryCode: 63,
flagSymbol: '🇵🇭', flagSymbol: '🇵🇭',
nameForLocale: 'Philippines', nameForLocale: 'Philippines',
nameForRegion: 'Philippines', nameForRegion: 'Pilipinas',
regionCode: 'PH', regionCode: 'PH',
}, },
], ],
@ -239,6 +239,74 @@ export function runInputTelDropdownSuite({ klass } = { klass: LionInputTelDropdo
restorePhoneUtilManager(); restorePhoneUtilManager();
spy.restore(); spy.restore();
}); });
it('has the correct nameForLocale, based on browser language', async () => {
const el = fixtureSync(html` <${tag}
.modelValue="${'+31612345678'}"
.allowedRegions="${['NL', 'PH']}"
.preferredRegions="${['PH']}"
></${tag}> `);
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', () => { describe('On dropdown value change', () => {

View file

@ -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');
});
});