Automatic language choices resolve only to supported languages; community translations are listed apart in Settings and offered as a one-click switch. waybetter i18n check reads `supported` and generates `tier` into languages.json. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
61 lines
3.9 KiB
TypeScript
61 lines
3.9 KiB
TypeScript
// Language tiers: automatic choices ("follow the site", "follow system") resolve only to supported
|
|
// languages through the fallback chain; a language picked explicitly applies whatever its tier;
|
|
// Settings → Language lists supported languages first and community translations apart.
|
|
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { communitySuggestion, resolveLocale } from '../src/frame/language.ts';
|
|
import { groupLanguages } from '../src/panel/languageModel.ts';
|
|
import type { PanelLanguage } from '../src/panel/site.ts';
|
|
|
|
const available = ['en', 'en-GB', 'de', 'pt', 'zh-Hans', 'zh-Hant', 'fr', 'ar', 'ar-x-fm', 'sv', 'pl'];
|
|
const supported = ['en', 'en-GB', 'de', 'pt', 'zh-Hant', 'fr', 'ar'];
|
|
|
|
test('automatic choices resolve only to supported languages, through the fallback chain', () => {
|
|
const auto = (system: string[]) => resolveLocale('system', null, system, available, supported);
|
|
assert.equal(auto(['pt-BR']), 'pt');
|
|
assert.equal(auto(['en-US']), 'en');
|
|
assert.equal(auto(['en-GB']), 'en-GB');
|
|
assert.equal(auto(['de-AT', 'en']), 'de');
|
|
assert.equal(resolveLocale('site', 'pt-BR', ['de'], available, supported), 'pt');
|
|
// A community language stays on English: system, site and the site's own tag alike.
|
|
assert.equal(auto(['sv-SE']), 'en');
|
|
assert.equal(auto(['pl']), 'en');
|
|
assert.equal(resolveLocale('site', 'sv', ['de'], available, supported), 'en', 'the site is Swedish (community): English, not the system language');
|
|
assert.equal(resolveLocale('site', null, ['sv'], available, supported), 'en');
|
|
// The next preference wins over English when it is supported.
|
|
assert.equal(auto(['sv', 'fr']), 'fr');
|
|
// Private-use variants and scripts fall back within the supported set.
|
|
assert.equal(auto(['ar-x-fm']), 'ar');
|
|
assert.equal(auto(['zh-Hant']), 'zh-Hant');
|
|
assert.equal(auto(['zh-Hans']), 'en', 'Simplified Chinese is community here');
|
|
});
|
|
|
|
test('with every language supported (the default) nothing changes', () => {
|
|
assert.equal(resolveLocale('system', null, ['sv-SE'], available), 'sv');
|
|
assert.equal(resolveLocale('site', 'pl', ['de'], available), 'pl');
|
|
});
|
|
|
|
test('an explicit pick always applies, whatever its tier', () => {
|
|
for (const code of available) assert.equal(resolveLocale(code, 'de', ['fr'], available, supported), code, code);
|
|
assert.equal(resolveLocale('sv-SE', null, ['fr'], available, supported), 'sv', 'a regional tag of a community language');
|
|
assert.equal(resolveLocale('xx', null, ['fr'], available, supported), 'fr', 'unknown: the system language');
|
|
});
|
|
|
|
test('a community language the site or system uses is suggested, never applied', () => {
|
|
assert.equal(communitySuggestion('site', 'sv', ['de'], available, supported), 'sv');
|
|
assert.equal(communitySuggestion('site', null, ['pl-PL'], available, supported), 'pl');
|
|
assert.equal(communitySuggestion('system', null, ['sv'], available, supported), 'sv');
|
|
assert.equal(communitySuggestion('site', 'pt-BR', ['sv'], available, supported), null, 'supported: nothing to suggest');
|
|
assert.equal(communitySuggestion('site', 'xx', ['de'], available, supported), null, 'not offered at all');
|
|
assert.equal(communitySuggestion('sv', 'sv', ['sv'], available, supported), null, 'an explicit pick needs no hint');
|
|
assert.equal(communitySuggestion('system', null, ['sv'], available), null, 'no tiers');
|
|
});
|
|
|
|
test('Settings groups supported languages first and community ones apart, order kept', () => {
|
|
const row = (code: string, tier: PanelLanguage['tier']): PanelLanguage => ({ code, name: code, englishName: code, dir: 'ltr', status: 'machine', tier, coverage: 1 });
|
|
const list = [row('en', 'supported'), row('sv', 'community'), row('de', 'supported'), row('pl', 'community')];
|
|
const groups = groupLanguages(list);
|
|
assert.deepEqual(groups.supported.map(language => language.code), ['en', 'de']);
|
|
assert.deepEqual(groups.community.map(language => language.code), ['sv', 'pl']);
|
|
assert.deepEqual(groupLanguages([row('en', 'supported')]).community, []);
|
|
});
|