Merge remote-tracking branch 'origin/main' into german/hal-638-fr

# Conflicts:
#	docs/CURRENT-STATE.md
#	docs/TRANSLATORS.md
#	scripts/package-boundaries.json
#	src/i18n/i18n.test.mjs
#	src/i18n/index.js
#	src/i18n/locale.js
#	src/i18n/same-as-english.json
#	src/scenes/recipes.js
#	src/ui/localePicker.test.mjs
#	src/ui/templates/context.html
This commit is contained in:
German Khokhlov committed 2026-10-29 17:55:01 +04:00
commit 727825b576
41 files changed
+10421 -102

No files matched your search

+19 -7
View File
@@ -31,6 +31,9 @@ const MANY = Object.keys(NAMES);
const codes = (rows) => rows.map((row) => row.code);
// Few enough languages that the picker has no search field.
const UNSEARCHED = ['en', 'es', 'ru', 'uk', 'zh-CN', 'zh-Hant'];
test('the current language comes first, the rest by their own names', () => {
assert.deepEqual(
codes(
@@ -40,7 +43,7 @@ test('the current language comes first, the rest by their own names', () => {
nativeNames: LOCALE_NAMES,
}),
),
['ru', 'en', 'es', 'fr', 'zh-CN', 'zh-Hant'],
['ru', 'uk', 'en', 'es', 'fr', 'it', 'pt', 'zh-CN', 'zh-Hant'],
);
assert.deepEqual(
codes(
@@ -50,7 +53,7 @@ test('the current language comes first, the rest by their own names', () => {
nativeNames: LOCALE_NAMES,
}),
),
['es', 'en', 'fr', 'ru', 'zh-CN', 'zh-Hant'],
['es', 'en', 'fr', 'it', 'pt', 'ru', 'uk', 'zh-CN', 'zh-Hant'],
);
assert.deepEqual(
codes(
@@ -60,7 +63,7 @@ test('the current language comes first, the rest by their own names', () => {
nativeNames: LOCALE_NAMES,
}),
),
['en', 'es', 'fr', 'ru', 'zh-CN', 'zh-Hant'],
['en', 'es', 'fr', 'it', 'pt', 'ru', 'uk', 'zh-CN', 'zh-Hant'],
);
const rows = buildLocaleOptions({
locales: MANY,
@@ -167,7 +170,10 @@ test('search folds case and diacritics, and matches either name or the code', ()
test('the search field appears only above the threshold', () => {
assert.equal(LOCALE_SEARCH_THRESHOLD, 8);
assert.equal(createLocalePickerModel({ current: 'en' }).searchable, false);
assert.equal(
createLocalePickerModel({ current: 'en' }).searchable,
LOCALES.length > LOCALE_SEARCH_THRESHOLD,
);
const eight = MANY.slice(0, 8);
assert.equal(
createLocalePickerModel({
@@ -252,6 +258,7 @@ test('type-ahead cycles by first letter and refines with more letters', () => {
test('keyboard model: open on the current language, move, choose, close', () => {
const model = createLocalePickerModel({
locales: UNSEARCHED,
current: 'ru',
localName: createLocalNameReader('ru'),
});
@@ -263,7 +270,8 @@ test('keyboard model: open on the current language, move, choose, close', () =>
model.openList();
assert.equal(model.activeOption.code, 'ru');
assert.deepEqual(model.keydown({ key: 'ArrowDown' }), { handled: true });
assert.equal(model.activeOption.code, 'en');
// Russian collation puts the other Cyrillic name next.
assert.equal(model.activeOption.code, 'uk');
model.keydown({ key: 'End' });
assert.equal(model.activeOption.code, 'zh-Hant');
model.keydown({ key: 'Home' });
@@ -277,7 +285,7 @@ test('keyboard model: open on the current language, move, choose, close', () =>
model.keydown({ key: 'ArrowDown' });
assert.deepEqual(model.keydown({ key: ' ' }), {
handled: true,
choose: 'en',
choose: 'uk',
});
assert.deepEqual(model.keydown({ key: 'Escape' }), {
handled: true,
@@ -294,7 +302,11 @@ test('keyboard model: open on the current language, move, choose, close', () =>
test('keyboard model: type-ahead resets after a pause and ignores shortcuts', () => {
let clock = 0;
const model = createLocalePickerModel({ current: 'en', now: () => clock });
const model = createLocalePickerModel({
locales: UNSEARCHED,
current: 'en',
now: () => clock,
});
model.openList();
assert.deepEqual(model.keydown({ key: 'e' }), { handled: true });
assert.equal(model.activeOption.code, 'es');