diff --git a/config/localization-coverage-allowlist.json b/config/localization-coverage-allowlist.json index b48256adf..b40959e7e 100644 --- a/config/localization-coverage-allowlist.json +++ b/config/localization-coverage-allowlist.json @@ -5,5 +5,40 @@ "text": "Terminal 1", "dynamic": false, "count": 1 + }, + { + "filePath": "src/renderer/src/components/settings/appearance-search.ts", + "kind": "object-property:keywords", + "text": "语言", + "dynamic": false, + "count": 1 + }, + { + "filePath": "src/renderer/src/components/settings/appearance-search.ts", + "kind": "object-property:keywords", + "text": "語言", + "dynamic": false, + "count": 1 + }, + { + "filePath": "src/renderer/src/components/settings/appearance-search.ts", + "kind": "object-property:keywords", + "text": "언어", + "dynamic": false, + "count": 1 + }, + { + "filePath": "src/renderer/src/components/settings/appearance-search.ts", + "kind": "object-property:keywords", + "text": "言語", + "dynamic": false, + "count": 1 + }, + { + "filePath": "src/renderer/src/components/settings/appearance-search.ts", + "kind": "object-property:keywords", + "text": "Idioma", + "dynamic": false, + "count": 1 } ] diff --git a/src/renderer/src/components/settings/appearance-search.test.ts b/src/renderer/src/components/settings/appearance-search.test.ts new file mode 100644 index 000000000..4b8c29781 --- /dev/null +++ b/src/renderer/src/components/settings/appearance-search.test.ts @@ -0,0 +1,32 @@ +import { afterEach, describe, expect, it } from 'vitest' + +import { i18n } from '@/i18n/i18n' +import { getLanguageEntries } from './appearance-search' +import { matchesSettingsSearch } from './settings-search' + +// Native word for "language" in each supported UI language. These must be +// findable no matter which locale the interface is currently rendered in, so a +// speaker can locate (and switch to) their language from any starting point. +const NATIVE_LANGUAGE_WORDS = ['语言', '語言', '언어', '言語', 'Idioma'] + +describe('getLanguageEntries', () => { + afterEach(async () => { + await i18n.changeLanguage('en') + }) + + it.each(['en', 'zh', 'ko', 'ja', 'es'])( + 'indexes every native word for "language" under the %s UI locale', + async (locale) => { + await i18n.changeLanguage(locale) + const entry = getLanguageEntries()[0] + for (const word of NATIVE_LANGUAGE_WORDS) { + expect(matchesSettingsSearch(word, entry)).toBe(true) + } + } + ) + + it('matches the Spanish native language name in English UI', async () => { + await i18n.changeLanguage('en') + expect(matchesSettingsSearch('Español', getLanguageEntries()[0])).toBe(true) + }) +}) diff --git a/src/renderer/src/components/settings/appearance-search.ts b/src/renderer/src/components/settings/appearance-search.ts index 3e15d2662..1886409e9 100644 --- a/src/renderer/src/components/settings/appearance-search.ts +++ b/src/renderer/src/components/settings/appearance-search.ts @@ -49,6 +49,15 @@ export const getLanguageEntries = createLocalizedCatalog((): SettingsSearchEntry ...translateSearchKeyword('settings.appearance.language.chinese', '中文(简体)'), ...translateSearchKeyword('settings.appearance.language.korean', '한국어'), ...translateSearchKeyword('settings.appearance.language.japanese', '日本語'), + ...translateSearchKeyword('settings.appearance.language.spanish', 'Español'), + // Why: the native word for "language" only reaches search via the localized + // title in its own UI locale — index each here so speakers can find (and + // switch to) their language whatever the current interface locale is. + '语言', // Chinese (Simplified) + '語言', // Chinese (Traditional) + '언어', // Korean + '言語', // Japanese + 'Idioma', // Spanish ...translateSearchKeyword( 'auto.components.settings.appearance.search.language.locale', 'locale'