feat(desktop): localize desktop chrome

Co-authored-by: Kiro 有点Yes <246816394+sdyckjq-lab@users.noreply.github.com>
This commit is contained in:
Jim Liu 宝玉
2026-06-06 07:51:44 -07:00
committed by Teknium
co-authored by Kiro 有点Yes
parent 812dc6957e
commit fbd423b94d
14 changed files with 297 additions and 70 deletions
+33 -1
View File
@@ -20,10 +20,12 @@ export const en: Translations = {
continue: 'Continue',
copied: 'Copied',
copy: 'Copy',
copyFailed: 'Copy failed',
delete: 'Delete',
docs: 'Docs',
done: 'Done',
error: 'Error',
failed: 'Failed',
free: 'Free',
loading: 'Loading…',
notSet: 'Not set',
@@ -110,6 +112,25 @@ export const en: Translations = {
openaiRejectedApiKey: 'OpenAI rejected the API key.',
openaiRejectedApiKeyWithStatus: status => `OpenAI rejected the API key (${status} invalid_api_key).`,
openaiTtsNeedsKey: 'OpenAI TTS needs VOICE_TOOLS_OPENAI_KEY or OPENAI_API_KEY.'
},
voice: {
configureSpeechToText: 'Configure speech-to-text to use voice mode.',
couldNotStartSession: 'Could not start voice session',
microphoneAccessDenied: 'Microphone access denied.',
microphoneConstraintsUnsupported: 'Microphone constraints are not supported by this device.',
microphoneFailed: 'Microphone failed',
microphoneInUse: 'Microphone is already in use by another app.',
microphonePermissionDenied: 'Microphone permission was denied.',
microphoneStartFailed: 'Could not start microphone recording.',
microphoneUnsupported: 'This runtime does not support microphone recording.',
noMicrophone: 'No microphone was found.',
noSpeechDetected: 'No speech detected',
playbackFailed: 'Voice playback failed',
recordingFailed: 'Voice recording failed',
transcriptionFailed: 'Voice transcription failed',
transcriptionUnavailable: 'Voice transcription is not available yet.',
tryRecordingAgain: 'Try recording again.',
unavailable: 'Voice unavailable'
}
},
@@ -1016,6 +1037,10 @@ export const en: Translations = {
stopDictation: 'Stop dictation',
transcribingDictation: 'Transcribing dictation',
voiceDictation: 'Voice dictation',
lookupLoading: 'Looking up…',
lookupNoMatches: 'No matches.',
lookupTry: 'Try',
lookupOr: 'or',
commonCommands: 'Common commands',
hotkeys: 'Hotkeys',
helpFooter: 'opens the full panel · backspace dismisses',
@@ -1524,7 +1549,11 @@ export const en: Translations = {
recoveredOne: 'Recovered after 1 failed step',
recoveredMany: count => `Recovered after ${count} failed steps`,
failedOne: '1 step failed',
failedMany: count => `${count} steps failed`
failedMany: count => `${count} steps failed`,
statusRunning: 'Running',
statusError: 'Error',
statusRecovered: 'Recovered',
statusDone: 'Done'
}
},
@@ -1587,6 +1616,9 @@ export const en: Translations = {
restartToUseSaveImage: 'Restart Hermes Desktop to use Save Image.',
restartToSaveImages: 'Restart Hermes Desktop to save images',
imageDownloadFailed: 'Image download failed',
openImage: 'Open image',
downloadImage: 'Download image',
savingImage: 'Saving image',
imagePreviewFailed: 'Image preview failed',
imageAttach: 'Image attach',
imageWriteFailed: 'Failed to write image to disk.',
+4 -1
View File
@@ -15,7 +15,10 @@ describe('desktop i18n runtime translator', () => {
it('translates string paths for the active runtime locale', () => {
setRuntimeI18nLocale('zh')
expect(translateNow('boot.ready')).toBe('Hermes Desktop 已就绪')
expect(translateNow('boot.ready')).toBe('Hermes 桌面版已就绪')
expect(translateNow('notifications.voice.noSpeechDetected')).toBe('没有检测到语音')
expect(translateNow('composer.lookupNoMatches')).toBe('没有匹配项。')
expect(translateNow('assistant.tool.statusRecovered')).toBe('已恢复')
})
it('passes arguments to function translations', () => {
+32
View File
@@ -35,10 +35,12 @@ export interface Translations {
continue: string
copied: string
copy: string
copyFailed: string
delete: string
docs: string
done: string
error: string
failed: string
free: string
loading: string
notSet: string
@@ -122,6 +124,25 @@ export interface Translations {
openaiRejectedApiKeyWithStatus: (status: string) => string
openaiTtsNeedsKey: string
}
voice: {
configureSpeechToText: string
couldNotStartSession: string
microphoneAccessDenied: string
microphoneConstraintsUnsupported: string
microphoneFailed: string
microphoneInUse: string
microphonePermissionDenied: string
microphoneStartFailed: string
microphoneUnsupported: string
noMicrophone: string
noSpeechDetected: string
playbackFailed: string
recordingFailed: string
transcriptionFailed: string
transcriptionUnavailable: string
tryRecordingAgain: string
unavailable: string
}
}
titlebar: {
@@ -831,6 +852,10 @@ export interface Translations {
stopDictation: string
transcribingDictation: string
voiceDictation: string
lookupLoading: string
lookupNoMatches: string
lookupTry: string
lookupOr: string
commonCommands: string
hotkeys: string
helpFooter: string
@@ -1270,6 +1295,10 @@ export interface Translations {
recoveredMany: (count: number) => string
failedOne: string
failedMany: (count: number) => string
statusRunning: string
statusError: string
statusRecovered: string
statusDone: string
}
}
@@ -1331,6 +1360,9 @@ export interface Translations {
restartToUseSaveImage: string
restartToSaveImages: string
imageDownloadFailed: string
openImage: string
downloadImage: string
savingImage: string
imagePreviewFailed: string
imageAttach: string
imageWriteFailed: string
+46 -14
View File
@@ -20,10 +20,12 @@ export const zh: Translations = {
continue: '继续',
copied: '已复制',
copy: '复制',
copyFailed: '复制失败',
delete: '删除',
docs: '文档',
done: '完成',
error: '错误',
failed: '失败',
free: '免费',
loading: '加载中…',
notSet: '未设置',
@@ -41,14 +43,14 @@ export const zh: Translations = {
},
boot: {
ready: 'Hermes Desktop 已就绪',
desktopBootFailedWithMessage: message => `桌面启动失败:${message}`,
ready: 'Hermes 桌面版已就绪',
desktopBootFailedWithMessage: message => `桌面启动失败${message}`,
steps: {
connectingGateway: '正在连接实时桌面网关',
connectingGateway: '正在连接桌面网关',
loadingSettings: '正在加载 Hermes 设置',
loadingSessions: '正在加载最近会话',
startingDesktopConnection: '正在启动桌面连接',
startingHermesDesktop: '正在启动 Hermes Desktop…'
startingHermesDesktop: '正在启动 Hermes 桌面版…'
},
errors: {
backgroundExited: 'Hermes 后台进程已退出。',
@@ -60,14 +62,14 @@ export const zh: Translations = {
},
failure: {
title: 'Hermes 无法启动',
description: '后台网关没有启动。请尝试下面的恢复步骤。这些操作不会删除你的对话或设置。',
description: '后台网关没有启动。请尝试下面的恢复步骤;这里不会删除你的对话或设置。',
remoteTitle: '需要重新登录远程网关',
remoteDescription: '你的远程网关会话已过期。请重新登录以恢复连接。这些操作不会删除你的对话或设置。',
retry: '重试',
repairInstall: '修复安装',
useLocalGateway: '使用本地网关',
openLogs: '打开日志',
repairHint: '修复会重新运行安装器在新机器上可能需要几分钟。',
repairHint: '修复会重新运行安装器在新机器上可能需要几分钟。',
remoteSignInHint: '打开网关登录窗口。也可以使用本地网关切换到随应用提供的后端。',
hideRecentLogs: '隐藏最近日志',
showRecentLogs: '显示最近日志',
@@ -106,6 +108,25 @@ export const zh: Translations = {
openaiRejectedApiKey: 'OpenAI 拒绝了该 API key。',
openaiRejectedApiKeyWithStatus: status => `OpenAI 拒绝了该 API key (${status} invalid_api_key)。`,
openaiTtsNeedsKey: 'OpenAI TTS 需要 VOICE_TOOLS_OPENAI_KEY 或 OPENAI_API_KEY。'
},
voice: {
configureSpeechToText: '配置语音转文字后即可使用语音模式。',
couldNotStartSession: '无法启动语音会话',
microphoneAccessDenied: '麦克风访问被拒绝。',
microphoneConstraintsUnsupported: '此设备不支持当前麦克风约束。',
microphoneFailed: '麦克风出错',
microphoneInUse: '麦克风正被其他应用占用。',
microphonePermissionDenied: '麦克风权限被拒绝。',
microphoneStartFailed: '无法开始麦克风录音。',
microphoneUnsupported: '当前运行环境不支持麦克风录音。',
noMicrophone: '未找到麦克风。',
noSpeechDetected: '没有检测到语音',
playbackFailed: '语音播放失败',
recordingFailed: '语音录制失败',
transcriptionFailed: '语音转写失败',
transcriptionUnavailable: '语音转写暂不可用。',
tryRecordingAgain: '请再录一次。',
unavailable: '语音不可用'
}
},
@@ -1166,6 +1187,10 @@ export const zh: Translations = {
stopDictation: '停止听写',
transcribingDictation: '正在转写听写',
voiceDictation: '语音听写',
lookupLoading: '查找中…',
lookupNoMatches: '没有匹配项。',
lookupTry: '试试',
lookupOr: '或',
commonCommands: '常用命令',
hotkeys: '快捷键',
helpFooter: '打开完整面板 · 退格键关闭',
@@ -1669,7 +1694,11 @@ export const zh: Translations = {
recoveredOne: '在 1 个失败步骤后已恢复',
recoveredMany: count => `${count} 个失败步骤后已恢复`,
failedOne: '1 个步骤失败',
failedMany: count => `${count} 个步骤失败`
failedMany: count => `${count} 个步骤失败`,
statusRunning: '运行中',
statusError: '错误',
statusRecovered: '已恢复',
statusDone: '完成'
}
},
@@ -1700,11 +1729,11 @@ export const zh: Translations = {
yoloSystem: active => `此会话 YOLO ${active ? '已开启' : '已关闭'}`,
yoloTitle: 'YOLO',
yoloToggleFailed: '无法切换 YOLO',
profileStatus: current => `Profile: ${current}。使用 /profile <name> 或“新建会话”选择器在其他 profile 中开始对话。`,
unknownProfile: '未知 profile',
noProfileNamed: (target, available) => `没有名为“${target}”的 profile。可用: ${available}`,
newChatsProfile: name => `新对话将使用 profile ${name}`,
setProfileFailed: '设置 profile 失败',
profileStatus: current => `配置档案:${current}。使用 /profile <name> 或“新建会话”选择器在其他配置档案中开始对话。`,
unknownProfile: '未知配置档案',
noProfileNamed: (target, available) => `没有名为“${target}”的配置档案。可用${available}`,
newChatsProfile: name => `新对话将使用配置档案 ${name}`,
setProfileFailed: '设置配置档案失败',
sttDisabled: '设置中已禁用语音转文字。',
stopFailed: '停止失败',
regenerateFailed: '重新生成失败',
@@ -1728,9 +1757,12 @@ export const zh: Translations = {
sessionExportFailed: '无法导出会话',
imageSaved: '图片已保存',
downloadStarted: '下载已开始',
restartToUseSaveImage: '重启 Hermes Desktop 后可使用保存图片。',
restartToSaveImages: '重启 Hermes Desktop 以保存图片',
restartToUseSaveImage: '重启 Hermes 桌面版后可使用保存图片。',
restartToSaveImages: '重启 Hermes 桌面版以保存图片',
imageDownloadFailed: '图片下载失败',
openImage: '打开图片',
downloadImage: '下载图片',
savingImage: '正在保存图片',
imagePreviewFailed: '图片预览失败',
imageAttach: '附加图片',
imageWriteFailed: '无法将图片写入磁盘。',