From b754d55d93fcab91478cab2706cbba06b5ef838e Mon Sep 17 00:00:00 2001 From: Eliezer Castro Date: Tue, 29 Jul 2025 12:17:43 -0300 Subject: [PATCH] feat: add support for Portuguese language (pt-BR) (#260) --- frontend/config/selection.ts | 1 + frontend/messages/pt-BR.json | 321 +++++++++++++++++++++++++++++++++++ frontend/src/i18n/routing.ts | 2 +- frontend/src/middleware.ts | 2 +- frontend/types/locale.ts | 2 +- 5 files changed, 325 insertions(+), 3 deletions(-) create mode 100644 frontend/messages/pt-BR.json diff --git a/frontend/config/selection.ts b/frontend/config/selection.ts index 7005610..a74fb6e 100644 --- a/frontend/config/selection.ts +++ b/frontend/config/selection.ts @@ -12,6 +12,7 @@ const categoricalPalette = ['#fba91e', '#6ea56c', '#3ac6e1', '#feda2f', '#f15f47 const locales: LocaleType[] = [ { code: 'en', name: 'English' }, { code: 'ja', name: '日本語' }, + { code: 'pt-BR', name: 'Português' }, ]; // The status of each test run diff --git a/frontend/messages/pt-BR.json b/frontend/messages/pt-BR.json new file mode 100644 index 0000000..ff7afec --- /dev/null +++ b/frontend/messages/pt-BR.json @@ -0,0 +1,321 @@ +{ + "RunStatus": { + "new": "Novo", + "inProgress": "Em progresso", + "underReview": "Em revisão", + "rejected": "Rejeitado", + "done": "Concluído", + "closed": "Fechado" + }, + "RunCaseStatus": { + "untested": "Não testado", + "passed": "Aprovado", + "failed": "Reprovado", + "retest": "Retestar", + "skipped": "Ignorado" + }, + "Priority": { + "critical": "Crítico", + "high": "Alto", + "medium": "Médio", + "low": "Baixo" + }, + "Type": { + "other": "Outro", + "security": "Segurança", + "performance": "Desempenho", + "accessibility": "Acessibilidade", + "functional": "Funcional", + "acceptance": "Aceitação", + "usability": "Usabilidade", + "smoke_sanity": "Smoke & Sanity", + "compatibility": "Compatibilidade", + "destructive": "Destrutivo", + "regression": "Regressão", + "automated": "Automatizado", + "manual": "Manual" + }, + "ProjectDialog": { + "project": "Projeto", + "project_name": "Nome do Projeto", + "project_detail": "Detalhe do Projeto", + "public": "Público", + "private": "Privado", + "if_you_make_public": "Tornar um projeto público o torna visível para usuários que não são membros do projeto.", + "close": "Fechar", + "create": "Criar", + "update": "Atualizar", + "please_enter": "Por favor, insira o nome do projeto" + }, + "Index": { + "get_started": "Comece Agora", + "demo": "Demonstração", + "oss_tcms": "Sistema de Gerenciamento de Casos de Teste de Código Aberto", + "integrate_and_manage": "Integre e gerencie todos os seus testes de software.", + "oss_title": "Código Aberto", + "oss_detail": "O UnitTCMS é gratuito e de código aberto. A aplicação pode ser auto-hospedada. Pode ser implantada em ambientes com requisitos de segurança rigorosos.", + "organize_title": "Organize Casos de Teste", + "organize_detail": "Os casos de teste podem ser organizados por projetos e pastas. A estrutura de UI moderna os torna rápidos.", + "usability_title": "Usabilidade", + "usability_detail": "Os casos de teste definidos podem ser usados repetidamente em execuções de teste. O status das execuções de teste e dos projetos pode ser visualizado graficamente.", + "universal_title": "Universal", + "universal_detail": "O suporte a vários idiomas e o tema escuro permitem que qualquer pessoa use o sistema sem qualquer inconveniente.", + "project_title": "Baseado em Projetos", + "project_subtitle": "Gerencie casos de teste e execuções de teste projeto por projeto. Nosso painel oferece uma visão geral dos tipos de casos de teste e seu progresso para cada projeto. Isso permite que você monitore o status do projeto em tempo real e gerencie com eficiência.", + "case_management_title": "Gerenciamento de Casos de Teste", + "case_management_subtitle": "Crie pastas dentro de projetos e defina casos de teste com facilidade usando nossa UI moderna e intuitiva. Anexar arquivos permite explicações detalhadas dos casos de teste, facilitando o compartilhamento de informações com toda a equipe.", + "run_management_title": "Gerenciamento de Execuções de Teste", + "run_management_subtitle": "Os casos de teste definidos podem ser reutilizados várias vezes em execuções de teste, permitindo ciclos de teste eficientes. Além disso, você pode monitorar visualmente o status das execuções de teste e dos projetos.", + "member_management_title": "Gerenciamento de Membros", + "member_management_subtitle": "Apoie o desenvolvimento da equipe adicionando ou removendo membros de projetos. Você pode atribuir funções e definir permissões para cada membro em detalhes. Oferecemos três funções principais: 'Gerente', que gerencia todo o projeto, 'Desenvolvedor', que projeta os testes, e 'Relator', que executa os testes." + }, + "Header": { + "title": "Sistema de Gerenciamento de Casos de Teste de Código Aberto", + "description": "Integre e gerencie todos os seus testes de software", + "docs": "Documentação", + "roadmap": "Roteiro", + "projects": "Projetos", + "admin": "Administração", + "account": "Conta", + "signup": "Cadastre-se", + "signin": "Entrar", + "signout": "Sair", + "links": "Links", + "languages": "Idiomas" + }, + "Toast": { + "need_signed_in": "Você precisa fazer login", + "session_expired": "Sessão expirada" + }, + "Auth": { + "account": "Conta", + "signup": "Cadastre-se", + "signin": "Entrar", + "or_signup": "Você precisa se cadastrar?", + "or_signin": "Você precisa entrar?", + "signin_as_guest": "Ou entre como Convidado", + "email": "E-mail", + "username": "Nome de usuário", + "password": "Senha", + "confirm_password": "Senha (confirmação)", + "invalid_email": "E-mail inválido", + "invalid_password": "A senha deve ter pelo menos 8 caracteres", + "username_empty": "O nome de usuário está vazio", + "password_empty": "A senha está vazia", + "password_not_match": "A senha não corresponde", + "email_already_exist": "E-mail já cadastrado", + "email_not_exist": "Endereço de e-mail não encontrado", + "signup_error": "Falha no cadastro", + "signin_error": "Falha no login", + "demo_page_warning": "Este é um ambiente de demonstração, quaisquer dados que você inserir serão redefinidos periodicamente.", + "your_projects": "Seus Projetos", + "public": "Público", + "private": "Privado", + "not_own_any_projects": "Você não possui nenhum projeto.", + "find_projects": "Encontrar projetos" + }, + "Health": { + "health_check": "Verificação de Saúde", + "status": "Status", + "ok": "OK", + "error": "Erro", + "api_server": "Servidor da API", + "unittcms_version": "Versão do UnitTCMS" + }, + "Admin": { + "user_management": "Gerenciamento de Usuários", + "avatar": "Avatar", + "id": "ID", + "email": "E-mail", + "username": "Nome de usuário", + "role": "Função", + "administrator": "Administrador", + "user": "Usuário", + "no_users_found": "Nenhum usuário encontrado", + "quit_admin": "Sair da Administração", + "close": "Fechar", + "quit": "Sair", + "quit_confirm": "Se você renunciar aos seus privilégios de administrador, não poderá mais acessar a página de administração.", + "role_changed": "Função alterada", + "lost_admin_auth": "Perdeu a autoridade de administrador", + "at_least": "É necessário pelo menos um administrador" + }, + "Projects": { + "project_list": "Lista de Projetos", + "new_project": "Novo Projeto", + "id": "ID", + "publicity": "Publicidade", + "public": "Público", + "private": "Privado", + "name": "Nome", + "detail": "Detalhe", + "last_update": "Última atualização", + "no_projects_found": "Nenhum projeto encontrado" + }, + "Project": { + "project": "Projeto", + "home": "Início", + "test_cases": "Casos de Teste", + "test_runs": "Execuções de Teste", + "members": "Membros", + "settings": "Configurações" + }, + "Home": { + "home": "Início", + "Folders": "Pastas", + "test_cases": "Casos de Teste", + "test_runs": "Execuções de Teste", + "progress": "Progresso", + "test_classification": "Classificação de Teste", + "by_type": "Por tipo de teste", + "by_priority": "Por prioridade de teste" + }, + "Folders": { + "folder": "Pasta", + "new_folder": "Nova Pasta", + "edit_folder": "Editar Pasta", + "delete_folder": "Excluir Pasta", + "folder_name": "Nome da Pasta", + "folder_detail": "Detalhe da Pasta", + "close": "Fechar", + "create": "Criar", + "update": "Atualizar", + "please_enter": "Por favor, insira o nome da pasta", + "delete": "Excluir", + "are_you_sure": "Tem certeza de que deseja excluir a pasta?", + "no_folders_found": "Nenhuma pasta encontrada" + }, + "Cases": { + "test_case_list": "Lista de Casos de Teste", + "id": "ID", + "title": "Título", + "priority": "Prioridade", + "actions": "Ações", + "delete_case": "Excluir caso de teste", + "delete": "Excluir", + "close": "Fechar", + "are_you_sure": "Tem certeza de que deseja excluir os casos de teste?", + "new_test_case": "Novo Caso de Teste", + "export": "Exportar", + "status": "Status", + "no_cases_found": "Nenhum caso de teste encontrado", + "case_title": "Título do Caso de Teste", + "case_description": "Descrição do Caso de Teste", + "create": "Criar", + "please_enter": "Por favor, insira o título do caso de teste" + }, + "Case": { + "back_to_cases": "Voltar para os casos de teste", + "updating": "Atualizando...", + "update": "Atualizar", + "updated_test_case": "Caso de teste atualizado", + "basic": "Básico", + "title": "Título", + "please_enter_title": "Por favor, insira o título", + "description": "Descrição", + "test_case_description": "Descrição do caso de teste", + "priority": "Prioridade", + "type": "Tipo", + "template": "Modelo", + "test_detail": "Detalhe do teste", + "preconditions": "Pré-condições", + "expected_result": "Resultado esperado", + "step": "Passo", + "text": "Texto", + "steps": "Passos", + "new_step": "Novo Passo", + "details_of_the_step": "Detalhes do passo", + "delete_this_step": "Excluir este passo", + "insert_step": "Inserir passo", + "attachments": "Anexos", + "delete": "Excluir", + "download": "Baixar", + "delete_file": "Excluir arquivo", + "click_to_upload": "Clique para enviar", + "or_drag_and_drop": " ou arraste e solte", + "max_file_size": "Tamanho máx. do arquivo", + "are_you_sure_leave": "Tem certeza de que deseja sair da página?" + }, + "Runs": { + "run_list": "Lista de Execuções de Teste", + "run": "Execução", + "new_run": "Nova Execução", + "edit_run": "Editar Execução", + "delete_run": "Excluir Execução", + "id": "ID", + "name": "Nome", + "description": "Descrição", + "last_update": "Última atualização", + "actions": "Ações", + "run_name": "Nome da execução", + "run_description": "Descrição da execução", + "no_runs_found": "Nenhuma execução encontrada", + "close": "Fechar", + "create": "Criar", + "update": "Atualizar", + "please_enter": "Por favor, insira o nome da execução", + "are_you_sure": "Tem certeza de que deseja excluir a execução?", + "delete": "Excluir" + }, + "Run": { + "back_to_runs": "Voltar para as execuções de teste", + "updating": "Atualizando...", + "update": "Atualizar", + "updated_test_run": "Execução de teste atualizada", + "export": "Exportar", + "progress": "Progresso", + "refresh": "Atualizar", + "id": "ID", + "title": "Título", + "please_enter": "Por favor, insira o nome da execução", + "description": "Descrição", + "priority": "Prioridade", + "status": "Status", + "actions": "Ações", + "select_test_case": "Selecionar casos de teste", + "test_case_selection": "Seleção de casos de teste", + "include_in_run": "Incluir na execução", + "exclude_from_run": "Excluir da execução", + "no_cases_found": "Nenhum caso encontrado", + "are_you_sure_leave": "Tem certeza de que deseja sair da página?", + "type": "Tipo", + "test_detail": "Detalhe do teste", + "steps": "Passos", + "preconditions": "Pré-condições", + "expected_result": "Resultado esperado", + "details_of_the_step": "Detalhes do passo", + "close": "Fechar" + }, + "Members": { + "member_management": "Gerenciamento de Membros", + "avatar": "Avatar", + "email": "E-mail", + "username": "Nome de usuário", + "role": "Função", + "manager": "Gerente", + "developer": "Desenvolvedor", + "reporter": "Relator", + "delete": "Excluir", + "deleteMember": "Excluir membro", + "no_members_found": "Nenhum membro encontrado", + "add_member": "Adicionar membro", + "user_name_or_email": "Nome de usuário ou e-mail", + "close": "Fechar", + "add": "Adicionar", + "are_you_sure": "Tem certeza de que deseja excluir o membro?" + }, + "Settings": { + "project_management": "Gerenciamento de Projetos", + "project_name": "Nome do Projeto", + "project_detail": "Detalhe do Projeto", + "project_owner": "Dono do Projeto", + "edit_project": "Editar Projeto", + "publicity": "Publicidade", + "public": "Público", + "private": "Privado", + "delete_project": "Excluir Projeto", + "delete": "Excluir", + "close": "Fechar", + "are_you_sure": "Tem certeza de que deseja excluir o projeto?" + } +} diff --git a/frontend/src/i18n/routing.ts b/frontend/src/i18n/routing.ts index e377d19..e7fca45 100644 --- a/frontend/src/i18n/routing.ts +++ b/frontend/src/i18n/routing.ts @@ -2,7 +2,7 @@ import { createNavigation } from 'next-intl/navigation'; import { defineRouting } from 'next-intl/routing'; export const routing = defineRouting({ - locales: ['en', 'ja'], + locales: ['en', 'ja', 'pt-BR'], defaultLocale: 'en', localePrefix: { mode: 'always', diff --git a/frontend/src/middleware.ts b/frontend/src/middleware.ts index c7943ef..e781684 100644 --- a/frontend/src/middleware.ts +++ b/frontend/src/middleware.ts @@ -4,5 +4,5 @@ import { routing } from './i18n/routing'; export default createMiddleware(routing); export const config = { - matcher: ['/', '/(ja|en)/:path*'], + matcher: ['/', '/(ja|en|pt-BR)/:path*'], }; diff --git a/frontend/types/locale.ts b/frontend/types/locale.ts index e3b790a..04ded07 100644 --- a/frontend/types/locale.ts +++ b/frontend/types/locale.ts @@ -1,4 +1,4 @@ -export type LocaleCodeType = 'en' | 'ja'; +export type LocaleCodeType = 'en' | 'ja' | 'pt-BR'; export type LocaleType = { code: LocaleCodeType;