From 9b8f02cc19a269f1146f9c04b0ee722177277950 Mon Sep 17 00:00:00 2001 From: Bryan Joshua Pedini Date: Wed, 6 May 2026 16:00:19 +0200 Subject: [PATCH 1/3] fix: updated main window to use internationalized labels --- src/pages/ConnectionManager.tsx | 6 +++--- src/shared/locales.ts | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/pages/ConnectionManager.tsx b/src/pages/ConnectionManager.tsx index 2dd70d5..099550a 100644 --- a/src/pages/ConnectionManager.tsx +++ b/src/pages/ConnectionManager.tsx @@ -121,9 +121,9 @@ export function ConnectionManager({ onConnect, onNavigate, activeSessions = 0 }:
Reflex
-

没有已保存的连接

+

{t('connection.noConnections')}

- 添加你的第一个 SSH 服务器,开始远程管理。 + {t('connection.addFirstConnection')}

) : filtered.length === 0 ? ( diff --git a/src/shared/locales.ts b/src/shared/locales.ts index 1b4189a..29fc073 100644 --- a/src/shared/locales.ts +++ b/src/shared/locales.ts @@ -83,12 +83,14 @@ export const translations = { }, connection: { new: 'New Connection', + add: 'Add Server', host: 'Host', port: 'Port', username: 'Username', password: 'Password', name: 'Name', - noConnections: 'No connections found. Create one to get started.' + noConnections: 'No connections found. Create one to get started.', + noConnectionsDesc: 'Add your first SSH server and start remote management.' }, agent: { thinking: 'Thinking...', @@ -229,12 +231,14 @@ export const translations = { }, connection: { new: '新建连接', + add: '添加服务器', host: '主机', port: '端口', username: '用户名', password: '密码', name: '名称', - noConnections: '未找到连接。创建一个以开始。' + noConnections: '未找到连接。创建一个以开始。', + noConnectionsDesc: '添加你的第一个 SSH 服务器,开始远程管理。' }, agent: { thinking: '正在思考...', @@ -375,12 +379,14 @@ export const translations = { }, connection: { new: '新規接続', + add: 'サーバーを追加', host: 'ホスト', port: 'ポート', username: 'ユーザー名', password: 'パスワード', name: '名前', - noConnections: '接続が見つかりません。新しい接続を作成してください。' + noConnections: '接続が見つかりません。新しい接続を作成してください。', + noConnectionsDesc: '最初のSSHサーバーを追加して、リモート管理を開始しましょう。' }, agent: { thinking: '考え中...', @@ -521,12 +527,14 @@ export const translations = { }, connection: { new: '새 연결', + add: '서버 추가', host: '호스트', port: '포트', username: '사용자 이름', password: '비밀번호', name: '이름', - noConnections: '연결을 찾을 수 없습니다. 시작하려면 연결을 생성하세요.' + noConnections: '연결을 찾을 수 없습니다. 시작하려면 연결을 생성하세요.', + noConnectionsDesc: '첫 번째 SSH 서버를 추가하고 원격 관리를 시작하세요.' }, agent: { thinking: '생각 중...', From 6963ce80443b1a8b333386a769cf479152fc072d Mon Sep 17 00:00:00 2001 From: Bryan Joshua Pedini Date: Wed, 6 May 2026 16:03:42 +0200 Subject: [PATCH 2/3] feat: added italian translation --- src/pages/Settings.tsx | 1 + src/shared/locales.ts | 148 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index 011ec8f..2931719 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -243,6 +243,7 @@ export function Settings({ onBack }: SettingsProps) { const languageOptions = [ { label: 'English', value: 'en' }, + { label: 'Italiano', value: 'it' }, { label: '中文', value: 'zh' }, { label: '日本語', value: 'ja' }, { label: '한국어', value: 'ko' }, diff --git a/src/shared/locales.ts b/src/shared/locales.ts index 29fc073..323f8e3 100644 --- a/src/shared/locales.ts +++ b/src/shared/locales.ts @@ -147,6 +147,154 @@ export const translations = { command: 'Command', }, }, + it: { + settings: { + title: 'Impostazioni', + tabs: { + app: 'Applicazione', + appearance: 'Aspetto', + terminal: 'Terminale', + ai: 'Assistente AI' + }, + appearance: { + title: 'Aspetto', + theme: 'Tema', + themeDesc: 'Seleziona un tema per personalizzare l\'aspetto dell\'applicazione.', + language: 'Lingua', + languageDesc: 'Seleziona la lingua.', + font: 'Font interfaccia', + fontDesc: 'Seleziona il font per l\'interfaccia grafica.', + opacity: 'Opacità finestre', + backgroundTheme: 'Tema di sfondo', + backgroundThemeDesc: 'Seleziona lo stile di sfondo.', + accentColor: 'Colore accento', + accentColorDesc: 'Seleziona il colore principale.' + }, + terminal: { + title: 'Impostazioni terminale', + fontFamily: 'Famiglia di caratteri', + fontFamilyDesc: 'Scegli il font per l\'interfaccia del terminale.', + fontSize: 'Dimensione carattere', + lineHeight: 'Altezza linea', + letterSpacing: 'Spaziatura caratteri', + cursorStyle: 'Stile cursore', + cursorBlink: 'Lampeggio cursore', + rendering: 'Rendering', + rendererType: 'Motore di rendering', + rendererTypeDesc: 'Passa tra canvas (stabile) e webgl (veloce, sperimentale).', + scrollback: 'Buffer di scorrimento', + scrollbackDesc: 'Numero di righe da mantenere nella cronologia.', + brightBold: 'Grassetto luminoso', + brightBoldDesc: 'Mostra il testo in grassetto con colori più luminosi.', + sound: 'Audio', + bellStyle: 'Segnale acustico del terminale' + }, + ai: { + title: 'Assistente AI', + desc: 'Configura i servizi AI per usare un linguaggio naturale nei comandi, nell\'analisi degli errori e altro.', + enable: 'Abilita AI', + enableDesc: 'Mostra la chat AI sotto il terminale.', + provider: 'Provider AI', + providerDesc: 'Seleziona il provider API per l\'AI.', + apiKey: 'Chiave API', + apiKeyDesc: 'Inserisci la chiave API (salvata localmente in modo sicuro).', + baseUrl: 'URL base personalizzato', + baseUrlDesc: 'Inserisci l\'URL dell\'endpoint API.', + model: 'Modello (opzionale)', + modelDesc: 'Lascia vuoto per usare il modello predefinito:', + privacy: 'Modalità privacy', + privacyDesc: 'Oscura automaticamente informazioni sensibili come IP e password.', + shortcut: 'Scorciatoia di invio', + shortcutDesc: 'Scegli la scorciatoia per inviare i messaggi.' + }, + about: { + title: 'Informazioni', + desc: 'Reflex v1.0.0\nRealizzato con Electron, React, e Shadcn UI.' + }, + back: 'Indietro' + }, + common: { + connect: 'Connetti', + disconnect: 'Disconnetti', + edit: 'Modifica', + delete: 'Elimina', + cancel: 'Annulla', + save: 'Salva', + confirm: 'Conferma', + loading: 'Caricamento...', + error: 'Errore', + success: 'Successo', + refresh: 'Ricarica', + close: 'Chiudi', + back: 'Indietro', + search: 'Cerca...', + }, + connection: { + new: 'Nuova connessione', + add: 'Aggiungi server', + host: 'Host', + port: 'Porta', + username: 'Nome utente', + password: 'Password', + name: 'Nome', + noConnections: 'Nessuna connessione trovata. Creane una per iniziare.', + noConnectionsDesc: 'Aggiungi il tuo primo server SSH e inizia la gestione remota.' + }, + agent: { + thinking: 'Sto pensando...', + placeholder: 'Di\' all\'AI cosa fare, es. Controlla il carico CPU...', + newSession: 'Nuova sessione', + sessionHistory: 'Cronologia chat', + terminalView: 'Vista terminale', + noHistory: 'Nessuna cronologia chat', + noHistoryHint: 'Inizia una conversazione per vedere la cronologia qui', + justNow: 'Proprio ora', + messages: 'messaggi', + }, + fileBrowser: { + title: 'Esplora file', + upload: 'Carica', + download: 'Scarica', + delete: 'Elimina', + rename: 'Rinomina', + newFolder: 'Nuova cartella', + loading: 'Caricamento...', + confirmDelete: 'Conferma', + emptyFolder: 'Cartella vuota', + root: 'Root', + }, + docker: { + containers: 'Container', + images: 'Immagini', + stats: 'Utilizzo disco', + start: 'Avvia', + stop: 'Arresta', + restart: 'Riavvia', + pause: 'Pausa', + resume: 'Riprendi', + remove: 'Rimuovi', + confirmRemove: 'Conferma', + cancelRemove: 'Annulla', + noDocker: 'Docker non trovato', + noDockerHint: 'Il motore Docker non è installato o avviato su questo server.', + logs: 'Log', + prune: 'Pulisci', + pruneContainers: 'Rimuovi i container arrestati', + pruneImages: 'Rimuovi le immagini inutilizzate', + pruneAll: 'Rimuovi tutte le immagini inutilizzate', + pruneVolumes: 'Rimuovi i volumi inutilizzati', + removeImage: 'Conferma', + }, + processList: { + title: 'Processi', + kill: 'Termina', + confirmKill: 'Conferma', + cpu: 'CPU', + mem: 'MEM', + user: 'Utente', + command: 'Comando', + }, + }, zh: { settings: { title: '设置', From 9767c629a609685d904c84b01059a3925fd14726 Mon Sep 17 00:00:00 2001 From: Bryan Joshua Pedini Date: Thu, 7 May 2026 09:51:32 +0200 Subject: [PATCH 3/3] feat(i18n): localize ConnectionForm field labels and text Replace hardcoded Chinese strings in `ConnectionForm` with translation lookups via `t(...)`, including form labels, auth method options, and key related field text. --- src/components/ConnectionForm.tsx | 52 +++++------ src/shared/locales.ts | 140 ++++++++++++++++++++++++++++-- 2 files changed, 161 insertions(+), 31 deletions(-) diff --git a/src/components/ConnectionForm.tsx b/src/components/ConnectionForm.tsx index c5ff878..4a9eb73 100644 --- a/src/components/ConnectionForm.tsx +++ b/src/components/ConnectionForm.tsx @@ -51,17 +51,17 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm {/* Basic Info */}
- + set({ name: e.target.value })} - placeholder={formData.host ? `${formData.username || 'root'}@${formData.host}` : '我的服务器'} + placeholder={formData.host ? `${formData.username || 'root'}@${formData.host}` : { t('connection.form.nameDesc') }} />
- + set({ host: e.target.value })} @@ -70,7 +70,7 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm />
- +
- + set({ username: e.target.value })} @@ -90,7 +90,7 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm {/* Auth Type Toggle */}
- +
@@ -116,7 +116,7 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm {/* Auth Fields */} {formData.authType === 'password' ? (
- +
- +
set({ privateKeyPath: e.target.value })} - placeholder="~/.ssh/id_rsa 或 /path/to/key.pem" + placeholder="~/.ssh/id_rsa {t('connection.form.or')} /path/to/key.pem" className="flex-1" />
- + set({ passphrase: e.target.value })} - placeholder="若密钥有密码则填写" + placeholder="{t('connection.form.passphraseDesc')}" />
@@ -170,13 +170,13 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm {/* Tags */}
- + set({ tags: e.target.value.split(',').map(s => s.trim()).filter(Boolean) })} placeholder="Prod, CN-Hangzhou, Web" /> -

用于在首页卡片上显示环境/地域标签

+

{t('connection.form.tagsDesc')}

{/* Jump Host (collapsible) */} @@ -188,10 +188,10 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm >
- 跳板机 / Bastion Host + {t('connection.form.bastion')} {formData.jumpHost && ( - 已配置 + {t('connection.form.configured')} )}
@@ -202,7 +202,7 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm
- + set({ jumpHost: e.target.value })} @@ -210,7 +210,7 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm />
- +
- + set({ jumpUsername: e.target.value })} @@ -227,16 +227,16 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm />
- + set({ jumpPassword: e.target.value })} - placeholder="或使用私钥路径" + placeholder="{t('connection.form.JumpPrivKeyDesc')}" />
- +
pickFile('jumpPrivateKeyPath')} className="px-2 py-1 rounded-md bg-secondary hover:bg-secondary/80 text-muted-foreground hover:text-foreground transition-colors border border-border" - title="浏览文件" + title="{t('connection.form.browse')}" > @@ -260,8 +260,8 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm {/* Actions */}
- - + +
); diff --git a/src/shared/locales.ts b/src/shared/locales.ts index 323f8e3..75876f3 100644 --- a/src/shared/locales.ts +++ b/src/shared/locales.ts @@ -90,7 +90,33 @@ export const translations = { password: 'Password', name: 'Name', noConnections: 'No connections found. Create one to get started.', - noConnectionsDesc: 'Add your first SSH server and start remote management.' + noConnectionsDesc: 'Add your first SSH server and start remote management.', + form: { + name: 'Connection name', + nameDesc: 'My Server', + hostIp: 'Host IP / Domain', + port: 'Port', + username: 'Username', + authMethod: 'Authentication method', + password: 'Password', + privKey: 'Private key', + privKeyFilePath: 'Private key file path', + or: 'or', + passphrase: 'Private key passphrase (optional)', + passphraseDesc: 'If the key has a password, please fill it in.', + tags: 'Tags (comma-separated)', + tagsDesc: 'Used to display environment/region tags on the homepage card.', + bastion: 'Bastion Host', + configured: 'Configured', + jumpIp: 'Jump server IP / Domain', + jumpUsername: 'Jump server username', + jumpPassword: 'Jump server password', + jumpPrivKeyDesc: 'Or use private key path', + jumpPrivKeyPath: 'Private key path for the jump server (optional)', + browse: 'Browse files', + cancel: 'Cancel', + confirm: 'Confirm' + } }, agent: { thinking: 'Thinking...', @@ -238,7 +264,33 @@ export const translations = { password: 'Password', name: 'Nome', noConnections: 'Nessuna connessione trovata. Creane una per iniziare.', - noConnectionsDesc: 'Aggiungi il tuo primo server SSH e inizia la gestione remota.' + noConnectionsDesc: 'Aggiungi il tuo primo server SSH e inizia la gestione remota.', + form: { + name: 'Nome connessione', + nameDesc: 'Il mio server', + hostIp: 'IP host / Dominio', + port: 'Porta', + username: 'Nome utente', + authMethod: 'Metodo di autenticazione', + password: 'Password', + privKey: 'Chiave privata', + privKeyFilePath: 'Percorso file chiave privata', + or: 'oppure', + passphrase: 'Passphrase della chiave privata (opzionale)', + passphraseDesc: 'Se la chiave ha una password, compilala.', + tags: 'Tag (separati da virgola)', + tagsDesc: 'Usati per mostrare i tag ambiente/regione nella scheda della homepage.', + bastion: 'Host bastion', + configured: 'Configurato', + jumpIp: 'IP / Dominio del server jump', + jumpUsername: 'Nome utente del server jump', + jumpPassword: 'Password del server jump', + jumpPrivKeyDesc: 'Oppure usa il percorso della chiave privata', + jumpPrivKeyPath: 'Percorso chiave privata per il server jump (opzionale)', + browse: 'Sfoglia file', + cancel: 'Annulla', + confirm: 'Conferma' + } }, agent: { thinking: 'Sto pensando...', @@ -386,7 +438,33 @@ export const translations = { password: '密码', name: '名称', noConnections: '未找到连接。创建一个以开始。', - noConnectionsDesc: '添加你的第一个 SSH 服务器,开始远程管理。' + noConnectionsDesc: '添加你的第一个 SSH 服务器,开始远程管理。', + form: { + name: '连接名称', + nameDesc: '我的服务器', + hostIp: '主机 IP / 域名', + port: '端口', + username: '用户名', + authMethod: '认证方式', + password: '密码', + privKey: '私钥', + privKeyFilePath: '私钥文件路径', + or: '或', + passphrase: '私钥口令(可选)', + passphraseDesc: '如果密钥有密码,请填写。', + tags: '标签(逗号分隔)', + tagsDesc: '用于在首页卡片上显示环境/区域标签。', + bastion: '堡垒机', + configured: '已配置', + jumpIp: '跳板机 IP / 域名', + jumpUsername: '跳板机用户名', + jumpPassword: '跳板机密码', + jumpPrivKeyDesc: '或使用私钥路径', + jumpPrivKeyPath: '跳板机私钥路径(可选)', + browse: '浏览文件', + cancel: '取消', + confirm: '确认' + } }, agent: { thinking: '正在思考...', @@ -534,7 +612,33 @@ export const translations = { password: 'パスワード', name: '名前', noConnections: '接続が見つかりません。新しい接続を作成してください。', - noConnectionsDesc: '最初のSSHサーバーを追加して、リモート管理を開始しましょう。' + noConnectionsDesc: '最初のSSHサーバーを追加して、リモート管理を開始しましょう。', + form: { + name: '接続名', + nameDesc: 'マイサーバー', + hostIp: 'ホスト IP / ドメイン', + port: 'ポート', + username: 'ユーザー名', + authMethod: '認証方式', + password: 'パスワード', + privKey: '秘密鍵', + privKeyFilePath: '秘密鍵ファイルパス', + or: 'または', + passphrase: '秘密鍵のパスフレーズ(任意)', + passphraseDesc: '鍵にパスワードがある場合は入力してください。', + tags: 'タグ(カンマ区切り)', + tagsDesc: 'ホーム画面カードに環境/リージョンタグを表示するために使用します。', + bastion: '踏み台ホスト', + configured: '設定済み', + jumpIp: '踏み台サーバー IP / ドメイン', + jumpUsername: '踏み台サーバーのユーザー名', + jumpPassword: '踏み台サーバーのパスワード', + jumpPrivKeyDesc: 'または秘密鍵パスを使用', + jumpPrivKeyPath: '踏み台サーバー用の秘密鍵パス(任意)', + browse: 'ファイルを参照', + cancel: 'キャンセル', + confirm: '確認' + } }, agent: { thinking: '考え中...', @@ -682,7 +786,33 @@ export const translations = { password: '비밀번호', name: '이름', noConnections: '연결을 찾을 수 없습니다. 시작하려면 연결을 생성하세요.', - noConnectionsDesc: '첫 번째 SSH 서버를 추가하고 원격 관리를 시작하세요.' + noConnectionsDesc: '첫 번째 SSH 서버를 추가하고 원격 관리를 시작하세요.', + form: { + name: '연결 이름', + nameDesc: '내 서버', + hostIp: '호스트 IP / 도메인', + port: '포트', + username: '사용자 이름', + authMethod: '인증 방식', + password: '비밀번호', + privKey: '개인 키', + privKeyFilePath: '개인 키 파일 경로', + or: '또는', + passphrase: '개인 키 암호문(선택 사항)', + passphraseDesc: '키에 비밀번호가 있으면 입력하세요.', + tags: '태그(쉼표로 구분)', + tagsDesc: '홈페이지 카드에 환경/리전 태그를 표시하는 데 사용됩니다.', + bastion: '배스천 호스트', + configured: '구성됨', + jumpIp: '점프 서버 IP / 도메인', + jumpUsername: '점프 서버 사용자 이름', + jumpPassword: '점프 서버 비밀번호', + jumpPrivKeyDesc: '또는 개인 키 경로 사용', + jumpPrivKeyPath: '점프 서버용 개인 키 경로(선택 사항)', + browse: '파일 찾아보기', + cancel: '취소', + confirm: '확인' + } }, agent: { thinking: '생각 중...',