diff --git a/app/src/i18n/index.ts b/app/src/i18n/index.ts index 8c293490..504fb3d8 100644 --- a/app/src/i18n/index.ts +++ b/app/src/i18n/index.ts @@ -3,11 +3,13 @@ import LanguageDetector from 'i18next-browser-languagedetector'; import { initReactI18next } from 'react-i18next'; import en from './locales/en/translation.json'; import ja from './locales/ja/translation.json'; +import ptBR from './locales/pt-BR/translation.json'; import zhCN from './locales/zh-CN/translation.json'; import zhTW from './locales/zh-TW/translation.json'; export const SUPPORTED_LANGUAGES = [ { code: 'en', label: 'English' }, + { code: 'pt-BR', label: 'Português (Brasil)' }, { code: 'ja', label: '日本語' }, { code: 'zh-CN', label: '简体中文' }, { code: 'zh-TW', label: '繁體中文' }, @@ -21,6 +23,7 @@ i18n .init({ resources: { en: { translation: en }, + 'pt-BR': { translation: ptBR }, ja: { translation: ja }, 'zh-CN': { translation: zhCN }, 'zh-TW': { translation: zhTW }, diff --git a/app/src/i18n/locales/pt-BR/translation.json b/app/src/i18n/locales/pt-BR/translation.json new file mode 100644 index 00000000..d2885d8e --- /dev/null +++ b/app/src/i18n/locales/pt-BR/translation.json @@ -0,0 +1,1241 @@ +{ + "common": { + "cancel": "Cancelar", + "save": "Salvar", + "delete": "Excluir", + "edit": "Editar", + "close": "Fechar", + "confirm": "Confirmar", + "loading": "Carregando…", + "error": "Erro", + "unknown": "Desconhecido", + "unknownError": "Erro desconhecido" + }, + "nav": { + "generate": "Gerar", + "stories": "Histórias", + "captures": "Capturas", + "voices": "Vozes", + "effects": "Efeitos", + "audio": "Áudio", + "models": "Modelos", + "settings": "Configurações", + "updateBadge": "Atualização" + }, + "captures": { + "title": "Capturas", + "beta": "Beta", + "searchPlaceholder": "Buscar transcrições…", + "snippetEmpty": "(sem transcrição)", + "noTranscriptError": "A captura ainda não tem transcrição", + "captureCardLabel": "Captura · {{when}}", + "header": { + "modelSummary": "Whisper {{stt}} · Qwen3 · {{llm}}" + }, + "source": { + "dictation": "Ditado", + "recording": "Gravação", + "file": "Arquivo" + }, + "transcript": { + "refined": "Refinada", + "raw": "Bruta", + "refinedHint": "Refinada com Qwen3 · {{model}}", + "rawHint": "Transcrita com Whisper {{model}}" + }, + "actions": { + "configure": "Configurar", + "import": "Importar", + "importing": "Enviando…", + "dictate": "Ditar", + "stop": "Parar", + "copy": "Copiar", + "refine": "Refinar", + "reRefine": "Refinar de novo", + "export": "Exportar", + "exportDropdownLabel": "Exportar captura como", + "exportAudio": "Áudio (WAV)", + "exportTranscript": "Transcrição (TXT)", + "exportMarkdown": "Markdown (MD)", + "delete": "Excluir", + "playAs": "Reproduzir como {{name}}", + "playAsFallback": "Reproduzir como…", + "playAsGenerating": "Gerando…", + "playAsStop": "Parar · {{name}}", + "playAsStopFallback": "Parar · Voz", + "playAsDropdownLabel": "Reproduzir transcrição como" + }, + "empty": { + "noMatches": "Nenhuma captura corresponde a \"{{query}}\"", + "none": "Nenhuma captura ainda.", + "loading": "Carregando capturas…", + "pickOne": "Escolha uma captura para ver a transcrição.", + "holdToRecord": "Segure para gravar", + "toggleHandsFree": "Alternar mãos-livres", + "pressShortcut": "Pressione o atalho em qualquer lugar da sua máquina para iniciar sua primeira captura.", + "turnOnShortcut": "Ative o atalho global para ditar de qualquer lugar — ou clique em Ditar acima para uma captura dentro do app.", + "openSettings": "Abrir configurações de Capturas" + }, + "deleteDialog": { + "title": "Excluir captura", + "description": "Isso vai excluir permanentemente a captura, seu áudio e sua transcrição. Não é possível desfazer.", + "deleting": "Excluindo…" + }, + "toast": { + "deleteFailed": "Falha ao excluir", + "playAsFailed": "Falha ao reproduzir como", + "noVoice": "Nenhum perfil de voz", + "noVoiceDescription": "Crie um perfil de voz antes de usar Reproduzir como.", + "transcriptCopied": "Transcrição copiada", + "copyFailed": "Falha ao copiar", + "exportSuccess": "Exportado para {{path}}", + "exportFailed": "Falha ao exportar", + "exportEmpty": "Nada para exportar", + "shortcutNotArmed": "Atalho ligado, mas ainda não armado", + "shortcutNotArmedDescription_one": "{{names}} ainda precisa ser baixado. Abra a aba Capturas para começar.", + "shortcutNotArmedDescription_other": "{{names}} ainda precisam ser baixados. Abra a aba Capturas para começar." + }, + "pill": { + "recording": "Gravando", + "transcribing": "Transcrevendo", + "refining": "Refinando", + "speaking": "Falando", + "completed": "Concluído", + "stopAria": "Parar gravação", + "errorFallback": "Algo deu errado", + "errorCopyTooltip": "Clique para copiar o erro" + }, + "chord": { + "capturing": "Capturando…", + "pressShortcut": "Pressione seu atalho", + "noKeys": "Nenhuma tecla ainda", + "unsupported": "\"{{key}}\" não é suportada em combinações. Tente um modificador ou uma letra.", + "notSet": "Não definido" + }, + "readiness": { + "title": "Algumas coisas antes de você poder ditar", + "subheading": "O atalho fica desligado até tudo abaixo estar pronto.", + "downloadButton": "Baixar", + "downloading": "Baixando…", + "downloadingPercent": "Baixando… {{pct}}%", + "downloadStarted": "Download iniciado", + "downloadStartedDescription": "{{name}} está baixando. O atalho vai se armar sozinho quando terminar.", + "downloadFailed": "Falha no download", + "stt": { + "label": "{{name}} (fala para texto)", + "ready": "Modelo baixado.", + "missing": "Necessário para transcrever seu áudio", + "missingWithSize": "Necessário para transcrever seu áudio · {{size}}" + }, + "llm": { + "label": "{{name}} (refinamento)", + "ready": "Modelo baixado.", + "missing": "Limpa a transcrição bruta antes de colar", + "missingWithSize": "Limpa a transcrição bruta antes de colar · {{size}}" + }, + "inputMonitoring": { + "label": "Permissão de Monitoramento de Entrada", + "ready": "O macOS permite que o Voicebox detecte seu atalho global.", + "missing": "O macOS precisa permitir que o Voicebox detecte o atalho global.", + "openSettings": "Abrir Ajustes" + }, + "accessibility": { + "label": "Permissão de Acessibilidade", + "ready": "O Voicebox pode colar transcrições em outros apps.", + "missing": "Necessária para que as transcrições possam ser coladas no app em foco.", + "openSettings": "Abrir Ajustes" + } + }, + "permissions": { + "accessibility": { + "title": "Conceda a permissão de Acessibilidade para ativar a colagem automática", + "body": "O Voicebox precisa de Ajustes do Sistema → Privacidade e Segurança → Acessibilidade para colar transcrições em outros apps. Seu ditado ainda aparece na aba Capturas sem isso.", + "openSettings": "Abrir Ajustes", + "recheck": "Já ativei", + "rechecking": "Verificando…", + "stillMissing": "Ainda não detectado. O macOS geralmente exige fechar e reabrir o Voicebox depois de alternar a permissão." + }, + "inputMonitoring": { + "title": "Conceda Monitoramento de Entrada para ativar o atalho global", + "body": "O Voicebox precisa de Ajustes do Sistema → Privacidade e Segurança → Monitoramento de Entrada para detectar sua combinação de ditado. A opção está ligada, mas o macOS está bloqueando os eventos de tecla até você permitir.", + "openSettings": "Abrir Ajustes", + "recheck": "Já ativei", + "rechecking": "Verificando…", + "stillMissing": "Ainda não detectado. O macOS geralmente exige fechar e reabrir o Voicebox depois de alternar a permissão." + } + } + }, + "voicesTab": { + "title": "Vozes", + "loading": "Carregando vozes…", + "searchPlaceholder": "Buscar vozes…", + "newVoice": "Nova Voz", + "avatarAlt": "Avatar de {{name}}", + "selectChannels": "Selecionar canais…", + "channelDefaultLabel": "{{name}} (Padrão)", + "columns": { + "name": "Nome", + "language": "Idioma", + "generations": "Gerações", + "samples": "Amostras", + "effects": "Efeitos", + "channels": "Canais" + } + }, + "voiceInspector": { + "loading": "Carregando…", + "defaultEffectsHint": "Aplicados automaticamente às novas gerações com esta voz.", + "fields": { + "description": "Descrição" + }, + "toast": { + "invalidImageFormat": "Selecione PNG, JPG ou WebP", + "avatarUpdated": "Avatar atualizado", + "savedDescription": "\"{{name}}\" salvo." + } + }, + "audioChannels": { + "title": "Canais de Áudio", + "newChannel": "Novo Canal", + "loading": "Carregando…", + "confirmDelete": "Excluir este canal?", + "noVoicesAssigned": "Nenhuma voz atribuída", + "selectDevice": "Selecionar dispositivo", + "addDevice": "Adicionar dispositivo", + "addVoice": "Adicionar voz", + "defaultSuffix": "padrão", + "empty": { + "message": "Nenhum canal de áudio ainda. Crie seu primeiro canal para rotear vozes a dispositivos específicos.", + "action": "Criar Canal" + }, + "labels": { + "outputDevices": "Dispositivos de Saída", + "assignedVoices": "Vozes Atribuídas" + }, + "devices": { + "title": "Dispositivos Disponíveis", + "defaultNote": "O canal padrão usa o dispositivo padrão do sistema", + "toggleHint": "Clique nos dispositivos para adicioná-los ou removê-los do canal selecionado", + "selectHint": "Selecione um canal para atribuir dispositivos", + "empty": "Nenhum dispositivo de áudio encontrado", + "requiresTauri": "A seleção de dispositivo de áudio requer o Tauri" + }, + "fields": { + "name": "Nome do Canal", + "namePlaceholder": "ex.: Virtual Cable, Transmissão" + }, + "createDialog": { + "title": "Criar Canal de Áudio", + "description": "Crie um novo canal de áudio (bus) para rotear vozes a dispositivos de saída específicos.", + "action": "Criar" + }, + "editDialog": { + "title": "Editar Canal", + "description": "Atualize as configurações do canal e as atribuições de voz." + } + }, + "profileForm": { + "createTitle": "Criar Voz", + "editTitle": "Editar Voz", + "createDescription": "Crie um novo perfil de voz a partir de uma amostra de áudio ou de uma voz integrada.", + "editDescription": "Atualize os detalhes do seu perfil de voz e gerencie as amostras.", + "draftRestored": "Rascunho restaurado", + "discard": "Descartar", + "source": { + "clone": "Clonar de áudio", + "builtin": "Voz integrada" + }, + "builtin": { + "hint": "Escolha uma voz pré-construída. Estas não precisam de uma amostra de áudio.", + "badge": "Voz Integrada", + "note": "Este perfil usa uma voz integrada. A voz não pode ser alterada após a criação." + }, + "sampleTabs": { + "upload": "Enviar", + "record": "Gravar", + "system": "Áudio do Sistema" + }, + "fields": { + "engine": "Motor", + "voice": "Voz", + "name": "Nome", + "namePlaceholder": "Minha Voz", + "descriptionLabel": "Descrição (Opcional)", + "descriptionPlaceholder": "Descreva esta voz…", + "language": "Idioma", + "referenceText": "Texto de Referência", + "referenceTextPlaceholder": "Digite o texto exato falado no áudio…", + "defaultEngine": "Motor Padrão", + "noPreference": "Sem preferência", + "defaultEngineHint": "Seleciona automaticamente este motor quando o perfil é escolhido.", + "defaultEffects": "Efeitos Padrão", + "defaultEffectsHint": "Efeitos aplicados automaticamente a todas as novas gerações com esta voz.", + "personalityLabel": "Personalidade", + "personalityPlaceholder": "ex.: \"um pirata rabugento que só fala em metáforas náuticas\"", + "personalityHint": "Quem é esta voz e como ela fala. Alimenta o botão Compor e a opção de reescrever no personagem na página de geração. Deixe em branco para ocultar ambos." + }, + "avatar": { + "alt": "Pré-visualização do avatar" + }, + "actions": { + "saving": "Salvando…", + "saveChanges": "Salvar Alterações", + "createProfile": "Criar Perfil" + }, + "validation": { + "nameRequired": "O nome é obrigatório", + "referenceRequired": "O texto de referência é obrigatório ao adicionar uma amostra", + "sampleRequired": "A amostra de áudio é obrigatória", + "referenceTextRequired": "O texto de referência é obrigatório", + "audioTooLong": "O áudio é muito longo ({{duration}}). A duração máxima é {{max}}.", + "audioFailed": "Falha ao validar o arquivo de áudio. Tente outro arquivo." + }, + "toast": { + "recordingComplete": "Gravação concluída", + "recordingCompleteDescription": "O áudio foi gravado com sucesso.", + "recordingError": "Erro de gravação", + "systemAudioCaptured": "Áudio do sistema capturado", + "systemAudioCapturedDescription": "O áudio foi capturado com sucesso.", + "systemAudioError": "Erro ao capturar áudio do sistema", + "transcribeFailed": "Falha na transcrição", + "transcribeFailedFallback": "Falha ao transcrever o áudio", + "noFile": "Nenhum arquivo selecionado", + "noFileDescription": "Selecione um arquivo de áudio primeiro.", + "invalidFile": "Tipo de arquivo inválido", + "invalidImageFormat": "Selecione um arquivo de imagem (PNG, JPG ou WebP)", + "fileTooLarge": "Arquivo muito grande", + "imageTooLargeDescription": "A imagem deve ter menos de 5 MB", + "avatarRemoved": "Avatar removido", + "avatarRemovedDescription": "A imagem do avatar foi removida com sucesso.", + "avatarRemoveFailed": "Falha ao remover o avatar", + "avatarUploadFailed": "Falha no envio do avatar", + "avatarUploadFailedFallback": "Falha ao enviar o avatar", + "effectsUpdateFailed": "Falha ao atualizar os efeitos", + "effectsUpdateFailedFallback": "Falha ao salvar a cadeia de efeitos", + "voiceUpdated": "Voz atualizada", + "voiceUpdatedDescription": "\"{{name}}\" foi atualizada com sucesso.", + "noVoiceSelected": "Nenhuma voz selecionada", + "noVoiceSelectedDescription": "Selecione uma voz integrada.", + "profileCreated": "Perfil criado", + "profileCreatedBuiltin": "\"{{name}}\" foi criado com uma voz integrada.", + "profileCreatedSample": "\"{{name}}\" foi criado com uma amostra.", + "sampleRequired": "Amostra de áudio obrigatória", + "sampleRequiredDescription": "Forneça uma amostra de áudio para criar o perfil de voz.", + "referenceTextRequired": "Texto de referência obrigatório", + "referenceTextRequiredDescription": "Forneça o texto de referência para a amostra de áudio.", + "invalidAudio": "Arquivo de áudio inválido", + "invalidAudioDescription": "A duração do áudio é {{duration}}, mas o máximo é {{max}}.", + "validationError": "Erro de validação", + "rollbackFailed": "Falha na reversão", + "rollbackFailedDescription": "O perfil criado não pôde ser removido após a falha no envio da amostra.", + "profileRolledBack": "O perfil foi revertido.", + "sampleFailed": "Falha ao adicionar a amostra", + "sampleFailedDescription": "Falha ao adicionar a amostra.", + "sampleFailedRolledBack": "Falha ao adicionar a amostra. O perfil foi revertido.", + "saveFailed": "Falha ao salvar o perfil" + } + }, + "audioSample": { + "chooseFile": "Escolher Arquivo", + "uploadHint": "Clique para escolher um arquivo ou arraste e solte. Duração máxima: 30 segundos.", + "fileUploaded": "Arquivo enviado", + "fileLabel": "Arquivo: {{name}}", + "play": "Reproduzir", + "pause": "Pausar", + "transcribe": "Transcrever", + "transcribing": "Transcrevendo…", + "remove": "Remover", + "startRecording": "Iniciar Gravação", + "recordHint": "Clique para iniciar a gravação. Duração máxima: 30 segundos.", + "stopRecording": "Parar Gravação", + "remaining": "{{time}} restante", + "recordingComplete": "Gravação concluída", + "recordAgain": "Gravar Novamente", + "startCapture": "Iniciar Captura", + "systemHint": "Capture o áudio do seu sistema. Duração máxima: 30 segundos.", + "stopCapture": "Parar Captura", + "captureComplete": "Captura concluída", + "captureAgain": "Capturar Novamente" + }, + "sampleList": { + "loading": "Carregando amostras…", + "empty": { + "title": "Nenhuma amostra ainda", + "hint": "Adicione sua primeira amostra de áudio para começar" + }, + "editing": "Editando transcrição", + "placeholder": "Digite o texto de referência…", + "saving": "Salvando…", + "editTranscription": "Editar transcrição", + "deleteSample": "Excluir amostra", + "addSample": "Adicionar Amostra", + "note": "Observação: uma única amostra de 30 segundos é o ponto ideal. A qualidade pode cair com várias amostras. Em uma atualização futura, as amostras poderão ser intercambiáveis e marcadas para variar estilos da mesma voz.", + "deleteDialog": { + "title": "Excluir Amostra", + "description": "Tem certeza de que deseja excluir esta amostra de áudio? Esta ação não pode ser desfeita.", + "deleting": "Excluindo…" + }, + "player": { + "play": "Reproduzir amostra", + "pause": "Pausar amostra", + "stop": "Parar", + "stopAria": "Parar reprodução", + "position": "Posição de reprodução da amostra", + "positionValue": "{{current}} de {{total}}" + }, + "toast": { + "invalidText": "Texto inválido", + "invalidTextDescription": "O texto de referência não pode ficar vazio.", + "updated": "Amostra atualizada", + "updatedDescription": "O texto de referência foi atualizado com sucesso.", + "updateFailed": "Falha na atualização", + "updateFailedFallback": "Falha ao atualizar a amostra" + } + }, + "profiles": { + "card": { + "noDescription": "Sem descrição", + "designed": "projetada", + "export": "Exportar perfil", + "edit": "Editar perfil", + "delete": "Excluir perfil", + "selectLabel": "{{name}}, {{language}}. Selecionar como voz para a geração.", + "selectLabelSelected": "{{name}}, {{language}}. Selecionada como voz para a geração." + }, + "list": { + "errorLoading": "Erro ao carregar perfis: {{message}}", + "empty": "Nenhum perfil de voz ainda. Crie seu primeiro perfil para começar.", + "createVoice": "Criar Voz", + "unsupportedNote": "Apenas perfis de voz suportados podem ser selecionados para o modelo atual." + }, + "deleteDialog": { + "title": "Excluir Perfil", + "body": "Tem certeza de que deseja excluir \"{{name}}\"? Esta ação não pode ser desfeita.", + "deleting": "Excluindo…" + } + }, + "effects": { + "title": "Efeitos", + "newPreset": "Novo Preset", + "noDescription": "Sem descrição", + "placeholder": "Selecione um preset ou crie um novo", + "effectCount_one": "{{count}} efeito", + "effectCount_other": "{{count}} efeitos", + "sections": { + "builtin": "Integrados", + "custom": "Personalizados", + "new": "Novo" + }, + "badge": { + "builtin": "integrado" + }, + "unsaved": { + "title": "Preset Não Salvo", + "hint": "Configure os efeitos no painel à direita." + }, + "detail": { + "newTitle": "Novo Preset", + "editTitle": "Editar Preset", + "savePreset": "Salvar Preset", + "saveAsCustom": "Salvar como Personalizado", + "saving": "Salvando…", + "deleting": "Excluindo…" + }, + "fields": { + "name": "Nome", + "namePlaceholder": "Meu preset…", + "description": "Descrição", + "descriptionPlaceholder": "Descreva o que este preset faz…" + }, + "preview": { + "label": "Prévia", + "button": "Pré-visualizar", + "processing": "Processando…", + "hint": "A prévia aplica os efeitos à versão limpa sem salvar." + }, + "saveAs": { + "title": "Salvar como Preset Personalizado", + "description": "Crie um novo preset personalizado com base na cadeia de efeitos atual.", + "suggestedName": "{{name}} (Cópia)" + }, + "toast": { + "saved": "Preset salvo", + "createdDescription": "\"{{name}}\" foi criado.", + "updated": "Preset atualizado", + "deleted": "Preset excluído", + "saveFailed": "Falha ao salvar", + "deleteFailed": "Falha ao excluir", + "previewFailed": "Falha na prévia", + "nameRequired": "Nome obrigatório" + }, + "chain": { + "loadPreset": "Carregar preset…", + "addEffect": "Adicionar efeito…", + "clear": "Limpar", + "enable": "Ativar", + "disable": "Desativar", + "remove": "Remover" + }, + "types": { + "chorus": { + "label": "Chorus / Flanger", + "params": { + "rate_hz": "Velocidade do LFO (Hz)", + "depth": "Profundidade de modulação", + "feedback": "Quantidade de feedback", + "centre_delay_ms": "Atraso central (ms)", + "mix": "Mistura processado/seco" + } + }, + "reverb": { + "label": "Reverb", + "params": { + "room_size": "Tamanho da sala", + "damping": "Amortecimento de altas frequências", + "wet_level": "Nível processado", + "dry_level": "Nível seco", + "width": "Largura estéreo" + } + }, + "delay": { + "label": "Delay", + "params": { + "delay_seconds": "Tempo de atraso (segundos)", + "feedback": "Quantidade de feedback", + "mix": "Mistura processado/seco" + } + }, + "compressor": { + "label": "Compressor", + "params": { + "threshold_db": "Limiar (dB)", + "ratio": "Razão de compressão", + "attack_ms": "Tempo de ataque (ms)", + "release_ms": "Tempo de liberação (ms)" + } + }, + "gain": { + "label": "Ganho", + "params": { + "gain_db": "Ganho (dB)" + } + }, + "highpass": { + "label": "Filtro Passa-Alta", + "params": { + "cutoff_frequency_hz": "Frequência de corte (Hz)" + } + }, + "lowpass": { + "label": "Filtro Passa-Baixa", + "params": { + "cutoff_frequency_hz": "Frequência de corte (Hz)" + } + }, + "pitch_shift": { + "label": "Mudança de Tom", + "params": { + "semitones": "Semitons para deslocar" + } + } + }, + "builtinPresets": { + "Robotic": { + "name": "Robótico", + "description": "Voz robótica metálica (flanger com LFO lento e feedback alto)" + }, + "Radio": { + "name": "Rádio", + "description": "Voz fina de rádio AM com filtragem passa-banda e compressão leve" + }, + "Echo Chamber": { + "name": "Câmara de Eco", + "description": "Reverb espaçoso com eco prolongado" + }, + "Deep Voice": { + "name": "Voz Grave", + "description": "Tom mais baixo com calor adicionado" + } + } + }, + "stories": { + "title": "Histórias", + "newStory": "Nova História", + "loading": "Carregando histórias…", + "searchPlaceholder": "Buscar histórias…", + "empty": { + "title": "Nenhuma história ainda", + "hint": "Crie sua primeira história para começar", + "noMatches": "Nenhuma história corresponde a \"{{query}}\"" + }, + "row": { + "itemCount_one": "{{count}} item", + "itemCount_other": "{{count}} itens", + "ariaLabel": "História {{name}}, {{count}} itens, {{updated}}", + "actionsLabel": "Ações para {{name}}" + }, + "createDialog": { + "title": "Criar Nova História", + "description": "Crie uma nova história para organizar suas gerações de voz em conversas.", + "action": "Criar", + "creating": "Criando…" + }, + "editDialog": { + "title": "Editar História", + "description": "Atualize o nome e a descrição da história.", + "saving": "Salvando…" + }, + "deleteDialog": { + "title": "Tem certeza?", + "description": "Isso vai excluir permanentemente a história e todos os seus itens. Esta ação não pode ser desfeita.", + "deleting": "Excluindo…" + }, + "fields": { + "name": "Nome", + "namePlaceholder": "Minha História", + "descriptionLabel": "Descrição (opcional)", + "descriptionPlaceholder": "Uma conversa entre…" + }, + "toast": { + "nameRequired": "Nome obrigatório", + "nameRequiredDescription": "Digite um nome para a história", + "created": "História criada", + "createdDescription": "\"{{name}}\" foi criada", + "createFailed": "Falha ao criar a história", + "updateFailed": "Falha ao atualizar a história", + "deleteFailed": "Falha ao excluir a história" + } + }, + "storyContent": { + "selectStory": { + "title": "Selecione uma história", + "hint": "Escolha uma história da lista para ver seu conteúdo" + }, + "loading": "Carregando história…", + "notFound": { + "title": "História não encontrada", + "hint": "A história selecionada não pôde ser carregada" + }, + "generatingCount_one": "Gerando {{count}} áudio", + "generatingCount_other": "Gerando {{count}} áudios", + "add": "Adicionar", + "searchPlaceholder": "Buscar por nome ou transcrição…", + "searchNoMatches": "Nenhuma geração correspondente encontrada", + "searchNoAvailable": "Nenhuma geração disponível", + "exportAudio": "Exportar Áudio", + "empty": { + "title": "Nenhum item nesta história", + "hint": "Gere fala usando a caixa abaixo para adicionar itens" + }, + "itemActions": { + "playFromHere": "Reproduzir a partir daqui", + "regenerate": "Regenerar", + "removeFromStory": "Remover da História" + }, + "importAudio": "Importar áudio…", + "importing": "Importando…", + "dropToImport": "Solte o áudio para importar", + "toast": { + "removeFailed": "Falha ao remover o item", + "reorderFailed": "Falha ao reordenar os itens", + "exportFailed": "Falha ao exportar o áudio", + "addFailed": "Falha ao adicionar a geração", + "regenerateFailed": "Falha ao regenerar", + "importFailed": "Falha ao importar o áudio" + } + }, + "history": { + "empty": "Nenhuma geração de voz ainda…", + "actions": { + "menu": "Ações", + "play": "Reproduzir", + "exportAudio": "Exportar Áudio", + "exportPackage": "Exportar Pacote", + "applyEffects": "Aplicar Efeitos", + "regenerate": "Regenerar" + }, + "deleteDialog": { + "title": "Excluir Geração", + "body": "Tem certeza de que deseja excluir esta geração de \"{{name}}\"? Esta ação não pode ser desfeita.", + "deleting": "Excluindo…" + }, + "clearFailedDialog": { + "title": "Limpar gerações com falha", + "body_one": "Isso vai excluir permanentemente {{count}} geração com falha do seu histórico. Não é possível desfazer.", + "body_other": "Isso vai excluir permanentemente {{count}} gerações com falha do seu histórico. Não é possível desfazer.", + "clearing": "Limpando…", + "clearAll": "Limpar tudo" + }, + "importDialog": { + "title": "Importar Geração", + "body": "Importar a geração de \"{{name}}\". Isso a adicionará ao seu histórico.", + "importing": "Importando…", + "action": "Importar" + }, + "effectsDialog": { + "title": "Aplicar Efeitos", + "body": "Configure os efeitos de pós-processamento a aplicar a esta geração. Uma nova versão será criada.", + "sourceLabel": "Origem", + "sourcePlaceholder": "Selecione a versão de origem", + "apply": "Aplicar", + "applying": "Aplicando…" + } + }, + "generation": { + "placeholder": { + "storyWithEffects": "Gerar fala para \"{{name}}\"… (digite / para efeitos)", + "story": "Gerar fala para \"{{name}}\"…", + "profile": "Gerar fala usando {{name}}…", + "effectsHint": "Digite / para efeitos como [laugh], [sigh]…", + "selectVoice": "Selecione um perfil de voz acima…" + }, + "button": { + "generate": "Gerar fala", + "generating": "Gerando…", + "selectFirst": "Selecione um perfil de voz primeiro" + }, + "instruct": { + "show": "Mostrar instruções de entrega", + "hide": "Ocultar instruções de entrega", + "tooltip": "Instruções de entrega (tom, emoção, ritmo)", + "placeholder": "Instruções de entrega — ex.: Fale devagar e com calor, Autoritário e claro…" + }, + "voiceSelector": { + "placeholder": "Selecione uma voz…" + }, + "effects": { + "none": "Sem efeitos", + "profileDefault": "Padrão do perfil" + }, + "compose": { + "tooltip": "Compor", + "ariaLabel": "Compor uma fala no personagem", + "failedTitle": "Falha ao compor", + "failedDescription": "Não foi possível gerar texto a partir desta personalidade." + }, + "persona": { + "tooltipActive": "Falando no personagem", + "tooltipInactive": "Falar no personagem", + "ariaLabelActive": "Falando no personagem", + "ariaLabelInactive": "Falar no personagem" + } + }, + "main": { + "importVoice": "Importar Voz", + "createVoice": "Criar Voz", + "import": { + "invalidTitle": "Tipo de arquivo inválido", + "invalidDescription": "Selecione um arquivo .voicebox.zip válido", + "successTitle": "Perfil importado", + "successDescription": "Perfil de voz importado com sucesso", + "failedTitle": "Falha ao importar o perfil", + "dialogTitle": "Importar Perfil", + "dialogDescription": "Importar o perfil de \"{{name}}\". Isso criará um novo perfil com todas as amostras.", + "importing": "Importando…", + "action": "Importar" + } + }, + "settings": { + "tabs": { + "general": "Geral", + "generation": "Geração", + "captures": "Capturas", + "mcp": "MCP", + "gpu": "GPU", + "logs": "Logs", + "changelog": "Novidades", + "about": "Sobre" + }, + "language": { + "label": "Idioma", + "description": "Escolha o idioma de exibição do Voicebox." + }, + "theme": { + "label": "Tema", + "description": "Acompanhe o sistema ou escolha uma aparência clara ou escura fixa.", + "options": { + "system": "Sistema", + "light": "Claro", + "dark": "Escuro" + } + }, + "general": { + "docs": { "title": "Ler a Documentação" }, + "discord": { "title": "Entrar no Discord", "subtitle": "Tire dúvidas e compartilhe vozes" }, + "serverUrl": { + "title": "URL do Servidor", + "description": "O endereço do seu servidor backend do Voicebox.", + "invalidUrl": "Digite uma URL válida", + "updatedTitle": "URL do servidor atualizada", + "updatedDescription": "Conectado a {{url}}" + }, + "keepServerRunning": { + "title": "Manter o servidor rodando ao fechar o app", + "description": "O servidor continuará rodando em segundo plano após fechar o app.", + "failedTitle": "Falha ao atualizar a configuração", + "failedDescription": "Não foi possível sincronizar a configuração com o backend.", + "updatedTitle": "Configuração atualizada", + "runningDescription": "O servidor continuará rodando ao fechar o app", + "stoppedDescription": "O servidor será parado ao fechar o app" + }, + "networkAccess": { + "title": "Permitir acesso à rede", + "description": "Torna o servidor acessível a partir de outros dispositivos na sua rede. Reinicie o app após alterar.", + "updatedTitle": "Configuração atualizada", + "enabled": "Acesso à rede ativado. Reinicie o app para aplicar.", + "disabled": "Acesso à rede desativado. Reinicie o app para aplicar." + }, + "connection": { + "connecting": "Conectando", + "offline": "Offline", + "online": "Online" + }, + "updates": { + "title": "Atualizações do App", + "devSuffix": " (dev)", + "devMode": { + "title": "Modo de desenvolvimento", + "description": "As atualizações automáticas estão desativadas no modo de desenvolvimento." + }, + "check": { + "title": "Verificar atualizações", + "available": "Versão {{version}} disponível", + "checking": "Verificando…", + "upToDate": "Você está atualizado", + "button": "Verificar" + }, + "error": "Erro na atualização", + "download": { + "title": "Atualizar para {{version}}", + "description": "Baixe e instale a versão mais recente.", + "button": "Baixar" + }, + "downloading": "Baixando atualização…", + "ready": { + "title": "Atualização pronta para instalar", + "description": "A versão {{version}} foi baixada. Reinicie para concluir.", + "button": "Reiniciar Agora" + } + }, + "api": { + "title": "Acesso à API", + "description": "Integre o Voicebox ao seu fluxo de trabalho via API REST em {{url}}", + "viewReference": "Ver a referência completa da API", + "endpoints": { + "generate": "Gerar fala", + "health": "Status do servidor", + "profiles": "Listar vozes", + "history": "Gerações anteriores" + } + } + }, + "generation": { + "title": "Geração", + "description": "Controles para geração de texto longo. Estas configurações se aplicam a todos os motores.", + "chunkLimit": { + "title": "Limite de divisão automática", + "description": "Textos longos são divididos em blocos nos limites das frases. Valores menores podem melhorar a qualidade em saídas longas.", + "value": "{{chars}} caracteres" + }, + "crossfade": { + "title": "Crossfade entre blocos", + "description": "Mistura o áudio entre blocos para suavizar as transições. Defina como 0 para um corte seco.", + "cut": "Corte", + "ms": "{{ms}}ms" + }, + "normalize": { + "title": "Normalizar áudio", + "description": "Ajusta o volume de saída para um nível consistente entre as gerações." + }, + "autoplay": { + "title": "Reprodução automática ao gerar", + "description": "Reproduz o áudio automaticamente quando uma geração é concluída." + }, + "folder": { + "title": "Pasta de gerações", + "description": "Onde os arquivos de áudio gerados são armazenados no disco.", + "open": "Abrir" + }, + "sidebar": { + "aboutTitle": "Sobre a geração de voz", + "aboutBody": "Clone uma voz a partir de uma amostra curta e gere fala em qualquer voz e em qualquer idioma. Leve TTS para agentes de IA, jogos, podcasts ou narração de formato longo.", + "differencesTitle": "O que muda", + "clone": { + "title": "Clone qualquer voz em segundos.", + "body": "Alguns segundos de áudio de referência já bastam. Suporte a múltiplas amostras para maior qualidade quando você quiser." + }, + "engines": { + "title": "Sete motores, 23 idiomas.", + "body": "Escolha o equilíbrio ideal — qualidade, velocidade ou cobertura multilíngue." + }, + "agentReady": { + "title": "Pronto para agentes.", + "body": "API REST com controle por perfil — dê a qualquer IA uma voz que você clonou." + } + } + }, + "captures": { + "dictation": { + "title": "Ditado", + "description": "Capture de qualquer lugar da sua máquina com um atalho global.", + "globalShortcut": { + "title": "Atalho global", + "description": "Segure o atalho para gravar de qualquer lugar da sua máquina. Solte para transcrever." + }, + "pushToTalk": { + "title": "Atalho de apertar para falar", + "description": "Segure estas teclas em qualquer lugar do sistema para gravar. Solte para parar e transcrever.", + "change": "Alterar" + }, + "toggle": { + "title": "Atalho de alternância", + "description": "Pressione uma vez para iniciar uma gravação mãos-livres. Pressione de novo para parar. Geralmente é o atalho de apertar para falar mais a barra de espaço.", + "change": "Alterar" + }, + "chordPicker": { + "pttTitle": "Definir atalho de apertar para falar", + "pttDescription": "Segure as teclas que deseja usar, depois solte e clique em Salvar. O selo de modificador da direita mostra se a tecla é a variante esquerda ou direita.", + "toggleTitle": "Definir atalho de alternância", + "toggleDescription": "Segure as teclas que deseja usar, depois solte e clique em Salvar. Escolha algo distinto da sua combinação de apertar para falar." + }, + "preview": { + "title": "Prévia", + "description": "O que aparece na tela enquanto você segura o atalho." + }, + "copyToClipboard": { + "title": "Copiar transcrição para a área de transferência", + "description": "A transcrição limpa vai para a área de transferência quando a captura termina." + }, + "autoPaste": { + "title": "Colar automaticamente no campo de texto em foco", + "description": "Se um campo de texto estiver em foco em outro app, cola diretamente nele. O Voicebox salva e restaura o que estava na sua área de transferência." + } + }, + "transcription": { + "title": "Transcrição", + "description": "Escolha qual modelo de fala para texto roda nas suas capturas.", + "model": { + "title": "Modelo de transcrição", + "description": "O Whisper vem com o Voicebox e roda inteiramente na sua máquina.", + "base": "Whisper Base · 74M · {{tail}}", + "small": "Whisper Small · 244M · {{tail}}", + "medium": "Whisper Medium · 769M · {{tail}}", + "large": "Whisper Large · 1.5B · {{tail}}", + "turbo": "Whisper Turbo · Large v3 podado · {{tail}}", + "tail": { + "fast": "Rápido", + "balanced": "Equilibrado", + "higher": "Maior precisão", + "best": "Melhor precisão", + "nearBest": "Quase a melhor, rápido" + } + }, + "language": { + "title": "Idioma", + "description": "A detecção automática funciona para a maioria das capturas. Trave o idioma se você sempre fala o mesmo.", + "auto": "Detecção automática", + "en": "Inglês", + "es": "Espanhol", + "fr": "Francês", + "de": "Alemão", + "ja": "Japonês", + "zh": "Chinês", + "hi": "Hindi" + }, + "archive": { + "title": "Arquivar áudio", + "description": "Mantenha a gravação original junto de cada transcrição." + } + }, + "refinement": { + "title": "Refinamento", + "description": "Opcionalmente, rode um LLM local sobre as transcrições para limpar palavras de preenchimento, pontuação e autocorreções.", + "auto": { + "title": "Refinar transcrições automaticamente", + "description": "Roda após cada captura. Você ainda pode alternar entre bruta e refinada na aba Capturas." + }, + "model": { + "title": "Modelo de refinamento", + "description": "Modelos maiores são mais lentos, mas lidam melhor com autocorreções sutis e vocabulário técnico.", + "size06": "Qwen3 · 0.6B · 400 MB · {{tail}}", + "size17": "Qwen3 · 1.7B · 1.1 GB · {{tail}}", + "size40": "Qwen3 · 4B · 2.5 GB · {{tail}}", + "tail": { + "veryFast": "Muito rápido", + "fast": "Rápido", + "fullQuality": "Qualidade total" + } + }, + "smartCleanup": { + "title": "Limpeza inteligente", + "description": "Remove palavras de preenchimento (hum, é, tipo), restaura a pontuação e corrige o uso de maiúsculas sem reformular." + }, + "selfCorrection": { + "title": "Remover autocorreções", + "description": "Quando você muda de ideia no meio da frase (\"na verdade, não...\", \"espera, quis dizer...\"), descarta a parte retratada e mantém a intenção final." + }, + "preserveTechnical": { + "title": "Preservar termos técnicos", + "description": "Mantém identificadores de código, nomes de comandos e siglas exatamente como falados. Ative quando ditar em um prompt de código." + } + }, + "playback": { + "title": "Reprodução", + "description": "Voz padrão para a ação \"Reproduzir como\" na aba Capturas.", + "defaultVoice": { + "title": "Voz padrão", + "description": "Usada quando você clica em Reproduzir como sem escolher uma voz antes. Você pode alterá-la por captura.", + "noClonedVoices": "Nenhuma voz clonada ainda", + "noneSelected": "Nenhuma selecionada", + "clonedVoices": "Vozes clonadas" + } + }, + "storage": { + "title": "Armazenamento", + "description": "As capturas são salvas como arquivos pareados de áudio e transcrição no seu diretório de dados do Voicebox.", + "retention": { + "title": "Retenção", + "description": "Por quanto tempo manter as capturas. Vale tanto para áudio quanto para transcrições.", + "forever": "Manter para sempre", + "d90": "90 dias", + "d30": "30 dias", + "d7": "7 dias" + }, + "folder": { + "title": "Pasta de capturas", + "description": "Onde o áudio e as transcrições das capturas são armazenados no disco.", + "open": "Abrir" + } + }, + "sidebar": { + "aboutTitle": "Sobre as Capturas", + "aboutBody": "Segure um atalho em qualquer lugar da sua máquina, fale, e o Voicebox transforma sua voz em texto. Reproduza-o em qualquer voz clonada, cole-o em qualquer app ou envie-o ao seu agente de programação.", + "differencesTitle": "O que muda", + "local": { + "title": "Totalmente local.", + "body": "O Whisper e o LLM de refinamento rodam no seu hardware. Sem nuvem, sem contas, sua voz nunca sai da máquina." + }, + "playAs": { + "title": "Reproduza como qualquer voz.", + "body": "As transcrições podem ser lidas de volta em qualquer perfil que você clonou." + }, + "crossPlatform": { + "title": "Multiplataforma.", + "body": "Mesmo atalho, mesmo fluxo no macOS, Windows e Linux." + }, + "windowsCaveat": { + "title": "Atenção no Windows", + "body": "O atalho não dispara enquanto o próprio Voicebox ou qualquer app rodando como administrador estiver em foco. Estamos trabalhando nisso." + } + } + }, + "mcp": { + "install": { + "title": "Instalar no seu agente", + "description": "O Voicebox expõe um servidor MCP local sempre que o app está aberto. Cole um destes trechos na configuração de MCP do seu agente.", + "http": { + "title": "HTTP (recomendado)", + "description": "Para clientes que falam MCP via HTTP — Claude Code, Cursor, Windsurf, VS Code." + }, + "claudeCode": { + "title": "Comando único do Claude Code", + "description": "Registra via a CLI do Claude Code." + }, + "stdio": { + "title": "Stdio (alternativa)", + "description": "Para clientes que só iniciam processos stdio. O binário shim vem com o app." + }, + "copy": "Copiar", + "copied": "Copiado" + }, + "defaultVoice": { + "title": "Voz padrão", + "description": "Usada quando um agente chama voicebox.speak sem um perfil específico e não tem vínculo por cliente.", + "label": "Voz de reprodução padrão", + "labelHint": "Compartilhada com o menu 'Reproduzir como voz' da aba Capturas — uma voz padrão para reprodução passiva.", + "none": "(nenhuma)" + }, + "bindings": { + "title": "Voz por agente", + "description": "Vincule agentes específicos a vozes específicas para saber quem está falando sem olhar. O agente se identifica pelo cabeçalho X-Voicebox-Client-Id (ou pela variável de ambiente VOICEBOX_CLIENT_ID no stdio).", + "empty": "Nenhum vínculo ainda. Adicione um abaixo e configure seu cliente MCP para enviar o X-Voicebox-Client-Id correspondente.", + "lastSeen": "visto pela última vez {{when}}", + "lastSeenTitle": "Visto pela última vez {{when}}", + "neverConnected": "nunca conectado", + "defaultOption": "(padrão)", + "removeAria": "Remover vínculo de {{client}}", + "add": { + "title": "Adicionar um vínculo", + "clientIdPlaceholder": "id do cliente (ex.: claude-code)", + "labelPlaceholder": "rótulo (opcional)", + "action": "Adicionar vínculo" + } + }, + "sidebar": { + "aboutTitle": "Sobre o MCP", + "aboutBody": "O Model Context Protocol permite que seu agente de programação com IA — Claude Code, Cursor, Windsurf — chame as ferramentas do Voicebox. Fale em uma voz clonada, transcreva áudio, navegue pelas capturas.", + "toolsTitle": "Ferramentas disponíveis", + "tools": { + "speak": "Falar texto em um perfil de voz.", + "transcribe": "Whisper STT em um trecho.", + "listCaptures": "Ditados / gravações recentes.", + "listProfiles": "Perfis de voz disponíveis." + }, + "postSpeak": "Também exposto como POST /speak para shell scripts, ACP, A2A." + } + }, + "gpu": { + "cpuOnly": "Somente CPU", + "vramUsed": "{{mb}} MB de VRAM", + "noAcceleration": "Nenhuma aceleração por GPU detectada", + "active": "Ativo", + "cuda": { + "title": "Backend CUDA", + "description": "Aceleração por GPU NVIDIA via um backend CUDA baixável.", + "downloading": "Baixando o backend CUDA…", + "downloadingShort": "Baixando…", + "updating": "Atualizando…" + }, + "restart": { + "ready": "Servidor reiniciado com sucesso", + "waiting": "Reiniciando o servidor…", + "stopping": "Parando o servidor…" + }, + "download": { + "title": "Baixar o backend CUDA", + "description": "Download de ~2,4 GB. Requer uma GPU NVIDIA com suporte a CUDA.", + "button": "Baixar" + }, + "switchToCuda": { + "title": "Mudar para o backend CUDA", + "description": "O backend CUDA foi baixado e está pronto. Reinicie para ativar.", + "button": "Reiniciar" + }, + "switchToCpu": { + "title": "Mudar para o backend de CPU", + "description": "Desativa a aceleração por GPU. Você pode baixar o CUDA novamente depois.", + "button": "Mudar" + }, + "remove": { + "title": "Remover o backend CUDA", + "description": "Exclui o binário CUDA baixado para liberar espaço em disco.", + "button": "Remover" + }, + "errors": { + "downloadFailed": "Falha no download", + "downloadStart": "Falha ao iniciar o download", + "restartFailed": "Falha ao reiniciar", + "switchCpu": "Falha ao mudar para CPU", + "deleteCuda": "Falha ao excluir o backend CUDA" + }, + "footer": "O Voicebox detecta e usa automaticamente a melhor GPU disponível no seu sistema. Em Macs com Apple Silicon, o backend MLX roda nativamente no Neural Engine e na GPU via Metal Performance Shaders (MPS), sem configuração adicional. No Windows e no Linux com GPUs NVIDIA, você pode baixar um backend CUDA opcional para inferência acelerada por hardware. AMD ROCm, Intel XPU e DirectML também são suportados quando disponíveis através do PyTorch. Quando nenhuma GPU é detectada, o Voicebox recorre à CPU — todos os motores ainda funcionam, só que mais devagar." + }, + "logs": { + "title": "Logs do Servidor", + "lineCount_one": "{{count}} linha", + "lineCount_other": "{{count}} linhas", + "scrollToBottom": "Rolar até o final", + "clear": "Limpar", + "empty": "Nenhuma saída de log ainda.", + "devHint": "Os logs do servidor só são capturados quando o app gerencia o processo do servidor (builds de produção)." + }, + "changelog": { + "devBadge": "dev", + "showLess": "Mostrar menos", + "showMore": "Mostrar mais" + }, + "about": { + "tagline": "O estúdio de síntese de voz de código aberto. Clone vozes, gere fala, aplique efeitos e crie apps com voz — tudo rodando localmente na sua máquina.", + "createdBy": "Criado por", + "buyCoffee": "Me pague um café", + "license": "Licenciado sob a MIT" + } + }, + "models": { + "title": "Modelos", + "subtitle": "Baixe e gerencie modelos de IA para geração de voz e transcrição", + "defaultName": "Modelo", + "unknownSize": "Tamanho desconhecido", + "sections": { + "voiceGeneration": "Geração de Voz", + "transcription": "Transcrição", + "languageModels": "Modelos de Linguagem" + }, + "status": { + "loaded": "Carregado" + }, + "storage": { + "location": "Local de armazenamento", + "open": "Abrir", + "change": "Alterar", + "migrating": "Migrando…", + "reset": "Restaurar", + "pickerTitle": "Escolher a pasta de armazenamento de modelos" + }, + "progress": { + "connecting": "Conectando…", + "connectingHf": "Conectando ao HuggingFace…" + }, + "problems": { + "title": "Problemas", + "clearAll": "Limpar Tudo", + "noDetails": "Nenhum detalhe de erro disponível. Tente baixar novamente.", + "startedAt": "iniciado às {{time}}" + }, + "detail": { + "loadingInfo": "Carregando informações do modelo…", + "byAuthor": "por {{author}}", + "downloads": "Downloads", + "likes": "Curtidas", + "license": "Licença", + "languagesCount": "{{count}} idiomas suportados", + "languagesList": "Idiomas: {{list}}", + "onDisk": "{{size}} em disco" + }, + "actions": { + "download": "Baixar", + "retry": "Tentar Baixar de Novo", + "unload": "Descarregar", + "unloading": "Descarregando…", + "unloadFirst": "Descarregue o modelo antes de excluir", + "deleteModel": "Excluir Modelo" + }, + "deleteDialog": { + "title": "Excluir Modelo", + "body": "Tem certeza de que deseja excluir {{name}}?", + "sizeNote": "Isso vai liberar {{size}} de espaço em disco. O modelo precisará ser baixado novamente se você quiser usá-lo de novo.", + "deleting": "Excluindo…" + }, + "migrateDialog": { + "title": "Mover os modelos para o novo local?", + "description": "O servidor será desligado enquanto os modelos são movidos para a nova pasta. Ele reiniciará automaticamente assim que a migração for concluída.", + "action": "Mover Modelos", + "preparing": "Preparando…", + "restartingServer": "Reiniciando o servidor…" + }, + "migrate": { + "title": "Movendo modelos", + "offline": "O servidor está offline enquanto os modelos são movidos." + }, + "toast": { + "downloadFailed": "Falha no download", + "cancelFailed": "Falha ao cancelar", + "cancelFailedDescription": "Não foi possível cancelar a tarefa de download.", + "deleted": "Modelo excluído", + "deletedDescription": "{{name}} foi excluído com sucesso.", + "deleteFailed": "Falha ao excluir", + "unloaded": "Modelo descarregado", + "unloadedDescription": "{{name}} foi descarregado da memória.", + "unloadFailed": "Falha ao descarregar", + "openFolderFailed": "Falha ao abrir a pasta do modelo", + "pickerFailed": "Falha ao abrir o seletor de pastas", + "resetToDefault": "Restaurado para o local padrão. Reiniciando o servidor…", + "noModelsToMigrate": "Nenhum modelo para migrar", + "noModelsToMigrateDescription": "Baixe pelo menos um modelo antes de alterar o local de armazenamento.", + "migrated": "Modelos movidos com sucesso", + "migrationFailed": "Falha na migração", + "migrationFailedGeneric": "Falha ao migrar os modelos", + "migrationConnectionLost": "Conexão perdida durante a migração" + } + } +}