+ // Own the search term and filter manually. cmdk's built-in shouldFilter
+ // reorders items by its fuzzy-match score (≈alphabetical with an empty
+ // query), which destroys the curated en→zh→zh-hant→ja order. We disable it
+ // and do a plain substring filter that preserves array order — matching
+ // model-picker.tsx. Match against the endonym, the (hidden) English name,
+ // and the locale code so "日本"/"japanese"/"ja" all find Japanese.
+ const q = search.trim().toLowerCase()
+
+ const filtered = allLocales.filter(
+ ([code, meta]) =>
+ !q ||
+ meta.name.toLowerCase().includes(q) ||
+ meta.englishName.toLowerCase().includes(q) ||
+ code.toLowerCase().includes(q)
+ )
+
+ return (
+
+
+
+ {filtered.length === 0 ? (
+
{noResults}
+ ) : (
+ filtered.map(([code, meta]) => {
+ const selected = code === locale
+
+ return (
+ onSelect(code)}
+ value={code}
+ >
+
+ {meta.name}
+ {code}
+
+ )
+ })
+ )}
+
+
)
}
diff --git a/apps/desktop/src/i18n/en.ts b/apps/desktop/src/i18n/en.ts
index 17c42e2d365..8f99e8cdac5 100644
--- a/apps/desktop/src/i18n/en.ts
+++ b/apps/desktop/src/i18n/en.ts
@@ -132,7 +132,9 @@ export const en: Translations = {
description: 'Choose the language for the desktop interface.',
saving: 'Saving language…',
saveError: 'Language update failed',
- switchTo: 'Switch language'
+ switchTo: 'Switch language',
+ searchPlaceholder: 'Search languages…',
+ noResults: 'No languages found'
},
settings: {
diff --git a/apps/desktop/src/i18n/ja.ts b/apps/desktop/src/i18n/ja.ts
index 3c93dd39555..93177c380cf 100644
--- a/apps/desktop/src/i18n/ja.ts
+++ b/apps/desktop/src/i18n/ja.ts
@@ -21,7 +21,9 @@ export const ja = defineLocale({
description: 'デスクトップインターフェイスの言語を選択します。',
saving: '言語を保存中…',
saveError: '言語の更新に失敗しました',
- switchTo: '言語を切り替え'
+ switchTo: '言語を切り替え',
+ searchPlaceholder: '言語を検索…',
+ noResults: '言語が見つかりません'
},
settings: {
diff --git a/apps/desktop/src/i18n/languages.ts b/apps/desktop/src/i18n/languages.ts
index 2694b3ba5c3..5b4990f4970 100644
--- a/apps/desktop/src/i18n/languages.ts
+++ b/apps/desktop/src/i18n/languages.ts
@@ -6,31 +6,36 @@ export const LOCALE_OPTIONS = [
{
id: 'en',
name: 'English',
+ englishName: 'English',
configValue: 'en'
},
{
id: 'zh',
name: '简体中文',
+ englishName: 'Simplified Chinese',
configValue: 'zh'
},
{
id: 'zh-hant',
name: '繁體中文',
+ englishName: 'Traditional Chinese',
configValue: 'zh-hant'
},
{
id: 'ja',
name: '日本語',
+ englishName: 'Japanese',
configValue: 'ja'
}
-] as const satisfies readonly { configValue: string; id: Locale; name: string }[]
+] as const satisfies readonly { configValue: string; englishName: string; id: Locale; name: string }[]
-// Endonyms (native names) for the language picker so users recognize their
-// language regardless of the current UI language. No country flags:
-// languages are not countries.
-export const LOCALE_META: Record = Object.fromEntries(
- LOCALE_OPTIONS.map(locale => [locale.id, { name: locale.name }])
-) as Record
+// `name` is the endonym (native name) shown in the picker so users recognize
+// their language regardless of the current UI language. No country flags:
+// languages are not countries. `englishName` is search-only (not shown) so an
+// English speaker can type "japanese"/"traditional" to filter the list.
+export const LOCALE_META: Record = Object.fromEntries(
+ LOCALE_OPTIONS.map(locale => [locale.id, { name: locale.name, englishName: locale.englishName }])
+) as Record
const LOCALE_ALIASES: Record = {
en: 'en',
diff --git a/apps/desktop/src/i18n/types.ts b/apps/desktop/src/i18n/types.ts
index 6e7da1cbddc..7e794fc900d 100644
--- a/apps/desktop/src/i18n/types.ts
+++ b/apps/desktop/src/i18n/types.ts
@@ -144,6 +144,8 @@ export interface Translations {
saving: string
saveError: string
switchTo: string
+ searchPlaceholder: string
+ noResults: string
}
settings: {
diff --git a/apps/desktop/src/i18n/zh-hant.ts b/apps/desktop/src/i18n/zh-hant.ts
index fbfc0124312..d6d1b8c8b12 100644
--- a/apps/desktop/src/i18n/zh-hant.ts
+++ b/apps/desktop/src/i18n/zh-hant.ts
@@ -21,7 +21,9 @@ export const zhHant = defineLocale({
description: '選擇桌面介面的語言。',
saving: '正在儲存語言…',
saveError: '語言更新失敗',
- switchTo: '切換語言'
+ switchTo: '切換語言',
+ searchPlaceholder: '搜尋語言…',
+ noResults: '找不到語言'
},
settings: {
diff --git a/apps/desktop/src/i18n/zh.ts b/apps/desktop/src/i18n/zh.ts
index 3cdc6a01870..f9546491c1e 100644
--- a/apps/desktop/src/i18n/zh.ts
+++ b/apps/desktop/src/i18n/zh.ts
@@ -128,7 +128,9 @@ export const zh: Translations = {
description: '选择桌面界面的语言。',
saving: '正在保存语言…',
saveError: '语言更新失败',
- switchTo: '切换语言'
+ switchTo: '切换语言',
+ searchPlaceholder: '搜索语言…',
+ noResults: '未找到语言'
},
settings: {