feat(V2-1d): packages/i18n 추출 — Electron 독립 i18n 엔진
packages/i18n (@d3ro/i18n) 신규:
- src/locales/ 12개 JSON (ko/en/ja/zh/zh-TW/es/fr/de/pt/ru/vi/th)
- src/index.tsx: TFunction/Locale/LOCALE_META/resolveTranslation/
포맷 유틸(createFormatDate/Number/RelativeDate/Time)/
I18nContext/useI18n/I18nProvider
Electron 독립성 확보 (monorepo 원칙 준수):
- I18nStorage interface 신설 (load/save 어댑터 추상화)
- window.electronAPI.config 직접 호출 제거
- I18nProvider는 storage prop으로 영속화 어댑터 주입
- 기본값 noopStorage (메모리 한정, 세션 범위)
- 결과: packages/i18n은 React에만 의존, web/mobile에서 재사용 가능
apps/desktop 어댑터:
- App.tsx에 electronI18nStorage 구현 (config.get/set 래핑)
- <I18nProvider storage={electronI18nStorage}>로 주입
apps/desktop 설정:
- package.json: @d3ro/i18n '*' dep 추가
- tsconfig.node/web.json paths에 @d3ro/i18n 추가
- electron.vite.config.ts alias + externalize exclude 추가
- vitest.config.ts alias 추가
일괄 치환 (29 파일):
- ./i18n, ../i18n, ../../i18n → @d3ro/i18n
apps/desktop/src/renderer/i18n/ 디렉토리 완전 제거.
검증: typecheck + build + dev 런타임 모두 통과.
Phase V2-1 전체 완료 (a/b/c/d).
This commit is contained in:
parent
a041f1b6a9
commit
3524e958ba
51 changed files with 175 additions and 66 deletions
282
packages/i18n/src/locales/pt.json
Normal file
282
packages/i18n/src/locales/pt.json
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
{
|
||||
"app.name": "D3RO Voice",
|
||||
"app.tagline": "Assistente de voz com IA local",
|
||||
"nav.dashboard": "Painel",
|
||||
"nav.history": "Histórico",
|
||||
"nav.dictionary": "Dicionário",
|
||||
"nav.commands": "Comandos",
|
||||
"nav.settings": "Configurações",
|
||||
"dashboard.sessionOverview": "Visão geral da sessão",
|
||||
"dashboard.systemStatus": "Status do sistema",
|
||||
"dashboard.sessionsToday": "Sessões hoje",
|
||||
"dashboard.pressToRecord": "Pressione {{key}} para iniciar a gravação",
|
||||
"dashboard.hotkeyNotSet": "Atalho não configurado",
|
||||
"dashboard.words": "palavras",
|
||||
"dashboard.total": "total",
|
||||
"dashboard.streak": "sequência",
|
||||
"dashboard.days": "dias",
|
||||
"dashboard.recording": "gravando",
|
||||
"dashboard.sessions": "sessões",
|
||||
"dashboard.today": "hoje",
|
||||
"dashboard.recentTranscriptions": "Transcrições recentes",
|
||||
"dashboard.noHistory": "Sem histórico — pressione o atalho para começar a gravar",
|
||||
"dashboard.copy": "Copiar",
|
||||
"dashboard.entries": "{{count}} entradas",
|
||||
"dashboard.stat": "estatísticas",
|
||||
"dashboard.sys": "sistema",
|
||||
"history.title": "Histórico de transcrições",
|
||||
"history.search": "Pesquisar...",
|
||||
"history.entries": "{{count}} entradas",
|
||||
"history.loading": "Carregando...",
|
||||
"history.noResults": "Sem resultados",
|
||||
"history.noHistory": "Sem histórico — comece a gravar",
|
||||
"history.count": "{{count}} entradas",
|
||||
"dictionary.title": "Dicionário personalizado",
|
||||
"dictionary.words": "{{count}} palavras",
|
||||
"dictionary.add": "Adicionar",
|
||||
"dictionary.search": "Pesquisar...",
|
||||
"dictionary.loading": "Carregando...",
|
||||
"dictionary.noResults": "Sem resultados",
|
||||
"dictionary.noWords": "Sem palavras — adicione palavras personalizadas para melhorar a precisão do STT",
|
||||
"dictionary.used": "usado {{count}} vezes",
|
||||
"dictionary.editTitle": "Editar palavra",
|
||||
"dictionary.addTitle": "Adicionar palavra",
|
||||
"dictionary.word": "Palavra",
|
||||
"dictionary.pronunciation": "Pronúncia (opcional)",
|
||||
"commands.title": "Comandos LLM",
|
||||
"commands.count": "{{count}} comandos",
|
||||
"commands.add": "Adicionar",
|
||||
"commands.activeCommand": "Comando ativo",
|
||||
"commands.none": "Nenhum",
|
||||
"commands.loading": "Carregando...",
|
||||
"commands.noCommands": "Sem comandos — clique em adicionar para criar um",
|
||||
"commands.editTitle": "Editar comando",
|
||||
"commands.addTitle": "Adicionar comando",
|
||||
"commands.name": "Nome",
|
||||
"commands.description": "Descrição",
|
||||
"commands.promptTemplate": "Modelo de prompt",
|
||||
"commands.promptHelp": "{{text}} será substituído pelo texto transcrito",
|
||||
"commands.defaultPrompt": "Por favor, melhore {{text}}.",
|
||||
"settings.title": "Configurações",
|
||||
"settings.tabs.general": "Geral",
|
||||
"settings.tabs.audio": "Áudio",
|
||||
"settings.tabs.stt": "STT",
|
||||
"settings.tabs.llm": "LLM",
|
||||
"settings.tabs.about": "Sobre",
|
||||
"settings.shortcuts": "Atalhos",
|
||||
"settings.dictation": "Ditado",
|
||||
"settings.dictation.desc": "Mantenha pressionado para falar. A transcrição começa ao soltar.",
|
||||
"settings.agent": "Modo agente",
|
||||
"settings.agent.descWithKey": "Clique duas vezes em {{key}} para entrar no modo agente.",
|
||||
"settings.agent.descNoKey": "Configure primeiro o atalho de ditado.",
|
||||
"settings.oneTouch": "Modo de um toque",
|
||||
"settings.oneTouch.desc": "Pressione para iniciar, pressione novamente para parar. Requer um atalho separado.",
|
||||
"settings.key": "Tecla",
|
||||
"settings.notSet": "Não configurado",
|
||||
"settings.enabled": "Ativado",
|
||||
"settings.disabled": "Desativado",
|
||||
"settings.interface": "Interface",
|
||||
"settings.theme": "Tema",
|
||||
"settings.theme.system": "Sistema",
|
||||
"settings.theme.light": "Claro",
|
||||
"settings.theme.dark": "Escuro",
|
||||
"settings.language": "Idioma",
|
||||
"settings.appBehavior": "Comportamento do aplicativo",
|
||||
"settings.closeToTray": "Minimizar para a bandeja",
|
||||
"settings.autoLaunch": "Iniciar com o sistema",
|
||||
"settings.autoInsert": "Inserir texto automaticamente após a transcrição",
|
||||
"settings.soundEffects": "Efeitos sonoros",
|
||||
"settings.microphone": "Microfone",
|
||||
"settings.inputDevice": "Dispositivo de entrada",
|
||||
"settings.deviceDefault": "(padrão)",
|
||||
"settings.textInsert": "Inserção de texto",
|
||||
"settings.insertMethod": "Método de inserção",
|
||||
"settings.insertClipboard": "Área de transferência (Ctrl+V)",
|
||||
"settings.insertKeyboard": "Digitação pelo teclado",
|
||||
"settings.whisperModel": "Modelo Whisper",
|
||||
"settings.model.tiny": "tiny (39 MB, mais rápido)",
|
||||
"settings.model.base": "base (74 MB, equilibrado)",
|
||||
"settings.model.small": "small (244 MB, bom)",
|
||||
"settings.model.medium": "medium (769 MB, muito bom)",
|
||||
"settings.model.large": "large-v3 (1,5 GB, melhor)",
|
||||
"settings.sttLanguage": "Idioma de reconhecimento",
|
||||
"settings.sttLang.auto": "Detecção automática",
|
||||
"settings.ollamaServer": "Servidor Ollama",
|
||||
"settings.ollamaUrl": "URL do servidor Ollama",
|
||||
"settings.ollamaHint": "D3RO Voice conecta-se automaticamente quando o Ollama está em execução. Baixe modelos diretamente pelo Ollama (ex: ollama pull qwen3:4b).",
|
||||
"settings.postProcess": "Pós-processamento de voz",
|
||||
"settings.defaultAction": "Ação de pós-processamento padrão",
|
||||
"settings.action.none": "Nenhuma (texto original sem alterações)",
|
||||
"settings.action.refine": "Refinar (gramática + naturalidade)",
|
||||
"settings.action.translate": "Traduzir",
|
||||
"settings.action.summarize": "Resumir",
|
||||
"settings.action.grammar": "Correção gramatical",
|
||||
"settings.action.custom": "Prompt personalizado",
|
||||
"settings.actionHint": "O pós-processamento LLM selecionado é aplicado ao texto transcrito após gravar com o atalho. Só funciona quando o Ollama está conectado.",
|
||||
"settings.about.version": "Versão",
|
||||
"settings.about.techStack": "Stack tecnológico",
|
||||
"settings.about.techStackValue": "Electron + React 19 + MUI 7 + TypeScript",
|
||||
"settings.about.voiceEngine": "Motor de voz",
|
||||
"settings.about.voiceEngineValue": "STT: faster-whisper (local) / LLM: Ollama (local)",
|
||||
"settings.about.description": "Assistente de voz com IA totalmente local, baseado em engenharia reversa do Speakly. Funciona sem dependências de nuvem.",
|
||||
"settings.about.restartOnboarding": "Ver guia de configuração inicial novamente",
|
||||
"status.ollama": "OLLAMA",
|
||||
"status.offline": "OFFLINE",
|
||||
"status.nudge.title": "Ollama não está em execução",
|
||||
"status.nudge.desc": "O Ollama é necessário para o pós-processamento LLM (tradução, resumo, etc.).",
|
||||
"status.nudge.guide": "Ver guia de instalação →",
|
||||
"onboarding.welcome.title": "D3RO-VOICE",
|
||||
"onboarding.welcome.desc": "Sem digitar, por voz. Seu assistente de voz com IA local.",
|
||||
"onboarding.welcome.start": "Começar",
|
||||
"onboarding.mic.title": "Configurar microfone",
|
||||
"onboarding.mic.desc": "Selecione o microfone que deseja usar. Você pode alterá-lo depois nas configurações.",
|
||||
"onboarding.hotkey.title": "Configurar atalho",
|
||||
"onboarding.hotkey.desc": "Configure o atalho de ditado. A gravação continua enquanto você mantiver a tecla pressionada.",
|
||||
"onboarding.hotkey.notSet": "Nenhum atalho configurado",
|
||||
"onboarding.hotkey.change": "Alterar atalho",
|
||||
"onboarding.hotkey.set": "Configurar atalho",
|
||||
"onboarding.ollama.title": "Instalar Ollama (opcional)",
|
||||
"onboarding.ollama.desc": "O Ollama é necessário para pós-processamento LLM como tradução ou resumo. O ditado de voz funciona sem o Ollama.",
|
||||
"onboarding.ollama.download": "Baixar Ollama",
|
||||
"onboarding.ollama.modelHint": "Após instalar, baixe um modelo pelo terminal",
|
||||
"onboarding.done.title": "Configuração concluída!",
|
||||
"onboarding.done.descWithKey": "Mantenha {{key}} pressionado e fale para converter sua voz em texto.",
|
||||
"onboarding.done.descNoKey": "Configure um atalho nas configurações para começar a ditar.",
|
||||
"onboarding.done.start": "Começar",
|
||||
"onboarding.back": "Voltar",
|
||||
"onboarding.next": "Próximo",
|
||||
"hotkey.title": "Configurar atalho",
|
||||
"hotkey.dictationTitle": "Configurar atalho de ditado",
|
||||
"hotkey.oneTouchTitle": "Configurar atalho do modo de um toque",
|
||||
"hotkey.prompt": "Pressione uma combinação de teclas...",
|
||||
"hotkey.ready": "✓ {{keys}} — pressione salvar",
|
||||
"hotkey.noKey": "Por favor, insira uma tecla",
|
||||
"hotkey.reserved": "{{keys}} é um atalho reservado pelo sistema",
|
||||
"hotkey.current": "Atual: {{keys}}",
|
||||
"hotkey.hint": "Insira uma combinação (ex: Ctrl+Shift+Q) ou uma tecla única (ex: F5)",
|
||||
"hotkey.reset": "Inserir novamente",
|
||||
"ollama.title": "GUIA DE CONFIGURAÇÃO DO OLLAMA",
|
||||
"ollama.step1.title": "PASSO 1 — Instalar o Ollama",
|
||||
"ollama.step1.desc": "O Ollama é uma ferramenta gratuita para executar LLMs localmente.",
|
||||
"ollama.step2.title": "PASSO 2 — Baixar um modelo",
|
||||
"ollama.step2.desc": "Execute o seguinte comando no terminal para baixar o modelo recomendado:",
|
||||
"ollama.step2.alt": "Ou um modelo maior: ollama pull qwen3:8b (mais preciso, mais lento)",
|
||||
"ollama.step3.title": "PASSO 3 — Conexão automática",
|
||||
"ollama.step3.desc": "D3RO-VOICE detecta automaticamente quando o Ollama está em execução. Quando o LED da barra de status mudar de vermelho para verde, está pronto!",
|
||||
"service.sttEngine": "MOTOR STT",
|
||||
"service.ollamaLlm": "OLLAMA LLM",
|
||||
"service.hotkeyHook": "ATALHO DE TECLADO",
|
||||
"service.audioInput": "ENTRADA DE ÁUDIO",
|
||||
"service.ready": "PRONTO",
|
||||
"service.connected": "CONECTADO",
|
||||
"service.offline": "OFFLINE",
|
||||
"service.active": "ATIVO",
|
||||
"service.standby": "EM ESPERA",
|
||||
"common.cancel": "Cancelar",
|
||||
"common.save": "Salvar",
|
||||
"common.delete": "Excluir",
|
||||
"common.add": "Adicionar",
|
||||
"common.edit": "Editar",
|
||||
"common.close": "Fechar",
|
||||
"common.confirm": "Confirmar",
|
||||
"common.loading": "Carregando...",
|
||||
"common.copy": "Copiar",
|
||||
"common.test": "Testar",
|
||||
"common.stop": "Parar",
|
||||
"date.today": "Hoje",
|
||||
"date.yesterday": "Ontem",
|
||||
"settings.theme.nord": "Nord",
|
||||
"settings.theme.solarized": "Solarized",
|
||||
"settings.theme.catppuccin": "Catppuccin",
|
||||
"settings.theme.dracula": "Dracula",
|
||||
"settings.sttLang.ko": "Coreano",
|
||||
"settings.sttLang.en": "Inglês",
|
||||
"settings.sttLang.ja": "Japonês",
|
||||
"settings.sttLang.zh": "Chinês",
|
||||
"template.outputHelperText": "Use {{nomeCampo}} para marcadores de posição",
|
||||
"nav.meeting": "Reunião",
|
||||
"meeting.title": "Modo Reunião",
|
||||
"meeting.newMeeting": "Nova Reunião",
|
||||
"meeting.startRecording": "Iniciar Gravação",
|
||||
"meeting.stopRecording": "Parar Gravação",
|
||||
"meeting.recording": "Gravando",
|
||||
"meeting.processing": "Gerando ata...",
|
||||
"meeting.completed": "Concluído",
|
||||
"meeting.error": "Erro",
|
||||
"meeting.elapsed": "Tempo decorrido",
|
||||
"meeting.memoPlaceholder": "Digite um memo (Enter para adicionar)",
|
||||
"meeting.memoAdded": "Memo adicionado",
|
||||
"meeting.noSessions": "Nenhuma gravação de reunião",
|
||||
"meeting.noSessionsDesc": "Pressione Nova Reunião para começar a gravar",
|
||||
"meeting.summary": "Resumo",
|
||||
"meeting.decisions": "Decisões",
|
||||
"meeting.actionItems": "Itens de ação",
|
||||
"meeting.timeline": "Linha do tempo",
|
||||
"meeting.transcript": "Transcrição bruta",
|
||||
"meeting.memos": "Memos",
|
||||
"meeting.exportPdf": "Exportar PDF",
|
||||
"meeting.exportMarkdown": "Exportar Markdown",
|
||||
"meeting.delete": "Excluir",
|
||||
"meeting.deleteConfirm": "Excluir este registro de reunião?",
|
||||
"meeting.backToList": "Voltar à lista",
|
||||
"meeting.notificationTitle": "Ata pronta",
|
||||
"meeting.notificationBody": "A ata da reunião foi gerada.",
|
||||
"meeting.sessions": "{{count}} sessões",
|
||||
"meeting.duration": "{{minutes}} min",
|
||||
"meeting.editTitle": "Editar título",
|
||||
"meeting.untitled": "Reunião sem título",
|
||||
"meeting.processingStep.merging": "Mesclando transcrição...",
|
||||
"meeting.processingStep.generating": "Gerando ata com LLM...",
|
||||
"meeting.processingStep.parsing": "Analisando ata...",
|
||||
"meeting.processingStep.saving": "Salvando...",
|
||||
"meeting.processingStep.notifying": "Enviando notificação...",
|
||||
"meeting.transcriptTab": "Transcrição",
|
||||
"meeting.addDocument": "Adicionar documento",
|
||||
"meeting.selectTemplate": "Selecionar modelo",
|
||||
"meeting.generate": "Gerar",
|
||||
"meeting.generating": "Gerando documento...",
|
||||
"meeting.editMode": "Editar",
|
||||
"meeting.previewMode": "Visualizar",
|
||||
"meeting.modified": "Modificado",
|
||||
"meeting.originalText": "Original",
|
||||
"meeting.editedText": "Editado",
|
||||
"meeting.exportDocx": "Exportar DOCX",
|
||||
"meeting.exportTxt": "Exportar TXT",
|
||||
"meeting.exportFormat": "Exportar",
|
||||
"meeting.customPrompt": "Prompt personalizado",
|
||||
"meeting.templateName": "Nome do modelo",
|
||||
"meeting.templatePrompt": "Prompt de IA",
|
||||
"meeting.templateSave": "Salvar modelo",
|
||||
"meeting.documentDeleted": "Documento excluído",
|
||||
"meeting.autoSaved": "Salvo automaticamente",
|
||||
"meeting.minutesTemplate": "Ata de reunião",
|
||||
"meeting.reportTemplate": "Relatório",
|
||||
"meeting.ideaNoteTemplate": "Nota de ideias",
|
||||
"meeting.customTemplate": "Personalizado",
|
||||
"meeting.downloadTranscript": "Baixar transcrição",
|
||||
"meeting.polish": "Polir com IA",
|
||||
"meeting.polishing": "IA está polindo a transcrição...",
|
||||
"meeting.polished": "Polimento IA concluído",
|
||||
"meeting.mindmapTemplate": "Mapa mental",
|
||||
"meeting.chat": "Chat IA",
|
||||
"meeting.chatPlaceholder": "Pergunte sobre a reunião...",
|
||||
"meeting.chatSend": "Enviar",
|
||||
"meeting.chatClear": "Limpar chat",
|
||||
"meeting.copyToClipboard": "Copiar para área de transferência",
|
||||
"meeting.copied": "Copiado",
|
||||
"meeting.chatCollapse": "Recolher chat",
|
||||
"meeting.chatExpand": "Expandir chat",
|
||||
"meeting.exportMd": "Markdown (.md)",
|
||||
"meeting.exportPdfFmt": "PDF (.pdf)",
|
||||
"meeting.polishFailed": "Falha no polimento de IA",
|
||||
"meeting.viewDetailError": "Falha ao carregar detalhes da reunião",
|
||||
"meeting.startRecordingError": "Falha ao iniciar gravação",
|
||||
"meeting.diarize": "Identificar oradores",
|
||||
"meeting.diarizing": "Identificando oradores...",
|
||||
"meeting.diarizeComplete": "Identificação concluída",
|
||||
"meeting.speaker": "Orador",
|
||||
"settings.hfToken": "Token do HuggingFace",
|
||||
"settings.hfTokenHint": "Um token do HuggingFace é necessário para identificar oradores",
|
||||
"settings.diarization": "Identificação de oradores",
|
||||
"settings.diarizationHint": "Identifica automaticamente os oradores após o término da gravação"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue