From 63dfcf66598717890f16f82667cbd26ef940e7ea Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 19 Feb 2026 17:44:25 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20adicionar=20suporte=20a=20Portugu=C3=AA?= =?UTF-8?q?s=20Brasileiro=20(pt=5FBR)=20no=20projeto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Adiciona arquivo de tradução pt_BR.js para manager-web (~1332 chaves) - Adiciona arquivo de tradução pt_BR.ts para manager-mobile (~440 chaves) - Cria README_pt_BR.md com documentação traduzida completa - Registra pt_BR no sistema i18n de ambos os frontends (web e mobile) - Adiciona pt_BR nos seletores de idioma (HeaderBar, login, retrievePassword) - Adiciona badge "Português (Brasil)" em todos os READMEs existentes - Adiciona detecção automática de idioma pt/pt-BR no navegador - Adiciona chave language.ptBR em todos os arquivos de tradução existentes https://claude.ai/code/session_01XJMVWKBjy7UwqskN9BbsYM --- README.md | 1 + README_de.md | 1 + README_en.md | 1 + README_pt_BR.md | 377 +++++ README_vi.md | 1 + main/manager-mobile/src/i18n/index.ts | 3 + main/manager-mobile/src/i18n/pt_BR.ts | 440 ++++++ main/manager-mobile/src/store/lang.ts | 2 +- main/manager-web/src/components/HeaderBar.vue | 8 + main/manager-web/src/i18n/de.js | 1 + main/manager-web/src/i18n/en.js | 1 + main/manager-web/src/i18n/index.js | 7 +- main/manager-web/src/i18n/pt_BR.js | 1334 +++++++++++++++++ main/manager-web/src/i18n/vi.js | 1 + main/manager-web/src/i18n/zh_CN.js | 1 + main/manager-web/src/i18n/zh_TW.js | 1 + main/manager-web/src/views/login.vue | 5 + .../src/views/retrievePassword.vue | 2 + 18 files changed, 2185 insertions(+), 2 deletions(-) create mode 100644 README_pt_BR.md create mode 100644 main/manager-mobile/src/i18n/pt_BR.ts create mode 100644 main/manager-web/src/i18n/pt_BR.js diff --git a/README.md b/README.md index 17e2b886..43607867 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ README in English Tiếng Việt Deutsch + Português (Brasil) GitHub Contributors diff --git a/README_de.md b/README_de.md index 403fc921..b4fffabb 100644 --- a/README_de.md +++ b/README_de.md @@ -21,6 +21,7 @@ Unterstützt MQTT+UDP-Protokoll, Websocket-Protokoll, MCP-Endpunkte und Stimmabd README in English Tiếng Việt Deutsch + Português (Brasil) GitHub Contributors diff --git a/README_en.md b/README_en.md index e071e7fa..a6fdb170 100644 --- a/README_en.md +++ b/README_en.md @@ -21,6 +21,7 @@ Support for MQTT+UDP protocol, Websocket protocol, MCP access point, voiceprint README in English Tiếng Việt Deutsch + Português (Brasil) GitHub Contributors diff --git a/README_pt_BR.md b/README_pt_BR.md new file mode 100644 index 00000000..acccd9fb --- /dev/null +++ b/README_pt_BR.md @@ -0,0 +1,377 @@ +[![Banners](docs/images/banner1.png)](https://github.com/xinnan-tech/xiaozhi-esp32-server) + +

Serviço Backend Xiaozhi xiaozhi-esp32-server

+ +

+Este projeto é baseado na teoria e tecnologia de inteligência simbiótica humano-máquina para desenvolver sistemas inteligentes de hardware e software para terminais
fornecendo serviços de backend para o projeto de hardware inteligente de código aberto +xiaozhi-esp32
+Implementado usando Python, Java e Vue de acordo com o Protocolo de Comunicação Xiaozhi
+Suporte ao protocolo MQTT+UDP, protocolo WebSocket, ponto de acesso MCP, reconhecimento de impressão vocal e base de conhecimento +

+ +

+Perguntas FrequentesReportar ProblemasDocumentação de ImplantaçãoNotas de Lançamento +

+ +

+ 简体中文版自述文件 + README in English + Tiếng Việt + Deutsch + Português (Brasil) + + GitHub Contributors + + + GitHub pull requests + + + stars + +

+ +

+Liderado pela Equipe do Professor Siyuan Liu (Universidade de Tecnologia do Sul da China) +
+刘思源教授团队主导研发(华南理工大学) +
+Universidade de Tecnologia do Sul da China (华南理工大学) +

+ +--- + +## Público-Alvo 👥 + +Este projeto requer dispositivos de hardware ESP32 para funcionar. Se você adquiriu hardware relacionado ao ESP32, conectou-se com sucesso ao serviço backend implantado pelo Brother Xia e deseja construir seu próprio serviço backend `xiaozhi-esp32` de forma independente, então este projeto é perfeito para você. + +Quer ver os efeitos de uso? Clique nos vídeos abaixo 🎥 + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Experiência de velocidade de resposta + + + + + + Segredo da otimização de velocidade + + + + + + Cenário médico complexo + + + + + + Envio de comandos MQTT + + + + + + Reconhecimento de impressão vocal + + +
+ + + Controle de interruptores de eletrodomésticos + + + + + + Ponto de acesso MCP + + + + + + Tarefas com múltiplos comandos + + + + + + Reproduzir música + + + + + + Plugin de clima + + +
+ + + Interrupção em tempo real + + + + + + Fotografar e identificar objetos + + + + + + Timbre de voz personalizado + + + + + + Comunicação em cantonês + + + + + + Transmissão de notícias + + +
+ +--- + +## Avisos ⚠️ + +1. Este projeto é um software de código aberto. Este software não possui parceria comercial com nenhum provedor de serviços de API de terceiros (incluindo, mas não se limitando a reconhecimento de fala, modelos de linguagem, síntese de voz e outras plataformas) com os quais se conecta, e não fornece nenhuma forma de garantia quanto à qualidade de serviço ou segurança financeira desses provedores. Recomenda-se que os usuários priorizem provedores de serviço com licenças comerciais relevantes e leiam cuidadosamente seus termos de serviço e políticas de privacidade. Este software não armazena nenhuma chave de conta, não participa de fluxos de fundos e não assume o risco de perda de fundos recarregados. + +2. A funcionalidade deste projeto não está completa e não passou por avaliação de segurança de rede. Por favor, não o utilize em ambientes de produção. Se você implantar este projeto para fins de aprendizado em um ambiente de rede pública, certifique-se de que as medidas de proteção necessárias estejam em vigor. + +--- + +## Documentação de Implantação + +![Banners](docs/images/banner2.png) + +Este projeto oferece dois métodos de implantação. Por favor, escolha de acordo com suas necessidades específicas: + +#### 🚀 Seleção do Método de Implantação +| Método de Implantação | Funcionalidades | Cenários Aplicáveis | Documentação de Implantação | Requisitos de Configuração | Tutoriais em Vídeo | +|---------|------|---------|---------|---------|---------| +| **Instalação Simplificada** | Diálogo inteligente, gerenciamento de agente único | Ambientes de baixa configuração, dados armazenados em arquivos de configuração, sem necessidade de banco de dados | [①Versão Docker](./docs/Deployment.md#%E6%96%B9%E5%BC%8F%E4%B8%80docker%E5%8F%AA%E8%BF%90%E8%A1%8Cserver) / [②Implantação via Código-Fonte](./docs/Deployment.md#%E6%96%B9%E5%BC%8F%E4%BA%8C%E6%9C%AC%E5%9C%B0%E6%BA%90%E7%A0%81%E5%8F%AA%E8%BF%90%E8%A1%8Cserver)| 2 núcleos 4GB se usar `FunASR`, 2 núcleos 2GB se todas APIs | - | +| **Instalação de Módulo Completo** | Diálogo inteligente, gerenciamento multiusuário, gerenciamento de múltiplos agentes, operação de interface do console inteligente | Experiência com funcionalidade completa, dados armazenados em banco de dados |[①Versão Docker](./docs/Deployment_all.md#%E6%96%B9%E5%BC%8F%E4%B8%80docker%E8%BF%90%E8%A1%8C%E5%85%A8%E6%A8%A1%E5%9D%97) / [②Implantação via Código-Fonte](./docs/Deployment_all.md#%E6%96%B9%E5%BC%8F%E4%BA%8C%E6%9C%AC%E5%9C%B0%E6%BA%90%E7%A0%81%E8%BF%90%E8%A1%8C%E5%85%A8%E6%A8%A1%E5%9D%97) / [③Tutorial de Atualização Automática via Código-Fonte](./docs/dev-ops-integration.md) | 4 núcleos 8GB se usar `FunASR`, 2 núcleos 4GB se todas APIs| [Tutorial em Vídeo de Inicialização via Código-Fonte Local](https://www.bilibili.com/video/BV1wBJhz4Ewe) | + + +> 💡 Nota: Abaixo está uma plataforma de teste implantada com o código mais recente. Você pode gravar e testar se necessário. Usuários simultâneos: 6, os dados serão limpos diariamente. + +``` +Endereço do Console de Controle Inteligente: https://2662r3426b.vicp.fun +Endereço do Console de Controle Inteligente (H5): https://2662r3426b.vicp.fun/h5/index.html + +Ferramenta de Teste de Serviço: https://2662r3426b.vicp.fun/test/ +Endereço da Interface OTA: https://2662r3426b.vicp.fun/xiaozhi/ota/ +Endereço da Interface WebSocket: wss://2662r3426b.vicp.fun/xiaozhi/v1/ +``` + +#### 🚩 Descrição e Recomendações de Configuração +> [!Note] +> Este projeto oferece dois esquemas de configuração: +> +> 1. `Configurações Gratuitas Nível Básico`: Adequado para uso pessoal e doméstico, todos os componentes utilizam soluções gratuitas, sem necessidade de pagamento adicional. +> +> 2. `Configuração de Streaming`: Adequado para demonstrações, treinamentos, cenários com mais de 2 usuários simultâneos, etc. Utiliza tecnologia de processamento em streaming para velocidade de resposta mais rápida e melhor experiência. +> +> A partir da versão `0.5.2`, o projeto suporta configuração de streaming. Em comparação com versões anteriores, a velocidade de resposta é melhorada em aproximadamente `2,5 segundos`, melhorando significativamente a experiência do usuário. + +| Nome do Módulo | Configurações Gratuitas Nível Básico | Configuração de Streaming | +|:---:|:---:|:---:| +| ASR(Reconhecimento de Fala) | FunASR(Local) | 👍XunfeiStreamASR(Xunfei Streaming) | +| LLM(Modelo de Linguagem) | glm-4-flash(Zhipu) | 👍qwen-flash(Alibaba Bailian) | +| VLLM(Modelo de Visão) | glm-4v-flash(Zhipu) | 👍qwen2.5-vl-3b-instructh(Alibaba Bailian) | +| TTS(Síntese de Voz) | ✅LinkeraiTTS(Lingxi streaming) | 👍HuoshanDoubleStreamTTS(Volcano Streaming) | +| Intent(Reconhecimento de Intenção) | function_call(Chamada de função) | function_call(Chamada de função) | +| Memory(Função de Memória) | mem_local_short(Memória local de curto prazo) | mem_local_short(Memória local de curto prazo) | + +#### 🔧 Ferramentas de Teste +Este projeto fornece as seguintes ferramentas de teste para ajudá-lo a verificar o sistema e escolher modelos adequados: + +| Nome da Ferramenta | Localização | Método de Uso | Descrição da Função | +|:---:|:---|:---:|:---:| +| Ferramenta de Teste de Interação por Áudio | main》xiaozhi-server》test》test_page.html | Abrir diretamente com Google Chrome | Testa as funções de reprodução e recepção de áudio, verifica se o processamento de áudio no lado Python está normal | +| Ferramenta de Teste de Resposta de Modelo 1 | main》xiaozhi-server》performance_tester.py | Execute `python performance_tester.py` | Testa a velocidade de resposta de três módulos principais: ASR(reconhecimento de fala), LLM(modelo de linguagem), TTS(síntese de voz) | +| Ferramenta de Teste de Resposta de Modelo 2 | main》xiaozhi-server》performance_tester_vllm.py | Execute `python performance_tester_vllm.py` | Testa a velocidade de resposta do VLLM(modelo de visão) | + +> 💡 Nota: Ao testar a velocidade dos modelos, apenas os modelos com chaves configuradas serão testados. + +--- +## Lista de Funcionalidades ✨ +### Implementado ✅ +![请参考-全模块安装架构图](docs/images/deploy2.png) +| Módulo de Funcionalidade | Descrição | +|:---:|:---| +| Arquitetura Principal | Baseado em [gateway MQTT+UDP](https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/mqtt-gateway-integration.md), servidores WebSocket e HTTP, fornece sistema completo de gerenciamento de console e autenticação | +| Interação por Voz | Suporta ASR em streaming (reconhecimento de fala), TTS em streaming (síntese de voz), VAD (detecção de atividade vocal), suporta reconhecimento multilíngue e processamento de voz | +| Reconhecimento de Impressão Vocal | Suporta registro, gerenciamento e reconhecimento de impressão vocal de múltiplos usuários, processa em paralelo com o ASR, reconhecimento de identidade do falante em tempo real e repassa ao LLM para respostas personalizadas | +| Diálogo Inteligente | Suporta múltiplos LLM (modelos de linguagem de grande porte), implementa diálogo inteligente | +| Percepção Visual | Suporta múltiplos VLLM (modelos de visão de grande porte), implementa interação multimodal | +| Reconhecimento de Intenção | Suporta reconhecimento de intenção por LLM, Function Call (chamada de função), fornece mecanismo de processamento de intenção baseado em plugins | +| Sistema de Memória | Suporta memória local de curto prazo, memória via interface mem0ai, memória inteligente PowerMem, com funcionalidade de resumo de memória | +| Base de Conhecimento | Suporta base de conhecimento RAGFlow, permitindo que o LLM julgue se deve acionar a base de conhecimento após receber a pergunta do usuário, e então responda à pergunta | +| Envio de Comandos | Suporta envio de comandos MCP para dispositivos ESP32 via protocolo MQTT a partir do Console Inteligente | +| Chamada de Ferramentas | Suporta protocolo IOT do cliente, protocolo MCP do cliente, protocolo MCP do servidor, protocolo de endpoint MCP, funções de ferramentas personalizadas | +| Backend de Gerenciamento | Fornece interface de gerenciamento Web, suporta gerenciamento de usuários, configuração do sistema e gerenciamento de dispositivos; Suporta exibição em Chinês Simplificado, Chinês Tradicional e Inglês | +| Ferramentas de Teste | Fornece ferramentas de teste de desempenho, ferramentas de teste de modelo de visão e ferramentas de teste de interação por áudio | +| Suporte à Implantação | Suporta implantação via Docker e implantação local, fornece gerenciamento completo de arquivos de configuração | +| Sistema de Plugins | Suporta extensões de plugins funcionais, desenvolvimento de plugins personalizados e carregamento dinâmico de plugins | + +### Em Desenvolvimento 🚧 + +Para conhecer o progresso específico do plano de desenvolvimento, [clique aqui](https://github.com/users/xinnan-tech/projects/3) + +Se você é um desenvolvedor de software, aqui está uma [Carta Aberta aos Desenvolvedores](docs/contributor_open_letter.md). Seja bem-vindo a participar! + +--- + +## Ecossistema do Produto 👬 +Xiaozhi é um ecossistema. Ao utilizar este produto, você também pode conferir outros [projetos excelentes](https://github.com/78/xiaozhi-esp32?tab=readme-ov-file#related-open-source-projects) neste ecossistema + +| Nome do Projeto | Endereço do Projeto | Descrição do Projeto | +|:---------------------|:--------|:--------| +| Cliente Android Xiaozhi | [xiaozhi-android-client](https://github.com/TOM88812/xiaozhi-android-client) | Um aplicativo de diálogo por voz para Android e iOS baseado no xiaozhi-server, com suporte a interação por voz em tempo real e diálogo por texto.
Atualmente uma versão Flutter, conectando as plataformas iOS e Android. | +| Cliente Desktop Xiaozhi | [py-xiaozhi](https://github.com/Huang-junsen/py-xiaozhi) | Este projeto fornece um cliente de IA baseado em Python para iniciantes, permitindo que os usuários experimentem a funcionalidade de IA do Xiaozhi através de código, mesmo sem condições de hardware físico. | +| Servidor Java Xiaozhi | [xiaozhi-esp32-server-java](https://github.com/joey-zhou/xiaozhi-esp32-server-java) | O serviço backend de código aberto Xiaozhi na versão Java é um projeto de código aberto baseado em Java.
Inclui serviços de frontend e backend, visando fornecer aos usuários uma solução completa de serviço backend. | + +--- + +## Lista de Plataformas/Componentes Suportados 📋 +### LLM Modelos de Linguagem + +| Método de Uso | Plataformas Suportadas | Plataformas Gratuitas | +|:---:|:---:|:---:| +| Chamadas via interface OpenAI | Alibaba Bailian, Volcano Engine, DeepSeek, Zhipu, Gemini, iFLYTEK | Zhipu, Gemini | +| Chamadas via interface Ollama | Ollama | - | +| Chamadas via interface Dify | Dify | - | +| Chamadas via interface FastGPT | FastGPT | - | +| Chamadas via interface Coze | Coze | - | + +Na verdade, qualquer LLM que suporte chamadas via interface OpenAI pode ser integrado e utilizado, incluindo interfaces Xinference e HomeAssistant. + +--- + +### VLLM Modelos de Visão + +| Método de Uso | Plataformas Suportadas | Plataformas Gratuitas | +|:---:|:---:|:---:| +| Chamadas via interface OpenAI | Alibaba Bailian, Zhipu ChatGLMVLLM | Zhipu ChatGLMVLLM | + +Na verdade, qualquer VLLM que suporte chamadas via interface OpenAI pode ser integrado e utilizado. + +--- + +### TTS Síntese de Voz + +| Método de Uso | Plataformas Suportadas | Plataformas Gratuitas | +|:---:|:---:|:---:| +| Chamadas via interface | EdgeTTS, iFLYTEK, Volcano Engine, Tencent Cloud, Alibaba Cloud e Bailian, CosyVoiceSiliconflow, TTS302AI, CozeCnTTS, GizwitsTTS, ACGNTTS, OpenAITTS, Lingxi Streaming TTS, MinimaxTTS | Lingxi Streaming TTS, EdgeTTS, CosyVoiceSiliconflow(parcial) | +| Serviços locais | FishSpeech, GPT_SOVITS_V2, GPT_SOVITS_V3, MinimaxTTS | FishSpeech, GPT_SOVITS_V2, GPT_SOVITS_V3, MinimaxTTS | + +--- + +### VAD Detecção de Atividade Vocal + +| Tipo | Nome da Plataforma | Método de Uso | Modelo de Preço | Observações | +|:---:|:---------:|:----:|:----:|:--:| +| VAD | SileroVAD | Uso local | Gratuito | | + +--- + +### ASR Reconhecimento de Fala + +| Método de Uso | Plataformas Suportadas | Plataformas Gratuitas | +|:---:|:---:|:---:| +| Uso local | FunASR, SherpaASR | FunASR, SherpaASR | +| Chamadas via interface | FunASRServer, Volcano Engine, iFLYTEK, Tencent Cloud, Alibaba Cloud, Baidu Cloud, OpenAI ASR | FunASRServer | + +--- + +### Reconhecimento de Impressão Vocal + +| Método de Uso | Plataformas Suportadas | Plataformas Gratuitas | +|:---:|:---:|:---:| +| Uso local | 3D-Speaker | 3D-Speaker | + +--- + +### Armazenamento de Memória + +| Tipo | Nome da Plataforma | Método de Uso | Modelo de Preço | Observações | +|:------:|:---------------:|:----:|:---------:|:--:| +| Memória | mem0ai | Chamadas via interface | Cota de 1000 vezes/mês | | +| Memória | [powermem](./docs/powermem-integration.md) | Resumo local | Depende do LLM e BD | OceanBase de código aberto, suporta busca inteligente | +| Memória | mem_local_short | Resumo local | Gratuito | | +| Memória | nomem | Modo sem memória | Gratuito | | + +--- + +### Reconhecimento de Intenção + +| Tipo | Nome da Plataforma | Método de Uso | Modelo de Preço | Observações | +|:------:|:-------------:|:----:|:-------:|:---------------------:| +| Intenção | intent_llm | Chamadas via interface | Baseado no preço do LLM | Reconhece intenção através de modelos de linguagem, forte generalização | +| Intenção | function_call | Chamadas via interface | Baseado no preço do LLM | Completa a intenção através de chamada de função do modelo de linguagem, velocidade rápida, bom resultado | + +--- + +### RAG Geração Aumentada por Recuperação + +| Tipo | Nome da Plataforma | Método de Uso | Modelo de Preço | Observações | +|:------:|:-------------:|:----:|:-------:|:---------------------:| +| RAG | ragflow | Chamadas via interface | Cobrado com base nos tokens consumidos para fatiamento e segmentação de palavras | Utiliza o recurso de geração aumentada por recuperação do RagFlow para fornecer respostas de diálogo mais precisas | + +--- + +## Agradecimentos 🙏 + +| Logo | Projeto/Empresa | Descrição | +|:---:|:---:|:---| +| | [Robô de Diálogo por Voz Bailing](https://github.com/wwbin2017/bailing) | Este projeto foi inspirado pelo [Robô de Diálogo por Voz Bailing](https://github.com/wwbin2017/bailing) e implementado com base nele | +| | [Tenclass](https://www.tenclass.com/) | Agradecimentos à [Tenclass](https://www.tenclass.com/) por formular protocolos de comunicação padrão, soluções de compatibilidade multidispositivo e demonstrações práticas de cenários de alta concorrência para o ecossistema Xiaozhi; fornecendo suporte completo de documentação técnica para este projeto | +| | [Xuanfeng Technology (旋风科技)](https://github.com/Eric0308) | Agradecimentos à [Xuanfeng Technology](https://github.com/Eric0308) por contribuir com o framework de chamada de função, protocolo de comunicação MCP e implementação do mecanismo de chamada baseado em plugins. Através de um sistema padronizado de agendamento de instruções e capacidades de expansão dinâmica, melhora significativamente a eficiência de interação e extensibilidade funcional dos dispositivos de frontend (IoT) | +| | [huangjunsen](https://github.com/huangjunsen0406) | Agradecimentos a [huangjunsen](https://github.com/huangjunsen0406) por contribuir com o módulo `Console de Controle Inteligente Mobile`, que permite controle eficiente e interação em tempo real em dispositivos móveis, melhorando significativamente a conveniência operacional e a eficiência de gerenciamento do sistema em cenários móveis. | +| | [Huiyuan Design (汇源设计)](http://ui.kwd988.net/) | Agradecimentos à [Huiyuan Design](http://ui.kwd988.net/) por fornecer soluções visuais profissionais para este projeto, utilizando sua experiência prática de design atendendo mais de mil empresas para potencializar a experiência do usuário deste produto | +| | [Xi'an Qinren Information Technology (西安秦人信息科技)](https://www.029app.com/) | Agradecimentos à [Xi'an Qinren Information Technology](https://www.029app.com/) por aprofundar o sistema visual deste projeto, garantindo consistência e extensibilidade do estilo de design geral em aplicações de múltiplos cenários | +| | [Contribuidores de Código](https://github.com/xinnan-tech/xiaozhi-esp32-server/graphs/contributors) | Agradecimentos a [todos os contribuidores de código](https://github.com/xinnan-tech/xiaozhi-esp32-server/graphs/contributors), seus esforços tornaram o projeto mais robusto e poderoso. | + + + + + + + + Star History Chart + + diff --git a/README_vi.md b/README_vi.md index 4a2fbb6b..86ff4a1d 100644 --- a/README_vi.md +++ b/README_vi.md @@ -21,6 +21,7 @@ Hỗ trợ giao thức MQTT+UDP, giao thức Websocket, điểm truy cập MCP, README in English Tiếng Việt Deutsch + Português (Brasil) GitHub Contributors diff --git a/main/manager-mobile/src/i18n/index.ts b/main/manager-mobile/src/i18n/index.ts index ee967fd1..e8a606da 100644 --- a/main/manager-mobile/src/i18n/index.ts +++ b/main/manager-mobile/src/i18n/index.ts @@ -8,6 +8,7 @@ import en from './en' import zh_TW from './zh_TW' import de from './de' import vi from './vi' +import pt_BR from './pt_BR' // 语言包映射 const messages = { @@ -16,6 +17,7 @@ const messages = { zh_TW: zh_TW, de, vi, + pt_BR: pt_BR, } // 当前使用的语言 @@ -72,5 +74,6 @@ export function getSupportedLanguages(): { code: Language, name: string }[] { { code: 'zh_TW', name: '繁體中文' }, { code: 'de', name: 'Deutsch' }, { code: 'vi', name: 'Tiếng Việt' }, + { code: 'pt_BR', name: 'Português (Brasil)' }, ] } \ No newline at end of file diff --git a/main/manager-mobile/src/i18n/pt_BR.ts b/main/manager-mobile/src/i18n/pt_BR.ts new file mode 100644 index 00000000..732889ae --- /dev/null +++ b/main/manager-mobile/src/i18n/pt_BR.ts @@ -0,0 +1,440 @@ +// Pacote de idioma Português Brasileiro +export default { + // TabBar + 'tabBar.home': 'Início', + 'tabBar.deviceConfig': 'Config. de Rede', + 'tabBar.settings': 'Sistema', + // Settings page title + 'settings.title': 'Configurações', + // Login page + 'login.pageTitle': 'Entrar', + 'login.navigationTitle': 'Entrar', + 'login.fetchConfigError': 'Falha ao buscar configuração:', + 'login.selectLanguage': 'Selecionar Idioma', + 'login.selectLanguageTip': '中文', + 'login.welcomeBack': 'Bem-vindo de Volta', + 'login.pleaseLogin': 'Por favor, entre na sua conta', + 'login.enterUsername': 'Por favor, insira o nome de usuário', + 'login.enterPassword': 'Por favor, insira a senha', + 'login.enterCaptcha': 'Por favor, insira o código de verificação', + 'login.loginButton': 'Entrar', + 'login.loggingIn': 'Entrando...', + 'login.noAccount': 'Cadastrar', + 'login.enterPhone': 'Por favor, insira o número de telefone', + 'login.selectCountry': 'Selecionar País/Região', + 'login.confirm': 'Confirmar', + 'login.serverSetting': 'Configurações do Servidor', + 'login.requiredUsername': 'O nome de usuário não pode estar vazio', + 'login.requiredPassword': 'A senha não pode estar vazia', + 'login.requiredCaptcha': 'O código de verificação não pode estar vazio', + 'login.requiredMobile': 'Por favor, insira um número de telefone válido', + 'login.captchaError': 'Erro no código de verificação gráfico', + 'login.forgotPassword': 'Esqueceu a Senha', + + // Register page + 'register.pageTitle': 'Cadastro', + 'register.createAccount': 'Criar Conta', + 'register.enterUsername': 'Por favor, insira o nome de usuário', + 'register.enterPassword': 'Por favor, insira a senha', + 'register.confirmPassword': 'Por favor, confirme a senha', + 'register.enterPhone': 'Por favor, insira o número de telefone', + 'register.enterCode': 'Por favor, insira o código de verificação', + 'register.getCode': 'Obter Código', + 'register.agreeTerms': 'Li e concordo com os', + 'register.terms': 'Termos de Uso', + 'register.privacy': 'Política de Privacidade', + 'register.registerButton': 'Cadastrar', + 'register.registering': 'Cadastrando...', + 'register.haveAccount': 'Já tem uma conta?', + 'register.loginNow': 'Entrar Agora', + 'register.selectCountry': 'Selecionar País/Região', + 'register.confirm': 'Confirmar', + 'register.captchaSendSuccess': 'Código de verificação enviado com sucesso', + + // Home page + 'home.pageTitle': 'Início', + 'home.createAgent': 'Criar Agente', + 'home.agentName': 'Agente', + 'home.modelInfo': 'Info do Modelo', + 'home.lastActive': 'Última Atividade', + 'home.greeting': 'Olá Jarvis', + 'home.subtitle': 'Vamos ter', + 'home.wonderfulDay': 'um dia maravilhoso!', + 'home.emptyState': 'Nenhum agente disponível', + 'home.deviceManagement': 'Gerenciamento de Dispositivos', + 'home.lastConversation': 'Última Conversa:', + 'home.delete': 'Excluir', + 'home.createFirstAgent': 'Clique no botão + no canto inferior direito para criar seu primeiro agente', + 'home.dialogTitle': 'Criar Agente', + 'home.inputPlaceholder': 'ex: Assistente de Atendimento, Assistente de Voz, Perguntas e Respostas', + 'home.createError': 'Por favor, insira o nome do agente', + 'home.createNow': 'Criar Agora', + 'home.justNow': 'Agora mesmo', + 'home.minutesAgo': 'minutos atrás', + 'home.hoursAgo': 'horas atrás', + 'home.daysAgo': 'dias atrás', + + // Agent page + 'agent.pageTitle': 'Agente', + 'agent.roleConfig': 'Configuração de Papel', + 'agent.deviceManagement': 'Gerenciamento de Dispositivos', + 'agent.chatHistory': 'Histórico de Conversas', + 'agent.voiceprintManagement': 'Gerenciamento de Impressão Vocal', + 'agent.editTitle': 'Editar Agente', + 'agent.toolsTitle': 'Editar Funcionalidades', + 'agent.voiceActivityDetection': 'Detecção de Atividade de Voz', + 'agent.speechRecognition': 'Reconhecimento de Fala', + 'agent.largeLanguageModel': 'Modelo de Linguagem Grande', + 'agent.save': 'Salvar', + 'agent.cancel': 'Cancelar', + // Agent Edit Page + 'agent.basicInfo': 'Informações Básicas', + 'agent.agentName': 'Nome do Agente', + 'agent.inputAgentName': 'Por favor, insira o nome do agente', + 'agent.roleMode': 'Modo de Papel', + 'agent.roleDescription': 'Descrição do Papel', + 'agent.inputRoleDescription': 'Por favor, insira a descrição do papel', + 'agent.modelConfig': 'Configuração do Modelo', + 'agent.vad': 'Detecção de Atividade de Voz', + 'agent.asr': 'Reconhecimento de Fala', + 'agent.llm': 'Modelo de Linguagem Grande', + 'agent.vllm': 'Modelo de Linguagem Visual', + 'agent.intent': 'Reconhecimento de Intenção', + 'agent.memory': 'Memória', + 'agent.voiceSettings': 'Configurações de Voz', + 'agent.tts': 'Texto para Fala', + 'agent.voiceprint': 'Voz do Agente', + 'agent.plugins': 'Plugins', + 'agent.editFunctions': 'Editar Funções', + 'agent.historyMemory': 'Memória de Histórico', + 'agent.memoryContent': 'Conteúdo da memória', + 'agent.saving': 'Salvando...', + 'agent.saveSuccess': 'Salvo com sucesso', + 'agent.saveFail': 'Falha ao salvar', + 'agent.loadFail': 'Falha ao carregar', + 'agent.pleaseInputAgentName': 'Por favor, insira o nome do agente', + 'agent.pleaseInputRoleDescription': 'Por favor, insira a descrição do papel', + 'agent.pleaseSelect': 'Por favor, selecione', + + // Chat History Page + 'chatHistory.getChatSessions': 'Obter lista de sessões de conversa', + 'chatHistory.noSelectedAgent': 'Nenhum agente selecionado', + 'chatHistory.getChatSessionsFailed': 'Falha ao obter lista de sessões de conversa:', + 'chatHistory.unknownTime': 'Hora desconhecida', + 'chatHistory.justNow': 'Agora mesmo', + 'chatHistory.minutesAgo': '{minutes} minutos atrás', + 'chatHistory.hoursAgo': '{hours} horas atrás', + 'chatHistory.daysAgo': '{days} dias atrás', + 'chatHistory.conversationRecord': 'Registro de Conversas', + 'chatHistory.totalChats': '{count} conversas no total', + 'chatHistory.loading': 'Carregando...', + 'chatHistory.noMoreData': 'Não há mais dados', + 'chatHistory.noChatRecords': 'Nenhum registro de conversa', + 'chatRecordsDescription': 'Os registros de conversas com agentes serão exibidos aqui', + // Chat History Detail Page + 'chatHistory.pageTitle': 'Detalhe da Conversa', + 'chatHistory.assistantName': 'Assistente Inteligente', + 'chatHistory.userName': 'Usuário', + 'chatHistory.aiAssistantName': 'Assistente IA', + 'chatHistory.loadFailed': 'Falha ao carregar histórico de conversas', + 'chatHistory.parameterError': 'Erro de parâmetro da página', + 'chatHistory.invalidAudioId': 'ID de áudio inválido', + 'chatHistory.audioPlayFailed': 'Falha na reprodução de áudio', + 'chatHistory.playAudioFailed': 'Falha ao reproduzir áudio', + + // Device management page + 'device.pageTitle': 'Gerenciamento de Dispositivos', + 'device.noDevices': 'Nenhum dispositivo disponível', + 'device.macAddress': 'Endereço MAC', + 'device.firmwareVersion': 'Versão do Firmware', + 'device.lastConnected': 'Última Conversa', + 'device.otaUpdate': 'Atualização OTA', + 'device.unbind': 'Desvincular', + 'device.confirmUnbind': 'Confirmar', + 'device.bindDevice': 'Vincular Novo Dispositivo', + 'device.deviceType': 'Tipo de Dispositivo', + 'device.loading': 'Carregando...', + 'device.neverConnected': 'Nunca conectado', + 'device.justNow': 'Agora mesmo', + 'device.minutesAgo': '{minutes} minutos atrás', + 'device.hoursAgo': '{hours} horas atrás', + 'device.daysAgo': '{days} dias atrás', + 'device.otaAutoUpdateEnabled': 'Atualização automática OTA ativada', + 'device.otaAutoUpdateDisabled': 'Atualização automática OTA desativada', + 'device.operationFailed': 'Operação falhou, por favor tente novamente', + 'device.deviceUnbound': 'Dispositivo desvinculado', + 'device.unbindFailed': 'Falha ao desvincular, por favor tente novamente', + 'device.unbindDevice': 'Desvincular Dispositivo', + 'device.confirmUnbindDevice': 'Tem certeza que deseja desvincular o dispositivo "{macAddress}"?', + 'device.cancel': 'Cancelar', + 'device.noDevice': 'Nenhum Dispositivo', + 'device.pleaseSelectAgent': 'Por favor, selecione um agente primeiro', + 'device.deviceBindSuccess': 'Dispositivo vinculado com sucesso!', + 'device.bindFailed': 'Falha ao vincular, por favor verifique se o código de verificação está correto', + 'device.enterDeviceCode': 'Por favor, insira o código de verificação do dispositivo', + 'device.bindNow': 'Vincular Agora', + 'device.lastConnection': 'Última Conexão', + 'device.clickToBindFirstDevice': 'Clique no botão + no canto inferior direito para vincular seu primeiro dispositivo', + + // Common + 'common.success': 'Sucesso', + 'common.fail': 'Falhou', + 'common.loading': 'Carregando...', + 'common.confirm': 'Confirmar', + 'common.cancel': 'Cancelar', + 'common.delete': 'Excluir', + 'common.edit': 'Editar', + 'common.add': 'Adicionar', + 'common.pleaseSelect': 'Por favor, selecione', + 'common.unknownError': 'Erro desconhecido', + 'common.networkError': 'Erro de rede', + + // Retrieve Password page + 'retrievePassword.title': 'Redefinir Senha', + 'retrievePassword.subtitle': 'Recupere a senha da sua conta pelo número de celular', + 'retrievePassword.mobileRequired': 'Por favor, insira o número de celular', + 'retrievePassword.inputCorrectMobile': 'Por favor, insira um número de celular válido', + 'retrievePassword.captchaRequired': 'Por favor, insira o código de verificação gráfico', + 'retrievePassword.mobileCaptchaRequired': 'Por favor, insira o código de verificação por SMS', + 'retrievePassword.newPasswordRequired': 'Por favor, insira a nova senha', + 'retrievePassword.confirmNewPasswordRequired': 'Por favor, confirme a nova senha', + 'retrievePassword.passwordsNotMatch': 'As senhas não coincidem', + 'retrievePassword.mobilePlaceholder': 'Por favor, insira o número de celular', + 'retrievePassword.captchaPlaceholder': 'Por favor, insira o código de verificação gráfico', + 'retrievePassword.mobileCaptchaPlaceholder': 'Por favor, insira o código de verificação por SMS', + 'retrievePassword.newPasswordPlaceholder': 'Por favor, insira a nova senha', + 'retrievePassword.confirmNewPasswordPlaceholder': 'Por favor, confirme a nova senha', + 'retrievePassword.getMobileCaptcha': 'Obter Código', + 'retrievePassword.captchaSendSuccess': 'Código de verificação enviado com sucesso', + 'retrievePassword.passwordUpdateSuccess': 'Senha redefinida com sucesso', + 'retrievePassword.resetButton': 'Redefinir Senha', + 'retrievePassword.goToLogin': 'Voltar ao Login', + + // SM2 encryption related error messages + 'sm2.publicKeyNotConfigured': 'Chave pública SM2 não configurada, por favor entre em contato com o administrador', + 'sm2.encryptionFailed': 'Falha na criptografia da senha', + 'sm2.keyGenerationFailed': 'Falha na geração do par de chaves', + 'sm2.invalidPublicKey': 'Formato de chave pública inválido', + 'sm2.encryptionError': 'Ocorreu um erro durante a criptografia', + 'sm2.publicKeyRetry': 'Tentando obter a chave pública novamente...', + 'sm2.publicKeyRetryFailed': 'Falha na nova tentativa de obter a chave pública', + + // Voiceprint page + 'voiceprint.noSelectedAgent': 'Nenhum agente selecionado', + 'voiceprint.pleaseSelectAgent': 'Por favor, selecione um agente primeiro', + 'voiceprint.fetchHistoryFailed': 'Falha ao buscar histórico de conversas', + 'voiceprint.clickToSelectVector': 'Clique para selecionar vetor de impressão vocal', + 'voiceprint.pleaseInputName': 'Por favor, insira o nome', + 'voiceprint.pleaseSelectVector': 'Por favor, selecione o vetor de impressão vocal', + 'voiceprint.addSuccess': 'Adicionado com sucesso', + 'voiceprint.addFailed': 'Falha ao adicionar locutor', + 'voiceprint.editSuccess': 'Editado com sucesso', + 'voiceprint.editFailed': 'Falha ao editar locutor', + 'voiceprint.deleteConfirmMsg': 'Tem certeza que deseja excluir este locutor?', + 'voiceprint.deleteConfirmTitle': 'Confirmar Exclusão', + 'voiceprint.deleteSuccess': 'Excluído com sucesso', + 'voiceprint.loading': 'Carregando...', + 'voiceprint.delete': 'Excluir', + 'voiceprint.emptyTitle': 'Nenhum dado de impressão vocal', + 'voiceprint.emptyDesc': 'Clique no botão + no canto inferior direito para adicionar seu primeiro locutor', + 'voiceprint.addSpeaker': 'Adicionar Locutor', + 'voiceprint.voiceVector': 'Vetor de Impressão Vocal', + 'voiceprint.name': 'Nome', + 'voiceprint.description': 'Descrição', + 'voiceprint.pleaseInputDescription': 'Por favor, insira a descrição', + 'voiceprint.cancel': 'Cancelar', + 'voiceprint.save': 'Salvar', + 'voiceprint.editSpeaker': 'Editar Locutor', + 'voiceprint.selectVector': 'Selecionar Vetor de Impressão Vocal', + 'voiceprint.voiceprintInterfaceNotConfigured': 'Interface de impressão vocal não configurada', + + // Settings page + 'settings.pageTitle': 'Configurações', + 'settings.navigationTitle': 'Configurações', + 'settings.networkSettings': 'Configurações de Rede', + 'settings.serverApiUrl': 'URL da API do Servidor', + 'settings.validServerUrl': 'Por favor, insira um endereço de servidor válido (começando com http ou https e terminando com /xiaozhi)', + 'settings.saveSettings': 'Salvar Configurações', + 'settings.resetDefault': 'Restaurar Padrão', + 'settings.restartApp': 'Reiniciar App', + 'settings.restartNow': 'Reiniciar Agora', + 'settings.restartLater': 'Depois', + // About us + 'settings.aboutApp': 'Sobre o Console XiaoZhi', + 'settings.aboutContent': 'Console XiaoZhi\n\nUm aplicativo móvel de gerenciamento multiplataforma construído com Vue.js 3 + uni-app, oferecendo gerenciamento de dispositivos, configuração de agentes e outras funcionalidades para o hardware inteligente xiaozhi ESP32.\n\n© 2025 xiaozhi-esp32-server {version}', + 'settings.restartSuccess': 'Salvo, você pode reiniciar o app manualmente depois', + 'settings.serverUrlSavedAndCacheCleared': 'URL do servidor salva e cache limpo', + 'settings.resetToDefaultAndCacheCleared': 'Restaurado ao padrão e cache limpo', + 'settings.resetSuccess': 'Restauração bem-sucedida', + 'settings.enterServerUrl': 'Por favor, insira a URL do servidor', + 'settings.clearCacheFailed': 'Falha ao limpar o cache', + 'settings.cacheManagement': 'Gerenciamento de Cache', + 'settings.totalCacheSize': 'Tamanho Total do Cache', + 'settings.appDataSize': 'Tamanho Total dos Dados do App', + 'settings.cacheClear': 'Limpar Cache', + 'settings.clearAllCache': 'Limpar todos os dados de cache', + 'settings.clearCache': 'Limpar Cache', + 'settings.modifyWillClearCache': 'Modificações irão limpar o cache', + 'settings.appInfo': 'Informações do App', + 'settings.aboutUs': 'Sobre Nós', + 'settings.appVersion': 'Versão do App e Info da Equipe', + 'settings.confirmClear': 'Confirmar Limpeza', + 'settings.confirmClearMessage': 'Tem certeza que deseja limpar todo o cache? Isso excluirá todos os dados, incluindo o status de login, e exigirá novo login.', + 'settings.cacheCleared': 'Cache limpo com sucesso, redirecionando para a página de login', + 'settings.languageSettings': 'Configurações de Idioma', + 'settings.language': 'Idioma', + 'settings.selectLanguage': 'Selecionar Idioma', + 'settings.languageChanged': 'Idioma alterado com sucesso', + + // Messages + 'message.loginSuccess': 'Login realizado com sucesso!', + 'message.loginFail': 'Falha no login', + 'message.registerSuccess': 'Cadastro realizado com sucesso', + 'message.registerFail': 'Falha no cadastro', + 'message.saveSuccess': 'Salvo com sucesso', + 'message.saveFail': 'Falha ao salvar', + 'message.deleteSuccess': 'Excluído com sucesso', + 'message.deleteFail': 'Falha ao excluir', + 'message.bindSuccess': 'Vinculação realizada com sucesso', + 'message.bindFail': 'Falha na vinculação', + 'message.unbindSuccess': 'Desvinculação realizada com sucesso', + 'message.unbindFail': 'Falha na desvinculação', + 'message.networkError': 'Erro de rede, por favor verifique sua conexão', + 'message.serverError': 'Erro no servidor, por favor tente novamente mais tarde', + 'message.invalidAddress': 'Endereço inválido, por favor verifique se o servidor está iniciado ou se a conexão de rede está normal', + 'message.languageChanged': 'Idioma alterado', + 'message.passwordError': 'Conta ou senha incorretos', + 'message.phoneRegistered': 'Este número de telefone já está cadastrado', + + // Agent Tools Page + 'agent.tools.pageTitle': 'Ferramentas do Agente', + 'agent.tools.unselected': 'Não selecionado', + 'agent.tools.selected': 'Selecionado', + 'agent.tools.noMorePlugins': 'Não há mais plugins', + 'agent.tools.pleaseSelectPlugin': 'Por favor, selecione a função do plugin', + 'agent.tools.builtInPlugins': 'Plugins Integrados', + 'agent.tools.mcpAccessPoint': 'Ponto de Acesso MCP', + 'agent.tools.copy': 'Copiar', + 'agent.tools.noTools': 'Nenhuma ferramenta disponível', + 'agent.tools.parameterConfig': 'Configuração de Parâmetros', + 'agent.tools.noParamsNeeded': 'Nenhum parâmetro necessário', + 'agent.tools.pleaseInput': 'Por favor, insira', + 'agent.tools.inputOneItemPerLine': 'Insira um item por linha', + 'agent.tools.pleaseInputValidJson': 'Por favor, insira um formato JSON válido', + 'agent.tools.enableFunction': 'Ativar Função', + 'agent.tools.toggleFunction': 'Ativar ou desativar esta função', + 'agent.tools.jsonFormatError': 'Erro no formato JSON', + 'agent.tools.noMcpAddressToCopy': 'Nenhum endereço MCP para copiar', + 'agent.tools.mcpAddressCopied': 'Endereço MCP copiado para a área de transferência', + 'agent.tools.copyFailed': 'Falha ao copiar, por favor tente novamente', + 'agent.tools.defaultValue': 'Valor padrão', + 'agent.tools.notSelected': 'Não selecionado', + 'agent.tools.clickToConfigure': 'Clique para configurar', + 'agent.tools.mcpEndpoint': 'Endpoint MCP', + 'agent.tools.eachLineOneItem': 'Insira um item por linha', + + // Device Config page + 'deviceConfig.pageTitle': 'Configuração do Dispositivo', + 'deviceConfig.wifiConfig': 'Configuração WiFi', + 'deviceConfig.ultrasonicConfig': 'Configuração Ultrassônica', + 'deviceConfig.selectConfigMethod': 'Selecionar Método de Configuração', + 'deviceConfig.networkConfig': 'Configuração de Rede', + 'deviceConfig.selectedNetwork': 'Rede Selecionada', + 'deviceConfig.signal': 'Sinal', + 'deviceConfig.openNetwork': 'Rede Aberta', + 'deviceConfig.encryptedNetwork': 'Rede Criptografada', + 'deviceConfig.password': 'Senha', + 'deviceConfig.pleaseEnterPassword': 'Por favor, insira a senha do WiFi', + 'deviceConfig.startConfig': 'Iniciar Configuração', + 'deviceConfig.connectToXiaozhiHotspot': 'Por favor, conecte-se ao hotspot xiaozhi primeiro', + 'deviceConfig.detecting': 'Detectando...', + 'deviceConfig.reDetect': 'Detectar Novamente', + 'deviceConfig.alreadyConnected': 'Conectado ao hotspot xiaozhi', + 'deviceConfig.refreshStatus': 'Atualizar Status', + 'deviceConfig.wifiNetworks': 'Redes WiFi', + 'deviceConfig.selectWifiNetwork': 'Selecionar Rede WiFi', + 'deviceConfig.refreshScan': 'Atualizar Busca', + 'deviceConfig.noWifiNetworks': 'Nenhuma rede WiFi disponível', + 'deviceConfig.clickToRefreshScan': 'Por favor, clique em Atualizar Busca', + 'deviceConfig.signalStrong': 'Sinal Forte', + 'deviceConfig.signalGood': 'Sinal Bom', + 'deviceConfig.signalFair': 'Sinal Regular', + 'deviceConfig.signalWeak': 'Sinal Fraco', + 'deviceConfig.channel': 'Canal', + 'deviceConfig.about': 'aproximadamente', + 'deviceConfig.seconds': 'segundos', + 'deviceConfig.generating': 'Gerando...', + 'deviceConfig.playing': 'Reproduzindo...', + 'deviceConfig.generateAndPlaySoundWave': 'Gerar e Reproduzir Onda Sonora', + 'deviceConfig.playSoundWave': 'Reproduzir Onda Sonora', + 'deviceConfig.stopPlaying': 'Parar Reprodução', + 'deviceConfig.autoLoopPlaySoundWave': 'Reproduzir Onda Sonora em Loop Automático', + 'deviceConfig.configAudioFile': 'Arquivo de Áudio de Configuração', + 'deviceConfig.duration': 'Duração', + 'deviceConfig.ultrasonicConfigInstructions': 'Instruções de Configuração Ultrassônica', + 'deviceConfig.ensureWifiNetworkSelectedAndPasswordEntered': 'Certifique-se de que a rede WiFi foi selecionada e a senha foi inserida', + 'deviceConfig.clickGenerateAndPlaySoundWave': 'Clique em Gerar e Reproduzir Onda Sonora, o sistema codificará as informações de configuração em áudio', + 'deviceConfig.bringPhoneCloseToXiaozhiDevice': 'Aproxime o celular do dispositivo xiaozhi (distância de 1-2 metros)', + 'deviceConfig.duringAudioPlaybackXiaozhiWillReceive': 'Durante a reprodução do áudio, o xiaozhi receberá e decodificará as informações de configuração', + 'deviceConfig.afterConfigSuccessDeviceWillConnect': 'Após a configuração bem-sucedida, o dispositivo se conectará automaticamente à rede WiFi', + 'deviceConfig.usesAfskModulation': 'Utiliza tecnologia de modulação AFSK, transmitindo dados pelas frequências de 1800Hz e 1500Hz', + 'deviceConfig.ensureModeratePhoneVolume': 'Por favor, certifique-se de que o volume do celular está moderado para evitar interferência de ruídos ambientais', + 'deviceConfig.generatingUltrasonicConfigAudio': 'Gerando áudio de configuração ultrassônica', + 'deviceConfig.configData': 'Dados de configuração', + 'deviceConfig.dataBytesLength': 'Comprimento dos bytes de dados', + 'deviceConfig.bitStreamLength': 'Comprimento do fluxo de bits', + 'deviceConfig.base64Length': 'Comprimento Base64', + 'deviceConfig.audioFileTooLarge': 'Arquivo de áudio muito grande, por favor reduza o tamanho do SSID ou da senha', + 'deviceConfig.audioGenerationSuccess': 'Áudio gerado com sucesso', + 'deviceConfig.samplePoints': 'Pontos de amostra', + 'deviceConfig.soundWaveGenerationSuccess': 'Onda sonora gerada com sucesso', + 'deviceConfig.audioGenerationFailed': 'Falha na geração do áudio', + 'deviceConfig.soundWaveGenerationFailed': 'Falha na geração da onda sonora', + 'deviceConfig.pleaseGenerateAudioFirst': 'Por favor, gere o áudio primeiro', + 'deviceConfig.startPlayingUltrasonicConfigAudio': 'Iniciando reprodução do áudio de configuração ultrassônica', + 'deviceConfig.ultrasonicAudioStartedPlaying': 'Reprodução do áudio ultrassônico iniciada', + 'deviceConfig.startPlayingConfigSoundWave': 'Reprodução da onda sonora de configuração iniciada', + 'deviceConfig.ultrasonicAudioPlaybackEnded': 'Reprodução do áudio ultrassônico finalizada', + 'deviceConfig.audioPlaybackFailed': 'Falha na reprodução do áudio', + 'deviceConfig.audioResourceBusy': 'Recurso de áudio ocupado, por favor tente novamente mais tarde', + 'deviceConfig.audioFormatNotSupported': 'Formato de áudio não suportado, pode ser um problema de URI de dados', + 'deviceConfig.audioFileError': 'Erro no arquivo de áudio', + 'deviceConfig.cleaningUpAudioContext': 'Limpando contexto de áudio', + 'deviceConfig.cleaningUpAudioContextFailed': 'Falha ao limpar contexto de áudio', + 'deviceConfig.stoppedPlayingUltrasonicAudio': 'Reprodução do áudio ultrassônico interrompida', + 'deviceConfig.stoppedPlaying': 'Reprodução interrompida', + 'deviceConfig.configMethod': 'Método de Configuração', + 'deviceConfig.enterWifiPassword': 'Por favor, insira a senha do WiFi', + 'deviceConfig.xiaozhi': 'xiaozhi', + 'deviceConfig.connectXiaozhiHotspot': 'Por favor, conecte-se ao hotspot xiaozhi', + 'deviceConfig.wifiScanResponse': 'Resposta da busca WiFi', + 'deviceConfig.scanSuccess': 'Busca bem-sucedida', + 'deviceConfig.networks': 'redes', + 'deviceConfig.wifiScanFailed': 'Falha na busca WiFi', + 'deviceConfig.scanFailedCheckConnection': 'Falha na busca, por favor verifique a conexão', + 'deviceConfig.checking': 'Verificando', + 'deviceConfig.reCheck': 'Verificar Novamente', + 'deviceConfig.connectedXiaozhiHotspot': 'Conectado ao hotspot xiaozhi', + 'deviceConfig.wifiNetwork': 'Rede WiFi', + 'deviceConfig.scanning': 'Buscando', + 'deviceConfig.cancel': 'Cancelar', + 'deviceConfig.clickRefreshScan': 'Por favor, clique em Atualizar Busca', + 'deviceConfig.esp32ConnectionCheckFailed': 'Falha na verificação de conexão ESP32', + 'deviceConfig.startWifiConfig': 'Iniciando configuração WiFi', + 'deviceConfig.configSuccess': 'Configuração bem-sucedida', + 'deviceConfig.deviceWillConnectTo': 'O dispositivo se conectará a', + 'deviceConfig.deviceWillRestart': 'O dispositivo será reiniciado', + 'deviceConfig.pleaseDisconnectXiaozhiHotspot': 'Por favor, desconecte-se do hotspot xiaozhi', + 'deviceConfig.configFailed': 'Falha na configuração', + 'deviceConfig.wifiConfigFailed': 'Falha na configuração WiFi', + 'deviceConfig.pleaseCheckNetworkConnection': 'Por favor, verifique a conexão de rede', + 'deviceConfig.startWifiConfigButton': 'Iniciar Configuração', + 'deviceConfig.wifiConfigInstructions': 'Instruções de Configuração WiFi', + 'deviceConfig.phoneConnectXiaozhiHotspot': 'Conecte o celular ao hotspot xiaozhi', + 'deviceConfig.selectTargetWifiNetwork': 'Selecione a rede WiFi de destino', + 'deviceConfig.enterWifiPasswordIfNeeded': 'Insira a senha do WiFi se necessário', + 'deviceConfig.clickStartConfigAndWait': 'Clique em Iniciar Configuração e aguarde', + 'deviceConfig.afterConfigSuccessDeviceWillRestart': 'Após a configuração bem-sucedida, o dispositivo reiniciará automaticamente', + 'deviceConfig.audioPlaybackError': 'Erro na reprodução de áudio', + 'deviceConfig.playbackFailed': 'Falha na reprodução', +} diff --git a/main/manager-mobile/src/store/lang.ts b/main/manager-mobile/src/store/lang.ts index 9423d2af..fb8ad25c 100644 --- a/main/manager-mobile/src/store/lang.ts +++ b/main/manager-mobile/src/store/lang.ts @@ -2,7 +2,7 @@ import { ref } from 'vue' import { defineStore } from 'pinia' // 支持的语言类型 -export type Language = 'zh_CN' | 'en' | 'zh_TW' | 'de' | 'vi' +export type Language = 'zh_CN' | 'en' | 'zh_TW' | 'de' | 'vi' | 'pt_BR' export interface LangStore { currentLang: Language diff --git a/main/manager-web/src/components/HeaderBar.vue b/main/manager-web/src/components/HeaderBar.vue index dc9c6fb5..025beae5 100644 --- a/main/manager-web/src/components/HeaderBar.vue +++ b/main/manager-web/src/components/HeaderBar.vue @@ -254,6 +254,8 @@ export default { return this.$t("language.de"); case "vi": return this.$t("language.vi"); + case "pt_BR": + return this.$t("language.ptBR"); default: return this.$t("language.zhCN"); } @@ -272,6 +274,8 @@ export default { return require("@/assets/xiaozhi-ai_de.png"); case "vi": return require("@/assets/xiaozhi-ai_vi.png"); + case "pt_BR": + return require("@/assets/xiaozhi-ai_en.png"); default: return require("@/assets/xiaozhi-ai.png"); } @@ -303,6 +307,10 @@ export default { label: this.$t("language.vi"), value: "vi", }, + { + label: this.$t("language.ptBR"), + value: "pt_BR", + }, ], }, { diff --git a/main/manager-web/src/i18n/de.js b/main/manager-web/src/i18n/de.js index 77f75f4d..5efc0210 100644 --- a/main/manager-web/src/i18n/de.js +++ b/main/manager-web/src/i18n/de.js @@ -663,6 +663,7 @@ export default { 'language.en': 'English', 'language.de': 'Deutsch', 'language.vi': 'Tiếng Việt', + 'language.ptBR': 'Português (Brasil)', // Home page text 'home.addAgent': 'Agent hinzufügen', diff --git a/main/manager-web/src/i18n/en.js b/main/manager-web/src/i18n/en.js index 2ecabb97..8d6f0efe 100644 --- a/main/manager-web/src/i18n/en.js +++ b/main/manager-web/src/i18n/en.js @@ -663,6 +663,7 @@ export default { 'language.en': 'English', 'language.de': 'Deutsch', 'language.vi': 'Tiếng Việt', + 'language.ptBR': 'Português (Brasil)', // Home page text 'home.addAgent': 'Add Agent', diff --git a/main/manager-web/src/i18n/index.js b/main/manager-web/src/i18n/index.js index ed285fee..39c2207a 100644 --- a/main/manager-web/src/i18n/index.js +++ b/main/manager-web/src/i18n/index.js @@ -5,6 +5,7 @@ import zhTW from './zh_TW'; import en from './en'; import de from './de'; import vi from './vi'; +import ptBR from './pt_BR'; Vue.use(VueI18n); @@ -27,6 +28,9 @@ const getDefaultLanguage = () => { if (browserLang.indexOf('vi') === 0) { return 'vi'; } + if (browserLang === 'pt-BR' || browserLang === 'pt') { + return 'pt_BR'; + } return 'en'; }; @@ -38,7 +42,8 @@ const i18n = new VueI18n({ 'zh_TW': zhTW, 'en': en, 'de': de, - 'vi': vi + 'vi': vi, + 'pt_BR': ptBR } }); diff --git a/main/manager-web/src/i18n/pt_BR.js b/main/manager-web/src/i18n/pt_BR.js new file mode 100644 index 00000000..ed24e775 --- /dev/null +++ b/main/manager-web/src/i18n/pt_BR.js @@ -0,0 +1,1334 @@ +export default { + // Texto da página de login + 'login.requiredUsername': 'O nome de usuário não pode estar vazio', + 'login.requiredPassword': 'A senha não pode estar vazia', + 'login.requiredCaptcha': 'O captcha não pode estar vazio', + 'login.requiredMobile': 'Por favor, insira um número de celular válido', + 'login.loginSuccess': 'Login realizado com sucesso!', + + // Texto do componente HeaderBar + 'header.smartManagement': 'Agentes', + 'header.modelConfig': 'Modelos', + 'header.knowledgeBase': 'Conhecimento', + 'header.voiceCloneManagement': 'Clonagem de Voz', + 'header.voiceResourceManagement': 'Recurso de Voz', + 'header.userManagement': 'Usuários', + 'header.otaManagement': 'Gerenciamento OTA', + 'header.paramDictionary': 'Mais', + 'header.paramManagement': 'Gerenciamento de Parâmetros', + 'header.dictManagement': 'Gerenciamento de Dicionário', + 'header.agentTemplate': 'Modelos de Papel Padrão', + 'header.searchHistory': 'Histórico de Pesquisa', + 'header.clearHistory': 'Limpar Histórico', + 'header.providerManagement': 'Gerenciamento de Provedores', + 'header.serverSideManagement': 'Gerenciamento de Servidores', + 'header.featureManagement': 'Gerenciamento de Funcionalidades do Sistema', + 'header.changePassword': 'Alterar Senha', + 'header.logout': 'Sair', + 'header.searchPlaceholder': 'Pesquisar nome ou MAC', + + // Texto do componente McpToolCallDialog + 'mcpToolCall.title': 'Chamada de Ferramenta', + 'mcpToolCall.execute': 'Executar', + 'mcpToolCall.chooseFunction': '1、Escolher Função', + 'mcpToolCall.searchFunction': 'Pesquisar Função', + 'mcpToolCall.noResults': 'Nenhuma função correspondente encontrada', + 'mcpToolCall.settings': '2、Configuração de Parâmetros', + 'mcpToolCall.inputPlaceholder': 'Por favor, insira {label}', + 'mcpToolCall.valueRange': 'Faixa de valores: {min} - {max}', + 'mcpToolCall.selectPlaceholder': 'Por favor, selecione {label}', + 'mcpToolCall.lightTheme': 'Tema Claro', + 'mcpToolCall.darkTheme': 'Tema Escuro', + 'mcpToolCall.pleaseSelect': 'Por favor, selecione uma função', + 'mcpToolCall.cancel': 'Cancelar', + 'mcpToolCall.requiredField': 'Por favor, insira {field}', + 'mcpToolCall.minValue': 'O valor mínimo é {value}', + 'mcpToolCall.maxValue': 'O valor máximo é {value}', + 'mcpToolCall.selectTool': 'Por favor, selecione uma ferramenta para executar', + 'mcpToolCall.executionResult': '3、Resultado da Execução', + 'mcpToolCall.copyResult': 'Copiar Resultado', + 'mcpToolCall.noResultYet': 'Nenhum resultado ainda', + 'mcpToolCall.loadingToolList': 'Carregando lista de ferramentas...', + + // Nomes de ferramentas + 'mcpToolCall.toolName.getDeviceStatus': 'Ver Status do Dispositivo', + 'mcpToolCall.toolName.setVolume': 'Definir Volume', + 'mcpToolCall.toolName.setBrightness': 'Definir Brilho', + 'mcpToolCall.toolName.setTheme': 'Definir Tema', + 'mcpToolCall.toolName.takePhoto': 'Tirar Foto e Reconhecer', + 'mcpToolCall.toolName.getSystemInfo': 'Informações do Sistema', + 'mcpToolCall.toolName.reboot': 'Reiniciar Dispositivo', + 'mcpToolCall.toolName.upgradeFirmware': 'Atualizar Firmware', + 'mcpToolCall.toolName.getScreenInfo': 'Informações da Tela', + 'mcpToolCall.toolName.snapshot': 'Captura de Tela', + 'mcpToolCall.toolName.previewImage': 'Pré-visualizar Imagem', + 'mcpToolCall.toolName.setDownloadUrl': 'Definir URL de Download', + + // Categorias de ferramentas + 'mcpToolCall.category.audio': 'Áudio', + 'mcpToolCall.category.display': 'Tela', + 'mcpToolCall.category.camera': 'Câmera', + 'mcpToolCall.category.system': 'Sistema', + 'mcpToolCall.category.assets': 'Recursos', + 'mcpToolCall.category.deviceInfo': 'Info do Dispositivo', + + // Categorias e propriedades da tabela + 'mcpToolCall.table.audioSpeaker': 'Alto-falante', + 'mcpToolCall.table.screen': 'Tela', + 'mcpToolCall.table.network': 'Rede', + 'mcpToolCall.table.audioControl': 'Controle de Áudio', + 'mcpToolCall.table.screenControl': 'Controle de Tela', + 'mcpToolCall.table.systemControl': 'Controle do Sistema', + 'mcpToolCall.table.screenInfo': 'Info da Tela', + 'mcpToolCall.table.hardwareInfo': 'Info do Hardware', + 'mcpToolCall.table.memoryInfo': 'Info da Memória', + 'mcpToolCall.table.applicationInfo': 'Info da Aplicação', + 'mcpToolCall.table.networkInfo': 'Info da Rede', + 'mcpToolCall.table.displayInfo': 'Info do Display', + 'mcpToolCall.table.deviceInfo': 'Info do Dispositivo', + 'mcpToolCall.table.systemInfo': 'Info do Sistema', + // Cabeçalhos das colunas da tabela + 'mcpToolCall.table.component': 'Componente', + 'mcpToolCall.table.property': 'Propriedade', + 'mcpToolCall.table.value': 'Valor', + + 'mcpToolCall.prop.volume': 'Volume', + 'mcpToolCall.prop.brightness': 'Brilho', + 'mcpToolCall.prop.theme': 'Tema', + 'mcpToolCall.prop.type': 'Tipo', + 'mcpToolCall.prop.ssid': 'SSID', + 'mcpToolCall.prop.signalStrength': 'Intensidade do Sinal', + 'mcpToolCall.prop.operationResult': 'Resultado da Operação', + 'mcpToolCall.prop.width': 'Largura', + 'mcpToolCall.prop.height': 'Altura', + 'mcpToolCall.prop.screenType': 'Tipo', + 'mcpToolCall.prop.chipModel': 'Modelo do Chip', + 'mcpToolCall.prop.cpuCores': 'Núcleos do CPU', + 'mcpToolCall.prop.chipVersion': 'Versão do Chip', + 'mcpToolCall.prop.flashSize': 'Tamanho do Flash', + 'mcpToolCall.prop.minFreeHeap': 'Heap Livre Mínimo', + 'mcpToolCall.prop.applicationName': 'Nome da Aplicação', + 'mcpToolCall.prop.applicationVersion': 'Versão da Aplicação', + 'mcpToolCall.prop.compileTime': 'Hora de Compilação', + 'mcpToolCall.prop.idfVersion': 'Versão IDF', + 'mcpToolCall.prop.macAddress': 'Endereço MAC', + 'mcpToolCall.prop.ipAddress': 'Endereço IP', + 'mcpToolCall.prop.wifiName': 'Nome WiFi', + 'mcpToolCall.prop.wifiChannel': 'Canal WiFi', + 'mcpToolCall.prop.screenSize': 'Tamanho da Tela', + 'mcpToolCall.prop.deviceUuid': 'UUID do Dispositivo', + 'mcpToolCall.prop.systemLanguage': 'Idioma do Sistema', + 'mcpToolCall.prop.currentOtaPartition': 'Partição OTA Atual', + 'mcpToolCall.prop.getResult': 'Obter Resultado', + 'mcpToolCall.prop.url': 'URL', + 'mcpToolCall.prop.quality': 'Qualidade', + 'mcpToolCall.prop.question': 'Pergunta', + + // Textos de ajuda das ferramentas + 'mcpToolCall.help.getDeviceStatus': 'Visualizar o status atual de execução do dispositivo, incluindo volume, tela, bateria e outras informações.', + 'mcpToolCall.help.setVolume': 'Ajustar o volume do dispositivo. Por favor, insira um valor entre 0-100.', + 'mcpToolCall.help.setBrightness': 'Ajustar o brilho da tela do dispositivo. Por favor, insira um valor entre 0-100.', + 'mcpToolCall.help.setTheme': 'Alternar o tema de exibição da tela do dispositivo. Você pode escolher entre modo claro ou escuro.', + 'mcpToolCall.help.takePhoto': 'Tirar fotos com a câmera do dispositivo e realizar análise de reconhecimento. Por favor, insira a pergunta que deseja fazer.', + 'mcpToolCall.help.getSystemInfo': 'Obter as informações do sistema do dispositivo, incluindo especificações de hardware, versão do software, etc.', + 'mcpToolCall.help.reboot': 'Reiniciar o dispositivo. O dispositivo será reiniciado após a execução.', + 'mcpToolCall.help.upgradeFirmware': 'Baixar e atualizar o firmware do dispositivo a partir da URL especificada. O dispositivo será reiniciado automaticamente após a atualização.', + 'mcpToolCall.help.getScreenInfo': 'Obter informações detalhadas sobre a tela, como resolução, tamanho e outros parâmetros.', + 'mcpToolCall.help.snapshot': 'Capturar a tela atual e enviar para a URL especificada.', + 'mcpToolCall.help.previewImage': 'Pré-visualizar imagens da URL especificada na tela do dispositivo.', + 'mcpToolCall.help.setDownloadUrl': 'Definir o endereço de download dos arquivos de recursos do dispositivo.', + + // Outros textos + 'mcpToolCall.text.strong': 'Forte', + 'mcpToolCall.text.medium': 'Médio', + 'mcpToolCall.text.weak': 'Fraco', + 'mcpToolCall.text.dark': 'Escuro', + 'mcpToolCall.text.light': 'Claro', + 'mcpToolCall.text.setSuccess': 'Configuração realizada com sucesso', + 'mcpToolCall.text.setFailed': 'Falha na configuração', + 'mcpToolCall.text.brightnessSetSuccess': 'Brilho configurado com sucesso', + 'mcpToolCall.text.brightnessSetFailed': 'Falha ao configurar brilho', + 'mcpToolCall.text.themeSetSuccess': 'Tema configurado com sucesso', + 'mcpToolCall.text.themeSetFailed': 'Falha ao configurar tema', + 'mcpToolCall.text.rebootCommandSent': 'Comando de reinicialização enviado', + 'mcpToolCall.text.rebootFailed': 'Falha ao reiniciar', + 'mcpToolCall.text.monochrome': 'Tela Monocromática', + 'mcpToolCall.text.color': 'Tela Colorida', + 'mcpToolCall.text.getSuccessParseFailed': 'Obtido com sucesso, mas falha ao analisar', + 'mcpToolCall.text.getFailed': 'Falha ao obter', + 'mcpToolCall.text.getSuccessFormatError': 'Obtido com sucesso, mas formato de dados anormal', + + // Diálogo de dados do dicionário + 'dictDataDialog.addDictData': 'Adicionar Dados do Dicionário', + 'dictDataDialog.dictLabel': 'Rótulo do Dicionário', + 'dictDataDialog.dictLabelPlaceholder': 'Por favor, insira o rótulo do dicionário', + 'dictDataDialog.dictValue': 'Valor do Dicionário', + 'dictDataDialog.dictValuePlaceholder': 'Por favor, insira o valor do dicionário', + 'dictDataDialog.sort': 'Ordenação', + 'dictDataDialog.requiredDictLabel': 'Por favor, insira o rótulo do dicionário', + 'dictDataDialog.requiredDictValue': 'Por favor, insira o valor do dicionário', + + // Diálogo de tipo de dicionário + 'dictTypeDialog.addDictType': 'Adicionar Tipo de Dicionário', + 'dictTypeDialog.dictName': 'Nome do Tipo de Dicionário', + 'dictTypeDialog.dictNamePlaceholder': 'Por favor, insira o nome do tipo de dicionário', + 'dictTypeDialog.dictType': 'Código do Tipo de Dicionário', + 'dictTypeDialog.dictTypePlaceholder': 'Por favor, insira o código do tipo de dicionário', + 'dictTypeDialog.requiredDictName': 'Por favor, insira o nome do tipo de dicionário', + 'dictTypeDialog.requiredDictType': 'Por favor, insira o código do tipo de dicionário', + + // Diálogo de edição de voz + 'editVoiceDialog.voiceCode': 'Código da Voz', + 'editVoiceDialog.voiceCodePlaceholder': 'Por favor, insira o código da voz', + 'editVoiceDialog.voiceName': 'Nome da Voz', + 'editVoiceDialog.voiceNamePlaceholder': 'Por favor, insira o nome da voz', + 'editVoiceDialog.languageType': 'Tipo de Idioma', + 'editVoiceDialog.languageTypePlaceholder': 'Por favor, insira o tipo de idioma', + 'editVoiceDialog.sortNumber': 'Número de Ordenação', + 'editVoiceDialog.remark': 'Observação', + 'editVoiceDialog.remarkPlaceholder': 'Por favor, insira o conteúdo da observação', + 'editVoiceDialog.generatePreview': 'Gerar Pré-visualização', + 'editVoiceDialog.defaultVoiceName': 'Wawa Xiaohe', + 'editVoiceDialog.defaultLanguageType': 'Chinês', + 'editVoiceDialog.requiredVoiceCode': 'Por favor, insira o código da voz', + 'editVoiceDialog.requiredVoiceName': 'Por favor, insira o nome da voz', + + // Diálogo de firmware + 'firmwareDialog.firmwareName': 'Nome do Firmware', + 'firmwareDialog.firmwareNamePlaceholder': 'Por favor, insira o nome do firmware (placa + versão)', + 'firmwareDialog.firmwareType': 'Tipo de Firmware', + 'firmwareDialog.firmwareTypePlaceholder': 'Por favor, selecione o tipo de firmware', + 'firmwareDialog.version': 'Versão', + 'firmwareDialog.versionPlaceholder': 'Por favor, insira a versão (formato x.x.x)', + 'firmwareDialog.firmwareFile': 'Arquivo de Firmware', + 'firmwareDialog.clickUpload': 'Clique para Enviar', + 'firmwareDialog.uploadTip': 'Apenas arquivos de firmware (.bin/.apk) são suportados, e o tamanho não deve exceder 100MB', + 'firmwareDialog.uploadHint': 'Lembrete: Por favor, envie o arquivo xiaozhi.bin pré-mesclado, não o arquivo merged-binary.bin mesclado', + 'firmwareDialog.remark': 'Observação', + 'firmwareDialog.remarkPlaceholder': 'Por favor, insira informações de observação', + 'firmwareDialog.requiredFirmwareName': 'Por favor, insira o nome do firmware (placa + versão)', + 'firmwareDialog.requiredFirmwareType': 'Por favor, selecione o tipo de firmware', + 'firmwareDialog.requiredVersion': 'Por favor, insira a versão', + 'firmwareDialog.versionFormatError': 'Formato de versão incorreto. Por favor, insira no formato x.x.x', + 'firmwareDialog.requiredFirmwareFile': 'Por favor, envie o arquivo de firmware', + 'firmwareDialog.invalidFileType': 'Apenas arquivos de firmware no formato .bin/.apk são suportados!', + 'firmwareDialog.invalidFileSize': 'O tamanho do arquivo de firmware não pode exceder 100MB!', + 'firmwareDialog.uploadSuccess': 'Arquivo de firmware enviado com sucesso', + 'firmwareDialog.uploadFailed': 'Falha no envio do arquivo', + + // Diálogo de impressão vocal + 'voicePrintDialog.addSpeaker': 'Adicionar Falante', + 'voicePrintDialog.voicePrintVector': 'Vetor de Impressão Vocal', + 'voicePrintDialog.selectVoiceMessage': 'Por favor, selecione uma mensagem de voz', + 'voicePrintDialog.name': 'Nome', + 'voicePrintDialog.enterName': 'Por favor, insira o nome', + 'voicePrintDialog.description': 'Descrição', + 'voicePrintDialog.enterDescription': 'Por favor, insira a descrição', + 'voicePrintDialog.save': 'Salvar', + 'voicePrintDialog.cancel': 'Cancelar', + 'voicePrintDialog.requiredDescription': 'Por favor, insira a descrição', + 'voicePrintDialog.requiredName': 'Por favor, insira o nome', + 'voicePrintDialog.requiredAudioVector': 'Por favor, selecione o vetor de áudio', + + // Diálogo de provedor de contexto + 'contextProviderDialog.title': 'Editar Fonte', + 'contextProviderDialog.noContextApi': 'Sem API de Contexto', + 'contextProviderDialog.add': 'Adicionar', + 'contextProviderDialog.apiUrl': 'URL da API', + 'contextProviderDialog.apiUrlPlaceholder': 'http://api.example.com/data', + 'contextProviderDialog.requestHeaders': 'Cabeçalhos da Requisição', + 'contextProviderDialog.headerKeyPlaceholder': 'Chave', + 'contextProviderDialog.headerValuePlaceholder': 'Valor', + 'contextProviderDialog.noHeaders': 'Sem Cabeçalhos', + 'contextProviderDialog.addHeader': 'Adicionar Cabeçalho', + 'contextProviderDialog.cancel': 'Cancelar', + 'contextProviderDialog.confirm': 'Confirmar', + + // Página de configuração de papel - provedor de contexto + 'roleConfig.contextProvider': 'Contexto', + 'roleConfig.contextProviderSuccess': '{count} fontes adicionadas com sucesso.', + 'roleConfig.contextProviderDocLink': 'Como implantar provedor de contexto', + 'roleConfig.editContextProvider': 'Editar Fonte', + + // Página de impressão vocal + 'voicePrint.pageTitle': 'Reconhecimento de Impressão Vocal', + 'voicePrint.name': 'Nome', + 'voicePrint.description': 'Descrição', + 'voicePrint.createTime': 'Data de Criação', + 'voicePrint.action': 'Ação', + 'voicePrint.edit': 'Editar', + 'voicePrint.delete': 'Excluir', + 'voicePrint.add': 'Adicionar', + 'voicePrint.addSpeaker': 'Adicionar Falante', + 'voicePrint.editSpeaker': 'Editar Falante', + 'voicePrint.fetchFailed': 'Falha ao buscar lista de impressões vocais', + 'voicePrint.updateSuccess': 'Atualizado com sucesso', + 'voicePrint.addSuccess': 'Adicionado com sucesso', + 'voicePrint.confirmDelete': 'Tem certeza de que deseja excluir esta impressão vocal?', + 'voicePrint.warning': 'Aviso', + 'voicePrint.confirm': 'Confirmar', + 'voicePrint.cancel': 'Cancelar', + 'voicePrint.deleteSuccess': 'Impressão vocal excluída com sucesso', + 'voicePrint.deleteFailed': 'Falha na exclusão. Por favor, tente novamente', + 'voicePrint.cancelDelete': 'Operação de exclusão cancelada', + 'voicePrint.closeOperation': 'Operação fechada', + 'voicePrint.loading': 'Carregando...', + + // Diálogo de adição manual de dispositivo + 'manualAddDeviceDialog.title': 'Adicionar Dispositivo Manualmente', + 'manualAddDeviceDialog.deviceType': 'Tipo de Dispositivo', + 'manualAddDeviceDialog.deviceTypePlaceholder': 'Por favor, selecione o tipo de dispositivo', + 'manualAddDeviceDialog.firmwareVersion': 'Versão do Firmware', + 'manualAddDeviceDialog.firmwareVersionPlaceholder': 'Por favor, insira a versão do firmware', + 'manualAddDeviceDialog.macAddress': 'Endereço MAC', + 'manualAddDeviceDialog.macAddressPlaceholder': 'Por favor, insira o endereço MAC', + 'manualAddDeviceDialog.confirm': 'Confirmar', + 'manualAddDeviceDialog.cancel': 'Cancelar', + 'manualAddDeviceDialog.requiredMacAddress': 'Por favor, insira o endereço MAC', + 'manualAddDeviceDialog.invalidMacAddress': 'Por favor, insira o formato correto de endereço MAC, ex.: 00:1A:2B:3C:4D:5E', + 'manualAddDeviceDialog.requiredDeviceType': 'Por favor, selecione o tipo de dispositivo', + 'manualAddDeviceDialog.requiredFirmwareVersion': 'Por favor, insira a versão do firmware', + 'manualAddDeviceDialog.getFirmwareTypeFailed': 'Falha ao obter tipo de firmware', + 'manualAddDeviceDialog.addSuccess': 'Dispositivo adicionado com sucesso', + 'manualAddDeviceDialog.addFailed': 'Falha ao adicionar', + + // Componente AddModelDialog + 'addModelDialog.requiredSupplier': 'Por favor, selecione um fornecedor', + + // Página de registro + 'register.title': 'Criar Conta', + 'register.welcome': 'Bem-vindo ao XiaoZhi AI', + 'register.usernamePlaceholder': 'Por favor, insira o nome de usuário', + 'register.mobilePlaceholder': 'Por favor, insira o número de celular', + 'register.captchaPlaceholder': 'Por favor, insira o captcha', + 'register.mobileCaptchaPlaceholder': 'Por favor, insira o código de verificação SMS', + 'register.passwordPlaceholder': 'Por favor, defina a senha', + 'register.confirmPasswordPlaceholder': 'Por favor, confirme a senha', + 'register.goToLogin': 'Já tem uma conta? Entrar', + 'register.registerButton': 'Registrar', + 'register.agreeTo': 'Ao se registrar, você concorda com nossos', + 'register.userAgreement': 'Termos de Uso', + 'register.privacyPolicy': 'Política de Privacidade', + 'register.notAllowRegister': 'O registro de usuários não é permitido', + 'register.captchaLoadFailed': 'Falha ao carregar captcha', + 'register.inputCaptcha': 'Por favor, insira o captcha', + 'register.inputCorrectMobile': 'Por favor, insira um número de celular válido', + 'register.captchaSendSuccess': 'Código de verificação enviado com sucesso', + 'register.captchaSendFailed': 'Falha ao enviar código de verificação', + 'register.passwordsNotMatch': 'As senhas não coincidem', + 'register.registerSuccess': 'Registro realizado com sucesso!', + 'register.registerFailed': 'Falha no registro', + 'register.requiredUsername': 'O nome de usuário não pode estar vazio', + 'register.requiredPassword': 'A senha não pode estar vazia', + 'register.requiredCaptcha': 'O captcha não pode estar vazio', + 'register.requiredMobileCaptcha': 'Por favor, insira o código de verificação SMS', + 'register.invalidCaptcha': 'Código de verificação inválido', + 'register.passwordLength': 'A senha deve ter entre 6 e 20 caracteres', + 'register.usernameFormat': 'Formato de nome de usuário inválido', + 'register.confirmPasswordRequired': 'A confirmação de senha não pode estar vazia', + 'register.sendCaptcha': 'Obter Código de Verificação', + 'register.secondsLater': 'segundos depois', + + // Diálogo de parâmetros + 'paramDialog.paramCode': 'Código do Parâmetro', + 'paramDialog.paramCodePlaceholder': 'Por favor, insira o código do parâmetro', + 'paramDialog.paramValue': 'Valor do Parâmetro', + 'paramDialog.paramValuePlaceholder': 'Por favor, insira o valor do parâmetro', + 'paramDialog.valueType': 'Tipo de Valor', + 'paramDialog.valueTypePlaceholder': 'Por favor, selecione o tipo de valor', + 'paramDialog.remark': 'Observação', + 'paramDialog.remarkPlaceholder': 'Por favor, insira a observação', + 'paramDialog.save': 'Salvar', + 'paramDialog.cancel': 'Cancelar', + 'paramDialog.requiredParamCode': 'Por favor, insira o código do parâmetro', + 'paramDialog.requiredParamValue': 'Por favor, insira o valor do parâmetro', + 'paramDialog.requiredValueType': 'Por favor, selecione o tipo de valor', + 'paramDialog.stringType': 'Texto', + 'paramDialog.numberType': 'Número', + 'paramDialog.booleanType': 'Booleano', + 'paramDialog.arrayType': 'Array', + 'paramDialog.jsonType': 'Objeto JSON', + + // Página de login + 'login.title': 'Entrar', + 'login.welcome': 'BEM-VINDO AO LOGIN', + 'login.username': 'Nome de Usuário', + 'login.usernamePlaceholder': 'Por favor, insira o nome de usuário', + 'login.mobilePlaceholder': 'Por favor, insira o número de celular', + 'login.password': 'Senha', + 'login.passwordPlaceholder': 'Por favor, insira a senha', + 'login.captchaPlaceholder': 'Por favor, insira o código de verificação', + 'login.loginButton': 'Entrar', + 'login.login': 'Entrar', + 'login.register': 'Registrar', + 'login.forgotPassword': 'Esqueceu a Senha', + 'login.forgetPassword': 'Esqueceu a Senha?', + 'login.mobileLogin': 'Login por Celular', + 'login.usernameLogin': 'Login por Usuário', + 'login.agreeTo': 'Ao entrar, você aceita os', + 'login.userAgreement': 'Termos de Uso', + 'login.and': 'e', + 'login.privacyPolicy': 'Política de Privacidade', + 'login.registerAccount': 'Registrar Conta', + + // Página de recuperação de senha + 'retrievePassword.title': 'Redefinir Senha', + 'retrievePassword.welcome': 'RECUPERAÇÃO DE SENHA', + 'retrievePassword.subtitle': 'Recuperar Senha', + 'retrievePassword.mobile': 'Celular', + 'retrievePassword.mobilePlaceholder': 'Por favor, insira o número de celular', + 'retrievePassword.captcha': 'Código de Verificação', + 'retrievePassword.captchaPlaceholder': 'Por favor, insira o código de verificação', + 'retrievePassword.mobileCaptcha': 'Código de Verificação por Celular', + 'retrievePassword.mobileCaptchaPlaceholder': 'Por favor, insira o código de verificação por celular', + 'retrievePassword.newPassword': 'Nova Senha', + 'retrievePassword.newPasswordPlaceholder': 'Por favor, insira a nova senha', + 'retrievePassword.confirmNewPassword': 'Confirmar Nova Senha', + 'retrievePassword.confirmNewPasswordPlaceholder': 'Por favor, confirme a nova senha', + 'retrievePassword.getMobileCaptcha': 'Obter Código de Verificação', + 'retrievePassword.resetButton': 'Redefinir Senha', + 'retrievePassword.updateButton': 'Atualizar Agora', + 'retrievePassword.goToLogin': 'Voltar ao Login', + 'retrievePassword.inputCorrectMobile': 'Por favor, insira um número de celular válido', + 'retrievePassword.captchaSendSuccess': 'Código de verificação enviado com sucesso', + 'retrievePassword.passwordsNotMatch': 'As duas senhas não coincidem', + 'retrievePassword.passwordLength': 'A senha deve ter entre 6 e 20 caracteres', + 'retrievePassword.mobileRequired': 'O número de celular não pode estar vazio', + 'retrievePassword.captchaRequired': 'O código de verificação não pode estar vazio', + 'retrievePassword.mobileCaptchaRequired': 'O código de verificação por celular não pode estar vazio', + 'retrievePassword.newPasswordRequired': 'A nova senha não pode estar vazia', + 'retrievePassword.confirmNewPasswordRequired': 'A confirmação da nova senha não pode estar vazia', + 'retrievePassword.passwordUpdateSuccess': 'Senha atualizada com sucesso', + 'retrievePassword.agreeTo': 'Redefinir significa concordar', + + // Página de alteração de senha + 'changePassword.title': 'Alterar Senha', + 'changePassword.oldPasswordLabel': 'Senha Atual:', + 'changePassword.oldPasswordPlaceholder': 'Por favor, insira a senha atual', + 'changePassword.newPasswordLabel': 'Nova Senha:', + 'changePassword.newPasswordPlaceholder': 'Por favor, insira a nova senha', + 'changePassword.confirmPasswordLabel': 'Confirmar Nova Senha:', + 'changePassword.confirmPasswordPlaceholder': 'Por favor, insira novamente a nova senha', + 'changePassword.confirmButton': 'Confirmar', + 'changePassword.cancelButton': 'Cancelar', + 'changePassword.allFieldsRequired': 'Por favor, preencha todos os campos', + 'changePassword.passwordsNotMatch': 'As duas novas senhas não coincidem', + 'changePassword.newPasswordSameAsOld': 'A nova senha não pode ser igual à senha atual', + 'changePassword.passwordChangedSuccessfully': 'Senha alterada com sucesso. Por favor, faça login novamente', + 'changePassword.changeFailed': 'Falha ao alterar senha', + + // Página de gerenciamento de dispositivos + 'device.management': 'Gerenciamento de Dispositivos', + 'device.add': 'Adicionar Dispositivo', + 'device.edit': 'Editar Dispositivo', + 'device.delete': 'Excluir Dispositivo', + 'device.name': 'Nome do Dispositivo', + 'device.type': 'Tipo de Dispositivo', + 'device.status': 'Status do Dispositivo', + 'device.dialogTitle': 'Adicionar Dispositivo', + 'device.verificationCode': 'Código de Verificação:', + 'device.verificationCodePlaceholder': 'Por favor, insira o código de verificação de 6 dígitos transmitido pelo dispositivo..', + 'device.confirmButton': 'Confirmar', + 'device.cancelButton': 'Cancelar', + 'device.input6DigitCode': 'Por favor, insira um código de verificação de 6 dígitos', + 'device.bindSuccess': 'Dispositivo vinculado com sucesso', + 'device.bindFailed': 'Falha na vinculação', + 'device.searchPlaceholder': 'Por favor, insira modelo do dispositivo ou endereço MAC para pesquisar', + 'device.model': 'Modelo do Dispositivo', + 'device.macAddress': 'Endereço MAC', + 'device.firmwareVersion': 'Versão do Firmware', + 'device.bindTime': 'Data de Vinculação', + 'device.lastConversation': 'Última Conversa', + 'device.remark': 'Observação', + 'device.autoUpdate': 'Atualização Automática', + 'device.operation': 'Operação', + 'device.search': 'Pesquisar', + 'device.selectAll': 'Selecionar Tudo/Desmarcar Tudo', + 'deviceManagement.loading': 'Carregando...', + 'device.bindWithCode': 'Vincular com Código de 6 Dígitos', + 'device.manualAdd': 'Adicionar Manualmente', + 'device.unbind': 'Desvincular', + 'device.deviceThemeGeneration': 'Geração de tema do dispositivo', + 'device.toolCall': 'Chamada de Ferramenta', + 'device.selectAtLeastOne': 'Por favor, selecione pelo menos um registro', + 'device.confirmBatchUnbind': 'Tem certeza de que deseja desvincular {count} dispositivos selecionados?', + 'device.batchUnbindSuccess': '{count} dispositivos desvinculados com sucesso', + 'device.batchUnbindError': 'Ocorreu um erro durante a desvinculação em lote', + 'device.remarkTooLong': 'A observação não pode exceder 64 caracteres', + 'device.remarkSaved': 'Observação salva com sucesso', + 'device.remarkSaveFailed': 'Falha ao salvar observação', + 'device.confirmUnbind': 'Tem certeza de que deseja desvincular este dispositivo?', + 'device.unbindSuccess': 'Dispositivo desvinculado com sucesso', + 'device.unbindFailed': 'Falha ao desvincular dispositivo', + 'device.getListFailed': 'Falha ao buscar lista de dispositivos', + 'device.autoUpdateEnabled': 'Atualização automática ativada', + 'device.autoUpdateDisabled': 'Atualização automática desativada', + 'device.batchUnbindSuccess': '{count} dispositivos desvinculados com sucesso', + 'device.getFirmwareTypeFailed': 'Falha ao buscar tipo de firmware', + 'device.deviceStatus': 'Status', + 'device.online': 'Online', + 'device.offline': 'Offline', + + // Mensagens de dica + 'message.success': 'Operação Realizada com Sucesso', + 'message.error': 'Falha na Operação', + 'message.warning': 'Aviso', + 'message.info': 'Informação', + + // Cache + 'cache.viewer': 'Visualizador de Cache', + + // Diálogo de histórico de chat + 'chatHistory.with': 'Com', + 'chatHistory.dialogTitle': ' - Histórico de Chat', + 'chatHistory.loading': 'Carregando...', + 'chatHistory.noMoreRecords': 'Não há mais registros', + 'chatHistory.selectSession': 'Por favor, selecione uma sessão para visualizar o histórico de chat', + 'chatHistory.today': 'Hoje', + 'chatHistory.yesterday': 'Ontem', + 'chatHistory.downloadCurrentSession': 'Baixar histórico de chat da sessão atual', + 'chatHistory.downloadCurrentWithPreviousSessions': 'Baixar histórico de chat da sessão atual e das 20 sessões anteriores', + 'chatHistory.downloadLinkFailed': 'Falha ao obter link de download', + + 'cache.status': 'Status do Cache', + 'cache.cdnEnabled': 'Modo CDN Ativado', + 'cache.cdnDisabled': 'Modo CDN Desativado', + 'cache.serviceWorkerRegistered': 'Service Worker Registrado', + 'cache.serviceWorkerNotRegistered': 'Service Worker Não Registrado', + 'cache.noCacheDetected': 'Nenhum cache detectado ainda. Por favor, atualize a página ou aguarde o cache ser estabelecido', + 'cache.swDevEnvWarning': 'No ambiente de desenvolvimento, o Service Worker pode não inicializar o cache corretamente', + 'cache.swCheckMethods': 'Por favor, tente os seguintes métodos para verificar se o Service Worker está funcionando:', + 'cache.swCheckMethod1': 'Verifique o status do Service Worker na aba Application/Aplicação das ferramentas de desenvolvedor', + 'cache.swCheckMethod2': 'Visualize o conteúdo do cache em Application/Cache/Cache Storage das ferramentas de desenvolvedor', + 'cache.swCheckMethod3': 'Use o build de produção (npm run build) e acesse através de um servidor HTTP para testar a funcionalidade completa', + 'cache.swDevEnvNormal': 'No ambiente de desenvolvimento, isso é normal', + 'cache.swProdOnly': 'O Service Worker geralmente funciona apenas no ambiente de produção', + 'cache.swTestingTitle': 'Para testar a funcionalidade do Service Worker:', + 'cache.swTestingStep1': 'Execute npm run build para compilar a versão de produção', + 'cache.swTestingStep2': 'Acesse a página compilada através de um servidor HTTP', + 'cache.swNotSupported': 'O navegador atual não suporta Service Worker. A função de cache de recursos CDN não está disponível', + 'cache.dialogTitle': 'Status de Cache de Recursos CDN', + 'cache.loading': 'Carregando informações de cache...', + 'cache.notSupported': 'Seu navegador não suporta Cache API ou o Service Worker não está instalado', + 'cache.refreshPage': 'Atualizar Página', + 'cache.noCachedResources': 'Nenhum recurso CDN em cache encontrado', + 'cache.noCachedResourcesDesc': 'O Service Worker pode não ter concluído a inicialização ou o cache não foi estabelecido. Por favor, atualize a página ou tente novamente mais tarde.', + 'cache.cdnCacheStatus': 'Status de Cache de Recursos CDN', + 'cache.totalCachedResources': 'Encontrados {count} recursos em cache no total', + 'cache.jsResources': 'Recursos JavaScript ({count})', + 'cache.cssResources': 'Recursos CSS ({count})', + 'cache.cached': 'Em Cache', + 'cache.notCached': 'Não Em Cache', + 'cache.refreshStatus': 'Atualizar Status do Cache', + 'cache.clearCache': 'Limpar Cache', + 'cache.refreshingStatus': 'Atualizando status do cache', + 'cache.confirmClear': 'Tem certeza de que deseja limpar todo o cache?', + 'cache.clearedSuccess': 'Cache limpo com sucesso', + 'cache.clearFailed': 'Falha ao limpar cache', + 'cache.clearCanceled': 'Operação de limpeza cancelada', + + // Botões comuns + 'button.ok': 'OK', + 'button.cancel': 'Cancelar', + 'button.save': 'Salvar', + 'button.close': 'Fechar', + + // Informações do sistema + 'system.name': 'Serviço XiaoZhi', + + // Impressão vocal + 'voiceprint.management': 'Gerenciamento de Impressão Vocal', + 'voiceprint.add': 'Adicionar Impressão Vocal', + 'voiceprint.delete': 'Excluir Impressão Vocal', + + // Página de gerenciamento de dicionário + 'dictManagement.pageTitle': 'Gerenciamento de Dicionário', + 'dictManagement.searchPlaceholder': 'Por favor, insira o rótulo do dicionário para pesquisar', + 'dictManagement.search': 'Pesquisar', + 'dictManagement.dictTypeName': 'Nome do Tipo de Dicionário', + 'dictManagement.operation': 'Operação', + 'dictManagement.edit': 'Editar', + 'dictManagement.dictLabel': 'Rótulo do Dicionário', + 'dictManagement.dictValue': 'Valor do Dicionário', + 'dictManagement.sort': 'Ordenação', + 'dictManagement.delete': 'Excluir', + 'dictManagement.selectAll': 'Selecionar Tudo', + 'dictManagement.deselectAll': 'Desmarcar Tudo', + 'dictManagement.addDictType': 'Adicionar Tipo de Dicionário', + 'dictManagement.batchDeleteDictType': 'Exclusão em Lote de Tipos de Dicionário', + 'dictManagement.addDictData': 'Adicionar Dados do Dicionário', + 'dictManagement.batchDeleteDictData': 'Exclusão em Lote de Dados do Dicionário', + 'dictManagement.itemsPerPage': '{items} itens/página', + 'dictManagement.firstPage': 'Primeira Página', + 'dictManagement.prevPage': 'Página Anterior', + 'dictManagement.nextPage': 'Próxima Página', + 'dictManagement.totalRecords': 'Total de {total} registros', + 'dictManagement.editDictType': 'Editar Tipo de Dicionário', + 'dictManagement.editDictData': 'Editar Dados do Dicionário', + 'dictManagement.saveSuccess': 'Salvo com Sucesso', + 'dictManagement.deleteSuccess': 'Excluído com Sucesso', + 'dictManagement.selectDictTypeToDelete': 'Por favor, selecione tipos de dicionário para excluir', + 'dictManagement.confirmDeleteDictType': 'Tem certeza de que deseja excluir os tipos de dicionário selecionados?', + 'dictManagement.confirm': 'Confirmar', + 'dictManagement.cancel': 'Cancelar', + 'dictManagement.selectDictTypeFirst': 'Por favor, selecione um tipo de dicionário primeiro', + 'dictManagement.confirmDeleteDictData': 'Tem certeza de que deseja excluir estes dados do dicionário?', + 'dictManagement.selectDictDataToDelete': 'Por favor, selecione dados do dicionário para excluir', + 'dictManagement.confirmBatchDeleteDictData': 'Tem certeza de que deseja excluir {count} itens de dados do dicionário selecionados?', + 'dictManagement.getDictDataFailed': 'Falha ao obter dados do dicionário', + + // Informações do usuário + 'user.info': 'Informações do Usuário', + 'user.username': 'Nome de Usuário', + 'user.mobile': 'Celular', + 'user.userid': 'ID do Usuário', + 'user.deviceCount': 'Quantidade de Dispositivos', + 'user.createDate': 'Data de Registro', + 'user.status': 'Status', + 'user.normal': 'Normal', + 'user.disabled': 'Desativado', + 'user.resetPassword': 'Redefinir Senha', + 'user.disableAccount': 'Desativar Conta', + 'user.enableAccount': 'Ativar Conta', + 'user.deleteUser': 'Excluir Usuário', + 'user.deselectAll': 'Desmarcar Tudo', + 'user.selectAll': 'Selecionar Tudo', + 'user.enable': 'Ativar', + 'user.disable': 'Desativar', + 'user.delete': 'Excluir', + 'user.selectUsersFirst': 'Por favor, selecione usuários para excluir primeiro', + 'user.confirmDeleteSelected': 'Tem certeza de que deseja excluir {count} usuários selecionados?', + 'user.deleting': 'Excluindo...', + 'user.deleteSuccess': '{count} usuários excluídos com sucesso', + 'user.deleteFailed': 'Falha na exclusão. Por favor, tente novamente', + 'user.partialDelete': '{successCount} usuários excluídos com sucesso, {failCount} falharam', + 'user.deleteError': 'Ocorreu um erro durante a exclusão', + 'user.deleteCancelled': 'Exclusão cancelada', + 'user.confirmResetPassword': 'Uma nova senha será gerada após a redefinição. Continuar?', + 'user.resetPasswordSuccess': 'Senha redefinida. Por favor, notifique o usuário para fazer login com a nova senha', + 'user.generatedPassword': 'Senha Padrão Gerada', + 'user.confirmDeleteUser': 'Tem certeza de que deseja excluir este usuário?', + 'user.deleteUserSuccess': 'Excluído com sucesso', + 'user.operationFailed': 'Falha na operação. Por favor, tente novamente', + 'user.confirmStatusChange': 'Tem certeza de que deseja {action} {count} usuários selecionados?', + 'user.statusChangeSuccess': '{count} usuários {action} com sucesso', + 'user.invalidUserId': 'Existem IDs de usuário inválidos', + 'user.searchPhone': 'Por favor, insira o número de celular para pesquisar', + 'user.search': 'Pesquisar', + + // Página de gerenciamento de provedores + 'providerManagement.categoryFilter': 'Filtro de Categoria', + 'providerManagement.searchPlaceholder': 'Por favor, insira o nome do provedor para pesquisar', + 'providerManagement.category': 'Categoria', + 'providerManagement.providerCode': 'Código do Provedor', + 'providerManagement.fieldConfig': 'Configuração de Campos', + 'providerManagement.selectToDelete': 'Por favor, selecione provedores para excluir primeiro', + 'providerManagement.confirmDelete': 'Tem certeza de que deseja excluir os {count} provedores selecionados?', + 'providerManagement.viewFields': 'Ver Campos', + + // Texto comum + 'common.all': 'Todos', + 'common.search': 'Pesquisar', + 'common.name': 'Nome', + 'common.sort': 'Ordenação', + 'common.action': 'Ação', + 'common.edit': 'Editar', + 'common.delete': 'Excluir', + 'common.selectAll': 'Selecionar Tudo', + 'common.deselectAll': 'Desmarcar Tudo', + 'common.add': 'Adicionar', + 'common.perPage': '{number}/página', + 'common.firstPage': 'Primeira Página', + 'common.prevPage': 'Página Anterior', + 'common.nextPage': 'Próxima Página', + 'common.totalRecords': 'Total de {number} registros', + 'common.addProvider': 'Adicionar Provedor', + 'common.success': 'Sucesso', + 'common.editProvider': 'Editar Provedor', + 'common.updateSuccess': 'Atualizado com Sucesso', + 'common.addSuccess': 'Adicionado com Sucesso', + 'common.deleteSuccess': 'Excluído com Sucesso', + 'common.deleteFailure': 'Falha ao Excluir. Por Favor, Tente Novamente', + 'common.deleteCancelled': 'Exclusão Cancelada', + 'common.warning': 'Aviso', + 'common.tip': 'Dica', + 'common.confirm': 'Confirmar', + 'common.cancel': 'Cancelar', + 'common.sensitive': 'Sensível', + 'common.loading': 'Carregando', + + // Troca de idioma + 'language.zhCN': '中文简体', + 'language.zhTW': '中文繁體', + 'language.en': 'English', + 'language.de': 'Deutsch', + 'language.vi': 'Tiếng Việt', + 'language.ptBR': 'Português (Brasil)', + + // Página inicial + 'home.addAgent': 'Adicionar Agente', + 'home.greeting': 'Olá XiaoZhi', + 'home.wish': 'Vamos ter um dia maravilhoso!', + 'home.languageModel': 'LLM', + 'home.voiceModel': 'TTS', + 'home.configureRole': 'Configurar Papel', + 'home.voiceprintRecognition': 'Impressão Vocal', + 'home.deviceManagement': 'Dispositivos', + 'home.chatHistory': 'Histórico de Chat', + 'home.lastConversation': 'Última Conversa', + 'home.noConversation': 'Nenhuma conversa', + 'home.justNow': 'Agora mesmo', + 'home.minutesAgo': 'Há {minutes} minutos', + 'home.hoursAgo': 'Há {hours} horas e {minutes} minutos', + 'home.confirmDeleteAgent': 'Tem certeza de que deseja excluir este agente?', + 'home.deleteSuccess': 'Excluído com sucesso', + 'home.deleteFailed': 'Falha ao excluir', + 'home.enableMemory': 'Por favor, ative a memória na página "Configurar Papel" primeiro', + + // Página de gerenciamento de parâmetros + 'paramManagement.pageTitle': 'Gerenciamento de Parâmetros', + 'paramManagement.searchPlaceholder': 'Por favor, insira código do parâmetro ou observação para pesquisar', + 'paramManagement.search': 'Pesquisar', + 'paramManagement.paramCode': 'Código do Parâmetro', + 'paramManagement.paramValue': 'Valor do Parâmetro', + 'paramManagement.remark': 'Observação', + 'paramManagement.operation': 'Operação', + 'paramManagement.hide': 'Ocultar', + 'paramManagement.view': 'Visualizar', + 'paramManagement.deselectAll': 'Desmarcar Tudo', + 'paramManagement.selectAll': 'Selecionar Tudo', + 'paramManagement.add': 'Adicionar', + 'paramManagement.delete': 'Excluir', + 'paramManagement.edit': 'Editar', + 'paramManagement.itemsPerPage': 'itens/página', + 'paramManagement.firstPage': 'Primeira Página', + 'paramManagement.prevPage': 'Página Anterior', + 'paramManagement.nextPage': 'Próxima Página', + 'paramManagement.totalRecords': 'Total de {total} registros', + 'paramManagement.addParam': 'Adicionar Parâmetro', + 'paramManagement.editParam': 'Editar Parâmetro', + 'paramManagement.getParamsListFailed': 'Falha ao obter lista de parâmetros', + 'paramManagement.selectParamsFirst': 'Por favor, selecione parâmetros para excluir primeiro', + 'paramManagement.confirmBatchDelete': 'Tem certeza de que deseja excluir {paramCount} parâmetros selecionados?', + 'paramManagement.invalidParamId': 'Existem IDs de parâmetro inválidos', + 'paramManagement.batchDeleteSuccess': '{paramCount} parâmetros excluídos com sucesso', + 'paramManagement.deleteFailed': 'Falha na exclusão. Por favor, tente novamente', + 'paramManagement.operationCancelled': 'Exclusão cancelada', + 'paramManagement.operationClosed': 'Operação fechada', + 'paramManagement.updateSuccess': 'Atualizado com sucesso. Algumas configurações só terão efeito após reiniciar o módulo xiaozhi-server.', + 'paramManagement.addSuccess': 'Adicionado com sucesso', + 'paramManagement.updateFailed': 'Falha na atualização', + 'paramManagement.addFailed': 'Falha ao adicionar', + + // Página de gerenciamento de servidores + 'serverSideManager.pageTitle': 'Gerenciamento de Servidores', + 'serverSideManager.wsAddress': 'Endereço WS', + 'serverSideManager.operation': 'Operação', + 'serverSideManager.restart': 'Reiniciar', + 'serverSideManager.updateConfig': 'Atualizar Configuração', + 'serverSideManager.restartServer': 'Reiniciar Servidor', + 'serverSideManager.updateConfigTitle': 'Atualizar Configuração', + 'serverSideManager.confirmRestart': 'Tem certeza de que deseja reiniciar o servidor?', + 'serverSideManager.confirmUpdateConfig': 'Tem certeza de que deseja atualizar a configuração?', + 'serverSideManager.loading': 'Carregando...', + 'serverSideManager.getServerListFailed': 'Falha ao obter lista de servidores', + 'serverSideManager.operationFailed': 'Falha na operação', + 'serverSideManager.restartSuccess': 'Reiniciado com sucesso', + 'serverSideManager.updateConfigSuccess': 'Configuração atualizada com sucesso', + + // Diálogo de adicionar agente + 'addAgentDialog.title': 'Adicionar Agente', + 'addAgentDialog.agentName': 'Nome do Agente', + 'addAgentDialog.placeholder': 'Por favor, insira o nome do agente..', + 'addAgentDialog.confirm': 'Confirmar', + 'addAgentDialog.cancel': 'Cancelar', + 'addAgentDialog.nameRequired': 'Por favor, insira o nome do agente', + 'addAgentDialog.addSuccess': 'Adicionado com sucesso', + + // Página de configuração de papel + 'roleConfig.title': 'Configuração de Papel', + 'roleConfig.restartNotice': 'Após salvar a configuração, é necessário reiniciar o dispositivo para que a nova configuração tenha efeito.', + 'roleConfig.saveConfig': 'Salvar Configuração', + 'roleConfig.reset': 'Redefinir', + 'roleConfig.agentName': 'Apelido', + 'roleConfig.roleTemplate': 'Modelo', + 'roleConfig.roleIntroduction': 'Introdução', + 'roleConfig.languageCode': 'Código do Idioma', + 'roleConfig.interactionLanguage': 'Idioma de Interação', + 'roleConfig.vad': 'Detecção de Voz', + 'roleConfig.asr': 'Reconhecimento de Fala', + 'roleConfig.llm': 'Modelo de Linguagem', + 'roleConfig.vllm': 'Modelo de Visão', + 'roleConfig.tts': 'Texto para Fala', + 'roleConfig.memoryHis': 'Memória', + 'roleConfig.memory': 'Modelo de Memória', + 'roleConfig.intent': 'Reconhecimento de Intenção', + 'roleConfig.voiceType': 'Tipo de Voz', + 'roleConfig.pleaseEnterContent': 'Por favor, insira o conteúdo', + 'roleConfig.pleaseEnterLangCode': 'Por favor, insira o código do idioma, ex.: pt_BR', + 'roleConfig.pleaseEnterLangName': 'Por favor, insira o idioma de interação, ex.: Português', + 'roleConfig.pleaseSelect': 'Por favor, selecione', + 'roleConfig.editFunctions': 'Editar Funções', + 'roleConfig.reportText': 'Somente Texto', + 'roleConfig.reportTextVoice': 'Texto e Voz', + 'roleConfig.saveSuccess': 'Configuração salva com sucesso', + 'roleConfig.saveFailed': 'Falha ao salvar configuração', + 'roleConfig.confirmReset': 'Tem certeza de que deseja redefinir a configuração?', + 'roleConfig.resetSuccess': 'Configuração redefinida', + 'roleConfig.fetchTemplatesFailed': 'Falha ao buscar lista de modelos', + 'roleConfig.templateApplied': 'modelo aplicado', + 'roleConfig.applyTemplateFailed': 'Falha ao aplicar modelo', + 'roleConfig.fetchConfigFailed': 'Falha ao buscar configuração', + 'roleConfig.fetchModelsFailed': 'Falha ao buscar lista de modelos', + 'roleConfig.fetchPluginsFailed': 'Falha ao buscar lista de plugins', + 'roleConfig.cannotResumeAudio': 'Não é possível retomar a reprodução de áudio', + 'roleConfig.selectVoiceFirst': 'Por favor, selecione uma voz primeiro', + 'roleConfig.audioLoadTimeout': 'O carregamento do áudio está demorando muito. Por favor, tente novamente mais tarde', + 'roleConfig.cloneAudioPlayFailed': 'Falha na reprodução do áudio clonado', + 'roleConfig.cannotPlayCloneAudio': 'Não é possível reproduzir áudio clonado', + 'roleConfig.getCloneAudioFailed': 'Falha ao obter áudio clonado', + 'roleConfig.noPreviewAudio': 'Esta voz não possui áudio de pré-visualização disponível', + 'roleConfig.audioPlayFailed': 'Falha na reprodução de áudio', + 'roleConfig.cannotPlayAudio': 'Não é possível reproduzir áudio', + 'roleConfig.audioPlayError': 'Ocorreu um erro durante a reprodução de áudio', + + // Diálogo de gerenciamento de funções + 'functionDialog.title': 'Gerenciamento de Funções', + 'functionDialog.unselectedFunctions': 'Funções Não Selecionadas', + 'functionDialog.selectedFunctions': 'Funções Selecionadas', + 'functionDialog.selectAll': 'Selecionar Tudo', + 'functionDialog.noMorePlugins': 'Não há mais plugins disponíveis', + 'functionDialog.pleaseSelectPlugin': 'Por favor, selecione funções de plugin', + 'functionDialog.paramConfig': 'Configuração de Parâmetros', + 'functionDialog.noNeedToConfig': ' não requer configuração de parâmetros', + 'functionDialog.pleaseSelectFunctionForParam': 'Por favor, selecione uma função configurada para definições de parâmetros', + 'functionDialog.mcpAccessPoint': 'Ponto de Acesso MCP', + 'functionDialog.mcpAddressDesc': 'Abaixo estão os endereços de ponto de acesso MCP do agente.', + 'functionDialog.howToDeployMcp': 'Como implantar ponto de acesso MCP', + 'functionDialog.howToIntegrateMcp': 'Como integrar funções MCP', + 'functionDialog.copy': 'Copiar', + 'functionDialog.accessPointStatus': 'Status do Ponto de Acesso', + 'functionDialog.connected': 'Conectado', + 'functionDialog.loading': 'Carregando...', + 'functionDialog.disconnected': 'Desconectado', + 'functionDialog.refresh': 'Atualizar', + 'functionDialog.noAvailableTools': 'Nenhuma ferramenta disponível', + 'functionDialog.cancel': 'Cancelar', + 'functionDialog.saveConfig': 'Salvar Configuração', + 'functionDialog.copiedToClipboard': 'Copiado para a área de transferência', + 'functionDialog.copyFailed': 'Falha ao copiar. Por favor, copie manualmente', + 'functionDialog.jsonFormatError': ' erro no formato do campo: formato JSON inválido', + 'functionDialog.defaultValue': 'Valor Padrão', + + // Página de configuração de modelos + 'modelConfig.searchPlaceholder': 'Por favor, insira o nome do modelo para pesquisar', + 'modelConfig.search': 'Pesquisar', + 'modelConfig.vad': 'Detecção de Atividade de Voz', + 'modelConfig.asr': 'Reconhecimento de Fala', + 'modelConfig.llm': 'Modelo de Linguagem Grande', + 'modelConfig.vllm': 'Modelo de Linguagem Visual', + 'modelConfig.intent': 'Reconhecimento de Intenção', + 'modelConfig.tts': 'Texto para Fala', + 'modelConfig.memory': 'Memória', + 'modelConfig.rag': 'RAG', + 'modelConfig.modelId': 'ID do Modelo', + 'modelConfig.modelName': 'Nome do Modelo', + 'modelConfig.provider': 'Tipo de Interface', + 'modelConfig.unknown': 'Desconhecido', + 'modelConfig.isEnabled': 'Ativado', + 'modelConfig.isDefault': 'Padrão', + 'modelConfig.defaultModelCannotDisable': 'A configuração do modelo padrão não pode ser desativada', + 'modelConfig.action': 'Ação', + 'modelConfig.voiceManagement': 'Gerenciamento de Voz', + 'modelConfig.edit': 'Editar', + 'modelConfig.duplicate': 'Duplicar', + 'modelConfig.delete': 'Excluir', + 'modelConfig.deselectAll': 'Desmarcar Tudo', + 'modelConfig.select': 'Selecionar', + 'modelConfig.selectAll': 'Selecionar Tudo', + 'modelConfig.add': 'Adicionar Novo', + 'modelConfig.selectModelsFirst': 'Por favor, selecione modelos para excluir primeiro', + 'modelConfig.confirmBatchDelete': 'Tem certeza de que deseja excluir os modelos selecionados?', + 'modelConfig.confirmDelete': 'Tem certeza de que deseja excluir este modelo?', + 'modelConfig.batchDeleteSuccess': 'Exclusão em lote realizada com sucesso', + 'modelConfig.partialDeleteFailed': 'Exclusão parcial falhou', + 'modelConfig.deleteSuccess': 'Excluído com sucesso', + 'modelConfig.deleteFailed': 'Falha ao excluir', + 'modelConfig.deleteCancelled': 'Exclusão cancelada', + 'modelConfig.duplicateSuccess': 'Duplicado com sucesso', + 'modelConfig.duplicateFailed': 'Falha ao duplicar', + 'modelConfig.saveSuccess': 'Salvo com sucesso', + 'modelConfig.saveFailed': 'Falha ao salvar', + 'modelConfig.addSuccess': 'Adicionado com sucesso', + 'modelConfig.addFailed': 'Falha ao adicionar', + 'modelConfig.fetchModelsFailed': 'Falha ao buscar lista de modelos', + 'modelConfig.enableSuccess': 'Ativado com sucesso', + 'modelConfig.disableSuccess': 'Desativado com sucesso', + 'modelConfig.operationFailed': 'Falha na operação', + 'modelConfig.setDefaultSuccess': 'Modelo padrão definido com sucesso. Por favor, reinicie o módulo xiaozhi-server manualmente', + 'modelConfig.itemsPerPage': '{items} itens/página', + 'modelConfig.firstPage': 'Primeira Página', + 'modelConfig.prevPage': 'Página Anterior', + 'modelConfig.nextPage': 'Próxima Página', + 'modelConfig.totalRecords': 'Total de {total} registros', + 'modelConfig.loading': 'Carregando...', + + // Diálogo de configuração de modelos + 'modelConfigDialog.addModel': 'Adicionar Modelo', + 'modelConfigDialog.editModel': 'Editar Modelo', + 'modelConfigDialog.duplicateModel': 'Duplicar Modelo', + 'modelConfigDialog.copySuffix': '_cópia', + 'modelConfigDialog.modelInfo': 'Informações do Modelo', + 'modelConfigDialog.enable': 'Ativar', + 'modelConfigDialog.setDefault': 'Definir como Padrão', + 'modelConfigDialog.modelId': 'ID do Modelo', + 'modelConfigDialog.enterModelId': 'Se não preenchido, será gerado automaticamente', + 'modelConfigDialog.invalidModelId': 'O ID do modelo não pode ser apenas texto ou espaços. Use letras, números, sublinhados ou hífens', + 'modelConfigDialog.modelName': 'Nome do Modelo', + 'modelConfigDialog.enterModelName': 'Por favor, insira o nome do modelo', + 'modelConfigDialog.modelCode': 'Código do Modelo', + 'modelConfigDialog.enterModelCode': 'Por favor, insira o código do modelo', + 'modelConfigDialog.supplier': 'Fornecedor', + 'modelConfigDialog.selectSupplier': 'Por favor, selecione', + 'modelConfigDialog.sortOrder': 'Ordem de Classificação', + 'modelConfigDialog.enterSortOrder': 'Por favor, insira a ordem de classificação', + 'modelConfigDialog.docLink': 'Link da Documentação', + 'modelConfigDialog.enterDocLink': 'Por favor, insira o link da documentação', + 'modelConfigDialog.remark': 'Observação', + 'modelConfigDialog.enterRemark': 'Por favor, insira a observação do modelo', + 'modelConfigDialog.callInfo': 'Informações de Chamada', + 'modelConfigDialog.enterJsonExample': 'Por favor, insira variáveis no formato JSON (exemplo: {"key":"value"})', + 'modelConfigDialog.save': 'Salvar', + + // Configuração de modelo TTS + 'ttsModel.select': 'Selecionar', + 'ttsModel.voiceCode': 'Código da Voz', + 'ttsModel.voiceName': 'Nome da Voz', + 'ttsModel.languageType': 'Tipo de Idioma', + 'ttsModel.preview': 'Pré-visualizar', + 'ttsModel.enterMp3Url': 'Por favor, insira a URL do MP3', + 'ttsModel.remark': 'Observação', + 'ttsModel.enterRemark': 'Esta é uma observação', + 'ttsModel.referenceAudioPath': 'Caminho do Áudio de Referência', + 'ttsModel.enterReferenceAudio': 'Este é o caminho do áudio de referência', + 'ttsModel.referenceText': 'Texto do Áudio de Referência', + 'ttsModel.enterReferenceText': 'Este é o texto do áudio de referência', + 'ttsModel.action': 'Ação', + 'ttsModel.operation': 'Operação', + 'ttsModel.operationFailed': 'Falha na operação', + 'ttsModel.operationClosed': 'Operação fechada', + 'ttsModel.edit': 'Editar', + 'ttsModel.delete': 'Excluir', + 'ttsModel.deleteVoiceSuccess': '{count} vozes excluídas com sucesso', + 'ttsModel.deleteFailed': 'Falha ao excluir vozes', + 'ttsModel.save': 'Salvar', + 'ttsModel.deselectAll': 'Desmarcar Tudo', + 'ttsModel.selectAll': 'Selecionar Tudo', + 'ttsModel.add': 'Adicionar', + 'ttsModel.fetchVoicesFailed': 'Falha ao buscar lista de vozes', + 'ttsModel.loadVoicesFailed': 'Falha ao carregar dados de voz', + 'ttsModel.unnamedVoice': 'Voz Sem Nome', + 'ttsModel.finishEditingFirst': 'Por favor, termine a edição atual primeiro', + 'ttsModel.selectVoiceToDelete': 'Por favor, selecione vozes para excluir', + 'ttsModel.warning': 'Aviso', + 'ttsModel.confirmDeleteVoice': 'Tem certeza de que deseja excluir {count} vozes?', + 'ttsModel.voiceCodeNameLanguageRequired': 'Código da voz, nome da voz e tipo de idioma não podem estar vazios', + 'ttsModel.deleteCancelled': 'Exclusão cancelada', + 'ttsModel.updateSuccess': 'Atualizado com sucesso', + 'ttsModel.saveSuccess': 'Salvo com sucesso', + + // Página de gerenciamento OTA + 'otaManagement.firmwareManagement': 'Gerenciamento de Firmware', + 'otaManagement.searchPlaceholder': 'Por favor, insira o nome do firmware para pesquisar', + 'otaManagement.search': 'Pesquisar', + 'otaManagement.firmwareName': 'Nome do Firmware', + 'otaManagement.firmwareType': 'Tipo de Firmware', + 'otaManagement.version': 'Versão', + 'otaManagement.fileSize': 'Tamanho do Arquivo', + 'otaManagement.remark': 'Observação', + 'otaManagement.createTime': 'Data de Criação', + 'otaManagement.updateTime': 'Data de Atualização', + 'otaManagement.action': 'Ação', + 'otaManagement.download': 'Baixar', + 'otaManagement.edit': 'Editar', + 'otaManagement.delete': 'Excluir', + 'otaManagement.selectAll': 'Selecionar Tudo', + 'otaManagement.deselectAll': 'Desmarcar Tudo', + 'otaManagement.addNew': 'Adicionar Novo', + 'otaManagement.addFirmware': 'Adicionar Firmware', + 'otaManagement.editFirmware': 'Editar Firmware', + 'otaManagement.itemsPerPage': '{items} itens/página', + 'otaManagement.firstPage': 'Primeira Página', + 'otaManagement.prevPage': 'Página Anterior', + 'otaManagement.nextPage': 'Próxima Página', + 'otaManagement.totalRecords': 'Total de {total} registros', + 'otaManagement.selectFirmwareFirst': 'Por favor, selecione firmware para excluir primeiro', + 'otaManagement.confirmBatchDelete': 'Tem certeza de que deseja excluir os {paramCount} firmware selecionados?', + 'otaManagement.operationCancelled': 'Operação de exclusão foi cancelada', + 'otaManagement.operationClosed': 'Operação foi fechada', + 'otaManagement.batchDeleteSuccess': '{paramCount} firmware excluídos com sucesso', + 'otaManagement.deleteFailed': 'Falha na exclusão. Por favor, tente novamente', + 'otaManagement.incompleteFirmwareInfo': 'Informações de firmware incompletas', + 'otaManagement.getDownloadUrlFailed': 'Falha ao obter link de download', + 'otaManagement.getFirmwareTypesFailed': 'Falha ao obter tipos de firmware', + 'otaManagement.updateSuccess': 'Atualizado com sucesso', + 'otaManagement.updateFailed': 'Falha na atualização', + 'otaManagement.addSuccess': 'Adicionado com sucesso', + 'otaManagement.addFailed': 'Falha ao adicionar', + 'otaManagement.fetchFirmwareListFailed': 'Falha ao buscar lista de firmware', + + // Tipos de modelo na página de gerenciamento de provedores + 'providerManagement.all': 'Todos', + 'providerManagement.modelType.ASR': 'Reconhecimento de Fala', + 'providerManagement.modelType.TTS': 'Texto para Fala', + 'providerManagement.modelType.LLM': 'Modelo de Linguagem Grande', + 'providerManagement.modelType.VLLM': 'Modelo de Linguagem Visual Grande', + 'providerManagement.modelType.Intent': 'Reconhecimento de Intenção', + 'providerManagement.modelType.Memory': 'Módulo de Memória', + 'providerManagement.modelType.VAD': 'Detecção de Atividade de Voz', + 'providerManagement.modelType.Plugin': 'Ferramenta de Plugin', + 'providerManagement.modelType.RAG': 'RAG', + + // Diálogo de provedor + 'providerDialog.category': 'Categoria', + 'providerDialog.selectCategory': 'Por favor, selecione a categoria', + 'providerDialog.code': 'Código', + 'providerDialog.inputCode': 'Por favor, insira o código do provedor', + 'providerDialog.name': 'Nome', + 'providerDialog.inputName': 'Por favor, insira o nome do provedor', + 'providerDialog.sort': 'Ordenação', + 'providerDialog.fieldConfig': 'Configuração de Campos', + 'providerDialog.add': 'Adicionar', + 'providerDialog.deselectAll': 'Desmarcar Tudo', + 'providerDialog.selectAll': 'Selecionar Tudo', + 'providerDialog.batchDelete': 'Exclusão em Lote', + 'providerDialog.fieldKey': 'Chave do Campo', + 'providerDialog.fieldLabel': 'Rótulo do Campo', + 'providerDialog.fieldType': 'Tipo do Campo', + 'providerDialog.type': 'Tipo', + 'providerDialog.stringType': 'Texto', + 'providerDialog.numberType': 'Número', + 'providerDialog.booleanType': 'Booleano', + 'providerDialog.dictType': 'Dicionário', + 'providerDialog.arrayType': 'Lista Separada por Ponto e Vírgula', + 'providerDialog.ragType': 'RAG', + 'providerDialog.defaultValue': 'Valor Padrão', + 'providerDialog.inputDefaultValue': 'Por favor, insira o valor padrão', + 'providerDialog.operation': 'Operação', + 'providerDialog.edit': 'Editar', + 'providerDialog.complete': 'Concluir', + 'providerDialog.delete': 'Excluir', + 'providerDialog.save': 'Salvar', + 'providerDialog.requiredCategory': 'Por favor, selecione a categoria', + 'providerDialog.requiredCode': 'Por favor, insira o código do provedor', + 'providerDialog.requiredName': 'Por favor, insira o nome do provedor', + 'providerDialog.completeFieldEdit': 'Por favor, conclua a edição do campo atual primeiro', + 'providerDialog.confirmDeleteField': 'Tem certeza de que deseja excluir este campo?', + 'providerDialog.selectFieldsToDelete': 'Por favor, selecione campos para excluir primeiro', + 'providerDialog.confirmBatchDeleteFields': 'Tem certeza de que deseja excluir {count} campos selecionados?', + 'providerDialog.batchDeleteFieldsSuccess': '{count} campos excluídos com sucesso', + + // Gerenciamento de modelos de agente + 'agentTemplateManagement.title': 'Gerenciamento de Papéis Padrão', + 'agentTemplateManagement.templateName': 'Nome do Modelo', + 'agentTemplateManagement.action': 'Ação', + 'agentTemplateManagement.createTemplate': 'Criar Modelo', + 'agentTemplateManagement.editTemplate': 'Editar Modelo', + 'agentTemplateManagement.deleteTemplate': 'Excluir Modelo', + 'agentTemplateManagement.deleteSuccess': 'Modelo excluído com sucesso', + 'agentTemplateManagement.batchDelete': 'Exclusão em Lote', + 'agentTemplateManagement.batchDeleteSuccess': 'Exclusão em lote realizada com sucesso', + 'agentTemplateManagement.selectTemplate': 'Por favor, selecione um modelo', + 'agentTemplateManagement.select': 'Selecionar', + 'agentTemplateManagement.searchPlaceholder': 'Por favor, insira o nome do modelo para pesquisar', + 'agentTemplateManagement.search': 'Pesquisar', + 'agentTemplateManagement.serialNumber': 'Número de Série', + 'agentTemplateManagement.selectAll': 'Selecionar Tudo', + 'agentTemplateManagement.deselectAll': 'Desmarcar Tudo', + 'agentTemplateManagement.loading': 'Carregando...', + 'agentTemplateManagement.confirmSingleDelete': 'Tem certeza de que deseja excluir este modelo?', + 'agentTemplateManagement.confirmBatchDelete': 'Tem certeza de que deseja excluir os {count} modelos selecionados?', + 'agentTemplateManagement.deleteFailed': 'Falha ao excluir modelo', + 'agentTemplateManagement.batchDeleteFailed': 'Falha na exclusão em lote de modelos', + 'agentTemplateManagement.deleteBackendError': 'Falha na exclusão. Verifique se o serviço de backend está funcionando normalmente', + + // Configuração rápida de modelo + 'templateQuickConfig.title': 'Configuração Rápida de Módulo', + 'templateQuickConfig.agentSettings.agentName': 'Apelido', + 'templateQuickConfig.agentSettings.agentNamePlaceholder': 'Por favor, insira o apelido', + 'templateQuickConfig.agentSettings.systemPrompt': 'Introdução', + 'templateQuickConfig.agentSettings.systemPromptPlaceholder': 'Por favor, insira a introdução', + 'templateQuickConfig.saveConfig': 'Salvar Configuração', + 'templateQuickConfig.resetConfig': 'Redefinir Configuração', + 'templateQuickConfig.saveSuccess': 'Configuração salva com sucesso', + 'templateQuickConfig.resetSuccess': 'Configuração redefinida com sucesso', + 'templateQuickConfig.confirmReset': 'Tem certeza de que deseja redefinir a configuração?', + 'templateQuickConfig.saveFailed': 'Falha ao salvar configuração', + 'templateQuickConfig.confirm': 'Confirmar', + 'templateQuickConfig.cancel': 'Cancelar', + 'templateQuickConfig.templateNotFound': 'Modelo não encontrado', + 'templateQuickConfig.newTemplate': 'Novo Modelo', + 'warning': 'Aviso', + 'info': 'Informação', + 'common.networkError': 'Falha na requisição de rede', + + // Criptografia SM2 + 'sm2.publicKeyNotConfigured': 'Chave pública SM2 não configurada. Por favor, entre em contato com o administrador', + 'sm2.encryptionFailed': 'Falha na criptografia da senha', + 'sm2.keyGenerationFailed': 'Falha na geração do par de chaves', + 'sm2.invalidPublicKey': 'Formato de chave pública inválido', + 'sm2.encryptionError': 'Ocorreu um erro durante a criptografia', + 'sm2.publicKeyRetry': 'Tentando obter a chave pública novamente...', + 'sm2.publicKeyRetryFailed': 'Falha na nova tentativa de obtenção da chave pública', + + // Clonagem de Voz e Gerenciamento de Recursos + 'voiceClone.title': 'Clonagem de Voz', + 'voiceResource.title': 'Recurso de Voz', + 'voiceClone.platformName': 'Nome da Plataforma', + 'voiceClone.voiceId': 'ID da Voz', + 'voiceClone.userId': 'Proprietário da Conta', + 'voiceClone.name': 'Nome da Voz', + 'voiceClone.clone': 'Clonar Voz', + 'voiceClone.action': 'Ação', + 'voiceClone.modelId': 'ID do Modelo', + 'voiceClone.trainStatus': 'Status do Treinamento', + 'voiceClone.trainError': 'Erro de Treinamento', + 'voiceClone.createdAt': 'Data de Criação', + 'voiceClone.search': 'Pesquisar', + 'voiceClone.searchPlaceholder': 'Por favor, insira o nome da voz ou ID da voz', + 'voiceClone.addNew': 'Adicionar', + 'voiceClone.delete': 'Excluir', + 'voiceClone.selectAll': 'Selecionar Tudo', + 'voiceClone.deselectAll': 'Desmarcar Tudo', + 'voiceClone.addVoiceClone': 'Adicionar Recurso de Voz', + 'voiceClone.confirmDelete': 'Tem certeza de que deseja excluir os {count} recursos de voz selecionados?', + 'voiceClone.deleteSuccess': '{count} recursos de voz excluídos com sucesso', + 'voiceClone.deleteFailed': 'Falha na exclusão', + 'voiceClone.addSuccess': 'Adicionado com sucesso', + 'voiceClone.addFailed': 'Falha ao adicionar', + 'voiceClone.updateSuccess': 'Atualizado com sucesso', + 'voiceClone.updateFailed': 'Falha na atualização', + 'voiceClone.selectFirst': 'Por favor, selecione recursos de voz para excluir primeiro', + 'voiceClone.operationCancelled': 'Cancelar', + 'voiceClone.operationClosed': 'Popup fechado', + 'voiceClone.cloneSuccess': 'Clonado com sucesso', + 'voiceClone.cloneFailed': 'Falha ao clonar', + 'voiceClone.confirmClone': 'Tem certeza de que deseja clonar esta voz?', + 'voiceClone.onlySuccessCanClone': 'Apenas vozes treinadas com sucesso podem ser clonadas', + 'common.insufficient': 'Insuficiente', + 'voiceClone.platformNameRequired': 'Por favor, selecione o nome da plataforma', + 'voiceClone.voiceIdRequired': 'Por favor, selecione o ID da voz', + 'voiceClone.userIdRequired': 'Por favor, selecione o proprietário da conta', + 'voiceClone.platformNamePlaceholder': 'Por favor, selecione o nome da plataforma', + 'voiceClone.voiceIdPlaceholder': 'Por favor, insira o ID da voz e pressione Enter', + 'voiceClone.userIdPlaceholder': 'Por favor, insira palavra-chave para selecionar o proprietário da conta', + 'voiceClone.waitingUpload': 'Aguardando envio', + 'voiceClone.waitingTraining': 'Aguardando clonagem', + 'voiceClone.training': 'Treinando', + 'voiceClone.trainSuccess': 'Treinamento bem-sucedido', + 'voiceClone.trainFailed': 'Treinamento falhou', + 'voiceClone.itemsPerPage': '{items} itens/página', + 'voiceClone.firstPage': 'Primeira Página', + 'voiceClone.prevPage': 'Página Anterior', + 'voiceClone.nextPage': 'Próxima Página', + 'voiceClone.totalRecords': '{total} registros no total', + 'voiceClone.noVoiceCloneAssigned': 'Sua conta não possui recursos de voz atribuídos', + 'voiceClone.contactAdmin': 'Por favor, entre em contato com o administrador para atribuição de recursos de voz', + 'voiceClone.dialogTitle': 'Clonagem de Voz', + 'voiceClone.stepUpload': 'Preparar Áudio', + 'voiceClone.stepEdit': 'Editar Áudio', + 'voiceClone.dragOrClick': 'Arraste o arquivo de áudio aqui ou clique para enviar', + 'voiceClone.uploadTip': 'Suporta todos os formatos de áudio principais. A duração selecionada deve ser entre 8 e 60 segundos', + 'voiceClone.editTip1': 'Por favor, confirme se o áudio enviado está satisfatório', + 'voiceClone.editTip2': 'Você pode ouvir e cortar o áudio. Se não estiver satisfeito, pode voltar para regravar ou reenviar', + 'voiceClone.selectedDuration': 'Segmento válido selecionado: {duration} segundos', + 'voiceClone.trim': 'Cortar segmento selecionado', + 'voiceClone.reset': 'Redefinir', + 'voiceClone.play': 'Reproduzir', + 'voiceClone.pause': 'Pausar', + 'voiceClone.stop': 'Parar', + 'voiceClone.cancel': 'Cancelar', + 'voiceClone.warning': 'Aviso', + 'voiceClone.ok': 'OK', + 'voiceClone.nextStep': 'Próximo', + 'voiceClone.prevStep': 'Anterior', + 'voiceClone.upload': 'Enviar Áudio', + 'voiceClone.pleaseSelectAudio': 'Por favor, selecione um arquivo de áudio primeiro', + 'voiceClone.durationError': 'A duração do áudio deve ser entre 8 e 60 segundos', + 'voiceClone.loadAudioFailed': 'Falha ao carregar áudio', + 'voiceClone.trimSuccess': 'Corte realizado com sucesso', + 'voiceClone.resetSuccess': 'Redefinido com sucesso', + 'voiceClone.uploadSuccess': 'Enviado com sucesso', + 'voiceClone.uploadFailed': 'Falha no envio', + 'voiceClone.updateNameSuccess': 'Nome atualizado com sucesso', + 'voiceClone.updateNameFailed': 'Falha ao atualizar nome', + 'voiceClone.playFailed': 'Falha na reprodução', + 'voiceClone.Details': 'Detalhes do Erro', + + // Página de gerenciamento da Base de Conhecimento + 'knowledgeBaseManagement.title': 'Base de Conhecimento', + 'knowledgeBaseManagement.searchPlaceholder': 'Por favor, insira o nome da base de conhecimento para pesquisar', + 'knowledgeBaseManagement.search': 'Pesquisar', + 'knowledgeBaseManagement.name': 'Nome da Base de Conhecimento', + 'knowledgeBaseManagement.description': 'Descrição da Base de Conhecimento', + 'knowledgeBaseManagement.documentCount': 'Quantidade de Documentos', + 'knowledgeBaseManagement.status': 'Ativado', + 'knowledgeBaseManagement.createdAt': 'Data de Criação', + 'knowledgeBaseManagement.operation': 'Operação', + 'knowledgeBaseManagement.add': 'Adicionar', + 'knowledgeBaseManagement.delete': 'Excluir', + 'knowledgeBaseManagement.edit': 'Editar', + 'knowledgeBaseManagement.itemsPerPage': 'itens/página', + 'knowledgeBaseManagement.firstPage': 'Primeira Página', + 'knowledgeBaseManagement.prevPage': 'Página Anterior', + 'knowledgeBaseManagement.nextPage': 'Próxima Página', + 'knowledgeBaseManagement.totalRecords': 'Total de {total} registros', + 'knowledgeBaseManagement.addKnowledgeBase': 'Adicionar Base de Conhecimento', + 'knowledgeBaseManagement.editKnowledgeBase': 'Editar Base de Conhecimento', + 'knowledgeBaseManagement.getKnowledgeBaseListFailed': 'Falha ao obter lista de bases de conhecimento', + 'knowledgeBaseManagement.selectKnowledgeBaseFirst': 'Por favor, selecione bases de conhecimento para excluir primeiro', + 'knowledgeBaseManagement.confirmBatchDelete': 'Tem certeza de que deseja excluir as {count} bases de conhecimento selecionadas?', + 'knowledgeBaseManagement.batchDeleteSuccess': '{count} bases de conhecimento excluídas com sucesso', + 'knowledgeBaseManagement.deleteFailed': 'Falha ao excluir. Por favor, tente novamente', + 'knowledgeBaseManagement.operationCancelled': 'Operação de exclusão foi cancelada', + 'knowledgeBaseManagement.updateSuccess': 'Atualizado com sucesso', + 'knowledgeBaseManagement.addSuccess': 'Adicionado com sucesso', + 'knowledgeBaseManagement.updateFailed': 'Falha na atualização', + 'knowledgeBaseManagement.addFailed': 'Falha ao adicionar', + 'knowledgeBaseManagement.selectAll': 'Selecionar Tudo', + 'knowledgeBaseManagement.cancelSelectAll': 'Desmarcar Tudo', + + // Diálogo da Base de Conhecimento + 'knowledgeBaseDialog.title': 'Base de Conhecimento', + 'knowledgeBaseDialog.name': 'Nome da Base de Conhecimento', + 'knowledgeBaseDialog.namePlaceholder': 'Por favor, insira o nome da base de conhecimento com precisão para melhorar a acurácia da chamada da base de conhecimento', + 'knowledgeBaseDialog.description': 'Descrição da Base de Conhecimento', + 'knowledgeBaseDialog.descriptionPlaceholder': 'Por favor, insira a descrição da base de conhecimento com precisão para ajudar o modelo a entender melhor o conteúdo', + 'knowledgeBaseDialog.ragModel': 'Modelo RAG', + 'knowledgeBaseDialog.ragModelPlaceholder': 'Por favor, selecione o modelo RAG', + 'knowledgeBaseDialog.ragModelRequired': 'Por favor, selecione o modelo RAG', + 'knowledgeBaseDialog.loadRAGModelsFailed': 'Falha ao carregar lista de modelos RAG', + 'knowledgeBaseDialog.status': 'Status', + 'knowledgeBaseDialog.statusEnabled': 'Ativado', + 'knowledgeBaseDialog.statusDisabled': 'Desativado', + 'knowledgeBaseDialog.save': 'Salvar', + 'knowledgeBaseDialog.cancel': 'Cancelar', + 'knowledgeBaseDialog.confirm': 'Confirmar', + 'knowledgeBaseDialog.requiredName': 'Por favor, insira o nome da base de conhecimento', + 'knowledgeBaseDialog.nameRequired': 'Por favor, insira o nome da base de conhecimento', + 'knowledgeBaseDialog.nameLength': 'O nome da base de conhecimento deve ter entre 1 e 50 caracteres', + 'knowledgeBaseDialog.namePattern': 'O nome da base de conhecimento pode conter apenas caracteres chinêses, inglêses, números, espaços, sublinhados e hífens', + 'knowledgeBaseDialog.descriptionLength': 'A descrição da base de conhecimento não pode exceder 200 caracteres', + 'knowledgeBaseDialog.nameLengthLimit': 'O nome da base de conhecimento não pode exceder 50 caracteres', + 'knowledgeBaseDialog.descriptionLengthLimit': 'A descrição da base de conhecimento não pode exceder 200 caracteres', + + // Botão de visualização na página de gerenciamento da base de conhecimento + 'knowledgeBaseManagement.view': 'Gerenciar Arquivos', + + // Página de upload de arquivos da base de conhecimento + 'knowledgeFileUpload.back': 'Voltar', + 'knowledgeFileUpload.searchPlaceholder': 'Por favor, insira o nome do documento para pesquisar', + 'knowledgeFileUpload.search': 'Pesquisar', + 'knowledgeFileUpload.addDocument': 'Adicionar Documento', + 'knowledgeFileUpload.documentName': 'Nome do Documento', + 'knowledgeFileUpload.uploadTime': 'Data de Envio', + 'knowledgeFileUpload.status': 'Status', + 'knowledgeFileUpload.operation': 'Operação', + 'knowledgeFileUpload.parse': 'Analisar', + 'knowledgeFileUpload.viewSlices': 'Ver Fatias', + 'knowledgeFileUpload.delete': 'Excluir', + 'knowledgeFileUpload.itemsPerPage': 'itens/página', + 'knowledgeFileUpload.firstPage': 'Primeira Página', + 'knowledgeFileUpload.prevPage': 'Página Anterior', + 'knowledgeFileUpload.nextPage': 'Próxima Página', + 'knowledgeFileUpload.totalRecords': 'Total de {total} registros', + 'knowledgeFileUpload.uploadDocument': 'Enviar Documento', + 'knowledgeFileUpload.documentNamePlaceholder': 'Por favor, insira o nome do documento', + 'knowledgeFileUpload.file': 'Arquivo', + 'knowledgeFileUpload.clickToUpload': 'Clique para enviar', + 'knowledgeFileUpload.uploadTip': 'Tipos de arquivo suportados: PDF, DOC, DOCX, TXT, MD, CSV, XLS, XLSX, PPT, PPTX. Máximo de 32 arquivos por envio, cada arquivo com até 10MB', + 'knowledgeFileUpload.dragOrClick': 'Arraste o arquivo aqui ou clique para enviar', + 'knowledgeFileUpload.cancel': 'Cancelar', + 'knowledgeFileUpload.confirm': 'Confirmar', + 'knowledgeFileUpload.knowledgeBaseName': 'Nome da Base de Conhecimento', + 'knowledgeFileUpload.statusNotStarted': 'Não Iniciado', + 'knowledgeFileUpload.statusProcessing': 'Processando', + 'knowledgeFileUpload.statusCancelled': 'Cancelado', + 'knowledgeFileUpload.statusCompleted': 'Concluído', + 'knowledgeFileUpload.statusFailed': 'Falhou', + 'knowledgeFileUpload.uploadSuccess': 'Documento enviado com sucesso', + 'knowledgeFileUpload.uploadFailed': 'Falha no envio do documento', + 'knowledgeFileUpload.parseSuccess': 'Documento analisado com sucesso', + 'knowledgeFileUpload.parseFailed': 'Falha na análise do documento', + 'knowledgeFileUpload.deleteSuccess': 'Documento excluído com sucesso', + 'knowledgeFileUpload.deleteFailed': 'Falha ao excluir documento', + 'knowledgeFileUpload.confirmDelete': 'Tem certeza de que deseja excluir este documento?', + 'knowledgeFileUpload.confirmParse': 'Tem certeza de que deseja analisar este documento?', + 'knowledgeFileUpload.nameRequired': 'Por favor, insira o nome do documento', + 'knowledgeFileUpload.fileRequired': 'Por favor, selecione um arquivo para enviar', + 'knowledgeFileUpload.getListFailed': 'Falha ao obter lista de documentos', + 'knowledgeFileUpload.parseCancelled': 'Análise cancelada', + 'knowledgeFileUpload.deleteCancelled': 'Exclusão cancelada', + 'knowledgeFileUpload.selectFilesFirst': 'Por favor, selecione arquivos para excluir primeiro', + 'knowledgeFileUpload.selectAll': 'Selecionar Tudo', + 'knowledgeFileUpload.deselectAll': 'Desmarcar Tudo', + 'knowledgeFileUpload.batchDelete': 'Excluir', + 'knowledgeFileUpload.confirmBatchDelete': 'Tem certeza de que deseja excluir os {count} arquivos selecionados?', + 'knowledgeFileUpload.batchDeleteSuccess': '{count} arquivos excluídos com sucesso', + 'knowledgeFileUpload.batchDeleteFailed': 'Falha na exclusão em lote', + 'knowledgeFileUpload.sliceCount': 'Quantidade de Fatias', + 'knowledgeFileUpload.add': 'Adicionar', + 'knowledgeFileUpload.retrievalTest': 'Teste de Recuperação', + 'knowledgeFileUpload.testQuestion': 'Pergunta de Teste', + 'knowledgeFileUpload.testQuestionPlaceholder': 'Por favor, insira a pergunta para testar', + 'knowledgeFileUpload.executeTest': 'Executar Teste', + 'knowledgeFileUpload.testResult': 'Resultado do Teste:', + 'knowledgeFileUpload.selectedFiles': 'Arquivos Selecionados', + 'knowledgeFileUpload.totalSlices': 'Total de {total} registros', + 'knowledgeFileUpload.slice': 'Fatia', + 'knowledgeFileUpload.noSliceData': 'Não há dados de fatia disponíveis', + 'knowledgeFileUpload.firstPage': 'Primeira', + 'knowledgeFileUpload.prevPage': 'Anterior', + 'knowledgeFileUpload.nextPage': 'Próxima', + 'knowledgeFileUpload.totalRecords': 'Total de {total} registros', + 'knowledgeFileUpload.testQuestion': 'Pergunta de Teste', + 'knowledgeFileUpload.testQuestionPlaceholder': 'Por favor, insira a pergunta para testar', + 'knowledgeFileUpload.runTest': 'Executar Teste', + 'knowledgeFileUpload.testResult': 'Resultado do Teste:', + 'knowledgeFileUpload.noRelatedSlices': 'Nenhuma fatia relacionada encontrada', + 'knowledgeFileUpload.comprehensiveSimilarity': 'Similaridade Geral', + 'knowledgeFileUpload.content': 'Conteúdo:', + 'knowledgeFileUpload.testQuestionRequired': 'Por favor, insira a pergunta de teste', + 'knowledgeBaseDialog.descriptionRequired': 'Por favor, insira a descrição da base de conhecimento', + + // Página de gerenciamento de funcionalidades + 'featureManagement.selectAll': 'Selecionar Tudo', + 'featureManagement.deselectAll': 'Desmarcar Tudo', + 'featureManagement.save': 'Salvar Configuração', + 'featureManagement.reset': 'Redefinir', + 'featureManagement.group.featureManagement': 'Ativar/Desativar a funcionalidade/seção', + 'featureManagement.group.voiceManagement': 'Visível para usuários durante a configuração do agente', + 'featureManagement.noFeatures': 'Nenhuma funcionalidade disponível', + 'featureManagement.contactAdmin': 'Por favor, entre em contato com o administrador para configurar funcionalidades', + 'featureManagement.saveSuccess': 'Configuração de funcionalidades salva com sucesso', + 'featureManagement.resetConfirm': 'Tem certeza de que deseja redefinir todas as configurações de funcionalidades?', + 'featureManagement.confirm': 'Confirmar', + 'featureManagement.cancel': 'Cancelar', + 'featureManagement.resetSuccess': 'Configuração de funcionalidades redefinida com sucesso', + 'featureManagement.noChanges': 'Nenhuma alteração para salvar', + + // Nomes e descrições de funcionalidades + 'feature.voiceprintRecognition.name': 'Reconhecimento de Impressão Vocal', + 'feature.voiceprintRecognition.description': 'Verificar a identidade do usuário através da tecnologia de reconhecimento de impressão vocal, proporcionando uma experiência segura de interação por voz', + 'feature.voiceClone.name': 'Clonagem de Voz', + 'feature.voiceClone.description': 'Clonar timbres de voz específicos usando tecnologia de IA para obter síntese de voz personalizada', + 'feature.knowledgeBase.name': 'Base de Conhecimento', + 'feature.knowledgeBase.description': 'Construir e gerenciar sistema de base de conhecimento para fornecer suporte de conhecimento profissional aos assistentes de IA', + 'feature.mcpAccessPoint.name': 'Ponto de Acesso MCP', + 'feature.mcpAccessPoint.description': 'Fornecer pontos de acesso do protocolo MCP para suportar integração de ferramentas e serviços externos', + 'feature.vad.name': 'Detecção de Atividade de Voz', + 'feature.vad.description': 'Detectar automaticamente atividade de voz para otimizar a eficiência de resposta da interação por voz', + 'feature.asr.name': 'Reconhecimento de Fala', + 'feature.asr.description': 'Converter fala em texto para habilitar a funcionalidade de interação por linguagem natural', + +} diff --git a/main/manager-web/src/i18n/vi.js b/main/manager-web/src/i18n/vi.js index 5fc17c24..6e678e25 100644 --- a/main/manager-web/src/i18n/vi.js +++ b/main/manager-web/src/i18n/vi.js @@ -663,6 +663,7 @@ export default { 'language.en': 'English', 'language.de': 'Deutsch', 'language.vi': 'Tiếng Việt', + 'language.ptBR': 'Português (Brasil)', // Home page text 'home.addAgent': 'Thêm tác nhân', diff --git a/main/manager-web/src/i18n/zh_CN.js b/main/manager-web/src/i18n/zh_CN.js index ef1c8511..c5e59611 100644 --- a/main/manager-web/src/i18n/zh_CN.js +++ b/main/manager-web/src/i18n/zh_CN.js @@ -663,6 +663,7 @@ export default { 'language.en': 'English', 'language.de': 'Deutsch', 'language.vi': 'Tiếng Việt', + 'language.ptBR': 'Português (Brasil)', // 首页文本 'home.addAgent': '添加智能体', diff --git a/main/manager-web/src/i18n/zh_TW.js b/main/manager-web/src/i18n/zh_TW.js index 6744f094..9794c64c 100644 --- a/main/manager-web/src/i18n/zh_TW.js +++ b/main/manager-web/src/i18n/zh_TW.js @@ -663,6 +663,7 @@ export default { 'language.en': 'English', 'language.de': 'Deutsch', 'language.vi': 'Tiếng Việt', + 'language.ptBR': 'Português (Brasil)', // 首頁文本 'home.addAgent': '添加智能體', diff --git a/main/manager-web/src/views/login.vue b/main/manager-web/src/views/login.vue index 0edbd2e5..a52aac19 100644 --- a/main/manager-web/src/views/login.vue +++ b/main/manager-web/src/views/login.vue @@ -55,6 +55,9 @@ {{ $t("language.vi") }} + + {{ $t("language.ptBR") }} + @@ -188,6 +191,8 @@ export default { return this.$t("language.de"); case "vi": return this.$t("language.vi"); + case "pt_BR": + return this.$t("language.ptBR"); default: return this.$t("language.zhCN"); } diff --git a/main/manager-web/src/views/retrievePassword.vue b/main/manager-web/src/views/retrievePassword.vue index 5241c2c0..75a50b10 100644 --- a/main/manager-web/src/views/retrievePassword.vue +++ b/main/manager-web/src/views/retrievePassword.vue @@ -137,6 +137,8 @@ export default { return require("@/assets/xiaozhi-ai_de.png"); case "vi": return require("@/assets/xiaozhi-ai_vi.png"); + case "pt_BR": + return require("@/assets/xiaozhi-ai_en.png"); default: return require("@/assets/xiaozhi-ai.png"); }