mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-19 13:21:46 +00:00
6072b969d6
* fix: collab chat input hidden by mobile bottom nav bar Closes #939 * chore: prepare database for nest + typeorm * fix(ssrf): relax internal network resolution (#947) * docs(ssrf): update Internal-Network-Access wiki to reflect relaxed guard Loopback, link-local, and .local/.internal hostnames are now all overridable with ALLOW_INTERNAL_NETWORK=true (commit9a08368). Merge the two-tier "always blocked / conditionally blocked" structure into a single table, add a warning about cloud metadata exposure. * fix(ssrf): let .local/.internal hostnames pass to IP-level checks The pre-DNS hostname block was redundant: any .local/.internal host that resolves to a private IP is already gated by isPrivateNetwork + ALLOW_INTERNAL_NETWORK, and any that resolves to loopback/link-local is caught by isAlwaysBlocked unconditionally. Dropping the hostname pre-check means Docker/LAN deployments can reach services on .local hostnames (e.g. immich.local) with ALLOW_INTERNAL_NETWORK=true, while loopback and link-local IPs (including 169.254.169.254) remain hard-blocked with no override. Reverts the isAlwaysBlocked guard loosening from9a08368. * fix(auth): trim username and email on all write paths Self-registration stored values verbatim, so trailing whitespace could produce rows that lookup code (which trims input) silently misses. Trim username and email before validation and INSERT in registerUser, adminService.updateUser, and oidcService.findOrCreateUser. updateSettings and adminService.createUser already trimmed correctly. Adds a one-shot backfill migration (trimUserWhitespace) that trims existing dirty rows; collisions are resolved by appending __migrated_<id> to the value with a loud console.warn so operators can review affected accounts. 18 new tests covering registration trim, duplicate detection, admin update trim, trip-member lookup regression, and all migration branches. * feat(notices): add v3014-whitespace-collision admin notice Adds a dismissible banner for admins on v3.0.14+ that fires only when the whitespace-trimming migration detected a username/email collision (stored in app_settings as whitespace_migration_collision=true). Notice conditions: existingUserBeforeVersion(3.0.14) + role=admin + custom predicate reading the app_settings flag. Predicate registered in registry.ts; migration step writes the flag when hadCollision=true. All 15 translation files updated with title/body keys. 7 integration tests added (SN-COLLISION-1 through -7) covering all condition branches: shown when all conditions met, hidden when flag absent/false, hidden for non-admin, hidden for new user, hidden below min app version, hidden after dismissal.
2361 lines
128 KiB
TypeScript
2361 lines
128 KiB
TypeScript
const br: Record<string, string | { name: string; category: string }[]> = {
|
||
// Common
|
||
'common.save': 'Salvar',
|
||
'common.showMore': 'Mostrar mais',
|
||
'common.showLess': 'Mostrar menos',
|
||
'common.cancel': 'Cancelar',
|
||
'common.clear': 'Limpar',
|
||
'common.delete': 'Excluir',
|
||
'common.edit': 'Editar',
|
||
'common.add': 'Adicionar',
|
||
'common.loading': 'Carregando...',
|
||
'common.import': 'Importar',
|
||
'common.select': 'Selecionar',
|
||
'common.selectAll': 'Selecionar tudo',
|
||
'common.deselectAll': 'Desmarcar tudo',
|
||
'common.error': 'Erro',
|
||
'common.unknownError': 'Erro desconhecido',
|
||
'common.tooManyAttempts': 'Muitas tentativas. Tente novamente mais tarde.',
|
||
'common.back': 'Voltar',
|
||
'common.all': 'Todos',
|
||
'common.close': 'Fechar',
|
||
'common.open': 'Abrir',
|
||
'common.upload': 'Enviar',
|
||
'common.search': 'Buscar',
|
||
'common.confirm': 'Confirmar',
|
||
'common.ok': 'OK',
|
||
'common.yes': 'Sim',
|
||
'common.no': 'Não',
|
||
'common.or': 'ou',
|
||
'common.none': 'Nenhum',
|
||
'common.date': 'Data',
|
||
'common.rename': 'Renomear',
|
||
'common.discardChanges': 'Descartar alterações',
|
||
'common.discard': 'Descartar',
|
||
'common.name': 'Nome',
|
||
'common.email': 'E-mail',
|
||
'common.password': 'Senha',
|
||
'common.saving': 'Salvando...',
|
||
'common.saved': 'Salvo',
|
||
'common.expand': 'Expandir',
|
||
'common.collapse': 'Recolher',
|
||
'trips.reminder': 'Lembrete',
|
||
'trips.reminderNone': 'Nenhum',
|
||
'trips.reminderDay': 'dia',
|
||
'trips.reminderDays': 'dias',
|
||
'trips.reminderCustom': 'Personalizado',
|
||
'trips.memberRemoved': '{username} removido',
|
||
'trips.memberRemoveError': 'Falha ao remover',
|
||
'trips.memberAdded': '{username} adicionado',
|
||
'trips.memberAddError': 'Falha ao adicionar',
|
||
'trips.reminderDaysBefore': 'dias antes da partida',
|
||
'trips.reminderDisabledHint': 'Os lembretes de viagem estão desativados. Ative-os em Admin > Configurações > Notificações.',
|
||
'common.update': 'Atualizar',
|
||
'common.change': 'Alterar',
|
||
'common.uploading': 'Enviando…',
|
||
'common.backToPlanning': 'Voltar ao planejamento',
|
||
'common.reset': 'Redefinir',
|
||
|
||
// Navbar
|
||
'nav.trip': 'Viagem',
|
||
'nav.share': 'Compartilhar',
|
||
'nav.settings': 'Configurações',
|
||
'nav.admin': 'Admin',
|
||
'nav.logout': 'Sair',
|
||
'nav.lightMode': 'Modo claro',
|
||
'nav.darkMode': 'Modo escuro',
|
||
'nav.autoMode': 'Automático',
|
||
'nav.administrator': 'Administrador',
|
||
|
||
// Dashboard
|
||
'dashboard.title': 'Minhas viagens',
|
||
'dashboard.subtitle.loading': 'Carregando viagens...',
|
||
'dashboard.subtitle.trips': '{count} viagens ({archived} arquivadas)',
|
||
'dashboard.subtitle.empty': 'Comece sua primeira viagem',
|
||
'dashboard.subtitle.activeOne': '{count} viagem ativa',
|
||
'dashboard.subtitle.activeMany': '{count} viagens ativas',
|
||
'dashboard.subtitle.archivedSuffix': ' · {count} arquivadas',
|
||
'dashboard.newTrip': 'Nova viagem',
|
||
'dashboard.gridView': 'Grade',
|
||
'dashboard.listView': 'Lista',
|
||
'dashboard.currency': 'Moeda',
|
||
'dashboard.timezone': 'Fusos horários',
|
||
'dashboard.localTime': 'Local',
|
||
'dashboard.timezoneCustomTitle': 'Fuso personalizado',
|
||
'dashboard.timezoneCustomLabelPlaceholder': 'Rótulo (opcional)',
|
||
'dashboard.timezoneCustomTzPlaceholder': 'ex.: America/Sao_Paulo',
|
||
'dashboard.timezoneCustomAdd': 'Adicionar',
|
||
'dashboard.timezoneCustomErrorEmpty': 'Informe um identificador de fuso',
|
||
'dashboard.timezoneCustomErrorInvalid': 'Fuso inválido. Use o formato Europe/Berlin',
|
||
'dashboard.timezoneCustomErrorDuplicate': 'Já adicionado',
|
||
'dashboard.emptyTitle': 'Nenhuma viagem ainda',
|
||
'dashboard.emptyText': 'Crie sua primeira viagem e comece a planejar!',
|
||
'dashboard.emptyButton': 'Criar primeira viagem',
|
||
'dashboard.nextTrip': 'Próxima viagem',
|
||
'dashboard.shared': 'Compartilhada',
|
||
'dashboard.sharedBy': 'Compartilhada por {name}',
|
||
'dashboard.days': 'Dias',
|
||
'dashboard.places': 'Lugares',
|
||
'dashboard.members': 'Parceiros de viagem',
|
||
'dashboard.archive': 'Arquivar',
|
||
'dashboard.copyTrip': 'Copiar',
|
||
'dashboard.copySuffix': 'cópia',
|
||
'dashboard.restore': 'Restaurar',
|
||
'dashboard.archived': 'Arquivada',
|
||
'dashboard.status.ongoing': 'Em andamento',
|
||
'dashboard.status.today': 'Hoje',
|
||
'dashboard.status.tomorrow': 'Amanhã',
|
||
'dashboard.status.past': 'Passada',
|
||
'dashboard.status.daysLeft': 'Faltam {count} dias',
|
||
'dashboard.toast.loadError': 'Não foi possível carregar as viagens',
|
||
'dashboard.toast.created': 'Viagem criada com sucesso!',
|
||
'dashboard.toast.createError': 'Não foi possível criar a viagem',
|
||
'dashboard.toast.updated': 'Viagem atualizada!',
|
||
'dashboard.toast.updateError': 'Não foi possível atualizar a viagem',
|
||
'dashboard.toast.deleted': 'Viagem excluída',
|
||
'dashboard.toast.deleteError': 'Não foi possível excluir a viagem',
|
||
'dashboard.toast.archived': 'Viagem arquivada',
|
||
'dashboard.toast.archiveError': 'Não foi possível arquivar',
|
||
'dashboard.toast.restored': 'Viagem restaurada',
|
||
'dashboard.toast.restoreError': 'Não foi possível restaurar',
|
||
'dashboard.toast.copied': 'Viagem copiada!',
|
||
'dashboard.toast.copyError': 'Não foi possível copiar a viagem',
|
||
'dashboard.confirm.delete': 'Excluir a viagem "{title}"? Todos os lugares e planos serão excluídos permanentemente.',
|
||
'dashboard.editTrip': 'Editar viagem',
|
||
'dashboard.createTrip': 'Criar nova viagem',
|
||
'dashboard.tripTitle': 'Título',
|
||
'dashboard.tripTitlePlaceholder': 'ex.: Verão no Japão',
|
||
'dashboard.tripDescription': 'Descrição',
|
||
'dashboard.tripDescriptionPlaceholder': 'Sobre o que é esta viagem?',
|
||
'dashboard.startDate': 'Data de início',
|
||
'dashboard.endDate': 'Data de término',
|
||
'dashboard.dayCount': 'Número de dias',
|
||
'dashboard.dayCountHint': 'Quantos dias planejar quando nenhuma data de viagem for definida.',
|
||
'dashboard.noDateHint': 'Sem datas — serão criados 7 dias padrão. Você pode alterar depois.',
|
||
'dashboard.coverImage': 'Imagem de capa',
|
||
'dashboard.addCoverImage': 'Adicionar capa (ou arrastar e soltar)',
|
||
'dashboard.addMembers': 'Companheiros de viagem',
|
||
'dashboard.addMember': 'Adicionar membro',
|
||
'dashboard.coverSaved': 'Capa salva',
|
||
'dashboard.coverUploadError': 'Falha no envio',
|
||
'dashboard.coverRemoveError': 'Falha ao remover',
|
||
'dashboard.titleRequired': 'O título é obrigatório',
|
||
'dashboard.endDateError': 'A data final deve ser depois da inicial',
|
||
|
||
// Settings
|
||
'settings.title': 'Configurações',
|
||
'settings.subtitle': 'Ajuste suas preferências pessoais',
|
||
'settings.tabs.display': 'Exibição',
|
||
'settings.tabs.map': 'Mapa',
|
||
'settings.tabs.notifications': 'Notificações',
|
||
'settings.tabs.integrations': 'Integrações',
|
||
'settings.tabs.account': 'Conta',
|
||
'settings.tabs.offline': 'Offline',
|
||
'settings.tabs.about': 'Sobre',
|
||
'settings.map': 'Mapa',
|
||
'settings.mapTemplate': 'Modelo de mapa',
|
||
'settings.mapTemplatePlaceholder.select': 'Selecione o modelo...',
|
||
'settings.mapDefaultHint': 'Deixe vazio para OpenStreetMap (padrão)',
|
||
'settings.mapTemplatePlaceholder': 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||
'settings.mapHint': 'URL do modelo de blocos do mapa',
|
||
'settings.mapProvider': 'Provedor de mapa',
|
||
'settings.mapProviderHint': 'Afeta os mapas do Planejador de Viagem e Diário. Atlas sempre usa Leaflet.',
|
||
'settings.mapLeafletSubtitle': 'Clássico 2D, quaisquer blocos raster',
|
||
'settings.mapMapboxSubtitle': 'Blocos vetoriais, prédios 3D & terreno',
|
||
'settings.mapExperimental': 'Experimental',
|
||
'settings.mapMapboxToken': 'Token de acesso Mapbox',
|
||
'settings.mapMapboxTokenHint': 'Token público (pk.*) de',
|
||
'settings.mapMapboxTokenLink': 'mapbox.com → Tokens de acesso',
|
||
'settings.mapStyle': 'Estilo do mapa',
|
||
'settings.mapStylePlaceholder': 'Selecionar um estilo Mapbox',
|
||
'settings.mapStyleHint': 'Preset ou sua própria URL mapbox://styles/USER/ID',
|
||
'settings.map3dBuildings': 'Prédios 3D & terreno',
|
||
'settings.map3dHint': 'Inclinação + extrusões 3D reais de prédios — funciona em todo estilo, incluindo satélite.',
|
||
'settings.mapHighQuality': 'Modo alta qualidade',
|
||
'settings.mapHighQualityHint': 'Antialiasing + projeção global para bordas mais nítidas e uma visão realista do mundo.',
|
||
'settings.mapHighQualityWarning': 'Pode afetar o desempenho em dispositivos menos potentes.',
|
||
'settings.mapTipLabel': 'Dica:',
|
||
'settings.mapTip': 'Clique direito e arraste para girar/inclinar o mapa. Clique do meio para adicionar um local (o clique direito é reservado para rotação).',
|
||
'settings.latitude': 'Latitude',
|
||
'settings.longitude': 'Longitude',
|
||
'settings.saveMap': 'Salvar mapa',
|
||
'settings.apiKeys': 'Chaves de API',
|
||
'settings.mapsKey': 'Chave da API Google Maps',
|
||
'settings.mapsKeyHint': 'Para busca de lugares. Requer Places API (New). Obtenha em console.cloud.google.com',
|
||
'settings.weatherKey': 'Chave OpenWeatherMap',
|
||
'settings.weatherKeyHint': 'Para dados meteorológicos. Grátis em openweathermap.org/api',
|
||
'settings.keyPlaceholder': 'Digite a chave...',
|
||
'settings.configured': 'Configurada',
|
||
'settings.saveKeys': 'Salvar chaves',
|
||
'settings.display': 'Exibição',
|
||
'settings.colorMode': 'Tema de cores',
|
||
'settings.light': 'Claro',
|
||
'settings.dark': 'Escuro',
|
||
'settings.auto': 'Automático',
|
||
'settings.language': 'Idioma',
|
||
'settings.temperature': 'Unidade de temperatura',
|
||
'settings.timeFormat': 'Formato de hora',
|
||
'settings.routeCalculation': 'Cálculo de rota',
|
||
'settings.blurBookingCodes': 'Ocultar códigos de reserva',
|
||
'settings.notifications': 'Notificações',
|
||
'settings.notifyTripInvite': 'Convites de viagem',
|
||
'settings.notifyBookingChange': 'Alterações de reserva',
|
||
'settings.notifyTripReminder': 'Lembretes de viagem',
|
||
'settings.notifyTodoDue': 'Tarefa com vencimento',
|
||
'settings.notifyVacayInvite': 'Convites de fusão Vacay',
|
||
'settings.notifyPhotosShared': 'Fotos compartilhadas (Immich)',
|
||
'settings.notifyCollabMessage': 'Mensagens de chat (Colab)',
|
||
'settings.notifyPackingTagged': 'Lista de mala: atribuições',
|
||
'settings.notifyWebhook': 'Notificações webhook',
|
||
'settings.notificationsDisabled': 'As notificações não estão configuradas. Peça a um administrador para ativar notificações por e-mail ou webhook.',
|
||
'settings.notificationsActive': 'Canal ativo',
|
||
'settings.notificationsManagedByAdmin': 'Os eventos de notificação são configurados pelo administrador.',
|
||
'admin.notifications.title': 'Notificações',
|
||
'admin.notifications.hint': 'Escolha um canal de notificação. Apenas um pode estar ativo por vez.',
|
||
'admin.notifications.none': 'Desativado',
|
||
'admin.notifications.email': 'E-mail (SMTP)',
|
||
'admin.notifications.webhook': 'Webhook',
|
||
'admin.notifications.save': 'Salvar configurações de notificação',
|
||
'admin.notifications.saved': 'Configurações de notificação salvas',
|
||
'admin.notifications.testWebhook': 'Enviar webhook de teste',
|
||
'admin.notifications.testWebhookSuccess': 'Webhook de teste enviado com sucesso',
|
||
'admin.notifications.testWebhookFailed': 'Falha ao enviar webhook de teste',
|
||
'admin.smtp.title': 'E-mail e notificações',
|
||
'admin.smtp.hint': 'Configuração SMTP para envio de notificações por e-mail.',
|
||
'admin.smtp.testButton': 'Enviar e-mail de teste',
|
||
'admin.webhook.hint': 'Enviar notificações para um webhook externo (Discord, Slack, etc.).',
|
||
'admin.smtp.testSuccess': 'E-mail de teste enviado com sucesso',
|
||
'admin.smtp.testFailed': 'Falha ao enviar e-mail de teste',
|
||
'dayplan.icsTooltip': 'Exportar calendário (ICS)',
|
||
'share.linkTitle': 'Link público',
|
||
'share.linkHint': 'Crie um link que qualquer pessoa pode usar para ver esta viagem sem fazer login. Somente leitura — sem edição possível.',
|
||
'share.createLink': 'Criar link',
|
||
'share.deleteLink': 'Excluir link',
|
||
'share.createError': 'Não foi possível criar o link',
|
||
'common.copy': 'Copiar',
|
||
'common.copied': 'Copiado',
|
||
'share.permMap': 'Mapa e plano',
|
||
'share.permBookings': 'Reservas',
|
||
'share.permPacking': 'Mala',
|
||
'shared.expired': 'Link expirado ou inválido',
|
||
'shared.expiredHint': 'Este link de viagem compartilhado não está mais ativo.',
|
||
'shared.readOnly': 'Visualização somente leitura',
|
||
'shared.tabPlan': 'Plano',
|
||
'shared.tabBookings': 'Reservas',
|
||
'shared.tabPacking': 'Bagagem',
|
||
'shared.tabBudget': 'Orçamento',
|
||
'shared.tabChat': 'Chat',
|
||
'shared.days': 'dias',
|
||
'shared.places': 'lugares',
|
||
'shared.other': 'Outros',
|
||
'shared.totalBudget': 'Orçamento total',
|
||
'shared.messages': 'mensagens',
|
||
'shared.sharedVia': 'Compartilhado via',
|
||
'shared.confirmed': 'Confirmado',
|
||
'shared.pending': 'Pendente',
|
||
'share.permBudget': 'Orçamento',
|
||
'share.permCollab': 'Chat',
|
||
'settings.on': 'Ligado',
|
||
'settings.off': 'Desligado',
|
||
'settings.account': 'Conta',
|
||
'settings.about': 'Sobre',
|
||
'settings.about.reportBug': 'Reportar um bug',
|
||
'settings.about.reportBugHint': 'Encontrou um problema? Nos avise',
|
||
'settings.about.featureRequest': 'Solicitar recurso',
|
||
'settings.about.featureRequestHint': 'Sugira um novo recurso',
|
||
'settings.about.wikiHint': 'Documentação e guias',
|
||
'settings.about.supporters.badge': 'Apoiadores Mensais',
|
||
'settings.about.supporters.title': 'Companheiros de viagem do TREK',
|
||
'settings.about.supporters.subtitle': 'Enquanto você planeja sua próxima rota, essas pessoas planejam junto o futuro do TREK. A contribuição mensal delas vai direto para o desenvolvimento e horas reais investidas — para o TREK continuar Open Source.',
|
||
'settings.about.supporters.since': 'apoiador desde {date}',
|
||
'settings.about.supporters.tierEmpty': 'Seja o primeiro',
|
||
'settings.about.supporter.tier.noReturnTicket': 'No Return Ticket',
|
||
'settings.about.supporter.tier.lostLuggageVip': 'Lost Luggage VIP',
|
||
'settings.about.supporter.tier.businessClassDreamer': 'Business Class Dreamer',
|
||
'settings.about.supporter.tier.budgetTraveller': 'Budget Traveller',
|
||
'settings.about.supporter.tier.hostelBunkmate': 'Hostel Bunkmate',
|
||
'settings.about.description': 'TREK é um planejador de viagens auto-hospedado que ajuda você a organizar suas viagens da primeira ideia à última lembrança. Planejamento diário, orçamento, listas de bagagem, fotos e muito mais — tudo em um só lugar, no seu próprio servidor.',
|
||
'settings.about.madeWith': 'Feito com',
|
||
'settings.about.madeBy': 'por Maurice e uma crescente comunidade open-source.',
|
||
'settings.username': 'Nome de usuário',
|
||
'settings.email': 'E-mail',
|
||
'settings.role': 'Função',
|
||
'settings.roleAdmin': 'Administrador',
|
||
'settings.oidcLinked': 'Vinculado a',
|
||
'settings.changePassword': 'Alterar senha',
|
||
'settings.currentPassword': 'Senha atual',
|
||
'settings.currentPasswordRequired': 'A senha atual é obrigatória',
|
||
'settings.newPassword': 'Nova senha',
|
||
'settings.confirmPassword': 'Confirmar nova senha',
|
||
'settings.updatePassword': 'Atualizar senha',
|
||
'settings.passwordRequired': 'Informe a senha atual e a nova',
|
||
'settings.passwordTooShort': 'A senha deve ter pelo menos 8 caracteres',
|
||
'settings.passwordMismatch': 'As senhas não coincidem',
|
||
'settings.passwordWeak': 'A senha deve ter maiúscula, minúscula, número e um caractere especial',
|
||
'settings.passwordChanged': 'Senha alterada com sucesso',
|
||
'settings.deleteAccount': 'Excluir conta',
|
||
'settings.deleteAccountTitle': 'Excluir sua conta?',
|
||
'settings.deleteAccountWarning': 'Sua conta e todas as viagens, lugares e arquivos serão excluídos permanentemente. Esta ação não pode ser desfeita.',
|
||
'settings.deleteAccountConfirm': 'Excluir permanentemente',
|
||
'settings.deleteBlockedTitle': 'Exclusão não permitida',
|
||
'settings.deleteBlockedMessage': 'Você é o único administrador. Promova outro usuário a administrador antes de excluir sua conta.',
|
||
'settings.roleUser': 'Usuário',
|
||
'settings.saveProfile': 'Salvar perfil',
|
||
'settings.toast.mapSaved': 'Configurações do mapa salvas',
|
||
'settings.toast.keysSaved': 'Chaves de API salvas',
|
||
'settings.toast.displaySaved': 'Configurações de exibição salvas',
|
||
'settings.toast.profileSaved': 'Perfil salvo',
|
||
'settings.uploadAvatar': 'Enviar foto do perfil',
|
||
'settings.removeAvatar': 'Remover foto do perfil',
|
||
'settings.avatarUploaded': 'Foto do perfil atualizada',
|
||
'settings.avatarRemoved': 'Foto do perfil removida',
|
||
'settings.avatarError': 'Falha no envio',
|
||
'settings.mfa.title': 'Autenticação em duas etapas (2FA)',
|
||
'settings.mfa.description': 'Adiciona uma segunda etapa ao entrar com e-mail e senha. Use um app autenticador (Google Authenticator, Authy, etc.).',
|
||
'settings.mfa.requiredByPolicy': 'O administrador exige autenticação em dois fatores. Configure um app autenticador abaixo antes de continuar.',
|
||
'settings.mfa.backupTitle': 'Códigos de backup',
|
||
'settings.mfa.backupDescription': 'Use estes códigos únicos se perder acesso ao app autenticador.',
|
||
'settings.mfa.backupWarning': 'Salve estes códigos agora. Cada código pode ser usado apenas uma vez.',
|
||
'settings.mfa.backupCopy': 'Copiar códigos',
|
||
'settings.mfa.backupDownload': 'Baixar TXT',
|
||
'settings.mfa.backupPrint': 'Imprimir / PDF',
|
||
'settings.mfa.backupCopied': 'Códigos de backup copiados',
|
||
'settings.mfa.enabled': 'O 2FA está ativado na sua conta.',
|
||
'settings.mfa.disabled': 'O 2FA não está ativado.',
|
||
'settings.mfa.setup': 'Configurar autenticador',
|
||
'settings.mfa.scanQr': 'Leia este QR code no app ou digite o segredo manualmente.',
|
||
'settings.mfa.secretLabel': 'Chave secreta (entrada manual)',
|
||
'settings.mfa.codePlaceholder': 'Código de 6 dígitos',
|
||
'settings.mfa.enable': 'Ativar 2FA',
|
||
'settings.mfa.cancelSetup': 'Cancelar',
|
||
'settings.mfa.disableTitle': 'Desativar 2FA',
|
||
'settings.mfa.disableHint': 'Digite sua senha e um código atual do autenticador.',
|
||
'settings.mfa.disable': 'Desativar 2FA',
|
||
'settings.mfa.toastEnabled': 'Autenticação em duas etapas ativada',
|
||
'settings.mfa.toastDisabled': 'Autenticação em duas etapas desativada',
|
||
'settings.mfa.demoBlocked': 'Indisponível no modo demonstração',
|
||
'settings.mcp.title': 'Configuração MCP',
|
||
'settings.mcp.endpoint': 'Endpoint MCP',
|
||
'settings.mcp.clientConfig': 'Configuração do cliente',
|
||
'settings.mcp.clientConfigHint': 'Substitua <your_token> por um token de API da lista abaixo. O caminho para o npx pode precisar ser ajustado para o seu sistema (ex.: C:\\PROGRA~1\\nodejs\\npx.cmd no Windows).',
|
||
'settings.mcp.clientConfigHintOAuth': 'Substitua <your_client_id> e <your_client_secret> pelas credenciais exibidas no cliente OAuth 2.1 criado acima. O mcp-remote abrirá seu navegador para concluir a autorização na primeira conexão. O caminho para o npx pode precisar ser ajustado para seu sistema (ex.: C:\\PROGRA~1\\nodejs\\npx.cmd no Windows).',
|
||
'settings.mcp.copy': 'Copiar',
|
||
'settings.mcp.copied': 'Copiado!',
|
||
'settings.mcp.apiTokens': 'Tokens de API',
|
||
'settings.mcp.createToken': 'Criar novo token',
|
||
'settings.mcp.noTokens': 'Nenhum token ainda. Crie um para conectar clientes MCP.',
|
||
'settings.mcp.tokenCreatedAt': 'Criado em',
|
||
'settings.mcp.tokenUsedAt': 'Usado em',
|
||
'settings.mcp.deleteTokenTitle': 'Excluir token',
|
||
'settings.mcp.deleteTokenMessage': 'Este token deixará de funcionar imediatamente. Qualquer cliente MCP que o utilize perderá o acesso.',
|
||
'settings.mcp.modal.createTitle': 'Criar token de API',
|
||
'settings.mcp.modal.tokenName': 'Nome do token',
|
||
'settings.mcp.modal.tokenNamePlaceholder': 'ex.: Claude Desktop, Notebook do trabalho',
|
||
'settings.mcp.modal.creating': 'Criando…',
|
||
'settings.mcp.modal.create': 'Criar token',
|
||
'settings.mcp.modal.createdTitle': 'Token criado',
|
||
'settings.mcp.modal.createdWarning': 'Este token será exibido apenas uma vez. Copie e guarde agora — não poderá ser recuperado.',
|
||
'settings.mcp.modal.done': 'Concluído',
|
||
'settings.mcp.toast.created': 'Token criado',
|
||
'settings.mcp.toast.createError': 'Falha ao criar token',
|
||
'settings.mcp.toast.deleted': 'Token excluído',
|
||
'settings.mcp.toast.deleteError': 'Falha ao excluir token',
|
||
'settings.mcp.apiTokensDeprecated': 'Os tokens de API estão obsoletos e serão removidos em uma versão futura. Por favor, use Clientes OAuth 2.1.',
|
||
'settings.oauth.clients': 'Clientes OAuth 2.1',
|
||
'settings.oauth.clientsHint': 'Registre clientes OAuth 2.1 para permitir que aplicações MCP de terceiros (Claude Web, Cursor, etc.) se conectem sem tokens estáticos.',
|
||
'settings.oauth.createClient': 'Novo cliente',
|
||
'settings.oauth.noClients': 'Nenhum cliente OAuth registrado.',
|
||
'settings.oauth.clientId': 'ID do cliente',
|
||
'settings.oauth.clientSecret': 'Segredo do cliente',
|
||
'settings.oauth.deleteClient': 'Excluir cliente',
|
||
'settings.oauth.deleteClientMessage': 'Este cliente e todas as sessões ativas serão removidos permanentemente. Qualquer aplicação que o utilize perderá o acesso imediatamente.',
|
||
'settings.oauth.rotateSecret': 'Renovar segredo',
|
||
'settings.oauth.rotateSecretMessage': 'Um novo segredo de cliente será gerado e todas as sessões existentes serão invalidadas imediatamente. Atualize sua aplicação antes de fechar esta janela.',
|
||
'settings.oauth.rotateSecretConfirm': 'Renovar',
|
||
'settings.oauth.rotateSecretConfirming': 'Renovando…',
|
||
'settings.oauth.rotateSecretDoneTitle': 'Novo segredo gerado',
|
||
'settings.oauth.rotateSecretDoneWarning': 'Este segredo é exibido apenas uma vez. Copie-o agora e atualize sua aplicação — todas as sessões anteriores foram invalidadas.',
|
||
'settings.oauth.activeSessions': 'Sessões OAuth ativas',
|
||
'settings.oauth.sessionScopes': 'Escopos',
|
||
'settings.oauth.sessionExpires': 'Expira',
|
||
'settings.oauth.revoke': 'Revogar',
|
||
'settings.oauth.revokeSession': 'Revogar sessão',
|
||
'settings.oauth.revokeSessionMessage': 'Isso revogará imediatamente o acesso desta sessão OAuth.',
|
||
'settings.oauth.modal.createTitle': 'Registrar cliente OAuth',
|
||
'settings.oauth.modal.presets': 'Configurações rápidas',
|
||
'settings.oauth.modal.clientName': 'Nome da aplicação',
|
||
'settings.oauth.modal.clientNamePlaceholder': 'ex.: Claude Web, Meu app MCP',
|
||
'settings.oauth.modal.redirectUris': 'URIs de redirecionamento',
|
||
'settings.oauth.modal.redirectUrisPlaceholder': 'https://your-app.com/callback\nhttps://your-app.com/auth',
|
||
'settings.oauth.modal.redirectUrisHint': 'Uma URI por linha. HTTPS obrigatório (localhost isento). Correspondência exata.',
|
||
'settings.oauth.modal.scopes': 'Escopos permitidos',
|
||
'settings.oauth.modal.scopesHint': 'list_trips e get_trip_summary estão sempre disponíveis — sem escopo necessário. Permitem à IA descobrir IDs de viagem.',
|
||
'settings.oauth.modal.selectAll': 'Selecionar tudo',
|
||
'settings.oauth.modal.deselectAll': 'Desmarcar tudo',
|
||
'settings.oauth.modal.creating': 'Registrando…',
|
||
'settings.oauth.modal.create': 'Registrar cliente',
|
||
'settings.oauth.modal.createdTitle': 'Cliente registrado',
|
||
'settings.oauth.modal.createdWarning': 'O segredo do cliente é exibido apenas uma vez. Copie-o agora — não pode ser recuperado.',
|
||
'settings.oauth.toast.createError': 'Falha ao registrar cliente OAuth',
|
||
'settings.oauth.toast.deleted': 'Cliente OAuth excluído',
|
||
'settings.oauth.toast.deleteError': 'Falha ao excluir cliente OAuth',
|
||
'settings.oauth.toast.revoked': 'Sessão revogada',
|
||
'settings.oauth.toast.revokeError': 'Falha ao revogar sessão',
|
||
'settings.oauth.toast.rotateError': 'Falha ao renovar segredo do cliente',
|
||
'settings.mustChangePassword': 'Você deve alterar sua senha antes de continuar. Defina uma nova senha abaixo.',
|
||
|
||
// Login
|
||
'login.error': 'Falha no login. Verifique suas credenciais.',
|
||
'login.tagline': 'Suas viagens.\nSeu plano.',
|
||
'login.description': 'Planeje viagens em equipe com mapas interativos, orçamento e sincronização em tempo real.',
|
||
'login.features.maps': 'Mapas interativos',
|
||
'login.features.mapsDesc': 'Google Places, rotas e agrupamento',
|
||
'login.features.realtime': 'Sincronização em tempo real',
|
||
'login.features.realtimeDesc': 'Planejem juntos via WebSocket',
|
||
'login.features.budget': 'Controle de orçamento',
|
||
'login.features.budgetDesc': 'Categorias, gráficos e custo por pessoa',
|
||
'login.features.collab': 'Colaboração',
|
||
'login.features.collabDesc': 'Vários usuários com viagens compartilhadas',
|
||
'login.features.packing': 'Listas de malas',
|
||
'login.features.packingDesc': 'Categorias, progresso e sugestões',
|
||
'login.features.bookings': 'Reservas',
|
||
'login.features.bookingsDesc': 'Voos, hotéis, restaurantes e mais',
|
||
'login.features.files': 'Documentos',
|
||
'login.features.filesDesc': 'Envie e gerencie documentos',
|
||
'login.features.routes': 'Rotas inteligentes',
|
||
'login.features.routesDesc': 'Otimize e exporte para o Google Maps',
|
||
'login.selfHosted': 'Auto-hospedado \u00B7 Código aberto \u00B7 Seus dados são seus',
|
||
'login.title': 'Entrar',
|
||
'login.subtitle': 'Bem-vindo de volta',
|
||
'login.signingIn': 'Entrando…',
|
||
'login.signIn': 'Entrar',
|
||
'login.createAdmin': 'Criar conta de administrador',
|
||
'login.createAdminHint': 'Configure a primeira conta de administrador do TREK.',
|
||
'login.setNewPassword': 'Definir nova senha',
|
||
'login.setNewPasswordHint': 'Você deve alterar sua senha antes de continuar.',
|
||
'login.createAccount': 'Criar conta',
|
||
'login.createAccountHint': 'Cadastre uma nova conta.',
|
||
'login.creating': 'Criando…',
|
||
'login.noAccount': 'Não tem conta?',
|
||
'login.hasAccount': 'Já tem conta?',
|
||
'login.register': 'Cadastrar',
|
||
'login.emailPlaceholder': 'seu@email.com',
|
||
'login.username': 'Nome de usuário',
|
||
'login.oidc.registrationDisabled': 'Cadastro desativado. Fale com o administrador.',
|
||
'login.oidc.noEmail': 'Nenhum e-mail recebido do provedor.',
|
||
'login.oidc.tokenFailed': 'Falha na autenticação.',
|
||
'login.oidc.invalidState': 'Sessão inválida. Tente novamente.',
|
||
'login.demoFailed': 'Falha no login de demonstração',
|
||
'login.oidcSignIn': 'Entrar com {name}',
|
||
'login.oidcOnly': 'Login por senha desativado. Use o provedor SSO.',
|
||
'login.oidcLoggedOut': 'Você foi desconectado. Entre novamente usando o provedor SSO.',
|
||
'login.demoHint': 'Experimente a demonstração — sem cadastro',
|
||
'login.mfaTitle': 'Autenticação em duas etapas',
|
||
'login.mfaSubtitle': 'Digite o código de 6 dígitos do seu app autenticador.',
|
||
'login.mfaCodeLabel': 'Código de verificação',
|
||
'login.mfaCodeRequired': 'Digite o código do app autenticador.',
|
||
'login.mfaHint': 'Abra o Google Authenticator, Authy ou outro app TOTP.',
|
||
'login.mfaBack': '← Voltar ao login',
|
||
'login.mfaVerify': 'Verificar',
|
||
'login.invalidInviteLink': 'Link de convite inválido ou expirado',
|
||
'login.oidcFailed': 'Falha no login OIDC',
|
||
'login.usernameRequired': 'Nome de usuário é obrigatório',
|
||
'login.passwordMinLength': 'A senha deve ter pelo menos 8 caracteres',
|
||
'login.forgotPassword': 'Esqueceu a senha?',
|
||
'login.forgotPasswordTitle': 'Redefinir sua senha',
|
||
'login.forgotPasswordBody': 'Digite o e-mail cadastrado. Se houver uma conta, enviaremos um link de redefinição.',
|
||
'login.forgotPasswordSubmit': 'Enviar link',
|
||
'login.forgotPasswordSentTitle': 'Verifique seu e-mail',
|
||
'login.forgotPasswordSentBody': 'Se houver uma conta para esse e-mail, o link está a caminho. Ele expira em 60 minutos.',
|
||
'login.forgotPasswordSmtpHintOff': 'Observação: seu administrador não configurou SMTP, então o link de redefinição será gravado no console do servidor em vez de ser enviado por e-mail.',
|
||
'login.backToLogin': 'Voltar ao login',
|
||
'login.newPassword': 'Nova senha',
|
||
'login.confirmPassword': 'Confirmar nova senha',
|
||
'login.passwordsDontMatch': 'As senhas não coincidem',
|
||
'login.mfaCode': 'Código 2FA',
|
||
'login.resetPasswordTitle': 'Definir uma nova senha',
|
||
'login.resetPasswordBody': 'Escolha uma senha forte que você ainda não tenha usado aqui. Mínimo de 8 caracteres.',
|
||
'login.resetPasswordMfaBody': 'Digite seu código 2FA ou um código de backup para concluir a redefinição.',
|
||
'login.resetPasswordSubmit': 'Redefinir senha',
|
||
'login.resetPasswordVerify': 'Verificar e redefinir',
|
||
'login.resetPasswordSuccessTitle': 'Senha atualizada',
|
||
'login.resetPasswordSuccessBody': 'Agora você pode entrar com sua nova senha.',
|
||
'login.resetPasswordInvalidLink': 'Link de redefinição inválido',
|
||
'login.resetPasswordInvalidLinkBody': 'Este link está ausente ou corrompido. Solicite um novo para continuar.',
|
||
'login.resetPasswordFailed': 'Falha na redefinição. O link pode ter expirado.',
|
||
|
||
// Register
|
||
'register.passwordMismatch': 'As senhas não coincidem',
|
||
'register.passwordTooShort': 'A senha deve ter pelo menos 8 caracteres',
|
||
'register.failed': 'Falha no cadastro',
|
||
'register.getStarted': 'Começar',
|
||
'register.subtitle': 'Crie uma conta e comece a planejar suas viagens.',
|
||
'register.feature1': 'Viagens ilimitadas',
|
||
'register.feature2': 'Mapa interativo',
|
||
'register.feature3': 'Gerencie lugares e categorias',
|
||
'register.feature4': 'Acompanhe reservas',
|
||
'register.feature5': 'Listas de malas',
|
||
'register.feature6': 'Fotos e arquivos',
|
||
'register.createAccount': 'Criar conta',
|
||
'register.startPlanning': 'Comece a planejar',
|
||
'register.minChars': 'Mín. 6 caracteres',
|
||
'register.confirmPassword': 'Confirmar senha',
|
||
'register.repeatPassword': 'Repita a senha',
|
||
'register.registering': 'Cadastrando...',
|
||
'register.register': 'Cadastrar',
|
||
'register.hasAccount': 'Já tem conta?',
|
||
'register.signIn': 'Entrar',
|
||
|
||
// Admin
|
||
'admin.title': 'Administração',
|
||
'admin.subtitle': 'Gestão de usuários e configurações do sistema',
|
||
'admin.tabs.users': 'Usuários',
|
||
'admin.tabs.categories': 'Categorias',
|
||
'admin.tabs.backup': 'Backup',
|
||
'admin.stats.users': 'Usuários',
|
||
'admin.stats.trips': 'Viagens',
|
||
'admin.stats.places': 'Lugares',
|
||
'admin.stats.photos': 'Fotos',
|
||
'admin.stats.files': 'Arquivos',
|
||
'admin.table.user': 'Usuário',
|
||
'admin.table.email': 'E-mail',
|
||
'admin.table.role': 'Função',
|
||
'admin.table.created': 'Criado',
|
||
'admin.table.lastLogin': 'Último acesso',
|
||
'admin.table.actions': 'Ações',
|
||
'admin.you': '(Você)',
|
||
'admin.editUser': 'Editar usuário',
|
||
'admin.newPassword': 'Nova senha',
|
||
'admin.newPasswordHint': 'Deixe em branco para manter a senha atual',
|
||
'admin.deleteUser': 'Excluir o usuário "{name}"? Todas as viagens serão excluídas permanentemente.',
|
||
'admin.deleteUserTitle': 'Excluir usuário',
|
||
'admin.newPasswordPlaceholder': 'Digite a nova senha…',
|
||
'admin.toast.loadError': 'Falha ao carregar dados do admin',
|
||
'admin.toast.userUpdated': 'Usuário atualizado',
|
||
'admin.toast.updateError': 'Falha ao atualizar',
|
||
'admin.toast.userDeleted': 'Usuário excluído',
|
||
'admin.toast.deleteError': 'Falha ao excluir',
|
||
'admin.toast.cannotDeleteSelf': 'Não é possível excluir a própria conta',
|
||
'admin.toast.userCreated': 'Usuário criado',
|
||
'admin.toast.createError': 'Falha ao criar usuário',
|
||
'admin.toast.fieldsRequired': 'Nome de usuário, e-mail e senha são obrigatórios',
|
||
'admin.createUser': 'Criar usuário',
|
||
'admin.invite.title': 'Links de convite',
|
||
'admin.invite.subtitle': 'Crie links de cadastro de uso único',
|
||
'admin.invite.create': 'Criar link',
|
||
'admin.invite.createAndCopy': 'Criar e copiar',
|
||
'admin.invite.empty': 'Nenhum link de convite criado ainda',
|
||
'admin.invite.maxUses': 'Máx. usos',
|
||
'admin.invite.expiry': 'Expira após',
|
||
'admin.invite.uses': 'usado(s)',
|
||
'admin.invite.expiresAt': 'expira',
|
||
'admin.invite.createdBy': 'por',
|
||
'admin.invite.active': 'Ativo',
|
||
'admin.invite.expired': 'Expirado',
|
||
'admin.invite.usedUp': 'Esgotado',
|
||
'admin.invite.copied': 'Link de convite copiado para a área de transferência',
|
||
'admin.invite.copyLink': 'Copiar link',
|
||
'admin.invite.deleted': 'Link de convite excluído',
|
||
'admin.invite.createError': 'Falha ao criar link de convite',
|
||
'admin.invite.deleteError': 'Falha ao excluir link de convite',
|
||
'admin.tabs.settings': 'Configurações',
|
||
'admin.allowRegistration': 'Permitir cadastro',
|
||
'admin.allowRegistrationHint': 'Novos usuários podem se cadastrar sozinhos',
|
||
'admin.authMethods': 'Authentication Methods',
|
||
'admin.passwordLogin': 'Password Login',
|
||
'admin.passwordLoginHint': 'Allow users to sign in with email and password',
|
||
'admin.passwordRegistration': 'Password Registration',
|
||
'admin.passwordRegistrationHint': 'Allow new users to register with email and password',
|
||
'admin.oidcLogin': 'SSO Login',
|
||
'admin.oidcLoginHint': 'Allow users to sign in with SSO',
|
||
'admin.oidcRegistration': 'SSO Auto-Provisioning',
|
||
'admin.oidcRegistrationHint': 'Automatically create accounts for new SSO users',
|
||
'admin.envOverrideHint': 'Password login settings are controlled by the OIDC_ONLY environment variable and cannot be changed here.',
|
||
'admin.lockoutWarning': 'At least one login method must remain enabled',
|
||
'admin.requireMfa': 'Exigir autenticação em dois fatores (2FA)',
|
||
'admin.requireMfaHint': 'Usuários sem 2FA precisam concluir a configuração em Configurações antes de usar o app.',
|
||
'admin.apiKeys': 'Chaves de API',
|
||
'admin.apiKeysHint': 'Opcional. Habilita dados estendidos de lugares, como fotos e clima.',
|
||
'admin.mapsKey': 'Chave da API Google Maps',
|
||
'admin.mapsKeyHint': 'Necessária para busca de lugares. Obtenha em console.cloud.google.com',
|
||
'admin.mapsKeyHintLong': 'Sem chave de API, o OpenStreetMap é usado na busca. Com uma chave Google, também podem ser carregadas fotos, avaliações e horários. Obtenha em console.cloud.google.com.',
|
||
'admin.recommended': 'Recomendado',
|
||
'admin.weatherKey': 'Chave OpenWeatherMap',
|
||
'admin.weatherKeyHint': 'Para dados meteorológicos. Grátis em openweathermap.org',
|
||
'admin.validateKey': 'Testar',
|
||
'admin.keyValid': 'Conectado',
|
||
'admin.keyInvalid': 'Inválida',
|
||
'admin.keySaved': 'Chaves de API salvas',
|
||
'admin.oidcTitle': 'Login Único (OIDC)',
|
||
'admin.oidcSubtitle': 'Permitir login via provedores externos como Google, Apple, Authentik ou Keycloak.',
|
||
'admin.oidcDisplayName': 'Nome exibido',
|
||
'admin.oidcIssuer': 'URL do emissor',
|
||
'admin.oidcIssuerHint': 'URL do emissor OpenID Connect do provedor, ex.: https://accounts.google.com',
|
||
'admin.oidcSaved': 'Configuração OIDC salva',
|
||
'admin.oidcOnlyMode': 'Desativar login por senha',
|
||
'admin.oidcOnlyModeHint': 'Quando ativado, só é permitido login SSO. Login e cadastro por senha ficam bloqueados.',
|
||
|
||
// File Types
|
||
'admin.fileTypes': 'Tipos de arquivo permitidos',
|
||
'admin.fileTypesHint': 'Configure quais tipos de arquivo os usuários podem enviar.',
|
||
'admin.fileTypesFormat': 'Extensões separadas por vírgula (ex.: jpg,png,pdf,doc). Use * para permitir todos.',
|
||
'admin.fileTypesSaved': 'Configurações de tipos de arquivo salvas',
|
||
|
||
// Packing Templates & Bag Tracking
|
||
'admin.placesPhotos.title': 'Fotos de Locais',
|
||
'admin.placesPhotos.subtitle': 'Busca fotos da Google Places API. Desative para economizar cota da API. Fotos do Wikimedia não são afetadas.',
|
||
'admin.placesAutocomplete.title': 'Autocompletar de Locais',
|
||
'admin.placesAutocomplete.subtitle': 'Usa a Google Places API para sugestões de pesquisa. Desative para economizar cota da API.',
|
||
'admin.placesDetails.title': 'Detalhes do Local',
|
||
'admin.placesDetails.subtitle': 'Busca informações detalhadas do local (horários, avaliação, site) da Google Places API. Desative para economizar cota da API.',
|
||
'admin.bagTracking.title': 'Rastreamento de malas',
|
||
'admin.bagTracking.subtitle': 'Ativar peso e atribuição de mala para itens da lista',
|
||
'admin.collab.chat.title': 'Chat',
|
||
'admin.collab.chat.subtitle': 'Mensagens em tempo real para colaboração',
|
||
'admin.collab.notes.title': 'Notas',
|
||
'admin.collab.notes.subtitle': 'Notas e documentos compartilhados',
|
||
'admin.collab.polls.title': 'Enquetes',
|
||
'admin.collab.polls.subtitle': 'Enquetes e votações em grupo',
|
||
'admin.collab.whatsnext.title': 'Próximos passos',
|
||
'admin.collab.whatsnext.subtitle': 'Sugestões de atividades e próximos passos',
|
||
'admin.tabs.config': 'Personalização',
|
||
'admin.tabs.defaults': 'Padrões do usuário',
|
||
'admin.defaultSettings.title': 'Configurações padrão do usuário',
|
||
'admin.defaultSettings.description': 'Defina padrões para toda a instância. Usuários que não alteraram uma configuração verão esses valores. As próprias alterações deles sempre têm prioridade.',
|
||
'admin.defaultSettings.saved': 'Padrão salvo',
|
||
'admin.defaultSettings.reset': 'Redefinir para o padrão integrado',
|
||
'admin.defaultSettings.resetToBuiltIn': 'redefinir',
|
||
'admin.tabs.templates': 'Modelos de mala',
|
||
'admin.packingTemplates.title': 'Modelos de mala',
|
||
'admin.packingTemplates.subtitle': 'Crie listas de mala reutilizáveis para suas viagens',
|
||
'admin.packingTemplates.create': 'Novo modelo',
|
||
'admin.packingTemplates.namePlaceholder': 'Nome do modelo (ex.: Praia)',
|
||
'admin.packingTemplates.empty': 'Nenhum modelo criado ainda',
|
||
'admin.packingTemplates.items': 'itens',
|
||
'admin.packingTemplates.categories': 'categorias',
|
||
'admin.packingTemplates.itemName': 'Nome do item',
|
||
'admin.packingTemplates.itemCategory': 'Categoria',
|
||
'admin.packingTemplates.categoryName': 'Nome da categoria (ex.: Roupas)',
|
||
'admin.packingTemplates.addCategory': 'Adicionar categoria',
|
||
'admin.packingTemplates.created': 'Modelo criado',
|
||
'admin.packingTemplates.deleted': 'Modelo excluído',
|
||
'admin.packingTemplates.loadError': 'Falha ao carregar modelos',
|
||
'admin.packingTemplates.createError': 'Falha ao criar modelo',
|
||
'admin.packingTemplates.deleteError': 'Falha ao excluir modelo',
|
||
'admin.packingTemplates.saveError': 'Falha ao salvar',
|
||
|
||
// Addons
|
||
'admin.tabs.addons': 'Complementos',
|
||
'admin.addons.title': 'Complementos',
|
||
'admin.addons.subtitle': 'Ative ou desative recursos para personalizar sua experiência no TREK.',
|
||
'admin.addons.catalog.memories.name': 'Memórias',
|
||
'admin.addons.catalog.memories.description': 'Álbuns de fotos compartilhados em cada viagem',
|
||
'admin.addons.catalog.packing.name': 'Listas',
|
||
'admin.addons.catalog.packing.description': 'Listas de bagagem e tarefas a fazer para suas viagens',
|
||
'admin.addons.catalog.budget.name': 'Orçamento',
|
||
'admin.addons.catalog.budget.description': 'Acompanhe despesas e planeje o orçamento da viagem',
|
||
'admin.addons.catalog.documents.name': 'Documentos',
|
||
'admin.addons.catalog.documents.description': 'Armazene e gerencie documentos de viagem',
|
||
'admin.addons.catalog.vacay.name': 'Férias',
|
||
'admin.addons.catalog.vacay.description': 'Planejador de férias pessoal com visão em calendário',
|
||
'admin.addons.catalog.atlas.name': 'Atlas',
|
||
'admin.addons.catalog.atlas.description': 'Mapa mundial com países visitados e estatísticas',
|
||
'admin.addons.catalog.collab.name': 'Colab',
|
||
'admin.addons.catalog.collab.description': 'Notas, enquetes e chat em tempo real para planejar a viagem',
|
||
'admin.addons.catalog.mcp.name': 'MCP',
|
||
'admin.addons.catalog.mcp.description': 'Model Context Protocol para integração com assistentes de IA',
|
||
'admin.addons.subtitleBefore': 'Ative ou desative recursos para personalizar sua ',
|
||
'admin.addons.subtitleAfter': ' experiência.',
|
||
'admin.addons.enabled': 'Ativado',
|
||
'admin.addons.disabled': 'Desativado',
|
||
'admin.addons.type.trip': 'Viagem',
|
||
'admin.addons.type.global': 'Global',
|
||
'admin.addons.type.integration': 'Integração',
|
||
'admin.addons.tripHint': 'Disponível como aba em cada viagem',
|
||
'admin.addons.globalHint': 'Disponível como seção própria na navegação principal',
|
||
'admin.addons.toast.updated': 'Complemento atualizado',
|
||
'admin.addons.toast.error': 'Falha ao atualizar complemento',
|
||
'admin.addons.noAddons': 'Nenhum complemento disponível',
|
||
'admin.addons.integrationHint': 'Serviços de backend e integrações de API sem página dedicada',
|
||
// Weather info
|
||
'admin.weather.title': 'Dados meteorológicos',
|
||
'admin.weather.badge': 'Desde 24 de março de 2026',
|
||
'admin.weather.description': 'O TREK usa Open-Meteo como fonte de clima. Open-Meteo é um serviço gratuito e de código aberto — sem chave de API.',
|
||
'admin.weather.forecast': 'Previsão de 16 dias',
|
||
'admin.weather.forecastDesc': 'Antes eram 5 dias (OpenWeatherMap)',
|
||
'admin.weather.climate': 'Dados climáticos históricos',
|
||
'admin.weather.climateDesc': 'Médias dos últimos 85 anos para dias além da previsão de 16 dias',
|
||
'admin.weather.requests': '10.000 requisições / dia',
|
||
'admin.weather.requestsDesc': 'Grátis, sem chave de API',
|
||
'admin.weather.locationHint': 'O clima usa o primeiro lugar com coordenadas de cada dia. Se nenhum lugar estiver atribuído ao dia, qualquer lugar da lista serve como referência.',
|
||
|
||
'admin.tabs.audit': 'Auditoria',
|
||
|
||
'admin.audit.subtitle': 'Eventos sensíveis de segurança e administração (backups, usuários, 2FA, configurações).',
|
||
'admin.audit.empty': 'Nenhum registro de auditoria.',
|
||
'admin.audit.refresh': 'Atualizar',
|
||
'admin.audit.loadMore': 'Carregar mais',
|
||
'admin.audit.showing': '{count} carregados · {total} no total',
|
||
'admin.audit.col.time': 'Hora',
|
||
'admin.audit.col.user': 'Usuário',
|
||
'admin.audit.col.action': 'Ação',
|
||
'admin.audit.col.resource': 'Recurso',
|
||
'admin.audit.col.ip': 'IP',
|
||
'admin.audit.col.details': 'Detalhes',
|
||
|
||
// GitHub
|
||
'admin.tabs.github': 'GitHub',
|
||
'admin.github.title': 'Histórico de versões',
|
||
'admin.github.subtitle': 'Últimas atualizações de {repo}',
|
||
'admin.github.latest': 'Mais recente',
|
||
'admin.github.prerelease': 'Pré-lançamento',
|
||
'admin.github.showDetails': 'Mostrar detalhes',
|
||
'admin.github.hideDetails': 'Ocultar detalhes',
|
||
'admin.github.loadMore': 'Carregar mais',
|
||
'admin.github.loading': 'Carregando...',
|
||
'admin.github.error': 'Falha ao carregar versões',
|
||
'admin.github.by': 'por',
|
||
'admin.github.support': 'Ajuda a continuar desenvolvendo o TREK',
|
||
|
||
'admin.update.available': 'Atualização disponível',
|
||
'admin.update.text': 'O TREK {version} está disponível. Você está na {current}.',
|
||
'admin.update.button': 'Ver no GitHub',
|
||
'admin.update.install': 'Instalar atualização',
|
||
'admin.update.confirmTitle': 'Instalar atualização?',
|
||
'admin.update.confirmText': 'O TREK será atualizado de {current} para {version}. O servidor reiniciará automaticamente em seguida.',
|
||
'admin.update.dataInfo': 'Todos os seus dados (viagens, usuários, chaves de API, envios, Vacay, Atlas, orçamentos) serão preservados.',
|
||
'admin.update.warning': 'O app ficará brevemente indisponível durante o reinício.',
|
||
'admin.update.confirm': 'Atualizar agora',
|
||
'admin.update.installing': 'Atualizando…',
|
||
'admin.update.success': 'Atualização instalada! O servidor está reiniciando…',
|
||
'admin.update.failed': 'Falha na atualização',
|
||
'admin.update.backupHint': 'Recomendamos criar um backup antes de atualizar.',
|
||
'admin.update.backupLink': 'Ir para Backup',
|
||
'admin.update.howTo': 'Como atualizar',
|
||
'admin.update.dockerText': 'Sua instância TREK roda no Docker. Para atualizar para {version}, execute no servidor:',
|
||
'admin.update.reloadHint': 'Recarregue a página em alguns segundos.',
|
||
|
||
// Vacay addon
|
||
'vacay.subtitle': 'Planeje e gerencie dias de férias',
|
||
'vacay.settings': 'Configurações',
|
||
'vacay.year': 'Ano',
|
||
'vacay.addYear': 'Adicionar próximo ano',
|
||
'vacay.addPrevYear': 'Adicionar ano anterior',
|
||
'vacay.removeYear': 'Remover ano',
|
||
'vacay.removeYearConfirm': 'Remover {year}?',
|
||
'vacay.removeYearHint': 'Todas as entradas de férias e feriados da empresa deste ano serão excluídas permanentemente.',
|
||
'vacay.remove': 'Remover',
|
||
'vacay.persons': 'Pessoas',
|
||
'vacay.noPersons': 'Nenhuma pessoa adicionada',
|
||
'vacay.addPerson': 'Adicionar pessoa',
|
||
'vacay.editPerson': 'Editar pessoa',
|
||
'vacay.removePerson': 'Remover pessoa',
|
||
'vacay.removePersonConfirm': 'Remover {name}?',
|
||
'vacay.removePersonHint': 'Todas as entradas de férias desta pessoa serão excluídas permanentemente.',
|
||
'vacay.personName': 'Nome',
|
||
'vacay.personNamePlaceholder': 'Digite o nome',
|
||
'vacay.color': 'Cor',
|
||
'vacay.add': 'Adicionar',
|
||
'vacay.legend': 'Legenda',
|
||
'vacay.publicHoliday': 'Feriado nacional',
|
||
'vacay.companyHoliday': 'Feriado da empresa',
|
||
'vacay.weekend': 'Fim de semana',
|
||
'vacay.modeVacation': 'Férias',
|
||
'vacay.modeCompany': 'Feriado da empresa',
|
||
'vacay.entitlement': 'Direito',
|
||
'vacay.entitlementDays': 'Dias',
|
||
'vacay.used': 'Usados',
|
||
'vacay.remaining': 'Restantes',
|
||
'vacay.carriedOver': 'de {year}',
|
||
'vacay.blockWeekends': 'Bloquear fins de semana',
|
||
'vacay.weekendDays': 'Dias de fim de semana',
|
||
'vacay.mon': 'Seg',
|
||
'vacay.tue': 'Ter',
|
||
'vacay.wed': 'Qua',
|
||
'vacay.thu': 'Qui',
|
||
'vacay.fri': 'Sex',
|
||
'vacay.sat': 'Sáb',
|
||
'vacay.sun': 'Dom',
|
||
'vacay.blockWeekendsHint': 'Impedir entradas de férias aos sábados e domingos',
|
||
'vacay.publicHolidays': 'Feriados nacionais',
|
||
'vacay.publicHolidaysHint': 'Marcar feriados nacionais no calendário',
|
||
'vacay.selectCountry': 'Selecione o país',
|
||
'vacay.selectRegion': 'Selecione a região (opcional)',
|
||
'vacay.addCalendar': 'Adicionar calendário',
|
||
'vacay.calendarLabel': 'Rótulo (opcional)',
|
||
'vacay.calendarColor': 'Cor',
|
||
'vacay.noCalendars': 'Nenhum calendário de feriados adicionado ainda',
|
||
'vacay.companyHolidays': 'Feriados da empresa',
|
||
'vacay.companyHolidaysHint': 'Permitir marcar dias de feriado em toda a empresa',
|
||
'vacay.companyHolidaysNoDeduct': 'Feriados da empresa não contam como dias de férias.',
|
||
'vacay.weekStart': 'Semana começa em',
|
||
'vacay.weekStartHint': 'Escolha se a semana começa na segunda-feira ou no domingo',
|
||
'vacay.carryOver': 'Acúmulo',
|
||
'vacay.carryOverHint': 'Levar automaticamente os dias de férias restantes para o ano seguinte',
|
||
'vacay.sharing': 'Compartilhamento',
|
||
'vacay.sharingHint': 'Compartilhe seu plano de férias com outros usuários do TREK',
|
||
'vacay.owner': 'Proprietário',
|
||
'vacay.shareEmailPlaceholder': 'E-mail do usuário TREK',
|
||
'vacay.shareSuccess': 'Plano compartilhado com sucesso',
|
||
'vacay.shareError': 'Não foi possível compartilhar o plano',
|
||
'vacay.dissolve': 'Encerrar fusão',
|
||
'vacay.dissolveHint': 'Separar os calendários novamente. Suas entradas serão mantidas.',
|
||
'vacay.dissolveAction': 'Encerrar',
|
||
'vacay.dissolved': 'Calendário separado',
|
||
'vacay.fusedWith': 'Fundido com',
|
||
'vacay.you': 'você',
|
||
'vacay.noData': 'Sem dados',
|
||
'vacay.changeColor': 'Alterar cor',
|
||
'vacay.inviteUser': 'Convidar usuário',
|
||
'vacay.inviteHint': 'Convide outro usuário TREK para compartilhar um calendário de férias combinado.',
|
||
'vacay.selectUser': 'Selecionar usuário',
|
||
'vacay.sendInvite': 'Enviar convite',
|
||
'vacay.inviteSent': 'Convite enviado',
|
||
'vacay.inviteError': 'Não foi possível enviar o convite',
|
||
'vacay.pending': 'pendente',
|
||
'vacay.noUsersAvailable': 'Nenhum usuário disponível',
|
||
'vacay.accept': 'Aceitar',
|
||
'vacay.decline': 'Recusar',
|
||
'vacay.acceptFusion': 'Aceitar e fundir',
|
||
'vacay.inviteTitle': 'Pedido de fusão',
|
||
'vacay.inviteWantsToFuse': 'quer compartilhar um calendário de férias com você.',
|
||
'vacay.fuseInfo1': 'Ambos verão todas as entradas de férias em um calendário compartilhado.',
|
||
'vacay.fuseInfo2': 'Ambos podem criar e editar entradas um do outro.',
|
||
'vacay.fuseInfo3': 'Ambos podem excluir entradas e alterar direitos de férias.',
|
||
'vacay.fuseInfo4': 'Configurações como feriados nacionais e da empresa são compartilhadas.',
|
||
'vacay.fuseInfo5': 'A fusão pode ser encerrada a qualquer momento por qualquer parte. Suas entradas serão preservadas.',
|
||
'nav.myTrips': 'Minhas viagens',
|
||
|
||
// Atlas addon
|
||
'atlas.subtitle': 'Sua pegada de viagens pelo mundo',
|
||
'atlas.countries': 'Países',
|
||
'atlas.trips': 'Viagens',
|
||
'atlas.places': 'Lugares',
|
||
'atlas.unmark': 'Remover',
|
||
'atlas.confirmMark': 'Marcar este país como visitado?',
|
||
'atlas.confirmUnmark': 'Remover este país da lista de visitados?',
|
||
'atlas.confirmUnmarkRegion': 'Remover esta região da lista de visitados?',
|
||
'atlas.markVisited': 'Marcar como visitado',
|
||
'atlas.markVisitedHint': 'Adicionar este país à lista de visitados',
|
||
'atlas.markRegionVisitedHint': 'Adicionar esta região à lista de visitados',
|
||
'atlas.addToBucket': 'Adicionar à lista de desejos',
|
||
'atlas.addPoi': 'Adicionar lugar',
|
||
'atlas.searchCountry': 'Buscar um país...',
|
||
'atlas.bucketNamePlaceholder': 'Nome (país, cidade, lugar…)',
|
||
'atlas.month': 'Mês',
|
||
'atlas.year': 'Ano',
|
||
'atlas.addToBucketHint': 'Salvar como lugar que você quer visitar',
|
||
'atlas.bucketWhen': 'Quando pretende visitar?',
|
||
'atlas.statsTab': 'Estatísticas',
|
||
'atlas.bucketTab': 'Lista de desejos',
|
||
'atlas.addBucket': 'Adicionar à lista de desejos',
|
||
'atlas.bucketNotesPlaceholder': 'Notas (opcional)',
|
||
'atlas.bucketEmpty': 'Sua lista de desejos está vazia',
|
||
'atlas.bucketEmptyHint': 'Adicione lugares que sonha em visitar',
|
||
'atlas.days': 'Dias',
|
||
'atlas.visitedCountries': 'Países visitados',
|
||
'atlas.cities': 'Cidades',
|
||
'atlas.noData': 'Ainda sem dados de viagem',
|
||
'atlas.noDataHint': 'Crie uma viagem e adicione lugares para ver o mapa mundial',
|
||
'atlas.lastTrip': 'Última viagem',
|
||
'atlas.nextTrip': 'Próxima viagem',
|
||
'atlas.daysLeft': 'dias restantes',
|
||
'atlas.streak': 'Sequência',
|
||
'atlas.years': 'anos',
|
||
'atlas.yearInRow': 'ano seguido',
|
||
'atlas.yearsInRow': 'anos seguidos',
|
||
'atlas.tripIn': 'viagem em',
|
||
'atlas.tripsIn': 'viagens em',
|
||
'atlas.since': 'desde',
|
||
'atlas.europe': 'Europa',
|
||
'atlas.asia': 'Ásia',
|
||
'atlas.northAmerica': 'América do Norte',
|
||
'atlas.southAmerica': 'América do Sul',
|
||
'atlas.africa': 'África',
|
||
'atlas.oceania': 'Oceania',
|
||
'atlas.other': 'Outro',
|
||
'atlas.firstVisit': 'Primeira viagem',
|
||
'atlas.lastVisitLabel': 'Última viagem',
|
||
'atlas.tripSingular': 'Viagem',
|
||
'atlas.tripPlural': 'Viagens',
|
||
'atlas.placeVisited': 'Lugar visitado',
|
||
'atlas.placesVisited': 'Lugares visitados',
|
||
|
||
// Trip Planner
|
||
'trip.tabs.plan': 'Plano',
|
||
'trip.tabs.transports': 'Transportes',
|
||
'trip.tabs.reservations': 'Reservas',
|
||
'trip.tabs.reservationsShort': 'Reservas',
|
||
'trip.tabs.packing': 'Lista de mala',
|
||
'trip.tabs.packingShort': 'Mala',
|
||
'trip.tabs.lists': 'Listas',
|
||
'trip.tabs.listsShort': 'Listas',
|
||
'trip.tabs.budget': 'Orçamento',
|
||
'trip.tabs.files': 'Arquivos',
|
||
'trip.loading': 'Carregando viagem...',
|
||
'trip.mobilePlan': 'Plano',
|
||
'trip.mobilePlaces': 'Lugares',
|
||
'trip.toast.placeUpdated': 'Lugar atualizado',
|
||
'trip.toast.placeAdded': 'Lugar adicionado',
|
||
'trip.toast.placeDeleted': 'Lugar excluído',
|
||
'trip.toast.selectDay': 'Selecione um dia primeiro',
|
||
'trip.toast.assignedToDay': 'Lugar atribuído ao dia',
|
||
'trip.toast.reorderError': 'Falha ao reordenar',
|
||
'trip.toast.reservationUpdated': 'Reserva atualizada',
|
||
'trip.toast.reservationAdded': 'Reserva adicionada',
|
||
'trip.toast.deleted': 'Excluído',
|
||
'trip.confirm.deletePlace': 'Tem certeza de que deseja excluir este lugar?',
|
||
'trip.confirm.deletePlaces': 'Excluir {count} lugares?',
|
||
'trip.toast.placesDeleted': '{count} lugares excluídos',
|
||
'trip.loadingPhotos': 'Carregando fotos dos lugares...',
|
||
|
||
// Day Plan Sidebar
|
||
'dayplan.emptyDay': 'Nenhum lugar planejado para este dia',
|
||
'dayplan.addNote': 'Adicionar nota',
|
||
'dayplan.editNote': 'Editar nota',
|
||
'dayplan.noteAdd': 'Adicionar nota',
|
||
'dayplan.noteEdit': 'Editar nota',
|
||
'dayplan.noteTitle': 'Nota',
|
||
'dayplan.noteSubtitle': 'Nota do dia',
|
||
'dayplan.totalCost': 'Custo total',
|
||
'dayplan.days': 'Dias',
|
||
'dayplan.dayN': 'Dia {n}',
|
||
'dayplan.calculating': 'Calculando...',
|
||
'dayplan.route': 'Rota',
|
||
'dayplan.optimize': 'Otimizar',
|
||
'dayplan.optimized': 'Rota otimizada',
|
||
'dayplan.routeError': 'Falha ao calcular a rota',
|
||
'dayplan.toast.needTwoPlaces': 'São necessários pelo menos dois lugares para otimizar a rota',
|
||
'dayplan.toast.routeOptimized': 'Rota otimizada',
|
||
'dayplan.toast.noGeoPlaces': 'Nenhum lugar com coordenadas para calcular a rota',
|
||
'dayplan.confirmed': 'Confirmada',
|
||
'dayplan.pendingRes': 'Pendente',
|
||
'dayplan.pdf': 'PDF',
|
||
'dayplan.pdfTooltip': 'Exportar plano do dia em PDF',
|
||
'dayplan.pdfError': 'Falha ao exportar PDF',
|
||
'dayplan.cannotReorderTransport': 'Reservas com horário fixo não podem ser reordenadas',
|
||
'dayplan.confirmRemoveTimeTitle': 'Remover horário?',
|
||
'dayplan.confirmRemoveTimeBody': 'Este lugar tem um horário fixo ({time}). Movê-lo removerá o horário e permitirá ordenação livre.',
|
||
'dayplan.confirmRemoveTimeAction': 'Remover horário e mover',
|
||
'dayplan.cannotDropOnTimed': 'Itens não podem ser colocados entre entradas com horário fixo',
|
||
'dayplan.cannotBreakChronology': 'Isso quebraria a ordem cronológica dos itens e reservas agendados',
|
||
|
||
// Places Sidebar
|
||
'places.addPlace': 'Adicionar lugar/atividade',
|
||
'places.importFile': 'Importar arquivo',
|
||
'places.sidebarDrop': 'Solte para importar',
|
||
'places.importFileHint': 'Importe arquivos .gpx, .kml ou .kmz de ferramentas como Google My Maps, Google Earth ou um rastreador GPS.',
|
||
'places.importFileDropHere': 'Clique para selecionar um arquivo ou arraste e solte aqui',
|
||
'places.importFileDropActive': 'Solte o arquivo para selecionar',
|
||
'places.importFileUnsupported': 'Tipo de arquivo não suportado. Use .gpx, .kml ou .kmz.',
|
||
'places.importFileTooLarge': 'O arquivo é muito grande. O tamanho máximo de upload é {maxMb} MB.',
|
||
'places.importFileError': 'Importação falhou',
|
||
'places.importAllSkipped': 'Todos os lugares já estavam na viagem.',
|
||
'places.gpxImported': '{count} lugares importados do GPX',
|
||
'places.gpxImportTypes': 'O que deseja importar?',
|
||
'places.gpxImportWaypoints': 'Pontos de caminho',
|
||
'places.gpxImportRoutes': 'Rotas',
|
||
'places.gpxImportTracks': 'Trilhas (com geometria de percurso)',
|
||
'places.gpxImportNoneSelected': 'Selecione pelo menos um tipo para importar.',
|
||
'places.kmlImportTypes': 'O que deseja importar?',
|
||
'places.kmlImportPoints': 'Pontos (Placemarks)',
|
||
'places.kmlImportPaths': 'Caminhos (LineStrings)',
|
||
'places.kmlImportNoneSelected': 'Selecione pelo menos um tipo.',
|
||
'places.selectionCount': '{count} selecionado(s)',
|
||
'places.deleteSelected': 'Excluir seleção',
|
||
'places.kmlKmzImported': '{count} lugares importados de KMZ/KML',
|
||
'places.urlResolved': 'Lugar importado da URL',
|
||
'places.importList': 'Importar lista',
|
||
'places.kmlKmzSummaryValues': 'Placemarks: {total} • Importados: {created} • Ignorados: {skipped}',
|
||
'places.importGoogleList': 'Lista Google',
|
||
'places.importNaverList': 'Lista Naver',
|
||
'places.googleListHint': 'Cole um link compartilhado de uma lista do Google Maps para importar todos os lugares.',
|
||
'places.googleListImported': '{count} lugares importados de "{list}"',
|
||
'places.googleListError': 'Falha ao importar lista do Google Maps',
|
||
'places.naverListHint': 'Cole um link compartilhado de uma lista do Naver Maps para importar todos os lugares.',
|
||
'places.naverListImported': '{count} lugares importados de "{list}"',
|
||
'places.naverListError': 'Falha ao importar lista do Naver Maps',
|
||
'places.viewDetails': 'Ver detalhes',
|
||
'places.assignToDay': 'Adicionar a qual dia?',
|
||
'places.all': 'Todos',
|
||
'places.unplanned': 'Não planejados',
|
||
'places.filterTracks': 'Trilhas',
|
||
'places.search': 'Buscar lugares...',
|
||
'places.allCategories': 'Todas as categorias',
|
||
'places.categoriesSelected': 'categorias',
|
||
'places.clearFilter': 'Limpar filtro',
|
||
'places.count': '{count} lugares',
|
||
'places.countSingular': '1 lugar',
|
||
'places.allPlanned': 'Todos os lugares estão planejados',
|
||
'places.noneFound': 'Nenhum lugar encontrado',
|
||
'places.editPlace': 'Editar lugar',
|
||
'places.formName': 'Nome',
|
||
'places.formNamePlaceholder': 'ex.: Torre Eiffel',
|
||
'places.formDescription': 'Descrição',
|
||
'places.formDescriptionPlaceholder': 'Breve descrição...',
|
||
'places.formAddress': 'Endereço',
|
||
'places.formAddressPlaceholder': 'Rua, cidade, país',
|
||
'places.formLat': 'Latitude (ex.: -23.5505)',
|
||
'places.formLng': 'Longitude (ex.: -46.6333)',
|
||
'places.formCategory': 'Categoria',
|
||
'places.noCategory': 'Sem categoria',
|
||
'places.categoryNamePlaceholder': 'Nome da categoria',
|
||
'places.formTime': 'Horário',
|
||
'places.startTime': 'Início',
|
||
'places.endTime': 'Fim',
|
||
'places.endTimeBeforeStart': 'O horário de fim é antes do início',
|
||
'places.timeCollision': 'Sobreposição de horário com:',
|
||
'places.formWebsite': 'Site',
|
||
'places.formNotes': 'Notas',
|
||
'places.formNotesPlaceholder': 'Notas pessoais...',
|
||
'places.formReservation': 'Reserva',
|
||
'places.reservationNotesPlaceholder': 'Notas da reserva, código de confirmação...',
|
||
'places.mapsSearchPlaceholder': 'Buscar lugares...',
|
||
'places.mapsSearchError': 'Falha na busca de lugares.',
|
||
'places.loadingDetails': 'Carregando detalhes do lugar…',
|
||
'places.osmHint': 'Busca via OpenStreetMap (sem fotos, horários ou avaliações). Adicione uma chave Google nas configurações para detalhes completos.',
|
||
'places.osmActive': 'Busca via OpenStreetMap (sem fotos, avaliações ou horário de funcionamento). Adicione uma chave Google em Configurações para mais dados.',
|
||
'places.categoryCreateError': 'Falha ao criar categoria',
|
||
'places.nameRequired': 'Digite um nome',
|
||
'places.saveError': 'Falha ao salvar',
|
||
// Place Inspector
|
||
'inspector.opened': 'Aberto',
|
||
'inspector.closed': 'Fechado',
|
||
'inspector.openingHours': 'Horário de funcionamento',
|
||
'inspector.showHours': 'Mostrar horário de funcionamento',
|
||
'inspector.files': 'Arquivos',
|
||
'inspector.filesCount': '{count} arquivos',
|
||
'inspector.removeFromDay': 'Remover do dia',
|
||
'inspector.remove': 'Remover',
|
||
'inspector.addToDay': 'Adicionar ao dia',
|
||
'inspector.confirmedRes': 'Reserva confirmada',
|
||
'inspector.pendingRes': 'Reserva pendente',
|
||
'inspector.google': 'Abrir no Google Maps',
|
||
'inspector.website': 'Abrir site',
|
||
'inspector.addRes': 'Reserva',
|
||
'inspector.editRes': 'Editar reserva',
|
||
'inspector.participants': 'Participantes',
|
||
'inspector.trackStats': 'Dados da trilha',
|
||
|
||
// Reservations
|
||
'reservations.title': 'Reservas',
|
||
'reservations.empty': 'Nenhuma reserva ainda',
|
||
'reservations.emptyHint': 'Adicione reservas de voos, hotéis e mais',
|
||
'reservations.add': 'Adicionar reserva',
|
||
'reservations.addManual': 'Reserva manual',
|
||
'reservations.placeHint': 'Dica: o ideal é criar reservas a partir de um lugar para vinculá-las ao plano do dia.',
|
||
'reservations.confirmed': 'Confirmada',
|
||
'reservations.pending': 'Pendente',
|
||
'reservations.summary': '{confirmed} confirmada(s), {pending} pendente(s)',
|
||
'reservations.fromPlan': 'Do plano',
|
||
'reservations.showFiles': 'Mostrar arquivos',
|
||
'reservations.editTitle': 'Editar reserva',
|
||
'reservations.status': 'Status',
|
||
'reservations.datetime': 'Data e hora',
|
||
'reservations.startTime': 'Horário de início',
|
||
'reservations.endTime': 'Horário de término',
|
||
'reservations.date': 'Data',
|
||
'reservations.time': 'Hora',
|
||
'reservations.timeAlt': 'Hora (alternativa, ex.: 19:30)',
|
||
'reservations.notes': 'Notas',
|
||
'reservations.notesPlaceholder': 'Notas adicionais...',
|
||
'reservations.meta.airline': 'Companhia aérea',
|
||
'reservations.meta.flightNumber': 'Nº do voo',
|
||
'reservations.meta.from': 'De',
|
||
'reservations.meta.to': 'Para',
|
||
'reservations.needsReview': 'Verificar',
|
||
'reservations.needsReviewHint': 'Aeroporto não pôde ser identificado automaticamente — confirme o local.',
|
||
'reservations.searchLocation': 'Buscar estação, porto, endereço...',
|
||
'airport.searchPlaceholder': 'Código ou cidade do aeroporto (ex. FRA)',
|
||
'map.connections': 'Conexões',
|
||
'map.showConnections': 'Mostrar rotas de reservas',
|
||
'map.hideConnections': 'Ocultar rotas de reservas',
|
||
'settings.bookingLabels': 'Rótulos das rotas de reservas',
|
||
'settings.bookingLabelsHint': 'Mostra nomes de estações / aeroportos no mapa. Desativado, apenas o ícone aparece.',
|
||
'reservations.meta.trainNumber': 'Nº do trem',
|
||
'reservations.meta.platform': 'Plataforma',
|
||
'reservations.meta.seat': 'Assento',
|
||
'reservations.meta.checkIn': 'Check-in',
|
||
'reservations.meta.checkInUntil': 'Check-in até',
|
||
'reservations.meta.checkOut': 'Check-out',
|
||
'reservations.meta.linkAccommodation': 'Hospedagem',
|
||
'reservations.meta.pickAccommodation': 'Vincular à hospedagem',
|
||
'reservations.meta.noAccommodation': 'Nenhuma',
|
||
'reservations.meta.hotelPlace': 'Hospedagem',
|
||
'reservations.meta.pickHotel': 'Selecionar hospedagem',
|
||
'reservations.meta.fromDay': 'De',
|
||
'reservations.meta.toDay': 'Até',
|
||
'reservations.meta.selectDay': 'Selecionar dia',
|
||
'reservations.type.flight': 'Voo',
|
||
'reservations.type.hotel': 'Hospedagem',
|
||
'reservations.type.restaurant': 'Restaurante',
|
||
'reservations.type.train': 'Trem',
|
||
'reservations.type.car': 'Carro',
|
||
'reservations.type.cruise': 'Cruzeiro',
|
||
'reservations.type.event': 'Evento',
|
||
'reservations.type.tour': 'Passeio',
|
||
'reservations.type.other': 'Outro',
|
||
'reservations.confirm.delete': 'Tem certeza de que deseja excluir a reserva "{name}"?',
|
||
'reservations.confirm.deleteTitle': 'Excluir reserva?',
|
||
'reservations.confirm.deleteBody': '"{name}" será excluído permanentemente.',
|
||
'reservations.toast.updated': 'Reserva atualizada',
|
||
'reservations.toast.removed': 'Reserva excluída',
|
||
'reservations.toast.fileUploaded': 'Arquivo enviado',
|
||
'reservations.toast.uploadError': 'Falha no envio',
|
||
'reservations.newTitle': 'Nova reserva',
|
||
'reservations.bookingType': 'Tipo de reserva',
|
||
'reservations.titleLabel': 'Título',
|
||
'reservations.titlePlaceholder': 'ex.: LATAM LA800, Hotel Copacabana...',
|
||
'reservations.locationAddress': 'Local / endereço',
|
||
'reservations.locationPlaceholder': 'Endereço, aeroporto, hotel...',
|
||
'reservations.confirmationCode': 'Código da reserva',
|
||
'reservations.confirmationPlaceholder': 'ex.: ABC12345',
|
||
'reservations.day': 'Dia',
|
||
'reservations.noDay': 'Sem dia',
|
||
'reservations.place': 'Lugar',
|
||
'reservations.noPlace': 'Sem lugar',
|
||
'reservations.pendingSave': 'será salvo…',
|
||
'reservations.uploading': 'Enviando...',
|
||
'reservations.attachFile': 'Anexar arquivo',
|
||
'reservations.linkExisting': 'Vincular arquivo existente',
|
||
'reservations.toast.saveError': 'Falha ao salvar',
|
||
'reservations.toast.updateError': 'Falha ao atualizar',
|
||
'reservations.toast.deleteError': 'Falha ao excluir',
|
||
'reservations.confirm.remove': 'Remover a reserva "{name}"?',
|
||
'reservations.linkAssignment': 'Vincular à atribuição do dia',
|
||
'reservations.pickAssignment': 'Selecione uma atribuição do seu plano...',
|
||
'reservations.noAssignment': 'Sem vínculo (avulsa)',
|
||
'reservations.price': 'Preço',
|
||
'reservations.budgetCategory': 'Categoria de orçamento',
|
||
'reservations.budgetCategoryPlaceholder': 'ex. Transporte, Acomodação',
|
||
'reservations.budgetCategoryAuto': 'Automático (pelo tipo de reserva)',
|
||
'reservations.budgetHint': 'Uma entrada de orçamento será criada automaticamente ao salvar.',
|
||
'reservations.departureDate': 'Partida',
|
||
'reservations.arrivalDate': 'Chegada',
|
||
'reservations.departureTime': 'Hora partida',
|
||
'reservations.arrivalTime': 'Hora chegada',
|
||
'reservations.pickupDate': 'Retirada',
|
||
'reservations.returnDate': 'Devolução',
|
||
'reservations.pickupTime': 'Hora retirada',
|
||
'reservations.returnTime': 'Hora devolução',
|
||
'reservations.endDate': 'Data final',
|
||
'reservations.meta.departureTimezone': 'TZ partida',
|
||
'reservations.meta.arrivalTimezone': 'TZ chegada',
|
||
'reservations.span.departure': 'Partida',
|
||
'reservations.span.arrival': 'Chegada',
|
||
'reservations.span.inTransit': 'Em trânsito',
|
||
'reservations.span.pickup': 'Retirada',
|
||
'reservations.span.return': 'Devolução',
|
||
'reservations.span.active': 'Ativo',
|
||
'reservations.span.start': 'Início',
|
||
'reservations.span.end': 'Fim',
|
||
'reservations.span.ongoing': 'Em andamento',
|
||
'reservations.validation.endBeforeStart': 'A data/hora final deve ser posterior à data/hora inicial',
|
||
'reservations.addBooking': 'Adicionar reserva',
|
||
|
||
// Budget
|
||
'budget.title': 'Orçamento',
|
||
'budget.exportCsv': 'Exportar CSV',
|
||
'budget.emptyTitle': 'Nenhum orçamento criado ainda',
|
||
'budget.emptyText': 'Crie categorias e lançamentos para planejar o orçamento da viagem',
|
||
'budget.emptyPlaceholder': 'Nome da categoria...',
|
||
'budget.createCategory': 'Criar categoria',
|
||
'budget.category': 'Categoria',
|
||
'budget.categoryName': 'Nome da categoria',
|
||
'budget.table.name': 'Nome',
|
||
'budget.table.total': 'Total',
|
||
'budget.table.persons': 'Pessoas',
|
||
'budget.table.days': 'Dias',
|
||
'budget.table.perPerson': 'Por pessoa',
|
||
'budget.table.perDay': 'Por dia',
|
||
'budget.table.perPersonDay': 'P. p. / dia',
|
||
'budget.table.note': 'Obs.',
|
||
'budget.table.date': 'Data',
|
||
'budget.newEntry': 'Novo lançamento',
|
||
'budget.defaultEntry': 'Novo lançamento',
|
||
'budget.defaultCategory': 'Nova categoria',
|
||
'budget.total': 'Total',
|
||
'budget.totalBudget': 'Orçamento total',
|
||
'budget.byCategory': 'Por categoria',
|
||
'budget.editTooltip': 'Clique para editar',
|
||
'budget.linkedToReservation': 'Vinculado a uma reserva — edite o nome por lá',
|
||
'budget.confirm.deleteCategory': 'Excluir a categoria "{name}" com {count} lançamento(s)?',
|
||
'budget.deleteCategory': 'Excluir categoria',
|
||
'budget.perPerson': 'Por pessoa',
|
||
'budget.paid': 'Pago',
|
||
'budget.open': 'Em aberto',
|
||
'budget.noMembers': 'Nenhum membro atribuído',
|
||
'budget.settlement': 'Acerto',
|
||
'budget.settlementInfo': 'Clique no avatar de um membro em um item do orçamento para marcá-lo em verde — significa que ele pagou. O acerto mostra quem deve quanto a quem.',
|
||
'budget.netBalances': 'Saldos líquidos',
|
||
|
||
// Files
|
||
'files.title': 'Arquivos',
|
||
'files.pageTitle': 'Arquivos e documentos',
|
||
'files.subtitle': '{count} arquivos para {trip}',
|
||
'files.download': 'Baixar',
|
||
'files.openError': 'Não foi possível abrir o arquivo',
|
||
'files.downloadPdf': 'Baixar PDF',
|
||
'files.count': '{count} arquivos',
|
||
'files.countSingular': '1 arquivo',
|
||
'files.uploaded': '{count} enviado(s)',
|
||
'files.uploadError': 'Falha no envio',
|
||
'files.dropzone': 'Solte os arquivos aqui',
|
||
'files.dropzoneHint': 'ou clique para escolher',
|
||
'files.allowedTypes': 'Imagens, PDF, DOC, DOCX, XLS, XLSX, TXT, CSV · Máx. 50 MB',
|
||
'files.uploading': 'Enviando...',
|
||
'files.filterAll': 'Todos',
|
||
'files.filterPdf': 'PDFs',
|
||
'files.filterImages': 'Imagens',
|
||
'files.filterDocs': 'Documentos',
|
||
'files.filterCollab': 'Notas Colab',
|
||
'files.sourceCollab': 'Das notas Colab',
|
||
'files.empty': 'Nenhum arquivo ainda',
|
||
'files.emptyHint': 'Envie arquivos para anexá-los à viagem',
|
||
'files.openTab': 'Abrir em nova aba',
|
||
'files.confirm.delete': 'Excluir este arquivo?',
|
||
'files.toast.deleted': 'Arquivo excluído',
|
||
'files.toast.deleteError': 'Falha ao excluir arquivo',
|
||
'files.sourcePlan': 'Plano do dia',
|
||
'files.sourceBooking': 'Reserva',
|
||
'files.sourceTransport': 'Transporte',
|
||
'files.attach': 'Anexar',
|
||
'files.pasteHint': 'Você também pode colar imagens da área de transferência (Ctrl+V)',
|
||
'files.trash': 'Lixeira',
|
||
'files.trashEmpty': 'A lixeira está vazia',
|
||
'files.emptyTrash': 'Esvaziar lixeira',
|
||
'files.restore': 'Restaurar',
|
||
'files.star': 'Favoritar',
|
||
'files.unstar': 'Remover favorito',
|
||
'files.assign': 'Atribuir',
|
||
'files.assignTitle': 'Atribuir arquivo',
|
||
'files.assignPlace': 'Lugar',
|
||
'files.assignBooking': 'Reserva',
|
||
'files.assignTransport': 'Transporte',
|
||
'files.unassigned': 'Não atribuído',
|
||
'files.unlink': 'Remover vínculo',
|
||
'files.toast.trashed': 'Movido para a lixeira',
|
||
'files.toast.restored': 'Arquivo restaurado',
|
||
'files.toast.trashEmptied': 'Lixeira esvaziada',
|
||
'files.toast.assigned': 'Arquivo atribuído',
|
||
'files.toast.assignError': 'Falha na atribuição',
|
||
'files.toast.restoreError': 'Falha ao restaurar',
|
||
'files.confirm.permanentDelete': 'Excluir permanentemente este arquivo? Não é possível desfazer.',
|
||
'files.confirm.emptyTrash': 'Excluir permanentemente todos os arquivos na lixeira? Não é possível desfazer.',
|
||
'files.noteLabel': 'Nota',
|
||
'files.notePlaceholder': 'Adicione uma nota...',
|
||
|
||
// Packing
|
||
'packing.title': 'Lista de mala',
|
||
'packing.empty': 'A lista de mala está vazia',
|
||
'packing.import': 'Importar',
|
||
'packing.importTitle': 'Importar lista de bagagem',
|
||
'packing.importHint': 'Um item por linha. Formato: Categoria, Nome, Peso (g), Bolsa, checked/unchecked (opcional)',
|
||
'packing.importPlaceholder': 'Higiene, Escova de dentes\nRoupas, Camisetas, 200\nDocumentos, Passaporte, , Mala de mão\nEletrônicos, Carregador, 50, Mala, checked',
|
||
'packing.importCsv': 'Carregar CSV/TXT',
|
||
'packing.importAction': 'Importar {count}',
|
||
'packing.importSuccess': '{count} itens importados',
|
||
'packing.importError': 'Falha na importação',
|
||
'packing.importEmpty': 'Nenhum item para importar',
|
||
'packing.progress': '{packed} de {total} na mala ({percent}%)',
|
||
'packing.clearChecked': 'Remover {count} marcado(s)',
|
||
'packing.clearCheckedShort': 'Remover {count}',
|
||
'packing.suggestions': 'Sugestões',
|
||
'packing.suggestionsTitle': 'Adicionar sugestões',
|
||
'packing.allSuggested': 'Todas as sugestões adicionadas',
|
||
'packing.allPacked': 'Tudo na mala!',
|
||
'packing.addPlaceholder': 'Adicionar item...',
|
||
'packing.categoryPlaceholder': 'Categoria...',
|
||
'packing.saveAsTemplate': 'Salvar como modelo',
|
||
'packing.templateName': 'Nome do modelo',
|
||
'packing.templateSaved': 'Lista de bagagem salva como modelo',
|
||
'packing.filterAll': 'Todos',
|
||
'packing.filterOpen': 'Abertos',
|
||
'packing.filterDone': 'Prontos',
|
||
'packing.emptyTitle': 'A lista de mala está vazia',
|
||
'packing.emptyHint': 'Adicione itens ou use as sugestões',
|
||
'packing.emptyFiltered': 'Nenhum item corresponde ao filtro',
|
||
'packing.menuRename': 'Renomear',
|
||
'packing.menuCheckAll': 'Marcar todos',
|
||
'packing.menuUncheckAll': 'Desmarcar todos',
|
||
'packing.menuDeleteCat': 'Excluir categoria',
|
||
'packing.noMembers': 'Nenhum membro na viagem',
|
||
'packing.addItem': 'Adicionar item',
|
||
'packing.addItemPlaceholder': 'Nome do item...',
|
||
'packing.addCategory': 'Adicionar categoria',
|
||
'packing.newCategoryPlaceholder': 'Nome da categoria (ex.: Roupas)',
|
||
'packing.applyTemplate': 'Aplicar modelo',
|
||
'packing.template': 'Modelo',
|
||
'packing.templateApplied': '{count} itens adicionados do modelo',
|
||
'packing.templateError': 'Falha ao aplicar modelo',
|
||
'packing.bags': 'Malas',
|
||
'packing.noBag': 'Sem mala',
|
||
'packing.totalWeight': 'Peso total',
|
||
'packing.bagName': 'Nome da mala...',
|
||
'packing.addBag': 'Adicionar mala',
|
||
'packing.changeCategory': 'Alterar categoria',
|
||
'packing.confirm.clearChecked': 'Remover {count} item(ns) marcado(s)?',
|
||
'packing.confirm.deleteCat': 'Excluir a categoria "{name}" com {count} item(ns)?',
|
||
'packing.defaultCategory': 'Outros',
|
||
'packing.toast.saveError': 'Falha ao salvar',
|
||
'packing.toast.deleteError': 'Falha ao excluir',
|
||
'packing.toast.renameError': 'Falha ao renomear',
|
||
'packing.toast.addError': 'Falha ao adicionar',
|
||
|
||
// Packing suggestions
|
||
'packing.suggestions.items': [
|
||
{ name: 'Passaporte', category: 'Documentos' },
|
||
{ name: 'Documento de identidade', category: 'Documentos' },
|
||
{ name: 'Seguro viagem', category: 'Documentos' },
|
||
{ name: 'Passagens aéreas', category: 'Documentos' },
|
||
{ name: 'Cartão de crédito', category: 'Finanças' },
|
||
{ name: 'Dinheiro', category: 'Finanças' },
|
||
{ name: 'Visto', category: 'Documentos' },
|
||
{ name: 'Camisetas', category: 'Roupas' },
|
||
{ name: 'Calças', category: 'Roupas' },
|
||
{ name: 'Roupa íntima', category: 'Roupas' },
|
||
{ name: 'Meias', category: 'Roupas' },
|
||
{ name: 'Jaqueta', category: 'Roupas' },
|
||
{ name: 'Pijama', category: 'Roupas' },
|
||
{ name: 'Traje de banho', category: 'Roupas' },
|
||
{ name: 'Capa de chuva', category: 'Roupas' },
|
||
{ name: 'Sapatos confortáveis', category: 'Roupas' },
|
||
{ name: 'Escova de dentes', category: 'Higiene' },
|
||
{ name: 'Creme dental', category: 'Higiene' },
|
||
{ name: 'Shampoo', category: 'Higiene' },
|
||
{ name: 'Desodorante', category: 'Higiene' },
|
||
{ name: 'Protetor solar', category: 'Higiene' },
|
||
{ name: 'Aparelho de barbear', category: 'Higiene' },
|
||
{ name: 'Carregador', category: 'Eletrônicos' },
|
||
{ name: 'Power bank', category: 'Eletrônicos' },
|
||
{ name: 'Fones de ouvido', category: 'Eletrônicos' },
|
||
{ name: 'Adaptador de viagem', category: 'Eletrônicos' },
|
||
{ name: 'Câmera', category: 'Eletrônicos' },
|
||
{ name: 'Medicamento para dor', category: 'Saúde' },
|
||
{ name: 'Curativos', category: 'Saúde' },
|
||
{ name: 'Desinfetante', category: 'Saúde' },
|
||
],
|
||
|
||
// Members / Sharing
|
||
'members.shareTrip': 'Compartilhar viagem',
|
||
'members.inviteUser': 'Convidar usuário',
|
||
'members.selectUser': 'Selecionar usuário…',
|
||
'members.invite': 'Convidar',
|
||
'members.allHaveAccess': 'Todos os usuários já têm acesso.',
|
||
'members.access': 'Acesso',
|
||
'members.person': 'pessoa',
|
||
'members.persons': 'pessoas',
|
||
'members.you': 'você',
|
||
'members.owner': 'Proprietário',
|
||
'members.leaveTrip': 'Sair da viagem',
|
||
'members.removeAccess': 'Remover acesso',
|
||
'members.confirmLeave': 'Sair da viagem? Você perderá o acesso.',
|
||
'members.confirmRemove': 'Remover o acesso deste usuário?',
|
||
'members.loadError': 'Falha ao carregar membros',
|
||
'members.added': 'adicionado',
|
||
'members.addError': 'Falha ao adicionar',
|
||
'members.removed': 'Membro removido',
|
||
'members.removeError': 'Falha ao remover',
|
||
|
||
// Categories (Admin)
|
||
'categories.title': 'Categorias',
|
||
'categories.subtitle': 'Gerenciar categorias de lugares',
|
||
'categories.new': 'Nova categoria',
|
||
'categories.empty': 'Nenhuma categoria ainda',
|
||
'categories.namePlaceholder': 'Nome da categoria',
|
||
'categories.icon': 'Ícone',
|
||
'categories.color': 'Cor',
|
||
'categories.customColor': 'Escolher cor personalizada',
|
||
'categories.preview': 'Pré-visualização',
|
||
'categories.defaultName': 'Categoria',
|
||
'categories.update': 'Atualizar',
|
||
'categories.create': 'Criar',
|
||
'categories.confirm.delete': 'Excluir categoria? Os lugares desta categoria não serão excluídos.',
|
||
'categories.toast.loadError': 'Falha ao carregar categorias',
|
||
'categories.toast.nameRequired': 'Digite um nome',
|
||
'categories.toast.updated': 'Categoria atualizada',
|
||
'categories.toast.created': 'Categoria criada',
|
||
'categories.toast.saveError': 'Falha ao salvar',
|
||
'categories.toast.deleted': 'Categoria excluída',
|
||
'categories.toast.deleteError': 'Falha ao excluir',
|
||
|
||
// Backup (Admin)
|
||
'backup.title': 'Backup de dados',
|
||
'backup.subtitle': 'Banco de dados e todos os arquivos enviados',
|
||
'backup.refresh': 'Atualizar',
|
||
'backup.upload': 'Enviar backup',
|
||
'backup.uploading': 'Enviando…',
|
||
'backup.create': 'Criar backup',
|
||
'backup.creating': 'Criando…',
|
||
'backup.empty': 'Nenhum backup ainda',
|
||
'backup.createFirst': 'Criar primeiro backup',
|
||
'backup.download': 'Baixar',
|
||
'backup.restore': 'Restaurar',
|
||
'backup.confirm.restore': 'Restaurar o backup "{name}"?\n\nTodos os dados atuais serão substituídos pelo backup.',
|
||
'backup.confirm.uploadRestore': 'Enviar e restaurar o arquivo "{name}"?\n\nTodos os dados atuais serão sobrescritos.',
|
||
'backup.confirm.delete': 'Excluir o backup "{name}"?',
|
||
'backup.toast.loadError': 'Falha ao carregar backups',
|
||
'backup.toast.created': 'Backup criado com sucesso',
|
||
'backup.toast.createError': 'Falha ao criar backup',
|
||
'backup.toast.restored': 'Backup restaurado. A página será recarregada…',
|
||
'backup.toast.restoreError': 'Falha ao restaurar',
|
||
'backup.toast.uploadError': 'Falha no envio',
|
||
'backup.toast.deleted': 'Backup excluído',
|
||
'backup.toast.deleteError': 'Falha ao excluir',
|
||
'backup.toast.downloadError': 'Falha no download',
|
||
'backup.toast.settingsSaved': 'Configurações de backup automático salvas',
|
||
'backup.toast.settingsError': 'Falha ao salvar configurações',
|
||
'backup.auto.title': 'Backup automático',
|
||
'backup.auto.subtitle': 'Backup automático em agenda',
|
||
'backup.auto.enable': 'Ativar backup automático',
|
||
'backup.auto.enableHint': 'Backups serão criados automaticamente conforme a agenda escolhida',
|
||
'backup.auto.interval': 'Intervalo',
|
||
'backup.auto.hour': 'Executar no horário',
|
||
'backup.auto.hourHint': 'Horário local do servidor (formato {format})',
|
||
'backup.auto.dayOfWeek': 'Dia da semana',
|
||
'backup.auto.dayOfMonth': 'Dia do mês',
|
||
'backup.auto.dayOfMonthHint': 'Limitado a 1–28 para compatibilidade com todos os meses',
|
||
'backup.auto.scheduleSummary': 'Agenda',
|
||
'backup.auto.summaryDaily': 'Todos os dias às {hour}:00',
|
||
'backup.auto.summaryWeekly': 'Toda {day} às {hour}:00',
|
||
'backup.auto.summaryMonthly': 'Dia {day} de cada mês às {hour}:00',
|
||
'backup.auto.envLocked': 'Docker',
|
||
'backup.auto.envLockedHint': 'O backup automático é configurado via variáveis de ambiente Docker. Para alterar essas configurações, atualize o docker-compose.yml e reinicie o contêiner.',
|
||
'backup.auto.copyEnv': 'Copiar variáveis de ambiente Docker',
|
||
'backup.auto.envCopied': 'Variáveis de ambiente Docker copiadas para a área de transferência',
|
||
'backup.auto.keepLabel': 'Excluir backups antigos após',
|
||
'backup.dow.sunday': 'Dom',
|
||
'backup.dow.monday': 'Seg',
|
||
'backup.dow.tuesday': 'Ter',
|
||
'backup.dow.wednesday': 'Qua',
|
||
'backup.dow.thursday': 'Qui',
|
||
'backup.dow.friday': 'Sex',
|
||
'backup.dow.saturday': 'Sáb',
|
||
'backup.interval.hourly': 'A cada hora',
|
||
'backup.interval.daily': 'Diário',
|
||
'backup.interval.weekly': 'Semanal',
|
||
'backup.interval.monthly': 'Mensal',
|
||
'backup.keep.1day': '1 dia',
|
||
'backup.keep.3days': '3 dias',
|
||
'backup.keep.7days': '7 dias',
|
||
'backup.keep.14days': '14 dias',
|
||
'backup.keep.30days': '30 dias',
|
||
'backup.keep.forever': 'Manter para sempre',
|
||
|
||
// Photos
|
||
'photos.title': 'Fotos',
|
||
'photos.subtitle': '{count} fotos para {trip}',
|
||
'photos.dropHere': 'Arraste fotos aqui...',
|
||
'photos.dropHereActive': 'Arraste fotos aqui',
|
||
'photos.captionForAll': 'Legenda (para todos)',
|
||
'photos.captionPlaceholder': 'Legenda opcional...',
|
||
'photos.addCaption': 'Adicionar legenda...',
|
||
'photos.allDays': 'Todos os dias',
|
||
'photos.noPhotos': 'Nenhuma foto ainda',
|
||
'photos.uploadHint': 'Envie suas fotos de viagem',
|
||
'photos.clickToSelect': 'ou clique para selecionar',
|
||
'photos.linkPlace': 'Vincular lugar',
|
||
'photos.noPlace': 'Sem lugar',
|
||
'photos.uploadN': 'Enviar {n} foto(s)',
|
||
'photos.linkDay': 'Vincular dia',
|
||
'photos.noDay': 'Nenhum dia',
|
||
'photos.dayLabel': 'Dia {number}',
|
||
'photos.photoSelected': 'Foto selecionada',
|
||
'photos.photosSelected': 'Fotos selecionadas',
|
||
'photos.fileTypeHint': 'JPG, PNG, WebP · máx. 10 MB · até 30 fotos',
|
||
|
||
// Backup restore modal
|
||
'backup.restoreConfirmTitle': 'Restaurar backup?',
|
||
'backup.restoreWarning': 'Todos os dados atuais (viagens, lugares, usuários, envios) serão permanentemente substituídos pelo backup. Esta ação não pode ser desfeita.',
|
||
'backup.restoreTip': 'Dica: crie um backup do estado atual antes de restaurar.',
|
||
'backup.restoreConfirm': 'Sim, restaurar',
|
||
|
||
// PDF
|
||
'pdf.travelPlan': 'Plano de viagem',
|
||
'pdf.planned': 'Planejado',
|
||
'pdf.costLabel': 'Custo (EUR)',
|
||
'pdf.preview': 'Pré-visualização do PDF',
|
||
'pdf.saveAsPdf': 'Salvar como PDF',
|
||
|
||
// Planner
|
||
'planner.places': 'Lugares',
|
||
'planner.bookings': 'Reservas',
|
||
'planner.packingList': 'Lista de mala',
|
||
'planner.documents': 'Documentos',
|
||
'planner.dayPlan': 'Plano do dia',
|
||
'planner.reservations': 'Reservas',
|
||
'planner.minTwoPlaces': 'São necessários pelo menos 2 lugares com coordenadas',
|
||
'planner.noGeoPlaces': 'Nenhum lugar com coordenadas disponível',
|
||
'planner.routeCalculated': 'Rota calculada',
|
||
'planner.routeCalcFailed': 'Não foi possível calcular a rota',
|
||
'planner.routeError': 'Erro ao calcular a rota',
|
||
'planner.icsExportFailed': 'Falha ao exportar ICS',
|
||
'planner.routeOptimized': 'Rota otimizada',
|
||
'planner.reservationUpdated': 'Reserva atualizada',
|
||
'planner.reservationAdded': 'Reserva adicionada',
|
||
'planner.confirmDeleteReservation': 'Excluir reserva?',
|
||
'planner.reservationDeleted': 'Reserva excluída',
|
||
'planner.days': 'Dias',
|
||
'planner.allPlaces': 'Todos os lugares',
|
||
'planner.totalPlaces': '{n} lugares no total',
|
||
'planner.noDaysPlanned': 'Nenhum dia planejado ainda',
|
||
'planner.editTrip': 'Editar viagem \u2192',
|
||
'planner.placeOne': '1 lugar',
|
||
'planner.placeN': '{n} lugares',
|
||
'planner.addNote': 'Adicionar nota',
|
||
'planner.noEntries': 'Nenhuma entrada neste dia',
|
||
'planner.addPlace': 'Adicionar lugar/atividade',
|
||
'planner.addPlaceShort': '+ Adicionar lugar/atividade',
|
||
'planner.resPending': 'Reserva pendente · ',
|
||
'planner.resConfirmed': 'Reserva confirmada · ',
|
||
'planner.notePlaceholder': 'Nota\u2026',
|
||
'planner.noteTimePlaceholder': 'Horário (opcional)',
|
||
'planner.noteExamplePlaceholder': 'ex.: metrô às 14:30 da estação central, barco do cais 7, pausa para almoço\u2026',
|
||
'planner.totalCost': 'Custo total',
|
||
'planner.searchPlaces': 'Buscar lugares\u2026',
|
||
'planner.allCategories': 'Todas as categorias',
|
||
'planner.noPlacesFound': 'Nenhum lugar encontrado',
|
||
'planner.addFirstPlace': 'Adicionar primeiro lugar',
|
||
'planner.noReservations': 'Nenhuma reserva',
|
||
'planner.addFirstReservation': 'Adicionar primeira reserva',
|
||
'planner.new': 'Novo',
|
||
'planner.addToDay': '+ Dia',
|
||
'planner.calculating': 'Calculando\u2026',
|
||
'planner.route': 'Rota',
|
||
'planner.optimize': 'Otimizar',
|
||
'planner.openGoogleMaps': 'Abrir no Google Maps',
|
||
'planner.selectDayHint': 'Selecione um dia na lista à esquerda para ver o plano do dia',
|
||
'planner.noPlacesForDay': 'Nenhum lugar neste dia ainda',
|
||
'planner.addPlacesLink': 'Adicionar lugares \u2192',
|
||
'planner.minTotal': 'mín. total',
|
||
'planner.noReservation': 'Sem reserva',
|
||
'planner.removeFromDay': 'Remover do dia',
|
||
'planner.addToThisDay': 'Adicionar ao dia',
|
||
'planner.overview': 'Visão geral',
|
||
'planner.noDays': 'Nenhum dia ainda',
|
||
'planner.editTripToAddDays': 'Edite a viagem para adicionar dias',
|
||
'planner.dayCount': '{n} dias',
|
||
'planner.clickToUnlock': 'Clique para desbloquear',
|
||
'planner.keepPosition': 'Manter posição durante a otimização da rota',
|
||
'planner.dayDetails': 'Detalhes do dia',
|
||
'planner.dayN': 'Dia {n}',
|
||
|
||
// Dashboard Stats
|
||
'stats.countries': 'Países',
|
||
'stats.cities': 'Cidades',
|
||
'stats.trips': 'Viagens',
|
||
'stats.places': 'Lugares',
|
||
'stats.worldProgress': 'Progresso no mundo',
|
||
'stats.visited': 'visitados',
|
||
'stats.remaining': 'restantes',
|
||
'stats.visitedCountries': 'Países visitados',
|
||
|
||
// Day Detail Panel
|
||
'day.precipProb': 'Probabilidade de chuva',
|
||
'day.precipitation': 'Precipitação',
|
||
'day.wind': 'Vento',
|
||
'day.sunrise': 'Nascer do sol',
|
||
'day.sunset': 'Pôr do sol',
|
||
'day.hourlyForecast': 'Previsão por hora',
|
||
'day.climateHint': 'Médias históricas — previsão real disponível até 16 dias desta data.',
|
||
'day.noWeather': 'Sem dados meteorológicos. Adicione um lugar com coordenadas.',
|
||
'day.overview': 'Resumo do dia',
|
||
'day.accommodation': 'Hospedagem',
|
||
'day.addAccommodation': 'Adicionar hospedagem',
|
||
'day.hotelDayRange': 'Aplicar aos dias',
|
||
'day.noPlacesForHotel': 'Adicione lugares à viagem primeiro',
|
||
'day.allDays': 'Todos',
|
||
'day.checkIn': 'Check-in',
|
||
'day.checkInUntil': 'Até',
|
||
'day.checkOut': 'Check-out',
|
||
'day.confirmation': 'Confirmação',
|
||
'day.editAccommodation': 'Editar hospedagem',
|
||
'day.reservations': 'Reservas',
|
||
|
||
// Collab Addon
|
||
'collab.tabs.chat': 'Chat',
|
||
'collab.tabs.notes': 'Notas',
|
||
'collab.tabs.polls': 'Enquetes',
|
||
'collab.whatsNext.title': 'Próximos passos',
|
||
'collab.whatsNext.today': 'Hoje',
|
||
'collab.whatsNext.tomorrow': 'Amanhã',
|
||
'collab.whatsNext.empty': 'Nenhuma atividade próxima',
|
||
'collab.whatsNext.until': 'até',
|
||
'collab.whatsNext.emptyHint': 'Atividades com horário aparecerão aqui',
|
||
'collab.chat.send': 'Enviar',
|
||
'collab.chat.placeholder': 'Digite uma mensagem...',
|
||
'collab.chat.empty': 'Inicie a conversa',
|
||
'collab.chat.emptyHint': 'As mensagens são compartilhadas com todos os membros da viagem',
|
||
'collab.chat.emptyDesc': 'Compartilhe ideias, planos e atualizações com o grupo',
|
||
'collab.chat.today': 'Hoje',
|
||
'collab.chat.yesterday': 'Ontem',
|
||
'collab.chat.deletedMessage': 'apagou uma mensagem',
|
||
'collab.chat.reply': 'Responder',
|
||
'collab.chat.loadMore': 'Carregar mensagens antigas',
|
||
'collab.chat.justNow': 'agora mesmo',
|
||
'collab.chat.minutesAgo': 'há {n} min',
|
||
'collab.chat.hoursAgo': 'há {n} h',
|
||
'collab.notes.title': 'Notas',
|
||
'collab.notes.new': 'Nova nota',
|
||
'collab.notes.empty': 'Nenhuma nota ainda',
|
||
'collab.notes.emptyHint': 'Comece a registrar ideias e planos',
|
||
'collab.notes.all': 'Todas',
|
||
'collab.notes.titlePlaceholder': 'Título da nota',
|
||
'collab.notes.contentPlaceholder': 'Escreva algo...',
|
||
'collab.notes.categoryPlaceholder': 'Categoria',
|
||
'collab.notes.newCategory': 'Nova categoria...',
|
||
'collab.notes.category': 'Categoria',
|
||
'collab.notes.noCategory': 'Sem categoria',
|
||
'collab.notes.color': 'Cor',
|
||
'collab.notes.save': 'Salvar',
|
||
'collab.notes.cancel': 'Cancelar',
|
||
'collab.notes.edit': 'Editar',
|
||
'collab.notes.delete': 'Excluir',
|
||
'collab.notes.pin': 'Fixar',
|
||
'collab.notes.unpin': 'Desafixar',
|
||
'collab.notes.daysAgo': 'há {n} d',
|
||
'collab.notes.categorySettings': 'Gerenciar categorias',
|
||
'collab.notes.create': 'Criar',
|
||
'collab.notes.website': 'Site',
|
||
'collab.notes.websitePlaceholder': 'https://...',
|
||
'collab.notes.attachFiles': 'Anexar arquivos',
|
||
'collab.notes.noCategoriesYet': 'Nenhuma categoria ainda',
|
||
'collab.notes.emptyDesc': 'Crie uma nota para começar',
|
||
'collab.polls.title': 'Enquetes',
|
||
'collab.polls.new': 'Nova enquete',
|
||
'collab.polls.empty': 'Nenhuma enquete ainda',
|
||
'collab.polls.emptyHint': 'Pergunte ao grupo e votem juntos',
|
||
'collab.polls.question': 'Pergunta',
|
||
'collab.polls.questionPlaceholder': 'O que vamos fazer?',
|
||
'collab.polls.addOption': '+ Adicionar opção',
|
||
'collab.polls.optionPlaceholder': 'Opção {n}',
|
||
'collab.polls.create': 'Criar enquete',
|
||
'collab.polls.close': 'Encerrar',
|
||
'collab.polls.closed': 'Encerrada',
|
||
'collab.polls.votes': '{n} votos',
|
||
'collab.polls.vote': '{n} voto',
|
||
'collab.polls.multipleChoice': 'Múltipla escolha',
|
||
'collab.polls.multiChoice': 'Múltipla escolha',
|
||
'collab.polls.deadline': 'Prazo',
|
||
'collab.polls.option': 'Opção',
|
||
'collab.polls.options': 'Opções',
|
||
'collab.polls.delete': 'Excluir',
|
||
'collab.polls.closedSection': 'Encerradas',
|
||
|
||
// Memories (Immich Photos)
|
||
'memories.title': 'Fotos',
|
||
'memories.notConnected': 'Immich não conectado',
|
||
'memories.notConnectedHint': 'Conecte sua instância Immich nas Configurações para ver suas fotos de viagem aqui.',
|
||
'memories.notConnectedMultipleHint': 'Conecte um destes provedores de fotos: {provider_names} nas Configurações para poder adicionar fotos a esta viagem.',
|
||
'memories.noDates': 'Adicione datas à sua viagem para carregar fotos.',
|
||
'memories.noPhotos': 'Nenhuma foto encontrada',
|
||
'memories.noPhotosHint': 'Nenhuma foto encontrada no Immich para o período desta viagem.',
|
||
'memories.photosFound': 'fotos',
|
||
'memories.fromOthers': 'de outros',
|
||
'memories.sharePhotos': 'Compartilhar fotos',
|
||
'memories.sharing': 'Compartilhando',
|
||
'memories.reviewTitle': 'Revise suas fotos',
|
||
'memories.reviewHint': 'Clique nas fotos para excluí-las do compartilhamento.',
|
||
'memories.shareCount': 'Compartilhar {count} fotos',
|
||
'memories.providerUrl': 'URL do servidor',
|
||
'memories.providerApiKey': 'Chave de API',
|
||
'memories.providerUsername': 'Nome de usuário',
|
||
'memories.providerPassword': 'Senha',
|
||
'memories.providerOTP': 'Código MFA (se habilitado)',
|
||
'memories.skipSSLVerification': 'Pular verificação de certificado SSL',
|
||
'memories.immichAutoUpload': 'Espelhar fotos da jornada no Immich ao enviar',
|
||
'memories.providerUrlHintSynology': 'Inclua o caminho do aplicativo Photos na URL, ex. https://nas:5001/photo',
|
||
'memories.testConnection': 'Testar conexão',
|
||
'memories.testShort': 'Testar',
|
||
'memories.testFirst': 'Teste a conexão primeiro',
|
||
'memories.connected': 'Conectado',
|
||
'memories.disconnected': 'Não conectado',
|
||
'memories.connectionSuccess': 'Conectado ao Immich',
|
||
'memories.connectionError': 'Não foi possível conectar ao Immich',
|
||
'memories.saved': 'Configurações do {provider_name} salvas',
|
||
'memories.providerDisconnectedBanner': 'Sua conexão com {provider_name} foi perdida. Reconecte nas Configurações para ver as fotos.',
|
||
'memories.saveError': 'Não foi possível salvar as configurações de {provider_name}',
|
||
'memories.addPhotos': 'Adicionar fotos',
|
||
'memories.linkAlbum': 'Vincular álbum',
|
||
'memories.selectAlbum': 'Selecionar álbum do Immich',
|
||
'memories.selectAlbumMultiple': 'Selecionar álbum',
|
||
'memories.noAlbums': 'Nenhum álbum encontrado',
|
||
'memories.syncAlbum': 'Sincronizar álbum',
|
||
'memories.unlinkAlbum': 'Desvincular',
|
||
'memories.photos': 'fotos',
|
||
'memories.selectPhotos': 'Selecionar fotos do Immich',
|
||
'memories.selectPhotosMultiple': 'Selecionar fotos',
|
||
'memories.selectHint': 'Toque nas fotos para selecioná-las.',
|
||
'memories.selected': 'selecionadas',
|
||
'memories.addSelected': 'Adicionar {count} fotos',
|
||
'memories.alreadyAdded': 'Já adicionada',
|
||
'memories.private': 'Privado',
|
||
'memories.stopSharing': 'Parar de compartilhar',
|
||
'memories.oldest': 'Mais antigas',
|
||
'memories.newest': 'Mais recentes',
|
||
'memories.allLocations': 'Todos os locais',
|
||
'memories.tripDates': 'Datas da viagem',
|
||
'memories.allPhotos': 'Todas as fotos',
|
||
'memories.confirmShareTitle': 'Compartilhar com membros da viagem?',
|
||
'memories.confirmShareHint': '{count} fotos serão visíveis para todos os membros desta viagem. Você pode tornar fotos individuais privadas depois.',
|
||
'memories.confirmShareButton': 'Compartilhar fotos',
|
||
|
||
// Permissions
|
||
'admin.tabs.permissions': 'Permissões',
|
||
'admin.tabs.mcpTokens': 'Acesso MCP',
|
||
'admin.mcpTokens.title': 'Acesso MCP',
|
||
'admin.mcpTokens.subtitle': 'Gerenciar sessões OAuth e tokens de API de todos os usuários',
|
||
'admin.mcpTokens.sectionTitle': 'Tokens de API',
|
||
'admin.mcpTokens.owner': 'Proprietário',
|
||
'admin.mcpTokens.tokenName': 'Nome do Token',
|
||
'admin.mcpTokens.created': 'Criado',
|
||
'admin.mcpTokens.lastUsed': 'Último uso',
|
||
'admin.mcpTokens.never': 'Nunca',
|
||
'admin.mcpTokens.empty': 'Nenhum token MCP foi criado ainda',
|
||
'admin.mcpTokens.deleteTitle': 'Excluir Token',
|
||
'admin.mcpTokens.deleteMessage': 'Isso revogará o token imediatamente. O usuário perderá o acesso MCP por este token.',
|
||
'admin.mcpTokens.deleteSuccess': 'Token excluído',
|
||
'admin.mcpTokens.deleteError': 'Falha ao excluir token',
|
||
'admin.mcpTokens.loadError': 'Falha ao carregar tokens',
|
||
'admin.oauthSessions.sectionTitle': 'Sessões OAuth',
|
||
'admin.oauthSessions.clientName': 'Cliente',
|
||
'admin.oauthSessions.owner': 'Proprietário',
|
||
'admin.oauthSessions.scopes': 'Permissões',
|
||
'admin.oauthSessions.created': 'Criado',
|
||
'admin.oauthSessions.empty': 'Nenhuma sessão OAuth ativa',
|
||
'admin.oauthSessions.revokeTitle': 'Revogar sessão',
|
||
'admin.oauthSessions.revokeMessage': 'Esta sessão OAuth será revogada imediatamente. O cliente perderá o acesso MCP.',
|
||
'admin.oauthSessions.revokeSuccess': 'Sessão revogada',
|
||
'admin.oauthSessions.revokeError': 'Falha ao revogar sessão',
|
||
'admin.oauthSessions.loadError': 'Falha ao carregar sessões OAuth',
|
||
'perm.title': 'Configurações de Permissões',
|
||
'perm.subtitle': 'Controle quem pode realizar ações no aplicativo',
|
||
'perm.saved': 'Configurações de permissões salvas',
|
||
'perm.resetDefaults': 'Restaurar padrões',
|
||
'perm.customized': 'personalizado',
|
||
'perm.level.admin': 'Apenas administrador',
|
||
'perm.level.tripOwner': 'Dono da viagem',
|
||
'perm.level.tripMember': 'Membros da viagem',
|
||
'perm.level.everybody': 'Todos',
|
||
'perm.cat.trip': 'Gerenciamento de Viagens',
|
||
'perm.cat.members': 'Gerenciamento de Membros',
|
||
'perm.cat.files': 'Arquivos',
|
||
'perm.cat.content': 'Conteúdo e Cronograma',
|
||
'perm.cat.extras': 'Orçamento, Bagagem e Colaboração',
|
||
'perm.action.trip_create': 'Criar viagens',
|
||
'perm.action.trip_edit': 'Editar detalhes da viagem',
|
||
'perm.action.trip_delete': 'Excluir viagens',
|
||
'perm.action.trip_archive': 'Arquivar / desarquivar viagens',
|
||
'perm.action.trip_cover_upload': 'Enviar imagem de capa',
|
||
'perm.action.member_manage': 'Adicionar / remover membros',
|
||
'perm.action.file_upload': 'Enviar arquivos',
|
||
'perm.action.file_edit': 'Editar metadados do arquivo',
|
||
'perm.action.file_delete': 'Excluir arquivos',
|
||
'perm.action.place_edit': 'Adicionar / editar / excluir lugares',
|
||
'perm.action.day_edit': 'Editar dias, notas e atribuições',
|
||
'perm.action.reservation_edit': 'Gerenciar reservas',
|
||
'perm.action.budget_edit': 'Gerenciar orçamento',
|
||
'perm.action.packing_edit': 'Gerenciar listas de bagagem',
|
||
'perm.action.collab_edit': 'Colaboração (notas, enquetes, chat)',
|
||
'perm.action.share_manage': 'Gerenciar links de compartilhamento',
|
||
'perm.actionHint.trip_create': 'Quem pode criar novas viagens',
|
||
'perm.actionHint.trip_edit': 'Quem pode alterar nome, datas, descrição e moeda da viagem',
|
||
'perm.actionHint.trip_delete': 'Quem pode excluir permanentemente uma viagem',
|
||
'perm.actionHint.trip_archive': 'Quem pode arquivar ou desarquivar uma viagem',
|
||
'perm.actionHint.trip_cover_upload': 'Quem pode enviar ou alterar a imagem de capa',
|
||
'perm.actionHint.member_manage': 'Quem pode convidar ou remover membros da viagem',
|
||
'perm.actionHint.file_upload': 'Quem pode enviar arquivos para uma viagem',
|
||
'perm.actionHint.file_edit': 'Quem pode editar descrições e links dos arquivos',
|
||
'perm.actionHint.file_delete': 'Quem pode mover arquivos para a lixeira ou excluí-los permanentemente',
|
||
'perm.actionHint.place_edit': 'Quem pode adicionar, editar ou excluir lugares',
|
||
'perm.actionHint.day_edit': 'Quem pode editar dias, notas dos dias e atribuições de lugares',
|
||
'perm.actionHint.reservation_edit': 'Quem pode criar, editar ou excluir reservas',
|
||
'perm.actionHint.budget_edit': 'Quem pode criar, editar ou excluir itens do orçamento',
|
||
'perm.actionHint.packing_edit': 'Quem pode gerenciar itens de bagagem e malas',
|
||
'perm.actionHint.collab_edit': 'Quem pode criar notas, enquetes e enviar mensagens',
|
||
'perm.actionHint.share_manage': 'Quem pode criar ou excluir links de compartilhamento públicos',
|
||
// Undo
|
||
'undo.button': 'Desfazer',
|
||
'undo.tooltip': 'Desfazer: {action}',
|
||
'undo.assignPlace': 'Local atribuído ao dia',
|
||
'undo.removeAssignment': 'Local removido do dia',
|
||
'undo.reorder': 'Locais reordenados',
|
||
'undo.optimize': 'Rota otimizada',
|
||
'undo.deletePlace': 'Local excluído',
|
||
'undo.deletePlaces': 'Lugares excluídos',
|
||
'undo.moveDay': 'Local movido para outro dia',
|
||
'undo.lock': 'Bloqueio do local alternado',
|
||
'undo.importGpx': 'Importação de GPX',
|
||
'undo.importKeyholeMarkup': 'Importação de KMZ/KML',
|
||
'undo.importGoogleList': 'Importação do Google Maps',
|
||
'undo.importNaverList': 'Importação do Naver Maps',
|
||
|
||
// Notifications
|
||
'notifications.title': 'Notificações',
|
||
'notifications.markAllRead': 'Marcar tudo como lido',
|
||
'notifications.deleteAll': 'Excluir tudo',
|
||
'notifications.showAll': 'Ver todas as notificações',
|
||
'notifications.empty': 'Sem notificações',
|
||
'notifications.emptyDescription': 'Você está em dia!',
|
||
'notifications.all': 'Todas',
|
||
'notifications.unreadOnly': 'Não lidas',
|
||
'notifications.markRead': 'Marcar como lido',
|
||
'notifications.markUnread': 'Marcar como não lido',
|
||
'notifications.delete': 'Excluir',
|
||
'notifications.system': 'Sistema',
|
||
'notifications.synologySessionCleared.title': 'Synology Photos desconectado',
|
||
'notifications.synologySessionCleared.text': 'Seu servidor ou conta foi alterado — vá para Configurações para testar sua conexão novamente.',
|
||
'memories.error.loadAlbums': 'Falha ao carregar álbuns',
|
||
'memories.error.linkAlbum': 'Falha ao vincular álbum',
|
||
'memories.error.unlinkAlbum': 'Falha ao desvincular álbum',
|
||
'memories.error.syncAlbum': 'Falha ao sincronizar álbum',
|
||
'memories.error.loadPhotos': 'Falha ao carregar fotos',
|
||
'memories.error.addPhotos': 'Falha ao adicionar fotos',
|
||
'memories.error.removePhoto': 'Falha ao remover foto',
|
||
'memories.error.toggleSharing': 'Falha ao atualizar compartilhamento',
|
||
'undo.addPlace': 'Local adicionado',
|
||
'undo.done': 'Desfeito: {action}',
|
||
'notifications.test.title': 'Notificação de teste de {actor}',
|
||
'notifications.test.text': 'Esta é uma notificação de teste simples.',
|
||
'notifications.test.booleanTitle': '{actor} solicita sua aprovação',
|
||
'notifications.test.booleanText': 'Notificação de teste booleana.',
|
||
'notifications.test.accept': 'Aprovar',
|
||
'notifications.test.decline': 'Recusar',
|
||
'notifications.test.navigateTitle': 'Confira algo',
|
||
'notifications.test.navigateText': 'Notificação de teste de navegação.',
|
||
'notifications.test.goThere': 'Ir lá',
|
||
'notifications.test.adminTitle': 'Transmissão do admin',
|
||
'notifications.test.adminText': '{actor} enviou uma notificação de teste para todos os admins.',
|
||
'notifications.test.tripTitle': '{actor} postou na sua viagem',
|
||
'notifications.test.tripText': 'Notificação de teste para a viagem "{trip}".',
|
||
|
||
// Todo
|
||
'todo.subtab.packing': 'Lista de bagagem',
|
||
'todo.subtab.todo': 'A fazer',
|
||
'todo.completed': 'concluído(s)',
|
||
'todo.filter.all': 'Todos',
|
||
'todo.filter.open': 'Aberto',
|
||
'todo.filter.done': 'Concluído',
|
||
'todo.uncategorized': 'Sem categoria',
|
||
'todo.namePlaceholder': 'Nome da tarefa',
|
||
'todo.descriptionPlaceholder': 'Descrição (opcional)',
|
||
'todo.unassigned': 'Não atribuído',
|
||
'todo.noCategory': 'Sem categoria',
|
||
'todo.hasDescription': 'Com descrição',
|
||
'todo.addItem': 'Nova tarefa',
|
||
'todo.sidebar.sortBy': 'Ordenar por',
|
||
'todo.priority': 'Prioridade',
|
||
'todo.newCategoryLabel': 'nova',
|
||
'budget.categoriesLabel': 'categorias',
|
||
'todo.newCategory': 'Nome da categoria',
|
||
'todo.addCategory': 'Adicionar categoria',
|
||
'todo.newItem': 'Nova tarefa',
|
||
'todo.empty': 'Nenhuma tarefa ainda. Adicione uma tarefa para começar!',
|
||
'todo.filter.my': 'Minhas tarefas',
|
||
'todo.filter.overdue': 'Atrasada',
|
||
'todo.sidebar.tasks': 'Tarefas',
|
||
'todo.sidebar.categories': 'Categorias',
|
||
'todo.detail.title': 'Tarefa',
|
||
'todo.detail.description': 'Descrição',
|
||
'todo.detail.category': 'Categoria',
|
||
'todo.detail.dueDate': 'Data de vencimento',
|
||
'todo.detail.assignedTo': 'Atribuído a',
|
||
'todo.detail.delete': 'Excluir',
|
||
'todo.detail.save': 'Salvar alterações',
|
||
'todo.detail.create': 'Criar tarefa',
|
||
'todo.detail.priority': 'Prioridade',
|
||
'todo.detail.noPriority': 'Nenhuma',
|
||
'todo.sortByPrio': 'Prioridade',
|
||
|
||
// Notification system (added from feat/notification-system)
|
||
'settings.notifyVersionAvailable': 'Nova versão disponível',
|
||
'settings.notificationPreferences.noChannels': 'Nenhum canal de notificação configurado. Peça a um administrador para configurar notificações por e-mail ou webhook.',
|
||
'settings.webhookUrl.label': 'URL do webhook',
|
||
'settings.webhookUrl.placeholder': 'https://discord.com/api/webhooks/...',
|
||
'settings.webhookUrl.hint': 'Insira a URL do seu webhook do Discord, Slack ou personalizado para receber notificações.',
|
||
'settings.webhookUrl.saved': 'URL do webhook salva',
|
||
'settings.webhookUrl.test': 'Testar',
|
||
'settings.webhookUrl.testSuccess': 'Webhook de teste enviado com sucesso',
|
||
'settings.webhookUrl.testFailed': 'Falha no webhook de teste',
|
||
'settings.ntfyUrl.topicLabel': 'Tópico Ntfy',
|
||
'settings.ntfyUrl.topicPlaceholder': 'my-trek-alerts',
|
||
'settings.ntfyUrl.serverLabel': 'URL do servidor Ntfy (opcional)',
|
||
'settings.ntfyUrl.serverPlaceholder': 'https://ntfy.sh',
|
||
'settings.ntfyUrl.hint': 'Insira seu tópico Ntfy para receber notificações push. Deixe o servidor em branco para usar o padrão configurado pelo seu administrador.',
|
||
'settings.ntfyUrl.tokenLabel': 'Token de acesso (opcional)',
|
||
'settings.ntfyUrl.tokenHint': 'Necessário para tópicos protegidos por senha.',
|
||
'settings.ntfyUrl.saved': 'Configurações do Ntfy salvas',
|
||
'settings.ntfyUrl.test': 'Testar',
|
||
'settings.ntfyUrl.testSuccess': 'Notificação de teste do Ntfy enviada com sucesso',
|
||
'settings.ntfyUrl.testFailed': 'Falha na notificação de teste do Ntfy',
|
||
'settings.ntfyUrl.tokenCleared': 'Token de acesso removido',
|
||
'settings.notificationPreferences.inapp': 'In-App',
|
||
'settings.notificationPreferences.webhook': 'Webhook',
|
||
'settings.notificationPreferences.email': 'Email',
|
||
'settings.notificationPreferences.ntfy': 'Ntfy',
|
||
'admin.notifications.emailPanel.title': 'Email (SMTP)',
|
||
'admin.notifications.webhookPanel.title': 'Webhook',
|
||
'admin.notifications.inappPanel.title': 'In-App',
|
||
'admin.notifications.inappPanel.hint': 'As notificações no aplicativo estão sempre ativas e não podem ser desativadas globalmente.',
|
||
'admin.notifications.adminWebhookPanel.title': 'Webhook de admin',
|
||
'admin.notifications.adminWebhookPanel.hint': 'Este webhook é usado exclusivamente para notificações de admin (ex. alertas de versão). É independente dos webhooks de usuários e dispara automaticamente quando uma URL está configurada.',
|
||
'admin.notifications.adminWebhookPanel.saved': 'URL do webhook de admin salva',
|
||
'admin.notifications.adminWebhookPanel.testSuccess': 'Webhook de teste enviado com sucesso',
|
||
'admin.notifications.adminWebhookPanel.testFailed': 'Falha no webhook de teste',
|
||
'admin.notifications.adminWebhookPanel.alwaysOnHint': 'O webhook de admin dispara automaticamente quando uma URL está configurada',
|
||
'admin.notifications.ntfy': 'Ntfy',
|
||
'admin.ntfy.hint': 'Permite que os usuários configurem seus próprios tópicos ntfy para notificações push. Configure o servidor padrão abaixo para preencher as configurações do usuário.',
|
||
'admin.notifications.testNtfy': 'Enviar Ntfy de teste',
|
||
'admin.notifications.testNtfySuccess': 'Ntfy de teste enviado com sucesso',
|
||
'admin.notifications.testNtfyFailed': 'Falha ao enviar Ntfy de teste',
|
||
'admin.notifications.adminNtfyPanel.title': 'Ntfy de admin',
|
||
'admin.notifications.adminNtfyPanel.hint': 'Este tópico Ntfy é usado exclusivamente para notificações de admin (ex. alertas de versão). É independente dos tópicos por usuário e sempre dispara quando configurado.',
|
||
'admin.notifications.adminNtfyPanel.serverLabel': 'URL do servidor Ntfy',
|
||
'admin.notifications.adminNtfyPanel.serverHint': 'Também usado como servidor padrão para notificações ntfy dos usuários. Deixe em branco para usar ntfy.sh. Os usuários podem substituir isso em suas próprias configurações.',
|
||
'admin.notifications.adminNtfyPanel.serverPlaceholder': 'https://ntfy.sh',
|
||
'admin.notifications.adminNtfyPanel.topicLabel': 'Tópico de admin',
|
||
'admin.notifications.adminNtfyPanel.topicPlaceholder': 'trek-admin-alerts',
|
||
'admin.notifications.adminNtfyPanel.tokenLabel': 'Token de acesso (opcional)',
|
||
'admin.notifications.adminNtfyPanel.tokenCleared': 'Token de acesso admin removido',
|
||
'admin.notifications.adminNtfyPanel.saved': 'Configurações de Ntfy de admin salvas',
|
||
'admin.notifications.adminNtfyPanel.test': 'Enviar Ntfy de teste',
|
||
'admin.notifications.adminNtfyPanel.testSuccess': 'Ntfy de teste enviado com sucesso',
|
||
'admin.notifications.adminNtfyPanel.testFailed': 'Falha ao enviar Ntfy de teste',
|
||
'admin.notifications.adminNtfyPanel.alwaysOnHint': 'O Ntfy de admin sempre dispara quando um tópico está configurado',
|
||
'admin.notifications.adminNotificationsHint': 'Configure quais canais entregam notificações de admin (ex. alertas de versão). O webhook dispara automaticamente se uma URL de webhook de admin estiver definida.',
|
||
'admin.notifications.tripReminders.title': 'Lembretes de viagem',
|
||
'admin.notifications.tripReminders.hint': 'Envia uma notificação de lembrete antes do início de uma viagem (requer dias de lembrete definidos na viagem).',
|
||
'admin.notifications.tripReminders.enabled': 'Lembretes de viagem ativados',
|
||
'admin.notifications.tripReminders.disabled': 'Lembretes de viagem desativados',
|
||
'admin.tabs.notifications': 'Notificações',
|
||
'notifications.versionAvailable.title': 'Atualização disponível',
|
||
'notifications.versionAvailable.text': 'TREK {version} já está disponível.',
|
||
'notifications.versionAvailable.button': 'Ver detalhes',
|
||
'notif.test.title': '[Teste] Notificação',
|
||
'notif.test.simple.text': 'Esta é uma notificação de teste simples.',
|
||
'notif.test.boolean.text': 'Você aceita esta notificação de teste?',
|
||
'notif.test.navigate.text': 'Clique abaixo para ir ao painel.',
|
||
|
||
// Notifications
|
||
'notif.trip_invite.title': 'Convite para viagem',
|
||
'notif.trip_invite.text': '{actor} convidou você para {trip}',
|
||
'notif.booking_change.title': 'Reserva atualizada',
|
||
'notif.booking_change.text': '{actor} atualizou uma reserva em {trip}',
|
||
'notif.trip_reminder.title': 'Lembrete de viagem',
|
||
'notif.trip_reminder.text': 'Sua viagem {trip} está chegando!',
|
||
'notif.todo_due.title': 'Tarefa com vencimento',
|
||
'notif.todo_due.text': '{todo} em {trip} vence em {due}',
|
||
'notif.vacay_invite.title': 'Convite Vacay Fusion',
|
||
'notif.vacay_invite.text': '{actor} convidou você para fundir planos de férias',
|
||
'notif.photos_shared.title': 'Fotos compartilhadas',
|
||
'notif.photos_shared.text': '{actor} compartilhou {count} foto(s) em {trip}',
|
||
'notif.collab_message.title': 'Nova mensagem',
|
||
'notif.collab_message.text': '{actor} enviou uma mensagem em {trip}',
|
||
'notif.packing_tagged.title': 'Atribuição de bagagem',
|
||
'notif.packing_tagged.text': '{actor} atribuiu você a {category} em {trip}',
|
||
'notif.version_available.title': 'Nova versão disponível',
|
||
'notif.version_available.text': 'TREK {version} está disponível',
|
||
'notif.action.view_trip': 'Ver viagem',
|
||
'notif.action.view_collab': 'Ver mensagens',
|
||
'notif.action.view_packing': 'Ver bagagem',
|
||
'notif.action.view_photos': 'Ver fotos',
|
||
'notif.action.view_vacay': 'Ver Vacay',
|
||
'notif.action.view_admin': 'Ir para admin',
|
||
'notif.action.view': 'Ver',
|
||
'notif.action.accept': 'Aceitar',
|
||
'notif.action.decline': 'Recusar',
|
||
'notif.generic.title': 'Notificação',
|
||
'notif.generic.text': 'Você tem uma nova notificação',
|
||
'notif.dev.unknown_event.title': '[DEV] Evento desconhecido',
|
||
'notif.dev.unknown_event.text': 'O tipo de evento "{event}" não está registrado em EVENT_NOTIFICATION_CONFIG',
|
||
|
||
// Journey, Dashboard, Nav, DayPlan
|
||
'common.justNow': 'agora mesmo',
|
||
'common.hoursAgo': 'há {count}h',
|
||
'common.daysAgo': 'há {count}d',
|
||
'memories.saveRouteNotConfigured': 'A rota de salvamento não está configurada para este provedor',
|
||
'memories.testRouteNotConfigured': 'A rota de teste não está configurada para este provedor',
|
||
'memories.fillRequiredFields': 'Por favor preencha todos os campos obrigatórios',
|
||
'journey.search.placeholder': 'Buscar jornadas…',
|
||
'journey.search.noResults': 'Nenhuma jornada corresponde a "{query}"',
|
||
'journey.title': 'Jornada',
|
||
'journey.subtitle': 'Registre suas viagens em tempo real',
|
||
'journey.new': 'Nova jornada',
|
||
'journey.create': 'Criar',
|
||
'journey.titlePlaceholder': 'Para onde você vai?',
|
||
'journey.empty': 'Nenhuma jornada ainda',
|
||
'journey.emptyHint': 'Comece a documentar sua próxima viagem',
|
||
'journey.deleted': 'Jornada excluída',
|
||
'journey.createError': 'Não foi possível criar a jornada',
|
||
'journey.deleteError': 'Não foi possível excluir a jornada',
|
||
'journey.deleteConfirmTitle': 'Excluir',
|
||
'journey.deleteConfirmMessage': 'Excluir "{title}"? Isso não pode ser desfeito.',
|
||
'journey.deleteConfirmGeneric': 'Tem certeza de que deseja excluir isso?',
|
||
'journey.notFound': 'Jornada não encontrada',
|
||
'journey.photos': 'Fotos',
|
||
'journey.timelineEmpty': 'Nenhuma parada ainda',
|
||
'journey.timelineEmptyHint': 'Adicione um check-in ou escreva uma entrada no diário para começar',
|
||
'journey.status.draft': 'Rascunho',
|
||
'journey.status.active': 'Ativa',
|
||
'journey.status.completed': 'Concluída',
|
||
'journey.status.upcoming': 'Próxima',
|
||
'journey.status.archived': 'Arquivado',
|
||
'journey.checkin.add': 'Fazer check-in',
|
||
'journey.checkin.namePlaceholder': 'Nome do local',
|
||
'journey.checkin.notesPlaceholder': 'Notas (opcional)',
|
||
'journey.checkin.save': 'Salvar',
|
||
'journey.checkin.error': 'Não foi possível salvar o check-in',
|
||
'journey.entry.add': 'Diário',
|
||
'journey.entry.edit': 'Editar entrada',
|
||
'journey.entry.titlePlaceholder': 'Título (opcional)',
|
||
'journey.entry.bodyPlaceholder': 'O que aconteceu hoje?',
|
||
'journey.entry.save': 'Salvar',
|
||
'journey.entry.error': 'Não foi possível salvar a entrada',
|
||
'journey.photo.add': 'Foto',
|
||
'journey.photo.uploadError': 'Falha no envio',
|
||
'journey.share.share': 'Compartilhar',
|
||
'journey.share.public': 'Público',
|
||
'journey.share.linkCopied': 'Link público copiado',
|
||
'journey.share.disabled': 'Compartilhamento público desativado',
|
||
'journey.editor.titlePlaceholder': 'Dê um nome a este momento...',
|
||
'journey.editor.bodyPlaceholder': 'Conte a história deste dia...',
|
||
'journey.editor.placePlaceholder': 'Localização (opcional)',
|
||
'journey.editor.tagsPlaceholder': 'Tags: joia escondida, melhor refeição, preciso voltar...',
|
||
'journey.visibility.private': 'Privado',
|
||
'journey.visibility.shared': 'Compartilhado',
|
||
'journey.visibility.public': 'Público',
|
||
'journey.emptyState.title': 'Sua história começa aqui',
|
||
'journey.emptyState.subtitle': 'Faça check-in em um lugar ou escreva sua primeira entrada no diário',
|
||
'journey.frontpage.subtitle': 'Transforme suas viagens em histórias que você nunca vai esquecer',
|
||
'journey.frontpage.createJourney': 'Criar jornada',
|
||
'journey.frontpage.activeJourney': 'Jornada ativa',
|
||
'journey.frontpage.allJourneys': 'Todas as jornadas',
|
||
'journey.frontpage.journeys': 'jornadas',
|
||
'journey.frontpage.createNew': 'Criar uma nova jornada',
|
||
'journey.frontpage.createNewSub': 'Escolha viagens, escreva histórias, compartilhe suas aventuras',
|
||
'journey.frontpage.live': 'Ao vivo',
|
||
'journey.frontpage.synced': 'Sincronizado',
|
||
'journey.frontpage.continueWriting': 'Continuar escrevendo',
|
||
'journey.frontpage.updated': 'Atualizado {time}',
|
||
'journey.frontpage.suggestionLabel': 'A viagem acabou de terminar',
|
||
'journey.frontpage.suggestionText': 'Transforme <strong>{title}</strong> em uma jornada',
|
||
'journey.frontpage.dismiss': 'Dispensar',
|
||
'journey.frontpage.journeyName': 'Nome da jornada',
|
||
'journey.frontpage.namePlaceholder': 'ex. Sudeste Asiático 2026',
|
||
'journey.frontpage.selectTrips': 'Selecionar viagens',
|
||
'journey.frontpage.tripsSelected': 'viagens selecionadas',
|
||
'journey.frontpage.trips': 'viagens',
|
||
'journey.frontpage.placesImported': 'lugares serão importados',
|
||
'journey.frontpage.places': 'lugares',
|
||
'journey.detail.backToJourney': 'Voltar à jornada',
|
||
'journey.detail.syncedWithTrips': 'Sincronizado com viagens',
|
||
'journey.detail.addEntry': 'Adicionar entrada',
|
||
'journey.detail.newEntry': 'Nova entrada',
|
||
'journey.detail.editEntry': 'Editar entrada',
|
||
'journey.detail.noEntries': 'Nenhuma entrada ainda',
|
||
'journey.detail.noEntriesHint': 'Adicione uma viagem para começar com entradas preliminares',
|
||
'journey.detail.noPhotos': 'Nenhuma foto ainda',
|
||
'journey.detail.noPhotosHint': 'Envie fotos para as entradas ou explore sua biblioteca do Immich/Synology',
|
||
'journey.detail.journeyStats': 'Estatísticas da jornada',
|
||
'journey.detail.syncedTrips': 'Viagens sincronizadas',
|
||
'journey.detail.noTripsLinked': 'Nenhuma viagem vinculada ainda',
|
||
'journey.detail.contributors': 'Colaboradores',
|
||
'journey.detail.readMore': 'Ler mais',
|
||
'journey.detail.prosCons': 'Prós e contras',
|
||
'journey.detail.photos': 'fotos',
|
||
'journey.detail.day': 'Dia {number}',
|
||
'journey.detail.places': 'lugares',
|
||
'journey.stats.days': 'Dias',
|
||
'journey.stats.cities': 'Cidades',
|
||
'journey.stats.entries': 'Entradas',
|
||
'journey.stats.photos': 'Fotos',
|
||
'journey.stats.places': 'Lugares',
|
||
'journey.skeletons.show': 'Mostrar sugestões',
|
||
'journey.skeletons.hide': 'Ocultar sugestões',
|
||
'journey.verdict.lovedIt': 'Adorei',
|
||
'journey.verdict.couldBeBetter': 'Poderia ser melhor',
|
||
'journey.synced.places': 'lugares',
|
||
'journey.synced.synced': 'sincronizado',
|
||
'journey.editor.discardChangesConfirm': 'Você tem alterações não salvas. Descartá-las?',
|
||
'journey.editor.uploadPhotos': 'Enviar fotos',
|
||
'journey.editor.uploading': 'Enviando...',
|
||
'journey.editor.fromGallery': 'Da galeria',
|
||
'journey.editor.allPhotosAdded': 'Todas as fotos já foram adicionadas',
|
||
'journey.editor.writeStory': 'Escreva sua história...',
|
||
'journey.editor.prosCons': 'Prós e contras',
|
||
'journey.editor.pros': 'Prós',
|
||
'journey.editor.cons': 'Contras',
|
||
'journey.editor.proPlaceholder': 'Algo ótimo...',
|
||
'journey.editor.conPlaceholder': 'Não tão bom...',
|
||
'journey.editor.addAnother': 'Adicionar outro',
|
||
'journey.editor.date': 'Data',
|
||
'journey.editor.location': 'Localização',
|
||
'journey.editor.searchLocation': 'Buscar localização...',
|
||
'journey.editor.mood': 'Humor',
|
||
'journey.editor.weather': 'Clima',
|
||
'journey.editor.photoFirst': '1º',
|
||
'journey.editor.makeFirst': 'Tornar 1º',
|
||
'journey.editor.searching': 'Pesquisando...',
|
||
'journey.mood.amazing': 'Incrível',
|
||
'journey.mood.good': 'Bom',
|
||
'journey.mood.neutral': 'Neutro',
|
||
'journey.mood.rough': 'Difícil',
|
||
'journey.weather.sunny': 'Ensolarado',
|
||
'journey.weather.partly': 'Parcialmente nublado',
|
||
'journey.weather.cloudy': 'Nublado',
|
||
'journey.weather.rainy': 'Chuvoso',
|
||
'journey.weather.stormy': 'Tempestuoso',
|
||
'journey.weather.cold': 'Nevando',
|
||
'journey.trips.linkTrip': 'Vincular viagem',
|
||
'journey.trips.searchTrip': 'Buscar viagem',
|
||
'journey.trips.searchPlaceholder': 'Nome da viagem ou destino...',
|
||
'journey.trips.noTripsAvailable': 'Nenhuma viagem disponível',
|
||
'journey.trips.link': 'Vincular',
|
||
'journey.trips.tripLinked': 'Viagem vinculada',
|
||
'journey.trips.linkFailed': 'Não foi possível vincular a viagem',
|
||
'journey.trips.addTrip': 'Adicionar viagem',
|
||
'journey.trips.unlinkTrip': 'Desvincular viagem',
|
||
'journey.trips.unlinkMessage': 'Desvincular "{title}"? Todas as entradas e fotos sincronizadas desta viagem serão excluídas permanentemente. Isso não pode ser desfeito.',
|
||
'journey.trips.unlink': 'Desvincular',
|
||
'journey.trips.tripUnlinked': 'Viagem desvinculada',
|
||
'journey.trips.unlinkFailed': 'Não foi possível desvincular a viagem',
|
||
'journey.trips.noTripsLinkedSettings': 'Nenhuma viagem vinculada',
|
||
'journey.contributors.invite': 'Convidar colaborador',
|
||
'journey.contributors.searchUser': 'Buscar usuário',
|
||
'journey.contributors.searchPlaceholder': 'Nome de usuário ou e-mail...',
|
||
'journey.contributors.noUsers': 'Nenhum usuário encontrado',
|
||
'journey.contributors.role': 'Função',
|
||
'journey.contributors.added': 'Colaborador adicionado',
|
||
'journey.contributors.addFailed': 'Não foi possível adicionar o colaborador',
|
||
'journey.share.publicShare': 'Compartilhamento público',
|
||
'journey.share.createLink': 'Criar link de compartilhamento',
|
||
'journey.share.linkCreated': 'Link de compartilhamento criado',
|
||
'journey.share.createFailed': 'Não foi possível criar o link',
|
||
'journey.share.copy': 'Copiar',
|
||
'journey.share.copied': 'Copiado!',
|
||
'journey.share.timeline': 'Linha do tempo',
|
||
'journey.share.gallery': 'Galeria',
|
||
'journey.share.map': 'Mapa',
|
||
'journey.share.removeLink': 'Remover link de compartilhamento',
|
||
'journey.share.linkDeleted': 'Link de compartilhamento removido',
|
||
'journey.share.deleteFailed': 'Não foi possível excluir',
|
||
'journey.share.updateFailed': 'Não foi possível atualizar',
|
||
|
||
// Journey — Invite
|
||
'journey.invite.role': 'Função',
|
||
'journey.invite.viewer': 'Visualizador',
|
||
'journey.invite.editor': 'Editor',
|
||
'journey.invite.invite': 'Convidar',
|
||
'journey.invite.inviting': 'Convidando...',
|
||
'journey.settings.title': 'Configurações da jornada',
|
||
'journey.settings.coverImage': 'Imagem de capa',
|
||
'journey.settings.changeCover': 'Alterar capa',
|
||
'journey.settings.addCover': 'Adicionar imagem de capa',
|
||
'journey.settings.name': 'Nome',
|
||
'journey.settings.subtitle': 'Subtítulo',
|
||
'journey.settings.subtitlePlaceholder': 'ex. Tailândia, Vietnã e Camboja',
|
||
'journey.settings.endJourney': 'Arquivar Jornada',
|
||
'journey.settings.reopenJourney': 'Restaurar Jornada',
|
||
'journey.settings.archived': 'Jornada arquivada',
|
||
'journey.settings.reopened': 'Jornada reaberta',
|
||
'journey.settings.endDescription': 'Oculta o selo Ao Vivo. Você pode reabrir a qualquer momento.',
|
||
'journey.settings.delete': 'Excluir',
|
||
'journey.settings.deleteJourney': 'Excluir jornada',
|
||
'journey.settings.deleteMessage': 'Excluir "{title}"? Todas as entradas e fotos serão perdidas.',
|
||
'journey.settings.saved': 'Configurações salvas',
|
||
'journey.settings.saveFailed': 'Não foi possível salvar',
|
||
'journey.settings.coverUpdated': 'Capa atualizada',
|
||
'journey.settings.coverFailed': 'Falha no envio',
|
||
'journey.settings.failedToDelete': 'Falha ao excluir',
|
||
'journey.entries.deleteTitle': 'Excluir entrada',
|
||
'journey.photosUploaded': '{count} fotos enviadas',
|
||
'journey.photosAdded': '{count} fotos adicionadas',
|
||
'journey.public.notFound': 'Não encontrado',
|
||
'journey.public.notFoundMessage': 'Esta jornada não existe ou o link expirou.',
|
||
'journey.public.readOnly': 'Somente leitura · Jornada pública',
|
||
'journey.public.tagline': 'Kit de recursos e exploração de viagens',
|
||
'journey.public.sharedVia': 'Compartilhado via',
|
||
'journey.public.madeWith': 'Feito com',
|
||
'journey.pdf.journeyBook': 'Livro da jornada',
|
||
'journey.pdf.madeWith': 'Feito com TREK',
|
||
'journey.pdf.day': 'Dia',
|
||
'journey.pdf.theEnd': 'Fim',
|
||
'journey.pdf.saveAsPdf': 'Salvar como PDF',
|
||
'journey.pdf.pages': 'páginas',
|
||
'journey.picker.tripPeriod': 'Período da viagem',
|
||
'journey.picker.dateRange': 'Período',
|
||
'journey.picker.allPhotos': 'Todas as fotos',
|
||
'journey.picker.albums': 'Álbuns',
|
||
'journey.picker.selected': 'selecionados',
|
||
'journey.picker.addTo': 'Adicionar a',
|
||
'journey.picker.newGallery': 'Nova galeria',
|
||
'journey.picker.selectAll': 'Selecionar tudo',
|
||
'journey.picker.deselectAll': 'Desmarcar tudo',
|
||
'journey.picker.noAlbums': 'Nenhum álbum encontrado',
|
||
'journey.picker.selectDate': 'Selecionar data',
|
||
'journey.picker.search': 'Pesquisar',
|
||
'dashboard.greeting.morning': 'Bom dia,',
|
||
'dashboard.greeting.afternoon': 'Boa tarde,',
|
||
'dashboard.greeting.evening': 'Boa noite,',
|
||
'dashboard.mobile.liveNow': 'Ao vivo agora',
|
||
'dashboard.mobile.tripProgress': 'Progresso da viagem',
|
||
'dashboard.mobile.daysLeft': '{count} dias restantes',
|
||
'dashboard.mobile.places': 'Lugares',
|
||
'dashboard.mobile.buddies': 'Companheiros',
|
||
'dashboard.mobile.newTrip': 'Nova viagem',
|
||
'dashboard.mobile.currency': 'Moeda',
|
||
'dashboard.mobile.timezone': 'Fuso horário',
|
||
'dashboard.mobile.upcomingTrips': 'Próximas viagens',
|
||
'dashboard.mobile.yourTrips': 'Suas viagens',
|
||
'dashboard.mobile.trips': 'viagens',
|
||
'dashboard.mobile.starts': 'Começa',
|
||
'dashboard.mobile.duration': 'Duração',
|
||
'dashboard.mobile.day': 'dia',
|
||
'dashboard.mobile.days': 'dias',
|
||
'dashboard.mobile.ongoing': 'Em andamento',
|
||
'dashboard.mobile.startsToday': 'Começa hoje',
|
||
'dashboard.mobile.tomorrow': 'Amanhã',
|
||
'dashboard.mobile.inDays': 'Em {count} dias',
|
||
'dashboard.mobile.inMonths': 'Em {count} meses',
|
||
'dashboard.mobile.completed': 'Concluído',
|
||
'dashboard.mobile.currencyConverter': 'Conversor de moedas',
|
||
'nav.profile': 'Perfil',
|
||
'nav.bottomSettings': 'Configurações',
|
||
'nav.bottomAdmin': 'Administração',
|
||
'nav.bottomLogout': 'Sair',
|
||
'nav.bottomAdminBadge': 'Admin',
|
||
'dayplan.mobile.addPlace': 'Adicionar lugar',
|
||
'dayplan.mobile.searchPlaces': 'Buscar lugares...',
|
||
'dayplan.mobile.allAssigned': 'Todos os lugares atribuídos',
|
||
'dayplan.mobile.noMatch': 'Sem correspondência',
|
||
'dayplan.mobile.createNew': 'Criar novo lugar',
|
||
'admin.addons.catalog.journey.name': 'Jornada',
|
||
'admin.addons.catalog.journey.description': 'Rastreamento de viagens e diário de viajante com check-ins, fotos e histórias diárias',
|
||
|
||
// OAuth scope groups
|
||
'oauth.scope.group.trips': 'Viagens',
|
||
'oauth.scope.group.places': 'Locais',
|
||
'oauth.scope.group.atlas': 'Atlas',
|
||
'oauth.scope.group.packing': 'Bagagem',
|
||
'oauth.scope.group.todos': 'Tarefas',
|
||
'oauth.scope.group.budget': 'Orçamento',
|
||
'oauth.scope.group.reservations': 'Reservas',
|
||
'oauth.scope.group.collab': 'Colaboração',
|
||
'oauth.scope.group.notifications': 'Notificações',
|
||
'oauth.scope.group.vacay': 'Férias',
|
||
'oauth.scope.group.geo': 'Geo',
|
||
'oauth.scope.group.weather': 'Clima',
|
||
'oauth.scope.group.journey': 'Jornada',
|
||
|
||
// OAuth scope labels & descriptions
|
||
'oauth.scope.trips:read.label': 'Ver viagens e itinerários',
|
||
'oauth.scope.trips:read.description': 'Ler viagens, dias, notas e membros',
|
||
'oauth.scope.trips:write.label': 'Editar viagens e itinerários',
|
||
'oauth.scope.trips:write.description': 'Criar e atualizar viagens, dias, notas e gerenciar membros',
|
||
'oauth.scope.trips:delete.label': 'Excluir viagens',
|
||
'oauth.scope.trips:delete.description': 'Excluir viagens permanentemente — esta ação é irreversível',
|
||
'oauth.scope.trips:share.label': 'Gerenciar links de compartilhamento',
|
||
'oauth.scope.trips:share.description': 'Criar, atualizar e revogar links de compartilhamento públicos',
|
||
'oauth.scope.places:read.label': 'Ver locais e dados do mapa',
|
||
'oauth.scope.places:read.description': 'Ler locais, atribuições de dias, tags e categorias',
|
||
'oauth.scope.places:write.label': 'Gerenciar locais',
|
||
'oauth.scope.places:write.description': 'Criar, atualizar e excluir locais, atribuições e tags',
|
||
'oauth.scope.atlas:read.label': 'Ver Atlas',
|
||
'oauth.scope.atlas:read.description': 'Ler países visitados, regiões e lista de desejos',
|
||
'oauth.scope.atlas:write.label': 'Gerenciar Atlas',
|
||
'oauth.scope.atlas:write.description': 'Marcar países e regiões como visitados, gerenciar lista de desejos',
|
||
'oauth.scope.packing:read.label': 'Ver listas de bagagem',
|
||
'oauth.scope.packing:read.description': 'Ler itens, malas e responsáveis por categoria',
|
||
'oauth.scope.packing:write.label': 'Gerenciar listas de bagagem',
|
||
'oauth.scope.packing:write.description': 'Adicionar, atualizar, excluir, marcar e reordenar itens e malas',
|
||
'oauth.scope.todos:read.label': 'Ver listas de tarefas',
|
||
'oauth.scope.todos:read.description': 'Ler tarefas da viagem e responsáveis por categoria',
|
||
'oauth.scope.todos:write.label': 'Gerenciar listas de tarefas',
|
||
'oauth.scope.todos:write.description': 'Criar, atualizar, marcar, excluir e reordenar tarefas',
|
||
'oauth.scope.budget:read.label': 'Ver orçamento',
|
||
'oauth.scope.budget:read.description': 'Ler itens de orçamento e detalhamento de despesas',
|
||
'oauth.scope.budget:write.label': 'Gerenciar orçamento',
|
||
'oauth.scope.budget:write.description': 'Criar, atualizar e excluir itens de orçamento',
|
||
'oauth.scope.reservations:read.label': 'Ver reservas',
|
||
'oauth.scope.reservations:read.description': 'Ler reservas e detalhes de acomodação',
|
||
'oauth.scope.reservations:write.label': 'Gerenciar reservas',
|
||
'oauth.scope.reservations:write.description': 'Criar, atualizar, excluir e reordenar reservas',
|
||
'oauth.scope.collab:read.label': 'Ver colaboração',
|
||
'oauth.scope.collab:read.description': 'Ler notas colaborativas, enquetes e mensagens',
|
||
'oauth.scope.collab:write.label': 'Gerenciar colaboração',
|
||
'oauth.scope.collab:write.description': 'Criar, atualizar e excluir notas, enquetes e mensagens',
|
||
'oauth.scope.notifications:read.label': 'Ver notificações',
|
||
'oauth.scope.notifications:read.description': 'Ler notificações e contagens não lidas',
|
||
'oauth.scope.notifications:write.label': 'Gerenciar notificações',
|
||
'oauth.scope.notifications:write.description': 'Marcar notificações como lidas e respondê-las',
|
||
'oauth.scope.vacay:read.label': 'Ver planos de férias',
|
||
'oauth.scope.vacay:read.description': 'Ler dados de planejamento de férias, entradas e estatísticas',
|
||
'oauth.scope.vacay:write.label': 'Gerenciar planos de férias',
|
||
'oauth.scope.vacay:write.description': 'Criar e gerenciar entradas de férias, feriados e planos de equipe',
|
||
'oauth.scope.geo:read.label': 'Mapas e geocodificação',
|
||
'oauth.scope.geo:read.description': 'Pesquisar locais, resolver URLs de mapa e geocodificar coordenadas',
|
||
'oauth.scope.weather:read.label': 'Previsão do tempo',
|
||
'oauth.scope.weather:read.description': 'Obter previsão do tempo para locais e datas da viagem',
|
||
'oauth.scope.journey:read.label': 'Ver jornadas',
|
||
'oauth.scope.journey:read.description': 'Ler jornadas, entradas e lista de colaboradores',
|
||
'oauth.scope.journey:write.label': 'Gerenciar jornadas',
|
||
'oauth.scope.journey:write.description': 'Criar, atualizar e excluir jornadas e suas entradas',
|
||
'oauth.scope.journey:share.label': 'Gerenciar links de jornadas',
|
||
'oauth.scope.journey:share.description': 'Criar, atualizar e revogar links de compartilhamento públicos para jornadas',
|
||
|
||
// System notices
|
||
'system_notice.welcome_v1.title': 'Bem-vindo ao TREK',
|
||
'system_notice.welcome_v1.body': 'Seu planejador de viagens tudo-em-um. Crie roteiros, compartilhe viagens com amigos e fique organizado — online ou offline.',
|
||
'system_notice.welcome_v1.cta_label': 'Planejar uma viagem',
|
||
'system_notice.welcome_v1.hero_alt': 'Destino de viagem pitoresco com a interface do TREK',
|
||
'system_notice.welcome_v1.highlight_plan': 'Roteiros dia a dia para qualquer viagem',
|
||
'system_notice.welcome_v1.highlight_share': 'Colabore com seus companheiros de viagem',
|
||
'system_notice.welcome_v1.highlight_offline': 'Funciona offline no celular',
|
||
'system_notice.dev_test_modal.title': '[Dev] Test notice',
|
||
'system_notice.dev_test_modal.body': 'This is a dev-only test notice.',
|
||
'system_notice.pager.prev': 'Aviso anterior',
|
||
'system_notice.pager.next': 'Próximo aviso',
|
||
'system_notice.pager.counter': '{current} / {total}',
|
||
'system_notice.pager.goto': 'Ir para o aviso {n}',
|
||
'system_notice.pager.position': 'Aviso {current} de {total}',
|
||
// System notices — 3.0.0 upgrade
|
||
'system_notice.v3_photos.title': 'Fotos foram movidas na versão 3.0',
|
||
'system_notice.v3_photos.body': '**Fotos** no Planejador de Viagens foram removidas. Suas fotos estão seguras — o TREK nunca modificou sua biblioteca Immich ou Synology.\n\nAs fotos agora vivem no addon **Journey**. Journey é opcional — se ainda não estiver disponível, peça ao seu admin para ativá-lo em Admin → Addons.',
|
||
'system_notice.v3_journey.title': 'Conheça o Journey — diário de viagem',
|
||
'system_notice.v3_journey.body': 'Documente suas viagens como histórias ricas com cronologias, galerias de fotos e mapas interativos.',
|
||
'system_notice.v3_journey.cta_label': 'Abrir Journey',
|
||
'system_notice.v3_journey.highlight_timeline': 'Linha do tempo e galeria diária',
|
||
'system_notice.v3_journey.highlight_photos': 'Importar do Immich ou Synology',
|
||
'system_notice.v3_journey.highlight_share': 'Compartilhar publicamente — sem login',
|
||
'system_notice.v3_journey.highlight_export': 'Exportar como álbum de fotos PDF',
|
||
'system_notice.v3_features.title': 'Mais destaques na versão 3.0',
|
||
'system_notice.v3_features.body': 'Algumas outras novidades que vale a pena conhecer nesta versão.',
|
||
'system_notice.v3_features.highlight_dashboard': 'Redesign do painel mobile-first',
|
||
'system_notice.v3_features.highlight_offline': 'Modo offline completo como PWA',
|
||
'system_notice.v3_features.highlight_search': 'Autocompleção de lugares em tempo real',
|
||
'system_notice.v3_features.highlight_import': 'Importar lugares de arquivos KMZ/KML',
|
||
|
||
// System notices — MCP OAuth 2.1 upgrade
|
||
'system_notice.v3_mcp.title': 'MCP: atualização OAuth 2.1',
|
||
'system_notice.v3_mcp.body': 'A integração MCP foi completamente reformulada. OAuth 2.1 agora é o método de autenticação recomendado. Tokens estáticos (trek_…) foram descontinuados e serão removidos em uma versão futura.',
|
||
'system_notice.v3_mcp.highlight_oauth': 'OAuth 2.1 recomendado (mcp-remote)',
|
||
'system_notice.v3_mcp.highlight_scopes': '24 escopos de permissão granulares',
|
||
'system_notice.v3_mcp.highlight_deprecated': 'Tokens estáticos trek_ descontinuados',
|
||
'system_notice.v3_mcp.highlight_tools': 'Conjunto de ferramentas e prompts expandido',
|
||
|
||
// System notices — personal thank you
|
||
'system_notice.v3_thankyou.title': 'Uma nota pessoal minha',
|
||
'system_notice.v3_thankyou.body': 'Antes de seguir em frente — quero fazer uma pausa.\n\nO TREK começou como um projeto paralelo que criei para minhas próprias viagens. Nunca imaginei que cresceria a ponto de 4.000 de vocês confiarem nele para planejar suas aventuras. Cada estrela, cada issue, cada pedido de recurso — eu leio todos, e eles me mantêm firme nas noites longas entre um trabalho em tempo integral e a universidade.\n\nQuero que saibam: o TREK sempre será open source, sempre self-hosted, sempre de vocês. Sem rastreamento, sem assinaturas, sem pegadinhas. Apenas uma ferramenta feita por alguém que ama viajar tanto quanto vocês.\n\nAgradecimento especial ao [jubnl](https://github.com/jubnl) — você se tornou um colaborador incrível. Muito do que torna a versão 3.0 especial tem a sua marca. Obrigado por acreditar neste projeto quando ele ainda era bem cru.\n\nE a cada um de vocês que reportou um bug, traduziu uma string, compartilhou o TREK com um amigo ou simplesmente o usou para planejar uma viagem — **obrigado**. Vocês são a razão de tudo isso existir.\n\nQue venham muitas mais aventuras juntos.\n\n— Maurice\n\n---\n\n[Junte-se à comunidade no Discord](https://discord.gg/7Q6M6jDwzf)\n\nSe o TREK torna suas viagens melhores, um [cafezinho](https://ko-fi.com/mauriceboe) sempre mantém as luzes acesas.',
|
||
// System notices — 3.0.14
|
||
'system_notice.v3014_whitespace_collision.title': 'Ação necessária: conflito de conta de usuário',
|
||
'system_notice.v3014_whitespace_collision.body': 'A atualização 3.0.14 detectou um ou mais conflitos de nome de usuário ou e-mail causados por espaços em branco no início ou fim dos valores armazenados. As contas afetadas foram renomeadas automaticamente. Verifique os logs do servidor por linhas começando com **[migration] WHITESPACE COLLISION** para identificar quais contas precisam de revisão.',
|
||
'transport.addTransport': 'Adicionar transporte',
|
||
'transport.modalTitle.create': 'Adicionar transporte',
|
||
'transport.modalTitle.edit': 'Editar transporte',
|
||
'transport.title': 'Transportes',
|
||
'transport.addManual': 'Transporte Manual',
|
||
}
|
||
|
||
export default br
|
||
|