diff --git a/web/src/components/features/settings/composables/useSettingsHub.ts b/web/src/components/features/settings/composables/useSettingsHub.ts index 4af82aa..a41e5b3 100644 --- a/web/src/components/features/settings/composables/useSettingsHub.ts +++ b/web/src/components/features/settings/composables/useSettingsHub.ts @@ -15,6 +15,7 @@ const LANGUAGE_OPTIONS = [ { label: 'Русский', value: 'ru' }, { label: 'Deutsch', value: 'de' }, { label: 'Español', value: 'es' }, + { label: 'Português do Brasil', value: 'ptBR' }, ] export function useSettingsHub() { diff --git a/web/src/locales/index.ts b/web/src/locales/index.ts index 3b32067..a647279 100644 --- a/web/src/locales/index.ts +++ b/web/src/locales/index.ts @@ -2,14 +2,16 @@ import de from './de' import en from './en' import es from './es' import ru from './ru' +import ptBR from './ptBR' export const messages = { en, ru, de, es, + ptBR } export type Locale = keyof typeof messages -export const locales: Locale[] = ['en', 'ru', 'de', 'es'] +export const locales: Locale[] = ['en', 'ru', 'de', 'es', 'ptBR'] export const defaultLocale: Locale = 'en' diff --git a/web/src/locales/ptBR.ts b/web/src/locales/ptBR.ts new file mode 100644 index 0000000..b5fbccb --- /dev/null +++ b/web/src/locales/ptBR.ts @@ -0,0 +1,1190 @@ +export default { + auth: { + welcome: 'Bem-vindo de volta', + signInToAccount: 'Entre na sua conta', + continueWithGoogle: 'Continuar com Google', + continueWithGithub: 'Continuar com GitHub', + continueWithApple: 'Continuar com Apple', + orContinueWith: 'Ou continuar com', + magicLink: 'Link mágico', + password: 'Senha', + termsText: 'Ao continuar, você concorda com nossos', + termsOfService: 'Termos de Serviço', + and: 'e', + privacyPolicy: 'Política de Privacidade', + + // Login by code + email: 'E-mail', + emailPlaceholder: 'você{\'@\'}examplo.com.br', + sendCode: 'Enviar código', + codeSent: 'Código enviado', + checkInbox: 'Verifique sua caixa de entrada em {email}', + enterCode: 'Digite o código de 6 dígitos enviado para', + verificationCode: 'Código de verificação', + verifyAndSignIn: 'Verificar e entrar', + back: 'Voltar', + resendCode: 'Reenviar código', + codeResent: 'Código reenviado', + newCodeSent: 'Novo código enviado para {email}', + + // Login by password + login: 'Login', + loginPlaceholder: 'Nome de usuário ou e-mail', + passwordLabel: 'Senha', + passwordPlaceholder: 'Sua senha', + forgotPassword: 'Esqueceu a senha?', + signIn: 'Entrar', + + // Forgot password + forgotPasswordTitle: 'Redefinir senha', + forgotPasswordDescription: 'Digite seu endereço de e-mail e enviaremos um link para redefinir sua senha.', + sendResetLink: 'Enviar link de redefinição', + backToLogin: 'Voltar para o login', + checkYourEmail: 'Verifique seu e-mail', + resetLinkSent: 'Enviamos um link para redefinir sua senha para', + emailSent: 'E-mail enviado', + checkInboxForReset: 'Verifique sua caixa de entrada para encontrar o link de redefinição de senha', + + // Reset password + setNewPassword: 'Definir nova senha', + setNewPasswordDescription: 'Digite uma nova senha para sua conta.', + newPassword: 'Nova senha', + newPasswordPlaceholder: 'Digite a nova senha', + confirmPassword: 'Confirmar senha', + confirmPasswordPlaceholder: 'Repita a nova senha', + resetPassword: 'Redefinir senha', + passwordReset: 'Senha redefinida', + passwordResetSuccess: 'Sua senha foi alterada com sucesso. Agora você pode entrar.', + invalidResetLink: 'Link inválido', + invalidResetLinkDescription: 'O link de redefinição de senha é inválido ou expirou.', + canNotResetPassword: 'Não foi possível redefinir a senha. Tente novamente.', + passwordTooShort: 'A senha deve ter pelo menos 6 caracteres', + passwordsDoNotMatch: 'As senhas não coincidem', + + // Messages + success: 'Sucesso', + error: 'Erro', + loggedIn: 'Bem-vindo ao TaskView', + invalidCode: 'Código inválido. Tente novamente.', + invalidCredentials: 'Login ou senha inválidos', + loginFailed: 'Falha ao entrar. Tente novamente.', + failedToSendCode: 'Falha ao enviar o código. Tente novamente.', + registrationDisabled: 'O cadastro está desativado neste servidor. Peça a um administrador para convidar você.', + failedToResendCode: 'Falha ao reenviar o código', + failedToSendResetLink: 'Falha ao enviar o link de redefinição. Tente novamente.', + tooManyAttempts: 'Muitas tentativas malsucedidas. Aguarde alguns minutos antes de tentar novamente.', + + // SSO + ssoSignIn: 'Entrar com SSO', + ssoNotFound: 'SSO não configurado', + ssoNotFoundDescription: 'Nenhum provedor de SSO encontrado para o domínio {domain}', + ssoError: 'Falha na autenticação SSO. Tente novamente.', + ssoDomainUnverified: 'O SSO não estará disponível até que a organização verifique este domínio de e-mail.', + ssoEmailInUse: 'Este e-mail já é usado por outra conta do TaskView.', + + // Validation + invalidEmail: 'Endereço de e-mail inválido', + loginRequired: 'O login é obrigatório', + passwordRequired: 'A senha é obrigatória', + codeMustBe6: 'O código deve ter 6 caracteres', + }, + projects: { + title: 'Projetos', + project: 'Projeto', + selectProject: 'Selecionar projeto', + edit: 'Editar projeto', + name: 'Nome', + namePlaceholder: 'Digite o nome do projeto', + description: 'Descrição', + descriptionPlaceholder: 'Digite a descrição do projeto', + estimateUnit: 'Unidade de estimativa', + estimateUnitHours: 'Horas', + estimateUnitPoints: 'Pontos de história', + deleteConfirm: 'Excluir projeto', + deleteMessage: 'Tem certeza de que deseja excluir o projeto "{name}"? Todo o histórico do projeto será excluído, incluindo o histórico de alterações de tarefas e listas. Esta ação não pode ser desfeita.', + addPlaceholder: 'Digite o nome do projeto', + createNew: 'Criar novo projeto', + add: 'Adicionar projeto', + empty: 'Nenhum projeto ainda', + inbox: 'Caixa de entrada', + }, + contextMenu: { + tasks: 'Tarefas', + kanban: 'Kanban', + graph: 'Gráfico', + sprints: 'Sprints', + collaboration: 'Colaboração', + integrations: 'Integrações', + webhooks: 'Webhooks', + messaging: 'Mensageiros', + timeReports: 'Relatórios de tempo', + edit: 'Editar', + moveToArchive: 'Mover para o arquivo', + restoreFromArchive: 'Restaurar do arquivo', + delete: 'Excluir', + }, + archive: { + title: 'Arquivo', + }, + lists: { + title: 'Listas', + selectList: 'Selecionar uma lista', + selectListToViewTasks: 'Selecione uma lista para ver as tarefas', + addPlaceholder: 'Digite o nome da lista', + add: 'Adicionar lista', + edit: 'Editar lista', + name: 'Nome', + namePlaceholder: 'Digite o nome da lista', + deleteConfirm: 'Excluir lista', + deleteMessage: 'Tem certeza de que deseja excluir a lista "{name}"? A lista será excluída, incluindo seu histórico de edições, bem como todas as tarefas da lista e seu histórico. Esta ação não pode ser desfeita.', + }, + common: { + cancel: 'Cancelar', + save: 'Salvar', + edit: 'Editar', + delete: 'Excluir', + done: 'Concluído', + yes: 'Sim', + no: 'Não', + loading: 'Carregando...', + close: 'Fechar', + add: 'Adicionar', + }, + kanban: { + title: 'Kanban', + description: 'Visualização do quadro Kanban em breve', + addColumn: 'Adicionar coluna', + addTask: 'Adicionar tarefa', + edit: 'Editar', + delete: 'Excluir', + deleteColumn: 'Excluir coluna', + deleteColumnConfirm: 'Tem certeza de que deseja excluir esta coluna? As tarefas serão movidas para o Backlog.', + editColumn: 'Editar coluna', + columnName: 'Nome da Coluna', + loadMore: 'Carregar mais', + sprintFilter: { + all: 'Todas as tarefas', + current: 'Sprint atual', + }, + }, + msg: { + allTasks: 'Backlog', + tools: 'Ferramentas', + tasks: 'Tarefas', + todayTasks: 'Hoje', + upcomingTasks: 'Próximas', + lastTasks: 'Tarefas recentes', + todayExplanation: 'Tarefas com prazo para hoje ou antes', + upcomingExplanation: 'Tarefas com prazo em futuro próximo', + lastAddedTasksExplanation: 'Tarefas adicionadas recentemente sem prazo', + lastCompletedTasksExplanation: 'Tarefas concluídas recentemente', + pending: 'Ativas', + completed: 'Concluídas', + noTasks: 'Nenhuma tarefa', + addTask: 'Adicionar tarefa', + addTaskToToday: 'Adicionar tarefa para hoje', + addTaskToUpcoming: 'Adicionar próxima tarefa', + groupByDate: 'Agrupar por data', + showAsList: 'Mostrar como lista', + noDeadline: 'Sem data', + addFirstProject: 'Adicione seu primeiro projeto', + today: 'Hoje', + lastAddedTasks: 'Adicionadas', + lastCompletedTasks: 'Concluídas', + }, + admin: { + search: 'Pesquisar tarefas...', + }, + motivationToday: [ + 'Ótimo dia para produtividade!', + 'Hoje é o seu dia!', + 'Comece com algo pequeno!', + 'Cada tarefa é um passo à frente!', + ], + motivationUpcoming: [ + 'Planeje com antecedência!', + 'O futuro está em suas mãos!', + 'Prepare-se para o sucesso!', + 'Coisas emocionantes pela frente!', + ], + deadline: { + startDate: 'Data de início', + endDate: 'Data de término', + selectTime: 'Selecionar horário', + selectRange: 'Selecionar período', + today: 'Hoje', + tomorrow: 'Amanhã', + yesterday: 'Ontem', + thisWeek: 'Esta semana', + thisMonth: 'Este mês', + }, + recurrence: { + title: 'Repetir', + noRepeat: 'Não repetir', + paused: 'Pausado', + ended: 'Encerrado', + skip: 'Pular ocorrência', + pause: 'Pausar', + resume: 'Retomar', + deleteSeries: 'Excluir série', + selectTime: 'Selecionar horário', + notifyOnOccurrence: 'Lembrar de cada ocorrência', + preview: 'Próximas ocorrências', + repeatEvery: 'Repetir a cada', + startDate: 'Data de início', + specifyTime: 'Especificar horário', + occurrenceTime: 'Horário da ocorrência', + datesCount: '{n} datas', + previewFooterTime: '{period} · às {time}', + previewApprox: 'Datas aproximadas — as datas reais dependem do dia de conclusão', + mode: { + title: 'Próxima ocorrência', + fixed: 'Em uma programação', + afterCompletion: 'Após a conclusão', + hint: 'A próxima tarefa é criada um intervalo após a atual ser realmente concluída', + }, + frequency: { + daily: 'Diariamente', + weekly: 'Semanalmente', + monthly: 'Mensalmente', + yearly: 'Anualmente', + }, + freqShort: { + none: 'Nenhum', + daily: 'Dia', + weekly: 'Semana', + monthly: 'Mês', + yearly: 'Ano', + }, + units: { + daily: 'dias', + weekly: 'semanas', + monthly: 'meses', + yearly: 'anos', + }, + summary: { + daily: 'Diariamente', + weekly: 'Semanalmente', + monthly: 'Mensalmente', + yearly: 'Anualmente', + everyN: 'A cada {n} {unit}', + afterCompletion: 'após a conclusão', + }, + weekdays: { + mon: 'Seg', + tue: 'Ter', + wed: 'Qua', + thu: 'Qui', + fri: 'Sex', + sat: 'Sáb', + sun: 'Dom', + }, + monthly: { + dayOfMonth: 'No dia {day}', + lastDay: 'No último dia do mês', + }, + ends: { + title: 'Termina', + never: 'Nunca', + after: 'Após N ocorrências', + onDate: 'Na data', + pickDate: 'Escolher uma data', + }, + toasts: { + saved: 'Recorrência salva', + skipped: 'Ocorrência ignorada', + deleted: 'Série excluída', + }, + }, + graph: { + title: 'Gráfico', + description: 'A visualização em gráfico estará disponível em breve', + addTask: 'Adicionar tarefa', + selectedEdge: 'Conexão selecionada', + }, + collaboration: { + title: 'Colaboração', + description: 'Collaboration features coming soon', + selectProject: 'Selecione um projeto para gerenciar a colaboração', + tabs: { + members: 'Membros', + roles: 'Funções', + }, + members: { + title: 'Membros da equipe', + add: 'Adicionar membro', + invite: 'Adicionar membro', + email: 'Endereço de e-mail', + emailPlaceholder: 'convidado{\'@\'}examplo.com.br', + sendInvite: 'Enviar convite', + pending: 'Pendente', + owner: 'Proprietário', + invitedAt: 'Convidado', + noRoles: 'Nenhuma função atribuída', + assignRoles: 'Atribuir funções', + selectRoles: 'Selecione as funções deste membro', + resendInvite: 'Reenviar convite', + remove: 'Remover membro', + empty: 'Nenhum membro da equipe ainda. Adicione alguém para colaborar!', + }, + roles: { + title: 'Funções', + create: 'Criar função', + name: 'Nome da função', + namePlaceholder: 'Digite o nome da função', + permissionsCount: '{count} permissões', + system: 'Sistema', + assignPermissions: 'Atribuir permissões', + systemRoleWarning: 'As funções do sistema não podem ser modificadas', + deleteConfirm: 'Excluir função', + deleteMessage: 'Tem certeza de que deseja excluir "{name}"? Os membros com esta função precisarão ser reatribuídos.', + empty: 'Nenhuma função personalizada ainda. Crie uma para definir permissões específicas.', + }, + permissions: { + searchPlaceholder: 'Pesquisar permissões...', + groups: { + tasks: 'Tarefas', + lists: 'Listas', + members: 'Membros', + roles: 'Funções', + }, + view_tasks: 'Visualizar tarefas', + view_tasksDesc: 'Pode visualizar tarefas no projeto', + create_tasks: 'Criar tarefas', + create_tasksDesc: 'Pode criar novas tarefas', + edit_tasks: 'Editar tarefas', + edit_tasksDesc: 'Pode editar tarefas existentes', + delete_tasks: 'Excluir tarefas', + delete_tasksDesc: 'Pode excluir tarefas', + view_lists: 'Visualizar listas', + view_listsDesc: 'Pode visualizar listas no projeto', + create_lists: 'Criar listas', + create_listsDesc: 'Pode criar novas listas', + edit_lists: 'Editar listas', + edit_listsDesc: 'Pode editar listas existentes', + delete_lists: 'Excluir listas', + delete_listsDesc: 'Pode excluir listas', + view_members: 'Visualizar membros', + view_membersDesc: 'Pode visualizar membros do projeto', + invite_members: 'Convidar membros', + invite_membersDesc: 'Pode convidar novos membros', + remove_members: 'Remover membros', + remove_membersDesc: 'Pode remover membros do projeto', + view_roles: 'Visualizar funções', + view_rolesDesc: 'Pode visualizar funções', + manage_roles: 'Gerenciar funções', + manage_rolesDesc: 'Pode criar, editar e excluir funções', + }, + }, + integrations: { + title: 'Integrações', + selectProject: 'Selecione um projeto para gerenciar integrações', + add: 'Adicionar integração', + addTitle: 'Conectar repositório', + connectDescription: 'Escolha um provedor para conectar seu repositório.', + provider: 'Provedor', + repoFullName: 'Repositório', + repoPlaceholder: 'dono/repositório', + empty: 'Ainda não há integrações. Conecte um repositório GitHub ou GitLab para sincronizar problemas.', + selectRepo: 'Selecionar Repositório', + searchRepos: 'Pesquisar repositórios...', + noReposFound: 'Nenhum repositório encontrado', + pendingSelectRepo: 'Repositório não selecionado', + private: 'Privado', + syncFailed: 'Falha na sincronização da issue', + syncFailedDescription: 'Não foi possível atualizar o problema no repositório remoto. Use o botão de sincronização na página de integrações para tentar novamente.', + sync: 'Sincronizar', + syncing: 'Sincronizando...', + }, + messaging: { + title: 'Integrações de mensageiros', + tabs: { + personal: 'Pessoal', + project: 'Projeto', + }, + personalHint: 'Receba mensagens diretas sobre suas tarefas em todos os seus projetos. Essa conexão é pessoal – ela se aplica a todos os lugares em que você trabalha, não apenas a este projeto.', + projectHint: 'Publique eventos do projeto em um grupo ou canal compartilhado.', + personalEmpty: 'Ainda não há integrações pessoais. Conecte o Telegram para receber notificações.', + projectEmpty: 'Ainda não há integrações de projeto. Conecte um grupo para postar eventos do projeto.', + selectProject: 'Selecione um projeto para gerenciar suas integrações com mensageiros.', + noAccess: 'Você não tem permissão para visualizar integrações deste projeto.', + connect: 'Conectar', + connectTitle: 'Conectar um mensageiro', + connectDescription: 'Escolha um mensageiro para conectar.', + telegram: 'Telegram', + slack: 'Slack', + soon: 'Em breve', + getLink: 'Obter link', + continueWithSlack: 'Continuar com Slack', + openInTelegram: 'Abrir no Telegram', + addBotToGroup: 'Adicionar bot ao grupo', + command: 'Em seguida, envie este comando no grupo:', + personalInstructions: 'Abra o bot no Telegram e pressione Iniciar para vincular sua conta.', + projectInstructions: 'Adicione o bot ao seu grupo e envie o comando abaixo nesse grupo para conectá-lo.', + connectedOn: 'Conectado em {date}', + disconnect: 'Desconectar', + disconnectConfirm: 'Tem certeza de que deseja desconectar esta integração? As notificações deixarão de ser entregues aqui.', + notConfigured: 'Este mensageiro não está configurado no servidor.', + connectFailed: 'Não foi possível criar o link de conexão.', + postContent: 'Envie a descrição da tarefa para o canal', + postContentHint: 'Desligado é mais seguro: o canal é compartilhado, então as descrições ignoram as permissões de conteúdo por usuário. Somente o título e o link da tarefa são postados quando desativados.', + eventsTitle: 'Eventos', + eventsDescription: 'Escolha quais eventos serão enviados para esta conexão.', + eventsCount: '{count} eventos', + showMoreEvents: 'Mostrar mais eventos', + showLessEvents: 'Mostrar menos eventos', + eventGroups: { + tasks: 'Tarefas', + sprints: 'Sprints', + members: 'Membros', + time: 'Controle de tempo', + recurrence: 'Regras recorrentes', + }, + eventLabels: { + taskCreated: 'Tarefa criada', + taskAssigned: 'Tarefa atribuída', + taskStatusChanged: 'Status da tarefa alterado', + taskCompleted: 'Tarefa concluída', + taskEdited: 'Tarefa editada', + taskAddedToSprint: 'Tarefa adicionada ao sprint', + taskDeleted: 'Tarefa excluída', + sprintCreated: 'Sprint criado', + sprintUpdated: 'Sprint editado', + sprintStarted: 'Sprint iniciado', + sprintReviewStarted: 'Revisão do sprint iniciada', + sprintCompleted: 'Sprint concluída', + sprintPaused: 'Sprint pausada', + sprintResumed: 'Sprint retomada', + sprintDeleted: 'Sprint excluída', + memberAdded: 'Membro adicionado', + memberRemoved: 'Membro removido', + memberRolesChanged: 'Funções do membro alteradas', + timeStarted: 'Cronômetro iniciado', + timeStopped: 'Cronômetro parado', + timeLogged: 'Tempo registrado', + timeUpdated: 'Registro de tempo editado', + timeDeleted: 'Registro de tempo excluído', + recurrenceCreated: 'Recorrência criada', + recurrenceUpdated: 'Recorrência editada', + recurrencePaused: 'Recorrência pausada', + recurrenceResumed: 'Recorrência retomada', + recurrenceEnded: 'Recorrência encerrada', + recurrenceDeleted: 'Recorrência excluída', + recurrenceSkipped: 'Ocorrência ignorada', + }, + }, + webhooks: { + title: 'Webhooks', + selectProject: 'Selecione um projeto para gerenciar webhooks', + add: 'Adicionar Webhook', + empty: 'Nenhum webhook ainda. Adicione um webhook para receber notificações de eventos.', + url: 'URL', + urlPlaceholder: 'https://examplo.com.br/webhook', + events: 'Eventos', + selectEvents: 'Selecionar eventos', + test: 'Testar', + deliveries: 'Entregas', + noDeliveries: 'Nenhuma entrega ainda', + rotateSecret: 'Renovar segredo', + secretTitle: 'Segredo do Webhook', + secretDescription: 'Copie este segredo e armazene-o com segurança. Não será mostrado novamente.', + event: 'Evento', + status: 'Status', + httpCode: 'Código HTTP', + attempts: 'Tentativas', + time: 'Horário', + payload: 'Payload', + viewPayload: 'Visualizar payload', + copy: 'Copiar', + edit: 'Editar', + allStatuses: 'Todos os status', + rotateConfirm: 'Tem certeza de que deseja alternar o segredo? O segredo atual deixará de funcionar imediatamente e todos os consumidores do webhook precisarão ser atualizados com o novo segredo.', + }, + main: 'Principal', + mainScreen: { + welcome: 'Bem-vindo', + selectProject: 'Selecione um projeto na barra lateral para começar', + }, + tasks: { + amount: 'Valor', + enterAmount: 'Digite o valor', + noTransactionType: 'Tipo de transação', + income: 'Receita', + expense: 'Despesa', + allTasks: 'Todas as tarefas', + addPlaceholder: 'Digite o nome da tarefa', + searchPlaceholder: 'Pesquisar tarefas...', + add: 'Adicionar tarefa', + details: 'Detalhes da tarefa', + description: 'Descrição', + addDescription: 'Adicione uma descrição...', + note: 'Observação', + addNote: 'Adicione uma observação...', + sourceOfTruthTitle: '{provider} é a fonte da verdade', + sourceOfTruthDescription: 'Esta tarefa está vinculada a um problema em {provider}. Se o título ou a descrição forem editados ali, a tarefa será atualizada automaticamente.', + priority: 'Prioridade', + priorityNone: 'Sem prioridade', + priorityLow: 'Baixa', + priorityMedium: 'Média', + priorityHigh: 'Alta', + priorityLowDesc: 'Pode esperar', + priorityMediumDesc: 'Importância normal', + priorityHighDesc: 'Urgente, faça primeiro', + dueDate: 'Data de vencimento', + deadline: 'Prazo', + addDueDate: 'Adicionar data de vencimento', + assignees: 'Responsáveis', + selectAssignees: 'Selecionar responsáveis', + searchUsers: 'Pesquisar usuários...', + noUsersAvailable: 'Nenhum usuário disponível', + list: 'Lista', + selectList: 'Selecionar lista', + searchLists: 'Pesquisar listas...', + noList: 'Nenhuma lista', + sprintNone: 'Nenhum sprint', + sprintUpdateFailed: 'Falha ao atualizar o sprint', + estimatePlaceholder: 'Pontos de história', + fields: { + sprint: 'Sprint', + estimate: 'Estimativa', + }, + status: 'Status', + selectStatus: 'Selecionar status', + searchStatuses: 'Pesquisar status...', + noStatus: 'Nenhum status', + tags: 'Tags', + addTag: 'Adicionar tag', + subtasks: 'Subtarefas', + addSubtask: 'Adicionar subtarefa', + notFound: 'Tarefa não encontrada', + copyId: 'Copiar ID da tarefa', + idCopied: 'ID da tarefa copiado', + noTasks: 'Nenhuma tarefa', + showCompleted: 'Mostrar concluídas', + hideCompleted: 'Ocultar concluídas', + sortNewestFirst: 'Mais recentes primeiro', + sortOldestFirst: 'Mais antigas primeiro', + sortBy: 'Ordenar por', + sortByDate: 'Data de criação', + sortByPriority: 'Prioridade', + sortHighestFirst: 'Maior primeiro', + sortLowestFirst: 'Menor primeiro', + deleteConfirm: 'Excluir tarefa', + deleteMessage: 'Tem certeza de que deseja excluir "{name}"? Esta ação não pode ser desfeita.', + }, + tags: { + createTag: 'Criar tag', + createNamed: 'Criar «{name}»', + editTag: 'Editar tag', + name: 'Nome', + namePlaceholder: 'Nome da tag', + color: 'Cor', + preview: 'Pré-visualização', + tagName: 'Nome da tag', + searchPlaceholder: 'Pesquisar tags...', + noTagsFound: 'Nenhuma tag encontrada', + noTagsAssigned: 'Nenhuma tag atribuída', + manageTags: 'Gerenciar', + deleteConfirm: 'Delete Tag', + deleteMessage: 'Tem certeza de que deseja excluir "{name}"? Esta ação não pode ser desfeita.', + }, + priority: { + low: 'Baixa', + medium: 'Média', + high: 'Alta', + }, + history: { + title: 'Histórico de alterações', + show: 'Mostrar histórico', + hide: 'Ocultar histórico', + empty: 'Nenhum histórico de alterações', + changed: 'Alterado', + restore: 'Restaurar', + details: 'Detalhes da alteração', + completeTrue: 'Concluídas', + completeFalse: 'Não concluída', + fields: { + note: 'Observação', + description: 'Descrição', + complete: 'Status de conclusão', + priority: 'Prioridade', + list: 'Lista', + endDate: 'Due date', + startDate: 'Data de início', + }, + }, + filters: { + title: 'Filtros', + assignee: 'Responsável', + selectAssignee: 'Selecionar responsável', + allUsers: 'Todos os usuários', + reset: 'Redefinir', + apply: 'Aplicar', + }, + userMenu: { + profile: 'Perfil', + appearance: 'Aparência', + light: 'Claro', + dark: 'Escuro', + language: 'Idioma', + taskDetailView: 'Visualização dos detalhes da tarefa', + taskDetailSlideover: 'Painel lateral', + taskDetailModal: 'Diálogo', + sidebarView: 'Visualização da barra lateral', + sidebarViewSecond: 'Compacta', + sidebarViewFirst: 'Clássica', + site: 'Site', + documentation: 'Documentação', + github: 'Repositório do GitHub', + docker: 'Imagens Docker', + accountSettings: 'Configurações da conta', + uiCustomization: 'Personalização da interface', + organizations: 'Organizações', + analytics: 'Análises', + timeReports: 'Relatórios de tempo', + switchOrganization: 'Trocar organização', + logout: 'Sair', + logoutFailed: 'Falha ao sair', + logoutFailedDescription: 'Tente limpar o cache do navegador para remover o token de autorização', + }, + settings: { + title: 'Configurações', + account: 'Conta', + appearance: 'Aparência', + layout: 'Layout', + about: 'Sobre', + system: 'Sistema', + version: 'Versão', + }, + analytics: { + page: { + title: 'Análises', + subtitle: 'Métricas de produtividade e saúde dos projetos', + emptyState: 'Ainda não há dados. Crie tarefas para visualizar as análises.', + emptyStateForPeriod: 'Não há dados para o período selecionado. Tente um período maior.', + partialFailure: 'Algumas seções não foram carregadas. Tente atualizar a página.', + }, + errors: { + forbidden: 'Você não tem acesso a essas análises.', + network: 'Não foi possível acessar o servidor. Verifique sua conexão.', + server: 'O servidor retornou um erro. Tente atualizar a página.', + unknown: 'Falha ao carregar análises.', + }, + help: { + aria: 'Ajuda para esta métrica', + }, + chartTypes: { + line: 'Linha', + bar: 'Barras', + area: 'Área', + stackedBar: 'Empilhado', + stackedArea: 'Área empilhada', + horizontalBar: 'Horiz.', + donut: 'Rosca', + histogram: 'Histograma', + radar: 'Radar', + }, + units: { + days: 'd', + hours: 'h', + }, + priorities: { + low: 'Baixa', + medium: 'Média', + high: 'Alta', + }, + filters: { + periods: { + month: 'Este mês', + '7d': '7 dias', + '30d': '30 dias', + '90d': '90 dias', + '180d': 'Trimestre', + '365d': 'Ano', + custom: 'Período personalizado', + }, + scopes: { + org: 'Toda a organização', + }, + }, + drillDown: { + defaultTitle: 'Tarefas', + empty: 'Nenhuma tarefa nesta seleção', + denied: 'Você não tem permissão para visualizar detalhes de tarefas individuais', + noTaskTitle: 'Sem título', + due: 'vence', + created: 'criada', + closed: 'encerrada', + }, + sectionCard: { + noData: 'Não há dados para o período selecionado', + }, + }, + account: { + title: 'Configurações da conta', + nav: 'Configurações', + management: 'Gerenciamento da conta', + deleteAccount: 'Excluir conta', + deleteConfirm: 'Tem certeza de que deseja excluir a conta e todos os dados associados?', + deleteWarning: 'Todos os dados associados a esta conta serão excluídos! Esta ação não pode ser desfeita!', + enterCode: 'Digite o código do e-mail', + confirm: 'Confirmar', + cancel: 'Cancelar', + deleted: 'Conta excluída', + codeSendError: 'Não foi possível enviar o código. Entre em contato com o suporte para excluir sua conta.', + password: 'Senha', + passwordDescription: 'Defina ou altere a senha que você usa para fazer login com seu e-mail. Enviaremos um código de confirmação para seu e-mail.', + passwordDescriptionByPassword: 'Altere a senha que você usa para fazer login. Confirme a alteração com sua senha atual.', + sendPasswordCode: 'Enviar código de confirmação', + confirmPasswordChange: 'Confirmar alteração de senha', + passwordCodeSent: 'Enviamos um código de confirmação para seu e-mail. Digite-o abaixo para definir a nova senha.', + changePassword: 'Alterar senha', + passwordChanged: 'Senha alterada', + passwordChangeError: 'Não foi possível atualizar a senha. Verifique o código e tente novamente.', + passwordCodeCooldown: 'Código já enviado. Tente novamente em um minuto.', + passwordCodeSendError: 'Não foi possível enviar o código. Tente novamente mais tarde.', + defaultCredsTitle: 'Login e e-mail', + defaultCredsWarning: 'As credenciais de login padrão são conhecidas publicamente', + defaultCredsDescription: 'Sua conta usa as credenciais pré-instaladas. Defina seu próprio login, e-mail e senha — você precisará fazer login novamente após salvar.', + newLogin: 'Novo login', + newLoginPlaceholder: 'Letras, digitos, . _ -', + newEmail: 'Novo e-mail', + currentPassword: 'Senha atual', + currentPasswordPlaceholder: 'Digite sua senha atual', + currentPasswordRequired: 'Digite sua senha atual', + loginInvalid: 'O login deve ter de 3 a 64 caracteres', + saveCredentials: 'Salvar e sair', + credentialsChanged: 'Credenciais atualizadas. Entre com o novo login e senha.', + credentialsChangeError: 'Não foi possível atualizar as credenciais. Tente novamente.', + wrongPassword: 'Senha incorreta', + loginTaken: 'Este login já está em uso', + emailTaken: 'Este e-mail já está em uso', + }, + organizations: { + title: 'Organizações', + create: 'Criar organização', + name: 'Nome', + namePlaceholder: 'ex. Meu Time', + slug: 'Slug', + slugPlaceholder: 'meu-time', + members: 'Membros', + addMember: 'Adicionar membro', + email: 'E-mail', + role: 'Função', + owner: 'Proprietário', + admin: 'Administrador', + member: 'Membro', + remove: 'Remover', + delete: 'Excluir organização', + deleteConfirm: 'Tem certeza de que deseja excluir esta organização e todos os seus projetos?', + empty: 'Nenhuma organização ainda', + currentOrg: 'Organização atual', + active: 'Ativas', + settings: 'Configurações', + general: 'Geral', + save: 'Salvar', + created: 'Organização criada', + updated: 'Organização atualizada', + deleted: 'Organização excluída', + memberAdded: 'Membro adicionado', + memberRemoved: 'Membro removido', + roleUpdated: 'Função atualizada', + close: 'Fechar', + slugTaken: 'Este slug já está em uso', + personal: 'Este é seu espaço de trabalho pessoal', + personalHint: 'Criado automaticamente junto com sua conta. Não pode ser excluído.', + }, + uiCustomization: { + title: 'Personalização da interface', + description: 'Alterne a visibilidade e reordene itens nas seções do aplicativo. Arraste pela alça à esquerda para reordenar. Todos os itens disponíveis são mostrados aqui — as verificações de permissão se aplicam ao site de renderização e ainda podem ocultar um item mesmo quando ativado.', + show: 'Mostrar', + hide: 'Ocultar', + narrow: 'Estreito', + wide: 'Largo', + empty: 'Nenhum item para personalizar', + sections: { + analyticsIndicators: 'Analytics — Indicadores', + analyticsCharts: 'Analytics — Gráficos', + tasks: 'Tarefas', + others: 'Others', + }, + others: { + weekStart: 'Primeiro dia da semana', + weekStartHint: 'Aplica-se a todos os seletores de data do calendário.', + weekStartDefault: 'Padrão', + monday: 'Segunda-feira', + tuesday: 'Terça-feira', + wednesday: 'Quarta-feira', + thursday: 'Quinta-feira', + friday: 'Sexta-feira', + saturday: 'Sábado', + sunday: 'Domingo', + defaultProject: 'Projeto padrão', + defaultProjectHint: 'Abra este projeto logo após fazer login.', + defaultProjectNone: 'Tela inicial (padrão)', + defaultView: 'Visualização padrão', + defaultViewHint: 'Qual visualização do projeto padrão abrir.', + viewTasks: 'Tarefas', + viewKanban: 'Kanban', + viewGraph: 'Gráfico', + viewSprints: 'Sprints', + }, + taskFields: { + subtasks: 'Subtarefas', + note: 'Descrição', + status: 'Status', + priority: 'Prioridade', + assignees: 'Responsáveis', + list: 'Lista', + sprint: 'Sprint', + estimate: 'Estimativa', + tags: 'Tags', + deadline: 'Prazo', + amount: 'Valor', + timeTracking: 'Controle de tempo', + history: 'História', + }, + }, + sso: { + noConfig: 'O SSO não está configurado para esta organização', + configure: 'Configurar SSO', + protocol: 'Protocolo', + displayName: 'Nome do provedor', + displayNamePlaceholder: 'ex: Okta, Azure AD', + emailDomain: 'Domínio do e-mail', + metadataUrl: 'URL de metadados do IdP', + metadataUrlRequired: 'Insira a URL dos metadados', + metadataSynced: 'Metadados sincronizados com sucesso', + metadataSyncFailed: 'Falha ao sincronizar metadados', + sync: 'Sincronizar', + samlEntryPoint: 'IdP SSO URL', + samlIssuer: 'SP Entity ID', + samlCert: 'Certificado IdP', + samlCertPlaceholder: 'Cole o certificado público do IdP (formato PEM)', + samlCallbackUrl: 'ACS URL (Callback)', + samlLogoutUrl: 'IdP Logout URL (SLO)', + requestSigning: 'Assinatura de solicitação (enterprise)', + requestSigningDescription: 'Assine AuthnRequests SAML com uma chave privada. Exigido por alguns IdPs para maior segurança.', + generateKeysTitle: 'openssl req -x509 -newkey rsa:2048 -keyout sp-key.pem -out sp-cert.pem -days 3650 -nodes -subj "/CN=taskview"', + generateKeysHint: 'sp-key.pem → Private Key field. sp-cert.pem → Certificate field + upload to IdP.', + samlSigningKey: 'SP Private Key (PEM)', + samlSigningKeyPlaceholder: 'Cole sua PEM private key (-----BEGIN PRIVATE KEY-----...)', + samlSigningCert: 'Certificado SP (PEM)', + samlSigningCertPlaceholder: 'Cole seu certificado PEM (-----BEGIN CERTIFICATE-----...)', + secretConfigured: 'Vo valor está configurado (deixe em branco para manter o atual)', + secretAlreadySet: 'Configurado - deixe em branco para manter o valor atual', + oidcIssuer: 'URL do emissor', + oidcClientId: 'ID do cliente', + oidcClientSecret: 'Segredo do cliente', + oidcCallbackUrl: 'URL de Callback', + callbackUrlAutoHint: 'Deixe em branco para detectar automaticamente', + enabled: 'Ativado', + disabled: 'Desativado', + callbackUrlLabel: 'URL de Callback (use isso em seu IdP)', + copied: 'Copiado para a área de transferência', + copyFailed: 'Falha ao copiar', + create: 'Criar', + save: 'Salvar', + cancel: 'Cancelar', + created: 'Provedor SSO criado', + updated: 'Provedor SSO atualizado', + deleted: 'Provedor SSO excluído', + domainAlreadyExists: 'A configuração de SSO para este domínio já existe', + saveFailed: 'Falha ao salvar a configuração do SSO', + deleteFailed: 'Falha ao excluir a configuração de SSO', + fillRequired: 'Por favor preencha todos os campos obrigatórios', + domainVerification: 'Verificação de domínio', + domainVerificationDescription: 'Prove que você é o proprietário deste domínio de e-mail antes que os usuários possam fazer login com SSO.', + domainVerified: 'Verificado', + domainUnverified: 'Não verificado', + domainTrustedHint: 'Este domínio é confiável para o servidor (SSO_TRUSTED_DOMAINS).', + domainVerifyDns: 'DNS TXT record', + domainVerifyHttp: 'Ou hospede este arquivo', + domainVerifyHttpBody: 'Conteúdo do arquivo: {token}', + domainVerifyCheck: 'Verificar domínio', + domainVerifySuccess: 'Domínio verificado. O login via SSO está habilitado.', + domainVerifyFailed: 'Domínio ainda não verificado. Verifique o registro DNS TXT ou o arquivo well-known.', + }, + scim: { + description: 'Sincronizar automaticamente o ciclo de vida dos usuários a partir do seu IdP', + endpointUrl: 'SCIM Endpoint URL', + generateToken: 'Gerar token SCIM', + regenerateToken: 'Gerar novo token', + tokenWarning: 'Copie este token agora. Não será mostrado novamente.', + tokenGenerated: 'Token SCIM gerado', + tokenFailed: 'Falha ao gerar o token', + toggleFailed: 'Falha ao alternar o SCIM', + }, + apiTokens: { + title: 'Tokens de API', + description: 'Crie tokens para acessar a API programaticamente.', + add: 'Gerar novo token', + name: 'Nome do token', + namePlaceholder: 'ex: CI/CD, Mobile App', + expiration: 'Expiração', + noExpiration: 'Sem expiração', + days30: '30 dias', + days60: '60 dias', + days90: '90 dias', + year1: '1 ano', + projects: 'Projetos', + projectsHint: 'Restrinja o token a projetos específicos. Deixe em branco para acesso a todos os projetos.', + allProjects: 'Todos os projetos', + permissions: 'Permissões', + permissionsCount: 'permissões', + permissionsDocs: 'Saiba mais sobre permissões', + generate: 'Gerar token', + tokenCreated: 'Token criado', + tokenDescription: 'Copie este token agora. Não será mostrado novamente.', + lastUsed: 'Último uso', + never: 'Nunca', + expires: 'Expira', + deleteConfirm: 'Tem certeza de que deseja excluir este token? Quaisquer aplicativos que o utilizem perderão o acesso.', + empty: 'Ainda não há tokens de API.', + }, + sessions: { + title: 'Sessões ativas', + description: 'Gerencie suas sessões ativas. Você pode revogar o acesso de qualquer sessão, exceto a atual.', + current: 'Sessão atual', + lastUsed: 'Último uso', + created: 'Criada', + deleteConfirm: 'Tem certeza de que deseja encerrar esta sessão? O dispositivo será desconectado.', + deleteAll: 'Encerrar todas as outras sessões', + deleteAllConfirm: 'Tem certeza de que deseja encerrar todas as outras sessões? Todos os dispositivos, exceto o atual, serão desconectados.', + empty: 'Nenhuma outra sessão ativa.', + unknown: 'Dispositivo desconhecido', + }, + notifications: { + title: 'Notificações', + empty: 'Nenhuma notificação', + markAllRead: 'Marcar todas como lidas', + loadMore: 'Carregar mais', + settings: { + title: 'Configurações de notificações', + description: 'Escolha quais notificações deseja receber e como.', + push: 'Push', + websocket: 'In-app', + types: { + deadline: 'Prazos', + deadlineDescription: 'Quando o prazo da tarefa é atingido', + assign: 'Atribuir', + assignDescription: 'Quando você é atribuído para uma tarefa', + }, + saved: 'Configurações salvas', + }, + }, + server: { + selectServer: 'Servidor', + addServer: 'Adicionar servidor', + addNewServer: 'Adicionar novo servidor', + serverUrl: 'URL do servidor', + serverUrlHint: 'Insira o URL completo do servidor API, ex: https://api.examplo.com.br', + defaultServer: 'Servidor padrão', + }, + connection: { + offline: 'Sem conexão com a internet', + restored: 'Conexão restaurada', + reload: 'Recarregar', + }, + timeTracking: { + title: 'Controle de tempo', + empty: 'Nenhum registro de tempo ainda', + you: 'Você', + unknownUser: 'Usuário desconhecido', + start: 'Iniciar', + stop: 'Parar', + running: 'Em andamento', + addManual: 'Adicionar manualmente', + startedAt: 'Iniciado em', + endedAt: 'Encerrado em', + description: 'Descrição', + billable: 'Faturável', + save: 'Salvar', + cancel: 'Cancelar', + willStopOther: 'Iniciar fará o cronômetro atual de outra tarefa parar', + previousStopped: 'Cronômetro anterior parado', + previousStoppedDescription: 'Seu cronômetro anterior estava funcionando por {duration} e foi interrompido', + activeTimerTooltip: 'Clique para abrir a tarefa – ícone quadrado para parar', + autostopHours: 'Parar cronômetros automaticamente após (horas)', + autostopHint: 'Deixe em branco para desativar', + delete: 'Excluir', + deleteConfirmTitle: 'Excluir registro de tempo?', + deleteConfirm: 'Esta ação não pode ser desfeita.', + errors: { + generic: 'Falha na ação de controle de tempo', + forbidden: 'Você não tem permissão para esta ação', + notFound: 'Entrada de hora não encontrada', + validation: 'Dados de entrada inválidos', + network: 'Erro de rede. Verifique sua conexão.', + }, + reports: { + title: 'Relatórios de tempo', + allProjects: 'Todos os projetos', + allUsers: 'Todos os usuários', + clearUser: 'Limpar filtro de usuário', + billableOnly: 'Somente faturável', + openTask: 'Abrir tarefa', + kpiTotal: 'Tempo total', + kpiBillable: 'Faturável', + kpiEntries: 'Registros', + byTask: 'Por tarefa', + byUser: 'Por usuário', + byDay: 'Por dia', + colTask: 'Tarefa', + colUser: 'Usuário', + colDay: 'Dia', + colHours: 'Horário', + colEntries: 'Registros', + empty: 'Nenhum dado para os filtros selecionados', + recentEntries: 'Registros recentes', + noPermission: 'Você não tem permissão para visualizar relatórios de tempo', + noPermissionHint: 'Peça a um administrador do projeto permissão de visualização de controle de tempo para acessar relatórios.', + }, + }, + sprints: { + title: 'Sprints', + create: 'Nova sprint', + editTitle: 'Editar sprint', + empty: 'Nenhuma sprint ainda', + noActive: 'Nenhuma sprint ativo', + noPermission: 'Você não tem permissão para visualizar sprints', + paused: 'Pausada', + deleteConfirm: 'Excluir sprint "{name}"? Isto não pode ser desfeito.', + tabs: { + backlog: 'Backlog', + active: 'Ativas', + planned: 'Planejada', + completed: 'Concluídas', + }, + status: { + draft: 'Rascunho', + planned: 'Planejada', + active: 'Ativas', + review: 'Revisão', + completed: 'Concluídas', + }, + fields: { + name: 'Nome', + namePlaceholder: 'ex: Sprint 14', + goal: 'Objetivo da sprint', + goalPlaceholder: 'Como será o sucesso desta sprint', + startDate: 'Data de início', + endDate: 'Data de término', + capacity: 'Capacidade (SP)', + capacityPlaceholder: 'pontos de história', + estimate: 'Estimativa', + }, + units: { + points: 'story points', + pointsShort: 'SP', + hours: 'horas', + hoursShort: 'h', + }, + actions: { + activate: 'Ativar', + startReview: 'Iniciar revisão', + close: 'Encerrar sprint', + pause: 'Pausar', + resume: 'Retomar', + delete: 'Excluir', + saveRetro: 'Salvar retrospectiva', + plan: 'Planejar', + }, + metrics: { + capacityUtilization: 'Utilização da capacidade', + noCapacity: 'Nenhuma capacidade definida', + planned: 'Planejada', + accepted: 'Aceita', + goal: 'Objetivo', + goalAchieved: 'Alcançada', + goalMissed: 'Não alcançada', + }, + taskList: { + title: 'Tarefas', + empty: 'Nenhuma tarefa nesta sprint', + estimate: 'Est', + }, + burndown: { + title: 'Burndown', + empty: 'Nenhum dado de burndown disponível', + ideal: 'Ideal', + actual: 'Real', + }, + velocity: { + title: 'Velocidade', + empty: 'Ainda não há dados de velocidade', + lastN: 'Últimas {n} sprints', + planned: 'Planejado', + accepted: 'Aceito', + }, + retro: { + title: 'Retrospectiva', + wentWell: 'O que deu certo', + wentWellPlaceholder: 'Coisas que funcionaram', + wentBad: 'O que deu errado', + wentBadPlaceholder: 'Coisas a melhorar', + actionItems: 'Itens de ação', + actionItemsPlaceholder: 'O que mudar na próxima sprint', + }, + review: { + title: 'Encerrar sprint', + hint: 'Defina um resultado para cada tarefa antes de encerrar a sprint.', + noTasks: 'Nenhuma tarefa para revisar', + goalAchieved: 'Objetivo da sprint alcançado', + carryTo: 'Transferir para', + backlogOption: 'Backlog', + warningTitle: 'Isso finaliza o sprint', + warning: 'Uma vez fechado, a sprint é marcado como concluída e conta para a velocidade. As tarefas inacabadas são transferidas ou descartadas de acordo com as opções abaixo.', + confirmTitle: 'Encerrar esta sprint?', + confirmMessage: 'A sprint será marcada como concluída e suas tarefas movidas de acordo com os resultados escolhidos. Continuar?', + }, + outcomes: { + accepted: 'Aceita', + carriedOver: 'Transferida', + dropped: 'Descartada', + }, + carryOver: { + backlog: 'Mover para o backlog', + next: 'Mover para a próxima sprint', + keep: 'Manter na sprint', + }, + planning: { + title: 'Planejamento da sprint', + backlog: 'Backlog', + backlogEmpty: 'Nenhuma tarefa no backlog', + inSprint: 'Na sprint', + sprintEmpty: 'Nenhuma tarefa atribuída ainda', + loadError: 'Falha ao carregar tarefas', + retry: 'Tentar novamente', + }, + cadence: { + button: 'Sprints automáticas', + title: 'Sprints automáticas', + description: 'Gere sprints em um cronograma fixo, como Linear. As sprints atuais e futuras são criadas para você. Ative cada um manualmente quando estiver pronto.', + enable: 'Ativar sprints automáticas', + enableHint: 'Você ainda pode criar e fechar sprints manualmente.', + length: 'Duração da sprint', + weeks: '{n} semana | {n} semanas', + startDate: 'Início da primeira sprint', + startDateHint: 'Data âncora – cada sprint conta a partir daqui.', + lookahead: 'Sprints futuras', + lookaheadHint: 'Quantas sprints futuras serão criadas além da atual.', + nameTemplate: 'Modelo de nome', + nameTemplateHint: 'Use {\'{n}\'} onde o número da sprint deve aparecer.', + saved: 'Configurações de sprints automáticos salvas', + }, + notifications: { + starting: 'Sprint começando em breve', + ending: 'Sprint terminando em breve', + completed: 'Sprint concluída', + }, + toasts: { + created: 'Sprint criada', + updated: 'Sprint alterada', + closed: 'Sprint encerrada', + retroSaved: 'Retrospectiva salva', + assignFailed: 'Falha ao alerar a tarefa', + closeFailed: 'Falha ao encerar a sprint', + }, + }, +}