diff --git a/desktop/src/i18n/locales/en.ts b/desktop/src/i18n/locales/en.ts index bffd7fcc..d7fc56f0 100644 --- a/desktop/src/i18n/locales/en.ts +++ b/desktop/src/i18n/locales/en.ts @@ -669,6 +669,9 @@ export const en = { 'settings.general.appearance.dark': 'Dark', 'settings.general.languageTitle': 'Language', 'settings.general.languageDescription': 'Choose the display language for the application.', + 'settings.general.responseLangTitle': 'Response Language', + 'settings.general.responseLangDescription': 'Instruct Claude to always respond in a specific language.', + 'settings.general.responseLangDefault': 'Default (English)', 'settings.general.effortTitle': 'Effort Level', 'settings.general.effortDescription': 'Controls how much computation the model uses.', 'settings.general.effort.low': 'Low', diff --git a/desktop/src/i18n/locales/zh.ts b/desktop/src/i18n/locales/zh.ts index 1e0bc841..753af5dd 100644 --- a/desktop/src/i18n/locales/zh.ts +++ b/desktop/src/i18n/locales/zh.ts @@ -671,6 +671,9 @@ export const zh: Record = { 'settings.general.appearance.dark': '暗色', 'settings.general.languageTitle': '语言', 'settings.general.languageDescription': '选择应用程序的显示语言。', + 'settings.general.responseLangTitle': '回复语言', + 'settings.general.responseLangDescription': '指定 Claude 始终以某种语言回复。', + 'settings.general.responseLangDefault': '默认(英语)', 'settings.general.effortTitle': '推理强度', 'settings.general.effortDescription': '控制模型使用的计算量。', 'settings.general.effort.low': '低', diff --git a/desktop/src/pages/Settings.tsx b/desktop/src/pages/Settings.tsx index 6b32c9c1..4ec32488 100644 --- a/desktop/src/pages/Settings.tsx +++ b/desktop/src/pages/Settings.tsx @@ -1368,6 +1368,8 @@ function GeneralSettings() { disableH5Access, regenerateH5AccessToken, updateH5AccessSettings, + responseLanguage, + setResponseLanguage, } = useSettingsStore() const t = useTranslation() const [webSearchDraft, setWebSearchDraft] = useState(webSearch) @@ -1426,6 +1428,31 @@ function GeneralSettings() { { value: 'zh', label: '中文' }, ] + const RESPONSE_LANGUAGES: Array<{ value: string; label: string }> = [ + { value: '', label: t('settings.general.responseLangDefault') }, + { value: 'english', label: 'English' }, + { value: 'chinese', label: '中文 (Chinese)' }, + { value: 'japanese', label: '日本語 (Japanese)' }, + { value: 'korean', label: '한국어 (Korean)' }, + { value: 'spanish', label: 'Español (Spanish)' }, + { value: 'french', label: 'Français (French)' }, + { value: 'german', label: 'Deutsch (German)' }, + { value: 'portuguese', label: 'Português (Portuguese)' }, + { value: 'italian', label: 'Italiano (Italian)' }, + { value: 'russian', label: 'Русский (Russian)' }, + { value: 'dutch', label: 'Nederlands (Dutch)' }, + { value: 'polish', label: 'Polski (Polish)' }, + { value: 'turkish', label: 'Türkçe (Turkish)' }, + { value: 'hindi', label: 'हिन्दी (Hindi)' }, + { value: 'indonesian', label: 'Bahasa Indonesia' }, + { value: 'ukrainian', label: 'Українська (Ukrainian)' }, + { value: 'greek', label: 'Ελληνικά (Greek)' }, + { value: 'czech', label: 'Čeština (Czech)' }, + { value: 'danish', label: 'Dansk (Danish)' }, + { value: 'swedish', label: 'Svenska (Swedish)' }, + { value: 'norwegian', label: 'Norsk (Norwegian)' }, + ] + const THEMES: Array<{ value: ThemeMode; label: string }> = [ { value: 'light', label: t('settings.general.appearance.light') }, { value: 'dark', label: t('settings.general.appearance.dark') }, @@ -1577,6 +1604,21 @@ function GeneralSettings() { ))} + {/* Response Language */} +

{t('settings.general.responseLangTitle')}

+

{t('settings.general.responseLangDescription')}

+
+ +
+ {/* Effort Level */}

{t('settings.general.effortTitle')}

{t('settings.general.effortDescription')}

diff --git a/desktop/src/stores/settingsStore.ts b/desktop/src/stores/settingsStore.ts index 82e82f35..eff03823 100644 --- a/desktop/src/stores/settingsStore.ts +++ b/desktop/src/stores/settingsStore.ts @@ -32,6 +32,7 @@ type SettingsStore = { webSearch: WebSearchSettings h5Access: H5AccessSettings h5AccessError: string | null + responseLanguage: string isLoading: boolean error: string | null @@ -53,6 +54,7 @@ type SettingsStore = { allowedOrigins?: string[] publicBaseUrl?: string | null }) => Promise + setResponseLanguage: (language: string) => Promise } const DEFAULT_H5_ACCESS_SETTINGS: H5AccessSettings = { @@ -76,6 +78,7 @@ export const useSettingsStore = create((set, get) => ({ webSearch: { mode: 'auto', tavilyApiKey: '', braveApiKey: '' }, h5Access: DEFAULT_H5_ACCESS_SETTINGS, h5AccessError: null, + responseLanguage: '', isLoading: false, error: null, @@ -106,6 +109,7 @@ export const useSettingsStore = create((set, get) => ({ webSearch: normalizeWebSearchSettings(userSettings.webSearch), h5Access: h5AccessResult.settings, h5AccessError: h5AccessResult.error, + responseLanguage: typeof userSettings.language === 'string' ? userSettings.language : '', isLoading: false, error: null, }) @@ -274,6 +278,16 @@ export const useSettingsStore = create((set, get) => ({ throw error } }, + + setResponseLanguage: async (language) => { + const prev = get().responseLanguage + set({ responseLanguage: language }) + try { + await settingsApi.updateUser({ language: language || undefined }) + } catch { + set({ responseLanguage: prev }) + } + }, })) function normalizeWebSearchSettings(settings: WebSearchSettings | undefined): WebSearchSettings { diff --git a/desktop/src/types/settings.ts b/desktop/src/types/settings.ts index 41382f48..07ac420d 100644 --- a/desktop/src/types/settings.ts +++ b/desktop/src/types/settings.ts @@ -36,5 +36,6 @@ export type UserSettings = { skipWebFetchPreflight?: boolean desktopNotificationsEnabled?: boolean webSearch?: WebSearchSettings + language?: string [key: string]: unknown }