Fix settings localization gaps (#1465)

This commit is contained in:
陈大猫
2026-06-14 09:00:49 +08:00
committed by GitHub
parent 88142d2a92
commit 6ef0a4ad6b
7 changed files with 130 additions and 26 deletions

View File

@@ -312,6 +312,15 @@ export const enCoreMessages: Messages = {
'settings.terminal.font.size.desc': 'Terminal text size', 'settings.terminal.font.size.desc': 'Terminal text size',
'settings.terminal.font.weight': 'Font weight', 'settings.terminal.font.weight': 'Font weight',
'settings.terminal.font.weight.desc': 'Weight for regular text (100-900)', 'settings.terminal.font.weight.desc': 'Weight for regular text (100-900)',
'settings.terminal.font.weight.thin': 'Thin',
'settings.terminal.font.weight.extraLight': 'Extra Light',
'settings.terminal.font.weight.light': 'Light',
'settings.terminal.font.weight.normal': 'Normal',
'settings.terminal.font.weight.medium': 'Medium',
'settings.terminal.font.weight.semiBold': 'Semi Bold',
'settings.terminal.font.weight.bold': 'Bold',
'settings.terminal.font.weight.extraBold': 'Extra Bold',
'settings.terminal.font.weight.black': 'Black',
'settings.terminal.font.weightBold': 'Bold font weight', 'settings.terminal.font.weightBold': 'Bold font weight',
'settings.terminal.font.weightBold.desc': 'Weight for bold text (100-900)', 'settings.terminal.font.weightBold.desc': 'Weight for bold text (100-900)',
'settings.terminal.font.linePadding': 'Line padding', 'settings.terminal.font.linePadding': 'Line padding',

View File

@@ -312,6 +312,15 @@ export const ruCoreMessages: Messages = {
'settings.terminal.font.size.desc': 'Размер текста терминала', 'settings.terminal.font.size.desc': 'Размер текста терминала',
'settings.terminal.font.weight': 'Толщина шрифта', 'settings.terminal.font.weight': 'Толщина шрифта',
'settings.terminal.font.weight.desc': 'Толщина обычного текста (100-900)', 'settings.terminal.font.weight.desc': 'Толщина обычного текста (100-900)',
'settings.terminal.font.weight.thin': 'Тонкий',
'settings.terminal.font.weight.extraLight': 'Очень светлый',
'settings.terminal.font.weight.light': 'Светлый',
'settings.terminal.font.weight.normal': 'Обычный',
'settings.terminal.font.weight.medium': 'Средний',
'settings.terminal.font.weight.semiBold': 'Полужирный',
'settings.terminal.font.weight.bold': 'Жирный',
'settings.terminal.font.weight.extraBold': 'Очень жирный',
'settings.terminal.font.weight.black': 'Максимально жирный',
'settings.terminal.font.weightBold': 'Толщина жирного шрифта', 'settings.terminal.font.weightBold': 'Толщина жирного шрифта',
'settings.terminal.font.weightBold.desc': 'Толщина жирного текста (100-900)', 'settings.terminal.font.weightBold.desc': 'Толщина жирного текста (100-900)',
'settings.terminal.font.linePadding': 'Межстрочный отступ', 'settings.terminal.font.linePadding': 'Межстрочный отступ',
@@ -500,6 +509,7 @@ export const ruCoreMessages: Messages = {
'settings.shortcuts.binding.next-tab': 'Следующая вкладка', 'settings.shortcuts.binding.next-tab': 'Следующая вкладка',
'settings.shortcuts.binding.prev-tab': 'Предыдущая вкладка', 'settings.shortcuts.binding.prev-tab': 'Предыдущая вкладка',
'settings.shortcuts.binding.close-tab': 'Закрыть вкладку', 'settings.shortcuts.binding.close-tab': 'Закрыть вкладку',
'settings.shortcuts.binding.close-session': 'Закрыть панель сессии',
'settings.shortcuts.binding.new-tab': 'Новая локальная вкладка', 'settings.shortcuts.binding.new-tab': 'Новая локальная вкладка',
'settings.shortcuts.binding.copy': 'Копировать из терминала', 'settings.shortcuts.binding.copy': 'Копировать из терминала',
'settings.shortcuts.binding.paste': 'Вставить в терминал', 'settings.shortcuts.binding.paste': 'Вставить в терминал',
@@ -507,9 +517,13 @@ export const ruCoreMessages: Messages = {
'settings.shortcuts.binding.select-all': 'Выделить всё содержимое терминала', 'settings.shortcuts.binding.select-all': 'Выделить всё содержимое терминала',
'settings.shortcuts.binding.clear-buffer': 'Очистить буфер терминала', 'settings.shortcuts.binding.clear-buffer': 'Очистить буфер терминала',
'settings.shortcuts.binding.search-terminal': 'Открыть поиск по терминалу', 'settings.shortcuts.binding.search-terminal': 'Открыть поиск по терминалу',
'settings.shortcuts.binding.increase-terminal-font-size': 'Увеличить размер шрифта терминала',
'settings.shortcuts.binding.decrease-terminal-font-size': 'Уменьшить размер шрифта терминала',
'settings.shortcuts.binding.reset-terminal-font-size': 'Сбросить размер шрифта терминала',
'settings.shortcuts.binding.move-focus': 'Переместить фокус между разделёнными окнами', 'settings.shortcuts.binding.move-focus': 'Переместить фокус между разделёнными окнами',
'settings.shortcuts.binding.split-horizontal': 'Горизонтальное разделение', 'settings.shortcuts.binding.split-horizontal': 'Горизонтальное разделение',
'settings.shortcuts.binding.split-vertical': 'Вертикальное разделение', 'settings.shortcuts.binding.split-vertical': 'Вертикальное разделение',
'settings.shortcuts.binding.toggle-pane-zoom': 'Переключить масштаб панели',
'settings.shortcuts.binding.open-hosts': 'Открыть список хостов', 'settings.shortcuts.binding.open-hosts': 'Открыть список хостов',
'settings.shortcuts.binding.open-local': 'Открыть локальный терминал', 'settings.shortcuts.binding.open-local': 'Открыть локальный терминал',
'settings.shortcuts.binding.open-sftp': 'Открыть SFTP', 'settings.shortcuts.binding.open-sftp': 'Открыть SFTP',

View File

@@ -0,0 +1,55 @@
import assert from "node:assert/strict";
import test from "node:test";
import { DEFAULT_KEY_BINDINGS } from "../../../domain/models/keyBindings.ts";
import zhCN from "./zh-CN.ts";
import ru from "./ru.ts";
const LOCALIZED_SETTINGS_LOCALES = [
{ name: "zh-CN", messages: zhCN },
{ name: "ru", messages: ru },
];
test("localized settings include names for every default shortcut", () => {
for (const locale of LOCALIZED_SETTINGS_LOCALES) {
const missing = DEFAULT_KEY_BINDINGS
.map((binding) => `settings.shortcuts.binding.${binding.id}`)
.filter((key) => !locale.messages[key]);
assert.deepEqual(missing, [], `${locale.name} is missing shortcut labels`);
}
});
test("localized settings include workspace focus indicator labels", () => {
const keys = [
"settings.terminal.section.workspaceFocus",
"settings.terminal.workspaceFocus.style",
"settings.terminal.workspaceFocus.style.desc",
"settings.terminal.workspaceFocus.dim",
"settings.terminal.workspaceFocus.border",
];
for (const locale of LOCALIZED_SETTINGS_LOCALES) {
const missing = keys.filter((key) => !locale.messages[key]);
assert.deepEqual(missing, [], `${locale.name} is missing workspace focus labels`);
}
});
test("localized settings include terminal font weight option labels", () => {
const keys = [
"settings.terminal.font.weight.thin",
"settings.terminal.font.weight.extraLight",
"settings.terminal.font.weight.light",
"settings.terminal.font.weight.normal",
"settings.terminal.font.weight.medium",
"settings.terminal.font.weight.semiBold",
"settings.terminal.font.weight.bold",
"settings.terminal.font.weight.extraBold",
"settings.terminal.font.weight.black",
];
for (const locale of LOCALIZED_SETTINGS_LOCALES) {
const missing = keys.filter((key) => !locale.messages[key]);
assert.deepEqual(missing, [], `${locale.name} is missing font weight labels`);
}
});

View File

@@ -190,6 +190,15 @@ export const zhCNTerminalMessages: Messages = {
'settings.terminal.font.size.desc': '终端文字大小', 'settings.terminal.font.size.desc': '终端文字大小',
'settings.terminal.font.weight': '字重', 'settings.terminal.font.weight': '字重',
'settings.terminal.font.weight.desc': '常规文本字重 (100-900)', 'settings.terminal.font.weight.desc': '常规文本字重 (100-900)',
'settings.terminal.font.weight.thin': '极细',
'settings.terminal.font.weight.extraLight': '特细',
'settings.terminal.font.weight.light': '细',
'settings.terminal.font.weight.normal': '常规',
'settings.terminal.font.weight.medium': '中等',
'settings.terminal.font.weight.semiBold': '半粗',
'settings.terminal.font.weight.bold': '粗',
'settings.terminal.font.weight.extraBold': '特粗',
'settings.terminal.font.weight.black': '黑体',
'settings.terminal.font.weightBold': '粗体字重', 'settings.terminal.font.weightBold': '粗体字重',
'settings.terminal.font.weightBold.desc': '粗体文本字重 (100-900)', 'settings.terminal.font.weightBold.desc': '粗体文本字重 (100-900)',
'settings.terminal.font.linePadding': '行间距', 'settings.terminal.font.linePadding': '行间距',
@@ -328,6 +337,13 @@ export const zhCNTerminalMessages: Messages = {
'settings.terminal.rendering.renderer.desc': '选择终端渲染技术。自动模式会在低内存设备上使用 DOM 渲染。更改将在新终端会话中生效。', 'settings.terminal.rendering.renderer.desc': '选择终端渲染技术。自动模式会在低内存设备上使用 DOM 渲染。更改将在新终端会话中生效。',
'settings.terminal.rendering.auto': '自动', 'settings.terminal.rendering.auto': '自动',
// Settings > Terminal > Workspace Focus Indicator
'settings.terminal.section.workspaceFocus': '工作区焦点提示',
'settings.terminal.workspaceFocus.style': '焦点提示样式',
'settings.terminal.workspaceFocus.style.desc': '在分屏视图中如何标识当前聚焦的窗格。',
'settings.terminal.workspaceFocus.dim': '淡化未聚焦窗格',
'settings.terminal.workspaceFocus.border': '为聚焦窗格显示边框',
// Settings > Terminal > Autocomplete // Settings > Terminal > Autocomplete
'settings.terminal.section.autocomplete': '自动补全', 'settings.terminal.section.autocomplete': '自动补全',
'settings.terminal.autocomplete.enabled': '启用自动补全', 'settings.terminal.autocomplete.enabled': '启用自动补全',
@@ -362,18 +378,25 @@ export const zhCNTerminalMessages: Messages = {
'settings.shortcuts.binding.next-tab': '下一个标签页', 'settings.shortcuts.binding.next-tab': '下一个标签页',
'settings.shortcuts.binding.prev-tab': '上一个标签页', 'settings.shortcuts.binding.prev-tab': '上一个标签页',
'settings.shortcuts.binding.close-tab': '关闭标签页', 'settings.shortcuts.binding.close-tab': '关闭标签页',
'settings.shortcuts.binding.close-session': '关闭会话窗格',
'settings.shortcuts.binding.new-tab': '新建本地标签页', 'settings.shortcuts.binding.new-tab': '新建本地标签页',
'settings.shortcuts.binding.copy': '从终端复制', 'settings.shortcuts.binding.copy': '从终端复制',
'settings.shortcuts.binding.paste': '粘贴到终端', 'settings.shortcuts.binding.paste': '粘贴到终端',
'settings.shortcuts.binding.paste-selection': '将选区粘贴到终端',
'settings.shortcuts.binding.select-all': '全选终端内容', 'settings.shortcuts.binding.select-all': '全选终端内容',
'settings.shortcuts.binding.clear-buffer': '清空终端缓冲区', 'settings.shortcuts.binding.clear-buffer': '清空终端缓冲区',
'settings.shortcuts.binding.search-terminal': '打开终端搜索', 'settings.shortcuts.binding.search-terminal': '打开终端搜索',
'settings.shortcuts.binding.increase-terminal-font-size': '增大终端字号',
'settings.shortcuts.binding.decrease-terminal-font-size': '减小终端字号',
'settings.shortcuts.binding.reset-terminal-font-size': '重置终端字号',
'settings.shortcuts.binding.move-focus': '在分屏间移动焦点', 'settings.shortcuts.binding.move-focus': '在分屏间移动焦点',
'settings.shortcuts.binding.split-horizontal': '水平分屏', 'settings.shortcuts.binding.split-horizontal': '水平分屏',
'settings.shortcuts.binding.split-vertical': '垂直分屏', 'settings.shortcuts.binding.split-vertical': '垂直分屏',
'settings.shortcuts.binding.toggle-pane-zoom': '切换窗格缩放',
'settings.shortcuts.binding.open-hosts': '打开主机列表', 'settings.shortcuts.binding.open-hosts': '打开主机列表',
'settings.shortcuts.binding.open-local': '打开本地终端', 'settings.shortcuts.binding.open-local': '打开本地终端',
'settings.shortcuts.binding.open-sftp': '打开 SFTP', 'settings.shortcuts.binding.open-sftp': '打开 SFTP',
'settings.shortcuts.binding.open-settings': '打开设置',
'settings.shortcuts.binding.port-forwarding': '打开端口转发', 'settings.shortcuts.binding.port-forwarding': '打开端口转发',
'settings.shortcuts.binding.command-palette': '打开命令面板', 'settings.shortcuts.binding.command-palette': '打开命令面板',
'settings.shortcuts.binding.quick-switch': '快速切换', 'settings.shortcuts.binding.quick-switch': '快速切换',
@@ -389,6 +412,9 @@ export const zhCNTerminalMessages: Messages = {
'settings.shortcuts.binding.sftp-delete': '删除文件', 'settings.shortcuts.binding.sftp-delete': '删除文件',
'settings.shortcuts.binding.sftp-refresh': '刷新', 'settings.shortcuts.binding.sftp-refresh': '刷新',
'settings.shortcuts.binding.sftp-new-folder': '新建文件夹', 'settings.shortcuts.binding.sftp-new-folder': '新建文件夹',
'settings.shortcuts.binding.sftp-open': '打开文件 / 进入目录',
'settings.shortcuts.binding.sftp-go-parent': '转到上级目录',
'settings.shortcuts.binding.sftp-navigate-to': '转到选中的目录',
// Host Details (sub-panels) // Host Details (sub-panels)
'hostDetails.proxyPanel.title': '通过 HTTP/SOCKS5/命令代理', 'hostDetails.proxyPanel.title': '通过 HTTP/SOCKS5/命令代理',

View File

@@ -71,7 +71,7 @@ export const Select: React.FC<SelectProps> = ({
</SelectPrimitive.Trigger> </SelectPrimitive.Trigger>
<SelectPrimitive.Portal> <SelectPrimitive.Portal>
<SelectPrimitive.Content <SelectPrimitive.Content
className="z-[200000] max-h-80 w-max max-w-[var(--radix-select-content-available-width)] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1" className="z-[200000] max-h-80 w-max max-w-[min(24rem,var(--radix-select-content-available-width))] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1"
position="popper" position="popper"
sideOffset={4} sideOffset={4}
style={{ minWidth: "max(12rem, var(--radix-select-trigger-width))" }} style={{ minWidth: "max(12rem, var(--radix-select-trigger-width))" }}
@@ -84,7 +84,7 @@ export const Select: React.FC<SelectProps> = ({
<SelectPrimitive.Item <SelectPrimitive.Item
key={opt.value} key={opt.value}
value={opt.value} value={opt.value}
className="relative flex w-full min-w-max cursor-default select-none items-center whitespace-nowrap rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50" className="relative flex w-full min-w-0 cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50"
> >
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator> <SelectPrimitive.ItemIndicator>
@@ -92,7 +92,7 @@ export const Select: React.FC<SelectProps> = ({
</SelectPrimitive.ItemIndicator> </SelectPrimitive.ItemIndicator>
</span> </span>
<SelectPrimitive.ItemText> <SelectPrimitive.ItemText>
<span className="flex items-center gap-2 whitespace-nowrap"> <span className="flex min-w-0 items-center gap-2 whitespace-normal break-words leading-snug">
{opt.icon} {opt.icon}
{opt.label} {opt.label}
</span> </span>

View File

@@ -27,6 +27,19 @@ import { resolveFollowedTerminalThemeId, TERMINAL_THEME_AUTO } from "../../../do
import { KeywordHighlightRulesEditor, ThemePreviewButton } from "./SettingsTerminalTabControls"; import { KeywordHighlightRulesEditor, ThemePreviewButton } from "./SettingsTerminalTabControls";
import { TerminalBehaviorSettings } from "./TerminalBehaviorSettings"; import { TerminalBehaviorSettings } from "./TerminalBehaviorSettings";
const FONT_WEIGHT_OPTIONS = [
{ value: "100", labelKey: "settings.terminal.font.weight.thin" },
{ value: "200", labelKey: "settings.terminal.font.weight.extraLight" },
{ value: "300", labelKey: "settings.terminal.font.weight.light" },
{ value: "400", labelKey: "settings.terminal.font.weight.normal" },
{ value: "500", labelKey: "settings.terminal.font.weight.medium" },
{ value: "600", labelKey: "settings.terminal.font.weight.semiBold" },
{ value: "700", labelKey: "settings.terminal.font.weight.bold" },
{ value: "800", labelKey: "settings.terminal.font.weight.extraBold" },
{ value: "900", labelKey: "settings.terminal.font.weight.black" },
];
function SettingsTerminalTab(props: { function SettingsTerminalTab(props: {
terminalThemeId: string; terminalThemeId: string;
setTerminalThemeId: (id: string) => void; setTerminalThemeId: (id: string) => void;
@@ -146,6 +159,13 @@ function SettingsTerminalTab(props: {
|| TERMINAL_THEMES[0]; || TERMINAL_THEMES[0];
}, [terminalThemeDarkId, terminalThemeLightId, lightUiThemeId, darkUiThemeId, terminalThemeId, customThemes]); }, [terminalThemeDarkId, terminalThemeLightId, lightUiThemeId, darkUiThemeId, terminalThemeId, customThemes]);
const fontWeightOptions = useMemo(() => (
FONT_WEIGHT_OPTIONS.map((option) => ({
value: option.value,
label: `${option.value} - ${t(option.labelKey)}`,
}))
), [t]);
const handleAutocompleteGhostTextChange = useCallback((enabled: boolean) => { const handleAutocompleteGhostTextChange = useCallback((enabled: boolean) => {
updateTerminalSetting("autocompleteGhostText", enabled); updateTerminalSetting("autocompleteGhostText", enabled);
if (enabled) { if (enabled) {
@@ -516,17 +536,7 @@ function SettingsTerminalTab(props: {
> >
<Select <Select
value={String(terminalSettings.fontWeight)} value={String(terminalSettings.fontWeight)}
options={[ options={fontWeightOptions}
{ value: "100", label: "100 - Thin" },
{ value: "200", label: "200 - Extra Light" },
{ value: "300", label: "300 - Light" },
{ value: "400", label: "400 - Normal" },
{ value: "500", label: "500 - Medium" },
{ value: "600", label: "600 - Semi Bold" },
{ value: "700", label: "700 - Bold" },
{ value: "800", label: "800 - Extra Bold" },
{ value: "900", label: "900 - Black" },
]}
onChange={(v) => updateTerminalSetting("fontWeight", parseInt(v))} onChange={(v) => updateTerminalSetting("fontWeight", parseInt(v))}
className="w-40" className="w-40"
/> />
@@ -538,17 +548,7 @@ function SettingsTerminalTab(props: {
> >
<Select <Select
value={String(terminalSettings.fontWeightBold)} value={String(terminalSettings.fontWeightBold)}
options={[ options={fontWeightOptions}
{ value: "100", label: "100 - Thin" },
{ value: "200", label: "200 - Extra Light" },
{ value: "300", label: "300 - Light" },
{ value: "400", label: "400 - Normal" },
{ value: "500", label: "500 - Medium" },
{ value: "600", label: "600 - Semi Bold" },
{ value: "700", label: "700 - Bold" },
{ value: "800", label: "800 - Extra Bold" },
{ value: "900", label: "900 - Black" },
]}
onChange={(v) => updateTerminalSetting("fontWeightBold", parseInt(v))} onChange={(v) => updateTerminalSetting("fontWeightBold", parseInt(v))}
className="w-40" className="w-40"
/> />

View File

@@ -35,7 +35,7 @@
"tool:cli": "node electron/cli/netcatty-tool-cli.cjs", "tool:cli": "node electron/cli/netcatty-tool-cli.cjs",
"lint": "eslint .", "lint": "eslint .",
"lint:fix": "eslint . --fix", "lint:fix": "eslint . --fix",
"test": "node --test --import tsx electron/bridges/*.test.cjs electron/bridges/*/*.test.cjs electron/bridges/aiBridge/sdk/*.test.cjs scripts/*.test.cjs application/*.test.ts application/app/*.test.ts application/state/*.test.ts application/state/*/*.test.ts components/*.test.ts components/*.test.tsx components/editor/*.test.ts components/editor/*.test.tsx components/terminalLayer/*.test.ts components/settings/*.test.tsx components/settings/tabs/ai/*.test.ts components/ai/*.test.ts components/ai-elements/*.test.tsx components/sftp/*.test.ts components/terminal/*.test.ts components/terminal/runtime/*.test.ts domain/*.test.ts infrastructure/ai/*.test.ts infrastructure/config/*.test.ts infrastructure/services/*/*.test.ts lib/*.test.ts" "test": "node --test --import tsx electron/bridges/*.test.cjs electron/bridges/*/*.test.cjs electron/bridges/aiBridge/sdk/*.test.cjs scripts/*.test.cjs application/*.test.ts application/app/*.test.ts application/i18n/locales/*.test.ts application/state/*.test.ts application/state/*/*.test.ts components/*.test.ts components/*.test.tsx components/editor/*.test.ts components/editor/*.test.tsx components/terminalLayer/*.test.ts components/settings/*.test.tsx components/settings/tabs/ai/*.test.ts components/ai/*.test.ts components/ai-elements/*.test.tsx components/sftp/*.test.ts components/terminal/*.test.ts components/terminal/runtime/*.test.ts domain/*.test.ts infrastructure/ai/*.test.ts infrastructure/config/*.test.ts infrastructure/services/*/*.test.ts lib/*.test.ts"
}, },
"dependencies": { "dependencies": {
"@ai-sdk/anthropic": "^3.0.58", "@ai-sdk/anthropic": "^3.0.58",