"""Pure-Python localization for multiline engineering and diagnostic reports."""

import re
from typing import Optional


_SUCCESS_STATUS_SOURCE = "".join(("P", "A", "S", "S"))


def normalize_locale(value: object) -> str:
    """Return the two supported locale identifiers with a safe English fallback."""
    normalized = str(value or "").strip().replace("-", "_").casefold()
    return "pt_BR" if normalized.startswith("pt") else "en"


_UI_EXACT_PT = {
    "HydroSizer — Hydraulic Pipe Sizing": "HydroSizer — Dimensionamento hidráulico de tubulações",
    "HydroSizer supports auditable hydraulic pipe sizing from project inspection through calculation-memory export.": "O HydroSizer oferece dimensionamento hidráulico auditável, da inspeção do projeto à exportação da memória de cálculo.",
    "Follow the five project steps from data connection to final documentation. Open Advanced tools only for diagnostics or single-pipe checks.": "Siga as cinco etapas do projeto, da conexão dos dados à documentação final. Abra as ferramentas avançadas somente para diagnósticos ou verificações de trecho único.",
    "Project": "Projeto",
    "Criteria": "Critérios",
    "Sizing": "Dimensionamento",
    "Apply": "Aplicação",
    "Documents": "Documentos",
    "Detect the hydraulic scenario, map project data, and validate the records used by HydroSizer.": "Detecte o cenário hidráulico, mapeie os dados do projeto e valide os registros usados pelo HydroSizer.",
    "Review the product catalog, hydraulic limits, selection rules, and endpoint-pressure settings.": "Revise o catálogo de produtos, os limites hidráulicos, as regras de seleção e as configurações de pressão nas extremidades.",
    "Run pipe sizing in memory, inspect every result, and choose the rows that belong to the design.": "Execute o dimensionamento das tubulações em memória, examine cada resultado e escolha os trechos que pertencem ao projeto.",
    "Optionally prepare and confirm audited changes to existing pipe attributes.": "Opcionalmente, prepare e confirme alterações auditadas nos atributos existentes das tubulações.",
    "Identify the project and export the reviewed calculation memory and detailed spreadsheet.": "Identifique o projeto e exporte a memória de cálculo revisada e a planilha detalhada.",
    "1. Detect Hydraulic Scenario": "1. Detectar cenário hidráulico",
    "2. Map Layers and Fields": "2. Mapear camadas e campos",
    "3. Validate Input Data": "3. Validar dados de entrada",
    "1. Product Catalog": "1. Catálogo de produtos",
    "2. Hydraulic and Selection Criteria": "2. Critérios hidráulicos e de seleção",
    "3. Endpoint Pressure Settings": "3. Configurações de pressão nas extremidades",
    "1. Run Sizing": "1. Executar dimensionamento",
    "2. Review and Include Results": "2. Revisar e incluir resultados",
    "Review and Apply Changes": "Revisar e aplicar alterações",
    "Project Calculation Memory": "Memória de cálculo do projeto",
    "{number}. {name}": "{number}. {name}",
    "Previous": "Anterior",
    "Next: {step}": "Próxima: {step}",
    "End of Workflow": "Fim do fluxo",
    "Step {current} of {total}: {name}\n{description}": "Etapa {current} de {total}: {name}\n{description}",
    "Advanced Tools…": "Ferramentas avançadas…",
    "HydroSizer — Advanced Tools": "HydroSizer — Ferramentas avançadas",
    "These optional tools support diagnostics and individual checks. They are not required for the normal project workflow.": "Estas ferramentas opcionais auxiliam diagnósticos e verificações individuais. Elas não são necessárias no fluxo normal do projeto.",
    "Environment Diagnostic": "Diagnóstico do ambiente",
    "Unit Calculator": "Calculadora de unidades",
    "Hazen–Williams Check": "Verificação Hazen–Williams",
    "Darcy–Weisbach Check": "Verificação Darcy–Weisbach",
    "QGIS environment": "Ambiente QGIS",
    "QGISRed options": "Opções do QGISRed",
    "Layers and fields": "Camadas e campos",
    "Data validation": "Validação de dados",
    "Units and basics": "Unidades e cálculos básicos",
    "Catalog": "Catálogo",
    "Hazen–Williams": "Hazen–Williams",
    "Darcy–Weisbach": "Darcy–Weisbach",
    "Combined criteria": "Critérios combinados",
    "Endpoint pressure": "Pressão nas extremidades",
    "Batch sizing": "Dimensionamento em lote",
    "Preview": "Prévia",
    "Safe apply": "Aplicação segura",
    "Calculation memory": "Memória de cálculo",
    "Inspect current project": "Inspecionar projeto atual",
    "Export JSON…": "Exportar JSON…",
    "Detect from current project": "Detectar no projeto atual",
    "Choose Options DBF…": "Escolher DBF de opções…",
    "Refresh project layers": "Atualizar camadas do projeto",
    "Store temporary mapping": "Armazenar mapeamento temporário",
    "Validate stored mapping": "Validar mapeamento armazenado",
    "Calculate demonstration": "Calcular demonstração",
    "Refresh / search": "Atualizar / pesquisar",
    "Add": "Adicionar",
    "Edit": "Editar",
    "Duplicate": "Duplicar",
    "Activate / deactivate": "Ativar / desativar",
    "Delete": "Excluir",
    "Import CSV…": "Importar CSV…",
    "Export CSV…": "Exportar CSV…",
    "Validate catalog": "Validar catálogo",
    "Evaluate active catalog products": "Avaliar produtos ativos do catálogo",
    "Evaluate combined criteria": "Avaliar critérios combinados",
    "Refresh layers and catalog": "Atualizar camadas e catálogo",
    "Verify endpoint pressures": "Verificar pressões nas extremidades",
    "Select / zoom pipe": "Selecionar / aproximar tubulação",
    "Select / zoom endpoint nodes": "Selecionar / aproximar nós das extremidades",
    "Run memory-only batch sizing": "Executar dimensionamento em lote somente em memória",
    "Apply filters": "Aplicar filtros",
    "Include selected rows": "Incluir linhas selecionadas",
    "Exclude selected rows": "Excluir linhas selecionadas",
    "Select selected rows on map": "Selecionar no mapa as linhas escolhidas",
    "Export displayed CSV...": "Exportar CSV exibido...",
    "Prepare before/after apply plan": "Preparar plano de aplicação antes/depois",
    "Apply confirmed changes": "Aplicar alterações confirmadas",
    "Export calculation memory HTML + CSV spreadsheet...": "Exportar memória de cálculo em HTML + planilha CSV...",
    "Close": "Fechar",
    "Cancel": "Cancelar",
    "Include": "Incluir",
    "All mapped pipes": "Todas as tubulações mapeadas",
    "Selected pipe features only": "Somente feições de tubulação selecionadas",
    "All rows": "Todas as linhas",
    "Included only": "Somente incluídas",
    "Excluded only": "Somente excluídas",
    "All statuses": "Todas as situações",
    "No solution": "Sem solução",
    "Not selected": "Não selecionado",
    "Not defined": "Não definido",
    "Required": "Obrigatório",
    "Warning only": "Somente alerta",
    "Disabled": "Desabilitado",
    "None": "Nenhuma",
    "Yes": "Sim",
    "No": "Não",
    "Active": "Ativo",
    "inactive": "inativo",
    "active": "ativo",
    "included": "incluído",
    "excluded": "excluído",
    "passed": "aprovado",
    "passed with warnings": "aprovado com alertas",
    "failed": "reprovado",
    "completed": "concluído",
    "cancelled safely": "cancelado com segurança",
    "Open HydroSizer": "Abrir HydroSizer",
    "Project and document identification": "Identificação do projeto e do documento",
    "Project title": "Título do projeto",
    "Client or owner": "Contratante ou proprietário",
    "Municipality/state": "Município/estado",
    "Basic design, detailed design...": "Projeto básico, projeto executivo...",
    "Peak hour, minimum level...": "Hora de pico, nível mínimo...",
    "Responsible professional:": "Responsável técnico:",
    "Professional registration:": "Registro profissional:",
    "Description/design concept:": "Descrição/concepção do projeto:",
    "Project stage:": "Fase do projeto:",
    "Hydraulic scenario:": "Cenário hidráulico:",
    "Document code:": "Código do documento:",
    "Revision:": "Revisão:",
    "Client:": "Contratante:",
    "Location:": "Localidade:",
    "Search:": "Pesquisar:",
    "Active products only": "Somente produtos ativos",
    "Material": "Material",
    "Manufacturer": "Fabricante",
    "Standard": "Norma",
    "Series / SDR / class": "Série / SDR / classe",
    "Priority": "Prioridade",
    "Notes:": "Observações:",
    "Pressure": "Pressão",
    "Roughness": "Rugosidade",
    "Diameter criteria": "Critérios de diâmetro",
    "Velocity criteria": "Critérios de velocidade",
    "Pressure and selection": "Pressão e seleção",
    "Demonstration inputs": "Entradas da demonstração",
    "Single-segment inputs": "Entradas do trecho único",
    "Method and segment": "Método e trecho",
    "Pipe, product, and optional margin": "Tubulação, produto e margem opcional",
    "Processing mode:": "Modo de processamento:",
    "Preview filters": "Filtros da prévia",
    "Destination fields": "Campos de destino",
    "Required audit output": "Saída de auditoria obrigatória",
    "Choose directory...": "Escolher pasta...",
    "HydroSizer diagnostic": "Diagnóstico do HydroSizer",
    "HydroSizer QGISRed detection": "Detecção do QGISRed pelo HydroSizer",
    "HydroSizer QGISRed options": "Opções do QGISRed no HydroSizer",
    "HydroSizer layer mapping": "Mapeamento de camadas do HydroSizer",
    "HydroSizer data validation": "Validação de dados do HydroSizer",
    "HydroSizer catalog": "Catálogo do HydroSizer",
    "HydroSizer batch sizing": "Dimensionamento em lote do HydroSizer",
    "HydroSizer safe apply": "Aplicação segura do HydroSizer",
    "HydroSizer export": "Exportação do HydroSizer",
    "<unsaved>": "<não salvo>",
    "Additive margin:": "Margem aditiva:",
    "Advanced fluid property": "Propriedade avançada do fluido",
    "Audit CSV: {path}": "CSV de auditoria: {path}",
    "Bresse coefficient K:": "Coeficiente K de Bresse:",
    "Darcy–Weisbach fluid property": "Propriedade do fluido para Darcy–Weisbach",
    "Default: 1.004 mm²/s = 1.004×10⁻⁶ m²/s, representative of water near 20 °C. Review it for the design temperature.": "Padrão: 1,004 mm²/s = 1,004×10⁻⁶ m²/s, representativo da água próxima de 20 °C. Revise para a temperatura de projeto.",
    "Environment diagnostic exported to: {path}": "Diagnóstico do ambiente exportado para: {path}",
    "HydroSizer dialog closed.": "Janela do HydroSizer fechada.",
    "HydroSizer dialog opened.": "Janela do HydroSizer aberta.",
    "HydroSizer {version} loaded.": "HydroSizer {version} carregado.",
    "HydroSizer {version} unloaded.": "HydroSizer {version} descarregado.",
    "Inclusion:": "Inclusão:",
    "Margin mode:": "Modo da margem:",
    "Metadata JSON: {path}": "JSON de metadados: {path}",
    "Multiplicative factor": "Fator multiplicativo",
    "Professional council and registration number": "Conselho profissional e número de registro",
    "Review or correct detected settings": "Revisar ou corrigir as configurações detectadas",
    "Water kinematic viscosity:": "Viscosidade cinemática da água:",
    "currency per ft": "moeda por pé",
    "currency per m": "moeda por m",
    "per ft": "por pé",
    "per m": "por m",
    "{summary} Audit CSV={csv}; metadata JSON={json}.": "{summary} CSV de auditoria={csv}; JSON de metadados={json}.",
    "{title}: {details}": "{title}: {details}",
    "Click “Inspect current project” to list project and layer metadata.": "Clique em “Inspecionar projeto atual” para listar os metadados do projeto e das camadas.",
    "Lists the current project, loaded layers, sanitized sources, providers, layer types, CRS information, and field definitions.": "Lista o projeto atual, as camadas carregadas, origens sanitizadas, provedores, tipos de camada, informações de SRC e definições de campos.",
    "Searches the project and local layer directories for *_Options.dbf, then opens the selected table through QGIS/OGR for read-only inspection.": "Pesquisa *_Options.dbf no projeto e nas pastas locais das camadas e abre a tabela escolhida pelo QGIS/OGR para inspeção somente leitura.",
    "Select the pipe layer, result layer, matching ID fields, flow field, and attribute-based pipe length. Only compatible fields are listed. Features are not read in this stage.": "Selecione as camadas de tubulações e resultados, os campos de ID correspondentes, o campo de vazão e o comprimento da tubulação por atributo. Somente campos compatíveis são listados. As feições não são lidas nesta etapa.",
    "Validates all mapped records for null or duplicate IDs, missing matches, invalid flow, and invalid attribute length. The reader requests no geometry and never starts editing.": "Valida todos os registros mapeados quanto a IDs nulos ou duplicados, correspondências ausentes, vazão inválida e comprimento de atributo inválido. A leitura não solicita geometria nem inicia edição.",
    "Demonstrates central unit conversion, mean velocity, and segment cost for manually entered values. No project layer is accessed.": "Demonstra a conversão central de unidades, a velocidade média e o custo do trecho para valores informados manualmente. Nenhuma camada do projeto é acessada.",
    "HydroSizer catalog stored separately from QGISRed. A new empty profile receives the bundled initial catalog; existing catalogs are never overwritten.": "O catálogo do HydroSizer é armazenado separadamente do QGISRed. Um perfil novo e vazio recebe o catálogo inicial incluído; catálogos existentes nunca são sobrescritos.",
    "Evaluates every active, hydraulically complete catalog product for one manually entered segment. Only maximum unit headloss determines admissibility; velocity and cost are informative.": "Avalia todos os produtos ativos e hidraulicamente completos do catálogo para um trecho informado manualmente. Somente a perda de carga unitária máxima determina a admissibilidade; velocidade e custo são informativos.",
    "Evaluates active catalog products using their absolute roughness. Reynolds number, flow regime, relative roughness, friction factor, velocity, and losses are reported.": "Avalia os produtos ativos do catálogo usando a rugosidade absoluta. São apresentados o número de Reynolds, regime de escoamento, rugosidade relativa, fator de atrito, velocidade e perdas.",
    "Applies all enabled required criteria to active catalog products, then uses a deterministic multicriteria selection order.": "Aplica aos produtos ativos do catálogo todos os critérios obrigatórios habilitados e usa uma ordem determinística de seleção multicritério.",
    "This optional single-pipe check keeps manual pressure input. Use Endpoint Pressure Settings below for read-only project mapping.": "Esta verificação opcional de trecho único mantém a pressão informada manualmente. Use Configurações de pressão nas extremidades abaixo para o mapeamento do projeto somente leitura.",
    "Matches pipe start/end geometry to node-result points, then checks the larger endpoint pressure against the selected product rating.": "Relaciona as geometrias inicial e final da tubulação aos pontos de resultado nodal e compara a maior pressão de extremidade com a classe do produto selecionado.",
    "Uses the stored and validated layer mapping, current Combined criteria, active catalog, and geometric endpoint mapping. Manual flow and length values on the Combined tab are replaced by each pipe's mapped attributes.": "Usa o mapeamento de camadas armazenado e validado, os critérios combinados atuais, o catálogo ativo e o mapeamento geométrico das extremidades. Os valores manuais de vazão e comprimento são substituídos pelos atributos mapeados de cada tubulação.",
    "Uses the validated project mapping, current hydraulic and selection criteria, active catalog, and geometric endpoint mapping. Manual check values are replaced by each pipe's mapped flow and length.": "Usa o mapeamento validado do projeto, os critérios hidráulicos e de seleção atuais, o catálogo ativo e o mapeamento geométrico das extremidades. Os valores da verificação manual são substituídos pela vazão e pelo comprimento mapeados de cada tubulação.",
    "Prerequisites: store the Layers and fields mapping; pass Data validation; review Combined criteria. If pressure is enabled, also review Endpoint pressure mapping and margin.": "Pré-requisitos: armazenar o mapeamento de Camadas e campos; aprovar a Validação de dados; revisar os Critérios combinados. Se a pressão estiver habilitada, revisar também o mapeamento e a margem de Pressão nas extremidades.",
    "Prerequisites: complete Project mapping and validation; review the Criteria activities. If pressure is enabled, also review endpoint mapping and margin.": "Pré-requisitos: concluir o mapeamento e a validação em Projeto; revisar as atividades de Critérios. Se a pressão estiver habilitada, revisar também o mapeamento das extremidades e a margem.",
    "Reviews the latest Batch sizing snapshot without recalculating. Only successfully sized rows are eligible for later apply.": "Revisa o retrato mais recente do dimensionamento em lote sem recalcular. Somente linhas dimensionadas com sucesso são elegíveis para aplicação posterior.",
    "Include/exclude changes only plugin memory. CSV export contains the currently displayed rows. There is no layer apply action in this stage.": "Incluir ou excluir altera somente a memória do plugin. A exportação CSV contém as linhas exibidas. Não há aplicação em camada nesta etapa.",
    "Map existing pipe fields explicitly. Prepare reviews current and proposed values without editing. Apply is enabled only for a current plan and always asks for confirmation.": "Mapeie explicitamente os campos existentes da tubulação. Preparar revisa os valores atuais e propostos sem editar. Aplicar é habilitado somente para um plano atual e sempre solicita confirmação.",
    "Successful values remain pending in the QGIS edit buffer. Use QGIS Save Layer Edits to persist or Undo to revert. QGISRed DBF catalog files are never changed.": "Os valores aplicados permanecem pendentes no buffer de edição do QGIS. Use Salvar edições da camada para persistir ou Desfazer para reverter. Os DBFs de catálogo do QGISRed nunca são alterados.",
    "Exports the project's hydraulic calculation memory as HTML and the detailed sizing spreadsheet as CSV. Complete the document control data before export. To obtain a PDF, print the HTML directly from the browser.": "Exporta a memória de cálculo hidráulico do projeto em HTML e a planilha detalhada de dimensionamento em CSV. Preencha os dados de controle do documento antes da exportação. Para obter PDF, imprima o HTML diretamente no navegador.",
    "The export uses only the in-memory snapshot and does not change layers or the catalog. The document must be reviewed and signed by the responsible professional.": "A exportação usa somente o retrato em memória e não altera camadas nem o catálogo. O documento deve ser revisado e assinado pelo responsável técnico.",
    "Batch sizing requires a stored Layers and fields mapping and a completed Data validation.": "O dimensionamento em lote exige um mapeamento de Camadas e campos armazenado e a Validação de dados concluída.",
    "Sizing requires completed layer mapping and data validation in the Project step.": "O dimensionamento exige o mapeamento de camadas e a validação de dados concluídos na etapa Projeto.",
    "Sizing requires a reviewed QGISRed flow unit before the project mapping is stored.": "O dimensionamento exige que a unidade de vazão do QGISRed seja revisada antes de armazenar o mapeamento do projeto.",
    "No current sizing is available. Complete Sizing and review the included pipe results.": "Não há dimensionamento atual disponível. Conclua Dimensionamento e revise os resultados de tubulações incluídos.",
    "Calculation memory export failed: {error}": "Falha ao exportar a memória de cálculo: {error}",
    "Temporary layer mapping stored: pipes={pipe_layer}[{pipe_id}]; results={result_layer}[{result_id}]; flow={flow}; length={length}.": "Mapeamento temporário armazenado: tubulações={pipe_layer}[{pipe_id}]; resultados={result_layer}[{result_id}]; vazão={flow}; comprimento={length}.",
    "Catalog product {catalog_id} added.": "Produto {catalog_id} adicionado ao catálogo.",
    "No current apply plan. Prepare the before/after plan first.": "Não há plano de aplicação atual. Prepare primeiro o plano antes/depois.",
    "HydroSizer catalog product": "Produto do catálogo HydroSizer",
    "Required fields are marked with *. Decimal comma or decimal point is accepted. Blank optional hydraulic values generate warnings.": "Os campos obrigatórios são marcados com *. Aceita-se vírgula ou ponto decimal. Valores hidráulicos opcionais em branco geram alertas.",
    "Material code *": "Código do material *",
    "Material name (pt-BR) *": "Nome do material (pt-BR) *",
    "Material name (English) *": "Nome do material (inglês) *",
    "Product code *": "Código do produto *",
    "Nominal diameter *": "Diâmetro nominal *",
    "Nominal diameter unit *:": "Unidade do diâmetro nominal *:",
    "Internal diameter *:": "Diâmetro interno *:",
    "Internal diameter unit *:": "Unidade do diâmetro interno *:",
    "Pressure class": "Classe de pressão",
    "Maximum allowable pressure": "Pressão máxima admissível",
    "Pressure unit:": "Unidade de pressão:",
    "Absolute roughness:": "Rugosidade absoluta:",
    "Roughness unit:": "Unidade de rugosidade:",
    "Cost per length:": "Custo por comprimento:",
    "Cost length unit:": "Unidade de comprimento do custo:",
    "Currency code": "Código da moeda",
    "QGISRed material value": "Valor do material no QGISRed",
    "Product available for selection": "Produto disponível para seleção",
    "Active:": "Ativo:",
    "QGISRed detection completed: {count} candidate(s); recommended network base is {network_base}.": "Detecção do QGISRed concluída: {count} candidato(s); a base de rede recomendada é {network_base}.",
    "Layer mapping inventory refreshed: {count} vector layer(s); suggested pipes={pipes}; results={results}.": "Inventário do mapeamento atualizado: {count} camada(s) vetorial(is); tubulações sugeridas={pipes}; resultados={results}.",
    "Endpoint pressure mapping refreshed without feature access: vectors={vectors}; active products={products}; pipe layer={pipe}; node results={nodes}.": "Mapeamento de pressão nas extremidades atualizado sem acesso a feições: vetores={vectors}; produtos ativos={products}; camada de tubulações={pipe}; resultados nodais={nodes}.",
    "Hydraulic calculation memory — Stage 15": "Memória de cálculo hidráulico — Etapa 15",
    "Operation: export only; layers and catalog unchanged": "Operação: somente exportação; camadas e catálogo inalterados",
    "Calculation memory issued: {rows} pipe(s), HTML and CSV spreadsheet.": "Memória de cálculo emitida: {rows} tubulação(ões), HTML e planilha CSV.",
}

# Complete sentence translations are intentional. UI text must never be assembled
# by translating isolated English words because that produces ambiguous engineering
# instructions and grammatically incorrect Portuguese.
_UI_EXACT_PT.update({
    "3. Automatic Pressure Check": "3. Verificação automática de pressão",
    "<missing layer>": "<camada ausente>",
    "<not set>": "<não definido>",
    "Absolute roughness ->": "Rugosidade absoluta ->",
    "Additive margin": "Margem aditiva",
    "Additive margin unit": "Unidade da margem aditiva",
    "Additive pressure": "Pressão aditiva",
    "All active materials": "Todos os materiais ativos",
    "Apply configuration changed. Prepare the plan again.": "A configuração de aplicação foi alterada. Prepare o plano novamente.",
    "Apply plan ready: included={included}; changes={changes}; maintained={maintained}. No layer edits yet.": "Plano de aplicação pronto: incluídos={included}; alterações={changes}; mantidos={maintained}. Nenhuma camada foi editada.",
    "Apply {count} confirmed change(s)": "Aplicar {count} alteração(ões) confirmada(s)",
    "Audit directory must be an absolute path.": "A pasta de auditoria deve ter um caminho absoluto.",
    "Automatic pressure mapping refreshed: {layer_count} vector layer(s); {product_count} active catalog product(s).": "Mapeamento automático de pressão atualizado: {layer_count} camada(s) vetorial(is); {product_count} produto(s) ativo(s) no catálogo.",
    "Basic calculation completed without layer access: |Q|={flow:.12g} m³/s; Di={diameter:.12g} m; V={velocity:.12g} m/s; cost={cost:.12g}.": "Cálculo básico concluído sem acesso às camadas: |Q|={flow:.12g} m³/s; Di={diameter:.12g} m; V={velocity:.12g} m/s; custo={cost:.12g}.",
    "Basic calculation completed: velocity={velocity:.6g} m/s; segment cost={cost:.6g}.": "Cálculo básico concluído: velocidade={velocity:.6g} m/s; custo do trecho={cost:.6g}.",
    "Basic calculation input error: {error}": "Erro nos dados do cálculo básico: {error}",
    "Batch sizing failed: {error}": "Falha no dimensionamento em lote: {error}",
    "Batch sizing input error: {error}": "Erro nos dados do dimensionamento em lote: {error}",
    "Batch sizing is blocked because Data validation failed.": "O dimensionamento em lote está bloqueado porque a validação dos dados foi reprovada.",
    "Batch sizing is running; the previous apply plan was cleared.": "O dimensionamento em lote está em execução; o plano de aplicação anterior foi descartado.",
    "Batch sizing is running; the previous preview was cleared.": "O dimensionamento em lote está em execução; a prévia anterior foi descartada.",
    "Batch sizing not run.": "O dimensionamento em lote ainda não foi executado.",
    "Batch sizing pipe layer no longer exists.": "A camada de tubulações usada no dimensionamento não existe mais.",
    "Batch sizing preparation failed: {error}": "Falha ao preparar o dimensionamento em lote: {error}",
    "Batch sizing prerequisite error: {error}": "Erro nos pré-requisitos do dimensionamento em lote: {error}",
    "Batch sizing {state}: {processed} of {requested} pipe(s) processed; sized={sized}; warnings={warnings}; no solution={no_solution}; insufficient={insufficient}.": "Dimensionamento em lote {state}: {processed} de {requested} tubulação(ões) processada(s); dimensionadas={sized}; alertas={warnings}; sem solução={no_solution}; dados insuficientes={insufficient}.",
    "Brief description of the project and adopted design concept": "Descrição breve do projeto e da concepção adotada",
    "CSV files (*.csv)": "Arquivos CSV (*.csv)",
    "CSV spreadsheet: {path}": "Planilha CSV: {path}",
    "Calculation memory export failed: {error_type}: {error}": "Falha ao exportar a memória de cálculo: {error_type}: {error}",
    "Cannot select preview rows: the mapped pipe layer is missing.": "Não foi possível selecionar as linhas da prévia: a camada de tubulações mapeada está ausente.",
    "Cannot select {entity} problems: the layer no longer exists.": "Não foi possível selecionar problemas em {entity}: a camada não existe mais.",
    "Cannot select {label}: mapped layer no longer exists.": "Não foi possível selecionar {label}: a camada mapeada não existe mais.",
    "Catalog CSV export failed": "Falha ao exportar o CSV do catálogo",
    "Catalog CSV exported: {target}; products={count}.": "CSV do catálogo exportado: {target}; produtos={count}.",
    "Catalog CSV import failed": "Falha ao importar o CSV do catálogo",
    "Catalog CSV imported: {path}; products={count}.": "CSV do catálogo importado: {path}; produtos={count}.",
    "Catalog contains {count} displayed product(s). Database: {path}": "O catálogo contém {count} produto(s) exibido(s). Banco de dados: {path}",
    "Catalog initialization failed": "Falha ao inicializar o catálogo",
    "Catalog not initialized.": "Catálogo não inicializado.",
    "Catalog product": "Produto do catálogo",
    "Catalog product added: catalog_id={catalog_id}.": "Produto adicionado ao catálogo: catalog_id={catalog_id}.",
    "Catalog product deleted: catalog_id={catalog_id}.": "Produto excluído do catálogo: catalog_id={catalog_id}.",
    "Catalog product duplicated as ID {catalog_id}.": "Produto do catálogo duplicado com o ID {catalog_id}.",
    "Catalog product duplicated: source={source}; new={new}.": "Produto do catálogo duplicado: origem={source}; novo={new}.",
    "Catalog product state changed: catalog_id={catalog_id}; active={active}.": "Situação do produto alterada: catalog_id={catalog_id}; ativo={active}.",
    "Catalog product updated: catalog_id={catalog_id}.": "Produto do catálogo atualizado: catalog_id={catalog_id}.",
    "Catalog product {catalog_id} deleted.": "Produto {catalog_id} excluído do catálogo.",
    "Catalog product {catalog_id} is now {state}.": "O produto {catalog_id} agora está {state}.",
    "Catalog product {catalog_id} no longer exists": "O produto {catalog_id} não existe mais no catálogo",
    "Catalog product {catalog_id} no longer exists; refresh the view.": "O produto {catalog_id} não existe mais no catálogo; atualize a exibição.",
    "Catalog product {catalog_id} updated.": "Produto {catalog_id} atualizado no catálogo.",
    "Catalog refresh failed": "Falha ao atualizar o catálogo",
    "Catalog validation and operation details will appear here.": "Os detalhes da validação e das operações do catálogo serão exibidos aqui.",
    "Catalog validation completed: {invalid} invalid product(s), {warnings} warning(s).": "Validação do catálogo concluída: {invalid} produto(s) inválido(s), {warnings} alerta(s).",
    "Catalog validation failed": "Falha na validação do catálogo",
    "Catalog view refreshed: {count} product(s).": "Exibição do catálogo atualizada: {count} produto(s).",
    "Central registry also supports pressure: mca, kPa, bar, psi; headloss gradient: m/m, m/km, ft/100 ft, ft/1000 ft.": "O registro central também aceita pressão em mca, kPa, bar e psi, e perda de carga unitária em m/m, m/km, ft/100 ft e ft/1000 ft.",
    "Changed attributes: {count}": "Atributos alterados: {count}",
    "Changed pipe features: {count}": "Feições de tubulação alteradas: {count}",
    "Choose HydroSizer audit directory": "Escolher pasta de auditoria do HydroSizer",
    "Choose QGISRed Options DBF": "Escolher DBF de opções do QGISRed",
    "Choose an audit directory before preparing the apply plan.": "Escolha uma pasta de auditoria antes de preparar o plano de aplicação.",
    "Choose the HydroSizer_Audit directory": "Escolher a pasta HydroSizer_Audit",
    "Configures the automatic batch pressure check. HydroSizer matches each pipe endpoint to node results and compares the larger pressure, including any margin, with each candidate product rating.": "Configura a verificação automática de pressão do dimensionamento. O HydroSizer relaciona as extremidades de cada tubulação aos resultados nodais e compara a maior pressão, acrescida da margem, com a pressão admissível de cada produto candidato.",
    "Confirm HydroSizer safe apply": "Confirmar aplicação segura do HydroSizer",
    "Cost": "Custo",
    "Cost basis:": "Base do custo:",
    "Could not add catalog product": "Não foi possível adicionar o produto ao catálogo",
    "Could not change product state": "Não foi possível alterar a situação do produto",
    "Could not delete catalog product": "Não foi possível excluir o produto do catálogo",
    "Could not duplicate catalog product": "Não foi possível duplicar o produto do catálogo",
    "Could not update catalog product": "Não foi possível atualizar o produto do catálogo",
    "D-W roughness destination unit:": "Unidade de destino da rugosidade D-W:",
    "DBF fields, records, and detected settings will appear here.": "Os campos, registros e parâmetros detectados no DBF serão exibidos aqui.",
    "Darcy–Weisbach (D-W)": "Darcy–Weisbach (D-W)",
    "Darcy–Weisbach calculation failed: {error}": "Falha no cálculo de Darcy–Weisbach: {error}",
    "Darcy–Weisbach demonstration completed: {count} active product(s) considered; no admissible product found.": "Demonstração de Darcy–Weisbach concluída: {count} produto(s) ativo(s) considerado(s); nenhum produto admissível encontrado.",
    "Darcy–Weisbach demonstration completed: {count} active product(s) considered; selected catalog ID {catalog_id} ({material}/{product}).": "Demonstração de Darcy–Weisbach concluída: {count} produto(s) ativo(s) considerado(s); selecionado o ID {catalog_id} do catálogo ({material}/{product}).",
    "Darcy–Weisbach demonstration not calculated.": "A demonstração de Darcy–Weisbach ainda não foi calculada.",
    "Darcy–Weisbach input error: {error}": "Erro nos dados de Darcy–Weisbach: {error}",
    "Data validation completed: pipes={pipes}; results={results}; matched={matched}; errors={errors}; warnings={warnings}.": "Validação dos dados concluída: tubulações={pipes}; resultados={results}; correspondências={matched}; erros={errors}; alertas={warnings}.",
    "Data validation failed: {error_type}: {error}": "Falha na validação dos dados: {error_type}: {error}",
    "Data validation rerun. Run Batch sizing again to create a preview.": "A validação dos dados foi executada novamente. Execute o dimensionamento em lote para criar outra prévia.",
    "Data validation rerun. Run Batch sizing again.": "A validação dos dados foi executada novamente. Execute o dimensionamento em lote outra vez.",
    "Defines project-wide sizing rules. Batch sizing supplies each pipe's flow, length, and endpoint pressures automatically.": "Define as regras gerais de dimensionamento do projeto. A vazão, o comprimento e as pressões nas extremidades de cada tubulação são obtidos automaticamente no dimensionamento em lote.",
    "Delete HydroSizer catalog product": "Excluir produto do catálogo HydroSizer",
    "Delete catalog ID {catalog_id} ({material} / {product})?": "Excluir o ID {catalog_id} do catálogo ({material} / {product})?",
    "Demonstration not calculated.": "Demonstração ainda não calculada.",
    "Destination mapping loaded for {method}; prepare a plan.": "Mapeamento de destino carregado para {method}; prepare um plano.",
    "Detected QGISRed settings: flow units={units}; headloss={headloss}.": "Parâmetros do QGISRed detectados: unidade de vazão={units}; perda de carga={headloss}.",
    "Detection scope and candidate files will appear here.": "O escopo da detecção e os arquivos candidatos serão exibidos aqui.",
    "Diagnostic export failed: {error_type}: {error}": "Falha ao exportar o diagnóstico: {error_type}: {error}",
    "Diameter unit:": "Unidade do diâmetro:",
    "Displayed {displayed} of {total} row(s); eligible={eligible}; included={included}; excluded={excluded}.": "Exibidas {displayed} de {total} linha(s); elegíveis={eligible}; incluídas={included}; excluídas={excluded}.",
    "Edit session started by HydroSizer: {answer}": "Sessão de edição iniciada pelo HydroSizer: {answer}",
    "Endpoint mapping has not been refreshed.": "O mapeamento das extremidades ainda não foi atualizado.",
    "Endpoint pressure configuration is incomplete: {fields}": "A configuração de pressão nas extremidades está incompleta: {fields}",
    "Endpoint pressure mapping failed: {error}": "Falha no mapeamento de pressão nas extremidades: {error}",
    "Endpoint pressure verification failed: {error}": "Falha na verificação de pressão nas extremidades: {error}",
    "Endpoint pressure verification input error: {error}": "Erro nos dados da verificação de pressão nas extremidades: {error}",
    "Endpoint pressure verification {status}: pipe={pipe}; initial={initial:.12g} Pa; final={final:.12g} Pa; verification={verification:.12g} Pa; allowable={allowable:.12g} Pa.": "Verificação de pressão nas extremidades {status}: tubulação={pipe}; inicial={initial:.12g} Pa; final={final:.12g} Pa; verificação={verification:.12g} Pa; admissível={allowable:.12g} Pa.",
    "Endpoint pressure verification {status}: pipe={pipe}; verification={verification:.12g} Pa.": "Verificação de pressão nas extremidades {status}: tubulação={pipe}; verificação={verification:.12g} Pa.",
    "Endpoint tolerance (pipe CRS units):": "Tolerância de coincidência (unidades do SRC da tubulação):",
    "Environment diagnostic completed: {total} layers ({vector} spatial vector, {tables} tables).": "Diagnóstico do ambiente concluído: {total} camada(s) ({vector} vetorial(is) espacial(is), {tables} tabela(s)).",
    "Environment diagnostic failed: {error_type}: {error}": "Falha no diagnóstico do ambiente: {error_type}: {error}",
    "Environment diagnostic not run.": "O diagnóstico do ambiente ainda não foi executado.",
    "Every mapping is optional, but at least one field is required. A destination field cannot be used twice. Material mapping requires qgisred_material_value in every selected product.": "Cada mapeamento é opcional, mas ao menos um campo é obrigatório. Um campo de destino não pode ser usado duas vezes. O mapeamento de material exige qgisred_material_value em todos os produtos selecionados.",
    "Exact pipe ID, for example 1 or P-001": "ID exato da tubulação, por exemplo 1 ou P-001",
    "Export HydroSizer catalog CSV": "Exportar CSV do catálogo HydroSizer",
    "Export HydroSizer sizing preview CSV": "Exportar CSV da prévia de dimensionamento do HydroSizer",
    "Export QGIS environment diagnostic": "Exportar diagnóstico do ambiente QGIS",
    "Export hydraulic calculation memory": "Exportar memória de cálculo hidráulico",
    "Exported {count} catalog product(s) to {target}.": "Foram exportados {count} produto(s) do catálogo para {target}.",
    "Exported {count} displayed preview row(s) to {target}.": "Foram exportadas {count} linha(s) exibida(s) da prévia para {target}.",
    "Feature access: none": "Acesso a feições: nenhum",
    "Flow": "Vazão",
    "Flow field:": "Campo de vazão:",
    "Flow field: {field}": "Campo de vazão: {field}",
    "Flow unit code: {code}": "Código da unidade de vazão: {code}",
    "Flow unit:": "Unidade de vazão:",
    "Flow value:": "Valor da vazão:",
    "Flow:": "Vazão:",
    "For every pipe, HydroSizer automatically uses the larger of the start and end node pressures, applies the configured margin, and rejects products with insufficient allowable pressure.": "Para cada tubulação, o HydroSizer usa automaticamente a maior pressão entre os nós inicial e final, aplica a margem configurada e rejeita produtos cuja pressão admissível seja insuficiente.",
    "Gradient unit:": "Unidade da perda de carga unitária:",
    "H-W C / absolute roughness ->": "C de H-W / rugosidade absoluta ->",
    "HTML files (*.html)": "Arquivos HTML (*.html)",
    "HTML: {path}": "HTML: {path}",
    "Hazen-Williams C ->": "C de Hazen-Williams ->",
    "Hazen–Williams (H-W)": "Hazen–Williams (H-W)",
    "Hazen–Williams C:": "C de Hazen–Williams:",
    "Hazen–Williams calculation failed: {error}": "Falha no cálculo de Hazen–Williams: {error}",
    "Hazen–Williams demonstration completed: {count} active product(s) considered; no admissible product found.": "Demonstração de Hazen–Williams concluída: {count} produto(s) ativo(s) considerado(s); nenhum produto admissível encontrado.",
    "Hazen–Williams demonstration completed: {count} active product(s) considered; selected catalog ID {catalog_id} ({material}/{product}).": "Demonstração de Hazen–Williams concluída: {count} produto(s) ativo(s) considerado(s); selecionado o ID {catalog_id} do catálogo ({material}/{product}).",
    "Hazen–Williams demonstration not calculated.": "A demonstração de Hazen–Williams ainda não foi calculada.",
    "Hazen–Williams input error: {error}": "Erro nos dados de Hazen–Williams: {error}",
    "Headloss code: {code}": "Código do método de perda de carga: {code}",
    "Headloss method:": "Método de cálculo da perda de carga:",
    "Headloss unit": "Unidade da perda de carga",
    "Highlight buttons change only the current QGIS selection. They do not change attributes or save edits.": "Os botões de destaque alteram somente a seleção atual no QGIS. Eles não modificam atributos nem salvam edições.",
    "Hydraulic Method and Headloss": "Método hidráulico e perda de carga",
    "Hydraulic method": "Método hidráulico",
    "Project material filter": "Materiais admitidos no projeto",
    "HydroSizer": "HydroSizer",
    "HydroSizer Catalog Validation — Stage 7": "Validação do catálogo HydroSizer — Etapa 7",
    "HydroSizer Safe Apply — Stage 14": "Aplicação segura do HydroSizer — Etapa 14",
    "HydroSizer catalog initialized: {path}": "Catálogo HydroSizer inicializado: {path}",
    "HydroSizer catalog seeded: {count} bundled product(s); {warnings} validation warning(s).": "Catálogo HydroSizer preenchido: {count} produto(s) incluído(s); {warnings} alerta(s) de validação.",
    "HydroSizer temporary mapping — Stage 4": "Mapeamento temporário do HydroSizer — Etapa 4",
    "ID": "ID",
    "Import HydroSizer catalog CSV": "Importar CSV do catálogo HydroSizer",
    "Imported {count} catalog product(s) atomically.": "Foram importados {count} produto(s) do catálogo de forma atômica.",
    "Included: {count}": "Incluídos: {count}",
    "Individual pressure check not run.": "A verificação individual de pressão ainda não foi executada.",
    "Insufficient data": "Dados insuficientes",
    "Insufficient data: {count}": "Dados insuficientes: {count}",
    "Internal D": "D interno",
    "Internal destination unit:": "Unidade de destino do diâmetro interno:",
    "Internal diameter ->": "Diâmetro interno ->",
    "Internal diameter:": "Diâmetro interno:",
    "Internal document code": "Código interno do documento",
    "Invalid products: {count}": "Produtos inválidos: {count}",
    "JSON files (*.json)": "Arquivos JSON (*.json)",
    "Kinematic viscosity:": "Viscosidade cinemática:",
    "Layer changes: none": "Alterações em camadas: nenhuma",
    "Layer inventory not loaded.": "O inventário de camadas ainda não foi carregado.",
    "Layer inventory refreshed. Store the mapping before validation.": "Inventário de camadas atualizado. Armazene o mapeamento antes da validação.",
    "Layer mapping inventory failed: {error_type}: {error}": "Falha no inventário do mapeamento de camadas: {error_type}: {error}",
    "Length": "Comprimento",
    "Length field: {field} (attribute only)": "Campo de comprimento: {field} (somente atributo)",
    "Length unit:": "Unidade de comprimento:",
    "Length will later be read only from the selected attribute. Geometry length is not used. No layer is edited in this stage.": "O comprimento será lido somente do atributo selecionado. O comprimento da geometria não é usado. Nenhuma camada é editada nesta etapa.",
    "Loaded {count} vector layer(s). Review the suggestions and store the temporary mapping.": "Foram carregadas {count} camada(s) vetorial(is). Revise as sugestões e armazene o mapeamento temporário.",
    "Mapped length attribute unit:": "Unidade do atributo de comprimento mapeado:",
    "Mapping changed. Review it and click “Store temporary mapping”.": "O mapeamento foi alterado. Revise-o e clique em “Armazenar mapeamento temporário”.",
    "Mapping changed. Run validation and Batch sizing again.": "O mapeamento foi alterado. Execute novamente a validação e o dimensionamento em lote.",
    "Mapping changed. Store it again before validation.": "O mapeamento foi alterado. Armazene-o novamente antes da validação.",
    "Mapping is incomplete. Store a complete mapping before validation.": "O mapeamento está incompleto. Armazene um mapeamento completo antes da validação.",
    "Margin mode": "Modo da margem",
    "Material scope": "Materiais permitidos",
    "Maximum unit headloss": "Perda de carga unitária máxima",
    "Maximum unit headloss:": "Perda de carga unitária máxima:",
    "Maximum velocity (m/s):": "Velocidade máxima (m/s):",
    "Maximum velocity is required": "Usar a velocidade máxima como critério obrigatório",
    "Memory-only run": "Execução somente em memória",
    "Minimum DN unit:": "Unidade do DN mínimo:",
    "Minimum DN value:": "Valor do DN mínimo:",
    "Minimum velocity (m/s):": "Velocidade mínima (m/s):",
    "Minimum velocity behavior:": "Tratamento da velocidade mínima:",
    "Name (pt-BR)": "Nome (pt-BR)",
    "Name of the responsible professional": "Nome do responsável técnico",
    "No (ineligible)": "Não (inelegível)",
    "No pipe-by-pipe action is required here. When the pressure criterion is enabled, batch sizing performs this check for every pipe automatically. This is not a transient analysis.": "Não é necessário verificar cada trecho nesta tela. Quando o critério de pressão está habilitado, o dimensionamento em lote executa essa verificação automaticamente em todas as tubulações. Esta não é uma análise de transientes hidráulicos.",
    "No preview is available. Run Batch sizing first.": "Não há prévia disponível. Execute primeiro o dimensionamento em lote.",
    "No solution: {count}": "Sem solução: {count}",
    "No stored mapping is available. Store the mapping first.": "Não há mapeamento armazenado. Armazene o mapeamento primeiro.",
    "Node result ID field:": "Campo de ID do resultado nodal:",
    "Node result layer/table:": "Camada/tabela de resultados nodais:",
    "Nominal destination unit:": "Unidade de destino do diâmetro nominal:",
    "Nominal diameter ->": "Diâmetro nominal ->",
    "Only maximum unit headloss determines admissibility in Stage 9. No project layer is inspected or edited.": "Somente a perda de carga unitária máxima determina a admissibilidade na Etapa 9. Nenhuma camada do projeto é inspecionada ou editada.",
    "Optional Pressure Margin": "Margem de pressão opcional",
    "Optional diagnostic for one pipe and one catalog product. The normal batch workflow performs the same endpoint-pressure rule automatically for every pipe.": "Diagnóstico opcional de uma tubulação e um produto do catálogo. O fluxo normal em lote aplica automaticamente a mesma regra de pressão nas extremidades a todas as tubulações.",
    "Options opened read-only: {name}; {count} records; units={units}; headloss={headloss}.": "Opções abertas somente para leitura: {name}; {count} registros; unidades={units}; perda de carga={headloss}.",
    "Persistence: memory only; cleared on plugin reload": "Persistência: somente em memória; descartada ao recarregar o plugin",
    "Pipe ID": "ID da tubulação",
    "Pipe ID field:": "Campo de ID da tubulação:",
    "Pipe ID field: {field}": "Campo de ID da tubulação: {field}",
    "Pipe ID to evaluate": "ID da tubulação a verificar",
    "Pipe ID, FID, status, material, product, or message": "ID da tubulação, FID, situação, material, produto ou mensagem",
    "Pipe Pressure Check": "Verificação de pressão por trecho",
    "Pipe layer:": "Camada de tubulações:",
    "Pipe layer: {layer}": "Camada de tubulações: {layer}",
    "Pipe length field:": "Campo de comprimento da tubulação:",
    "Pipes: {count}": "Tubulações: {count}",
    "Preparing memory-only sizing…": "Preparando o dimensionamento somente em memória…",
    "Pressure (Pa)": "Pressão (Pa)",
    "Pressure class ->": "Classe de pressão ->",
    "Pressure field:": "Campo de pressão:",
    "Preview CSV export failed: {error}": "Falha ao exportar o CSV da prévia: {error}",
    "Preview filter error: {error}": "Erro no filtro da prévia: {error}",
    "Preview inclusion changed. Prepare the apply plan again.": "A inclusão na prévia foi alterada. Prepare novamente o plano de aplicação.",
    "Preview inclusion error: {error}": "Erro ao alterar a inclusão na prévia: {error}",
    "Preview inclusion updated: requested={requested}; changed={changed}; ineligible={ineligible}. Plugin memory only; layers unchanged.": "Inclusão na prévia atualizada: solicitadas={requested}; alteradas={changed}; inelegíveis={ineligible}. Alteração somente na memória do plugin; camadas inalteradas.",
    "Preview snapshot created from the latest batch.": "Prévia criada a partir do dimensionamento em lote mais recente.",
    "Product": "Produto",
    "Product Pressure Criterion": "Critério de pressão do produto",
    "Products Allowed in This Project": "Produtos admitidos neste projeto",
    "Products: {count}": "Produtos: {count}",
    "Project sizing criteria changed. Run sizing and review again.": "Os critérios de dimensionamento do projeto foram alterados. Execute e revise o dimensionamento novamente.",
    "Project:": "Projeto:",
    "Project: {project}": "Projeto: {project}",
    "QGISRed detection completed: no *_Options.dbf candidate was found. Choose a file manually if available.": "Detecção do QGISRed concluída: nenhum arquivo *_Options.dbf foi encontrado. Se houver um arquivo disponível, selecione-o manualmente.",
    "QGISRed detection failed: {error_type}: {error}": "Falha na detecção do QGISRed: {error_type}: {error}",
    "QGISRed detection not run.": "A detecção do QGISRed ainda não foi executada.",
    "QGISRed material value ->": "Valor do material no QGISRed ->",
    "QGISRed options (*_Options.dbf);;DBF files (*.dbf)": "Opções do QGISRed (*_Options.dbf);;Arquivos DBF (*.dbf)",
    "QGISRed options inspection failed: {error_type}: {error}": "Falha na inspeção das opções do QGISRed: {error_type}: {error}",
    "QGISRed options opened read-only: {path}; {count} records.": "Opções do QGISRed abertas somente para leitura: {path}; {count} registros.",
    "Read-only endpoint mapping": "Mapeamento das extremidades (somente leitura)",
    "Replace calculation memory": "Substituir memória de cálculo",
    "Require a minimum nominal diameter": "Usar um diâmetro nominal mínimo como critério obrigatório",
    "Require product rating to support the maximum endpoint pressure": "Exigir que a pressão admissível do produto suporte a maior pressão nas extremidades",
    "Required fields are marked with *. Decimal comma or decimal point is accepted. Blank optional hydraulic values generate warnings. Project-specific material choices are configured outside the universal catalog.": "Os campos obrigatórios são marcados com *. Aceitam-se vírgula ou ponto decimal. Valores hidráulicos opcionais em branco geram alertas. A escolha de materiais específica do projeto é feita fora do catálogo universal.",
    "Rerun QGISRed manually after saving the proposed pipe values.": "Execute novamente o QGISRed após salvar os valores propostos para as tubulações.",
    "Result ID field:": "Campo de ID do resultado:",
    "Result ID field: {field}": "Campo de ID do resultado: {field}",
    "Result layer/table:": "Camada/tabela de resultados:",
    "Result layer/table: {layer}": "Camada/tabela de resultados: {layer}",
    "Run Batch sizing and review Preview inclusion before preparing a plan.": "Execute o dimensionamento em lote e revise a inclusão na prévia antes de preparar um plano.",
    "Run Batch sizing to create a preview snapshot.": "Execute o dimensionamento em lote para criar uma prévia.",
    "Run ID: {run_id}": "ID da execução: {run_id}",
    "Run batch sizing and review the preview before exporting.": "Execute o dimensionamento em lote e revise a prévia antes de exportar.",
    "Safe apply blocked by last-moment input revalidation: {error}. Run Data validation and Batch sizing again.": "A aplicação segura foi bloqueada pela revalidação final dos dados: {error}. Execute novamente a validação e o dimensionamento em lote.",
    "Safe apply cancelled at the explicit confirmation dialog.": "A aplicação segura foi cancelada na confirmação explícita.",
    "Safe apply cannot overwrite mapped pipe ID or length fields: {fields}": "A aplicação segura não pode sobrescrever os campos mapeados de ID ou comprimento da tubulação: {fields}",
    "Safe apply failed and the HydroSizer edit command was rolled back: {error_type}: {error}": "A aplicação segura falhou e o comando de edição do HydroSizer foi revertido: {error_type}: {error}",
    "Safe apply plan blocked: {error}": "Plano de aplicação segura bloqueado: {error}",
    "Safe apply plan failed: {error_type}: {error}": "Falha no plano de aplicação segura: {error_type}: {error}",
    "Safe apply requires a current Batch sizing preview.": "A aplicação segura exige uma prévia atual do dimensionamento em lote.",
    "Safe apply succeeded: {features} pipe(s), {attributes} attribute(s); edits pending save.": "Aplicação segura concluída: {features} tubulação(ões), {attributes} atributo(s); edições pendentes de salvamento.",
    "Safety factor": "Fator de segurança",
    "Search material, product, name, or manufacturer": "Pesquisar material, produto, nome ou fabricante",
    "Segment length:": "Comprimento do trecho:",
    "Select one catalog product to {action}.": "Selecione um produto do catálogo para {action}.",
    "Select one or more preview table rows first.": "Selecione primeiro uma ou mais linhas da tabela de prévia.",
    "Select/zoom problem pipes": "Selecionar/aproximar tubulações com problemas",
    "Select/zoom problem results": "Selecionar/aproximar resultados com problemas",
    "Selected {count} preview pipe(s) on the map.": "Foram selecionadas no mapa {count} tubulação(ões) da prévia.",
    "Selected {count} problematic {entity} feature(s) on layer {layer}; attributes unchanged.": "Foram selecionadas {count} feição(ões) problemática(s) de {entity} na camada {layer}; atributos inalterados.",
    "Selected {count} {label} feature(s); attributes unchanged.": "Foram selecionadas {count} feição(ões) de {label}; atributos inalterados.",
    "Selection first rejects products that fail an enabled criterion. Among the remaining products it chooses the smallest DN, then the lowest available cost, highest pressure rating, and stable ID.": "A seleção primeiro rejeita os produtos que não atendem a algum critério habilitado. Entre os produtos restantes, escolhe o menor DN; em caso de empate, o menor custo disponível, a maior pressão admissível e, por fim, o menor ID estável.",
    "Sized": "Dimensionado",
    "Sized with warning": "Dimensionado com alerta",
    "Sizing pipe {pipe_id}: {done} of {count} processed": "Dimensionando a tubulação {pipe_id}: {done} de {count} processada(s)",
    "Status": "Situação",
    "Status:": "Situação:",
    "Status: SUCCESS; changes are pending in the QGIS edit buffer": "Situação: SUCESSO; as alterações estão pendentes no buffer de edição do QGIS",
    "Store a complete mapping before validation.": "Armazene um mapeamento completo antes da validação.",
    "Temporary layer and field mapping": "Mapeamento temporário de camadas e campos",
    "Temporary mapping is incomplete: {fields}": "O mapeamento temporário está incompleto: {fields}",
    "Temporary mapping stored in memory. No features were read.": "Mapeamento temporário armazenado em memória. Nenhuma feição foi lida.",
    "Temporary mapping stored. Ready for validation.": "Mapeamento temporário armazenado. Pronto para validação.",
    "The associated CSV spreadsheet already exists:\n{path}\n\nDo you want to replace the HTML and CSV files?": "A planilha CSV associada já existe:\n{path}\n\nDeseja substituir os arquivos HTML e CSV?",
    "The in-memory mapping summary will appear here.": "O resumo do mapeamento em memória será exibido aqui.",
    "The progress dialog provides Cancel. Results are cleared on plugin reload. There is no apply action in this stage.": "A janela de progresso permite cancelar a operação. Os resultados são descartados ao recarregar o plugin. Não há aplicação em camada nesta etapa.",
    "The read-only validation report will appear here.": "O relatório de validação somente leitura será exibido aqui.",
    "These selections are temporary and are not used for sizing in this stage. They demonstrate the required manual fallback.": "Estas seleções são temporárias e não são usadas no dimensionamento nesta etapa. Elas demonstram a alternativa manual necessária.",
    "This demonstration does not inspect or edit project layers. Inactive and incomplete products are not eligible for selection.": "Esta demonstração não inspeciona nem edita camadas do projeto. Produtos inativos ou incompletos não podem ser selecionados.",
    "This is a universal HydroSizer product catalog, stored separately from QGISRed. Active means generally available; restrict materials for one project in the Criteria step instead of deactivating them.": "Este é o catálogo universal de produtos do HydroSizer, armazenado separadamente do QGISRed. Um produto ativo está disponível de forma geral; para restringir os materiais de um projeto, use a etapa Critérios em vez de desativar produtos.",
    "This operation will alter {count} pipe(s) in layer {layer}. Previous and proposed values will be written to CSV/JSON audit files. Changes will remain pending in the QGIS edit buffer so they can be undone or saved. Continue?": "Esta operação alterará {count} tubulação(ões) na camada {layer}. Os valores anteriores e propostos serão registrados em arquivos de auditoria CSV/JSON. As alterações permanecerão pendentes no buffer de edição do QGIS e poderão ser desfeitas ou salvas. Deseja continuar?",
    "This temporary filter does not change the universal catalog. Choose one material when the project must use only that material.": "Este filtro temporário não altera o catálogo universal. Selecione um material quando o projeto deva usar exclusivamente esse material.",
    "Unit cost:": "Custo unitário:",
    "Use Bresse as an initial minimum-diameter estimate": "Usar Bresse como estimativa inicial do diâmetro mínimo",
    "Use QGIS Save Layer Edits to persist, or Undo to revert.": "Use Salvar edições da camada no QGIS para persistir as alterações ou Desfazer para revertê-las.",
    "Use maximum unit headloss as a required criterion": "Usar a perda de carga unitária máxima como critério obrigatório",
    "Validation {status}: {errors} error(s), {warnings} warning(s), {matched} matched ID(s).": "Validação {status}: {errors} erro(s), {warnings} alerta(s), {matched} ID(s) correspondente(s).",
    "Verify One Pipe": "Verificar um trecho",
    "Version: {version}": "Versão: {version}",
    "Viscosity unit:": "Unidade da viscosidade:",
    "Warnings:": "Alertas:",
    "Warnings: {count}": "Alertas: {count}",
    "[ERROR] ID {catalog_id} {material}/{product}: {error}": "[ERRO] ID {catalog_id} {material}/{product}: {error}",
    "[WARNING] ID {catalog_id} {material}/{product}: {warning}": "[ALERTA] ID {catalog_id} {material}/{product}: {warning}",
    "activate or deactivate": "ativar ou desativar",
    "batch and endpoint mappings must use the same pipe ID field": "os mapeamentos do dimensionamento e das extremidades devem usar o mesmo campo de ID da tubulação",
    "batch and endpoint mappings must use the same pipe layer": "os mapeamentos do dimensionamento e das extremidades devem usar a mesma camada de tubulações",
    "catalog product": "produto do catálogo",
    "delete": "excluir",
    "duplicate": "duplicar",
    "edit": "editar",
    "endpoint pipe ID field": "campo de ID da tubulação no mapeamento das extremidades",
    "endpoint pipe layer": "camada de tubulações no mapeamento das extremidades",
    "endpoint pressure mapping is incomplete: {fields}": "o mapeamento de pressão nas extremidades está incompleto: {fields}",
    "endpoint pressure nodes": "nós das extremidades",
    "flow field": "campo de vazão",
    "mapped pipe/result IDs no longer pass Data validation": "os IDs mapeados de tubulações e resultados não são mais aprovados na validação dos dados",
    "no": "não",
    "node result ID field": "campo de ID do resultado nodal",
    "node result layer/table": "camada/tabela de resultados nodais",
    "none": "nenhum",
    "not detected": "não detectado",
    "pipe": "tubulação",
    "pipe ID field": "campo de ID da tubulação",
    "pipe ID to evaluate": "ID da tubulação a verificar",
    "pipe layer": "camada de tubulações",
    "pipe length field": "campo de comprimento da tubulação",
    "pressure field": "campo de pressão",
    "result": "resultado",
    "result ID field": "campo de ID do resultado",
    "result layer/table": "camada/tabela de resultados",
    "selected catalog product is unavailable or inactive": "o produto selecionado do catálogo está indisponível ou inativo",
    "verified pipe": "tubulação verificada",
    "yes": "sim",
    "{changed} row(s) {action}; {ineligible} ineligible row(s) unchanged.": "{changed} linha(s) {action}; {ineligible} linha(s) inelegível(is) permaneceu(ram) inalterada(s).",
    "{message} Attributes and geometries unchanged.": "{message} Atributos e geometrias inalterados.",
    "{message} Export only; project layers and catalog unchanged.": "{message} Somente exportação; camadas do projeto e catálogo inalterados.",
    "{summary} Endpoint and node geometries were read for topology matching; layers were not changed.": "{summary} As geometrias das extremidades e dos nós foram lidas para a correspondência topológica; as camadas não foram alteradas.",
    "{summary} HTML={html}; CSV={csv}. No layers or catalog were changed.": "{summary} HTML={html}; CSV={csv}. Nenhuma camada ou item do catálogo foi alterado.",
    "{summary} IDs and current target values captured for revalidation.": "{summary} IDs e valores atuais de destino registrados para revalidação.",
    "{summary} No project layer was accessed or changed.": "{summary} Nenhuma camada do projeto foi acessada ou alterada.",
    "{summary} Results are memory-only; layers unchanged.": "{summary} Os resultados existem somente em memória; camadas inalteradas.",
    "Bresse initial diameter": "Diâmetro inicial de Bresse",
    "Controlling criterion": "Critério controlador",
    "Hydraulic data": "Dados hidráulicos",
    "Maximum velocity": "Velocidade máxima",
    "Minimum nominal diameter": "Diâmetro nominal mínimo",
    "Minimum velocity": "Velocidade mínima",
    "Pressure ({unit})": "Pressão ({unit})",
    "Selection order": "Ordem de seleção",
    "Unit headloss": "Perda de carga unitária",
    "Warnings / issues": "Alertas / ocorrências",
})


_UI_PHRASES_PT = {
    "endpoint pressure verification": "verificação de pressão nas extremidades",
    "calculation memory": "memória de cálculo",
    "pipe sizing": "dimensionamento de tubulações",
    "batch sizing": "dimensionamento em lote",
    "safe apply": "aplicação segura",
    "data validation": "validação de dados",
    "endpoint pressure": "pressão nas extremidades",
    "pressure verification": "verificação de pressão",
    "unit headloss": "perda de carga unitária",
    "internal diameter": "diâmetro interno",
    "nominal diameter": "diâmetro nominal",
    "absolute roughness": "rugosidade absoluta",
    "flow field": "campo de vazão",
    "length field": "campo de comprimento",
    "pipe layer": "camada de tubulações",
    "result layer/table": "camada/tabela de resultados",
    "node result layer/table": "camada/tabela de resultados nodais",
    "pipe ID field": "campo de ID da tubulação",
    "result ID field": "campo de ID do resultado",
    "node result ID field": "campo de ID do resultado nodal",
    "pressure field": "campo de pressão",
    "no layer": "nenhuma camada",
    "no solution": "sem solução",
    "not calculated": "não calculado",
    "not run": "não executado",
    "not detected": "não detectado",
    "not initialized": "não inicializado",
    "read-only": "somente leitura",
    "memory-only": "somente em memória",
    "temporary mapping": "mapeamento temporário",
    "active catalog products": "produtos ativos do catálogo",
    "catalog product": "produto do catálogo",
    "catalog ID": "ID do catálogo",
    "project layers": "camadas do projeto",
    "project layer": "camada do projeto",
    "layer changes": "alterações em camadas",
    "project title": "título do projeto",
    "responsible professional": "responsável técnico",
    "professional registration": "registro profissional",
    "flow unit": "unidade de vazão",
    "length unit": "unidade de comprimento",
    "pressure unit": "unidade de pressão",
    "roughness unit": "unidade de rugosidade",
    "diameter unit": "unidade de diâmetro",
    "cost length unit": "unidade de comprimento do custo",
    "mapped layer": "camada mapeada",
    "current project": "projeto atual",
    "selected rows": "linhas selecionadas",
    "displayed rows": "linhas exibidas",
    "audit directory": "pasta de auditoria",
    "CSV spreadsheet": "planilha CSV",
    "HTML files": "arquivos HTML",
    "CSV files": "arquivos CSV",
    "JSON files": "arquivos JSON",
    "without layer access": "sem acesso a camadas",
    "without editing": "sem edição",
    "without feature access": "sem acesso a feições",
    "no attributes or geometries": "nenhum atributo ou geometria",
}


_UI_WORDS_PT = {
    "add": "adicionar", "edit": "editar", "delete": "excluir",
    "duplicate": "duplicar", "activate": "ativar", "deactivate": "desativar",
    "export": "exportar", "import": "importar", "choose": "escolher",
    "refresh": "atualizar", "search": "pesquisar", "select": "selecionar",
    "store": "armazenar", "validate": "validar", "prepare": "preparar",
    "apply": "aplicar", "replace": "substituir", "run": "executar",
    "evaluate": "avaliar", "verify": "verificar", "inspect": "inspecionar",
    "open": "abrir", "close": "fechar", "cancel": "cancelar",
    "failed": "falhou", "failure": "falha", "completed": "concluído",
    "changed": "alterado", "changes": "alterações", "unchanged": "inalterado",
    "required": "obrigatório", "optional": "opcional", "available": "disponível",
    "missing": "ausente", "invalid": "inválido", "incomplete": "incompleto",
    "current": "atual", "previous": "anterior", "latest": "mais recente",
    "temporary": "temporário", "stored": "armazenado", "mapped": "mapeado",
    "selected": "selecionado", "included": "incluído", "excluded": "excluído",
    "active": "ativo", "inactive": "inativo", "enabled": "habilitado",
    "disabled": "desabilitado", "warning": "alerta", "warnings": "alertas",
    "error": "erro", "errors": "erros", "result": "resultado", "results": "resultados",
    "pipe": "tubulação", "pipes": "tubulações", "layer": "camada",
    "layers": "camadas", "field": "campo", "fields": "campos", "row": "linha",
    "rows": "linhas", "node": "nó", "nodes": "nós", "product": "produto",
    "products": "produtos", "catalog": "catálogo", "project": "projeto",
    "file": "arquivo", "files": "arquivos", "directory": "pasta",
    "mapping": "mapeamento", "configuration": "configuração",
    "pressure": "pressão", "flow": "vazão", "length": "comprimento",
    "diameter": "diâmetro", "roughness": "rugosidade", "velocity": "velocidade",
    "cost": "custo", "unit": "unidade", "value": "valor", "values": "valores",
    "method": "método", "criteria": "critérios", "status": "situação",
    "summary": "resumo", "details": "detalhes", "description": "descrição",
    "name": "nome", "code": "código", "title": "título", "version": "versão",
    "all": "todos", "only": "somente", "none": "nenhum", "yes": "sim",
    "before": "antes", "after": "depois", "again": "novamente", "first": "primeiro",
    "within": "dentro", "above": "acima", "below": "abaixo", "maximum": "máximo",
    "minimum": "mínimo", "initial": "inicial", "final": "final", "manual": "manual",
}

_UI_WORDS_PT.update({
    "an": "um", "the": "o", "and": "e", "or": "ou",
    "of": "de", "to": "para", "from": "de", "in": "em", "on": "em",
    "at": "em", "by": "por", "for": "para", "with": "com", "without": "sem",
    "through": "até", "against": "contra", "their": "seus",
    "this": "este", "these": "estes", "they": "eles", "it": "isso",
    "is": "está", "are": "estão", "was": "foi", "were": "foram",
    "be": "ser", "been": "sido", "will": "será", "can": "pode",
    "cannot": "não pode", "could": "pôde", "must": "deve", "does": "faz",
    "not": "não", "also": "também", "always": "sempre",
    "already": "já", "only": "somente", "more": "mais", "every": "cada",
    "each": "cada", "one": "um", "same": "mesmo", "separate": "separado",
    "brief": "breve", "detailed": "detalhado", "basic": "básico",
    "existing": "existente", "new": "novo", "old": "anterior",
    "associated": "associado", "available": "disponível", "unavailable": "indisponível",
    "accepted": "aceito", "adopted": "adotado", "allowable": "admissível",
    "admissible": "admissível", "eligible": "elegível", "ineligible": "inelegível",
    "successful": "bem-sucedido", "successfully": "com sucesso", "success": "sucesso",
    "confirmed": "confirmado", "confirmation": "confirmação", "confirm": "confirmar",
    "blocked": "bloqueado", "ready": "pronto", "pending": "pendente",
    "running": "em execução", "preparing": "preparando", "processed": "processado",
    "sized": "dimensionado", "maintained": "mantido", "proposed": "proposto",
    "added": "adicionado", "deleted": "excluído", "updated": "atualizado", "change": "alterar",
    "created": "criado", "cleared": "apagado", "captured": "capturado",
    "loaded": "carregado", "opened": "aberto", "exported": "exportado",
    "imported": "importado", "issued": "emitido", "written": "gravado",
    "saved": "salvo", "signed": "assinado", "reviewed": "revisado",
    "revalidated": "revalidado", "rolled": "revertido", "replaced": "substituído",
    "started": "iniciado", "stored": "armazenado", "suggested": "sugerido",
    "access": "acesso", "accessed": "acessado", "action": "ação",
    "analysis": "análise", "attribute": "atributo", "attributes": "atributos",
    "audit": "auditoria", "basis": "base", "behavior": "comportamento",
    "blank": "vazio", "browser": "navegador", "buffer": "buffer",
    "button": "botão", "buttons": "botões", "candidate": "candidato",
    "calculated": "calculado", "calculation": "cálculo", "checks": "verificações",
    "class": "classe", "click": "clique", "combined": "combinado",
    "comma": "vírgula", "command": "comando", "compatible": "compatível",
    "complete": "completo", "concept": "concepção", "considered": "considerado",
    "contains": "contém", "continue": "continuar", "control": "controle",
    "controller": "controlador", "conversion": "conversão", "critical": "crítico",
    "currency": "moeda", "currently": "atualmente", "database": "banco de dados",
    "decimal": "decimal", "definitions": "definições", "demonstration": "demonstração",
    "demonstrates": "demonstra", "design": "projeto", "destination": "destino",
    "detected": "detectado", "detection": "detecção", "determines": "determina",
    "deterministic": "determinístico", "diagnostic": "diagnóstico", "dialog": "janela",
    "directly": "diretamente", "directories": "pastas", "displayed": "exibido",
    "document": "documento", "duplicated": "duplicado", "empty": "vazio",
    "end": "fim", "entered": "informado", "environment": "ambiente", "estimate": "estimativa",
    "evaluated": "avaliado", "exact": "exato", "example": "exemplo", "explicit": "explícito",
    "explicitly": "explicitamente", "exporting": "exportando", "exports": "exporta",
    "factor": "fator", "fallback": "alternativa", "feature": "feição",
    "features": "feições", "filter": "filtro", "found": "encontrado",
    "friction": "atrito", "generate": "gerar", "geometric": "geométrico",
    "geometries": "geometrias", "geometry": "geometria", "gradient": "gradiente",
    "headloss": "perda de carga", "here": "aqui", "highlight": "destacar",
    "hydraulic": "hidráulico", "hydraulically": "hidraulicamente", "information": "informações",
    "informative": "informativo", "initialization": "inicialização", "initialized": "inicializado",
    "initially": "inicialmente", "input": "entrada", "inspected": "inspecionado",
    "inspection": "inspeção", "insufficient": "insuficiente", "internal": "interno",
    "inventory": "inventário", "keeps": "mantém", "larger": "maior",
    "later": "posterior", "least": "menos", "list": "listar", "listed": "listado",
    "lists": "lista", "local": "local", "longer": "mais", "losses": "perdas",
    "manufacturer": "fabricante", "manually": "manualmente", "map": "mapa",
    "mappings": "mapeamentos", "margin": "margem", "marked": "marcado",
    "matched": "correspondente", "matches": "corresponde", "matching": "correspondência",
    "material": "material", "mean": "média", "memory": "memória", "message": "mensagem",
    "metadata": "metadados", "multicriteria": "multicritério", "network": "rede",
    "never": "nunca", "null": "nulo", "number": "número", "obtain": "obter",
    "operation": "operação", "options": "opções", "order": "ordem",
    "overwrite": "sobrescrever", "path": "caminho", "persistence": "persistência",
    "persist": "persistir", "plan": "plano", "plugin": "plugin", "point": "ponto",
    "points": "pontos", "preparation": "preparação", "prerequisite": "pré-requisito",
    "prerequisites": "pré-requisitos", "preview": "prévia", "print": "imprimir",
    "priority": "prioridade", "problem": "problema", "problematic": "problemático",
    "problems": "problemas", "professional": "profissional", "profile": "perfil",
    "progress": "progresso", "providers": "provedores", "provides": "fornece",
    "rating": "classe", "read": "ler", "reader": "leitor", "recalculating": "recalcular",
    "recommended": "recomendado", "records": "registros", "refreshed": "atualizado",
    "regime": "regime", "registry": "registro", "relative": "relativo", "reload": "recarregar",
    "remain": "permanecer", "report": "relatório", "reported": "informado",
    "requested": "solicitado", "requests": "solicita", "require": "exigir",
    "requires": "exige", "rerun": "executar novamente", "respect": "respeitar",
    "responsible": "responsável", "revalidation": "revalidação", "revert": "reverter",
    "review": "revisar", "reviews": "revisa", "save": "salvar", "saving": "salvamento",
    "scope": "escopo", "searches": "pesquisa", "segment": "trecho", "selection": "seleção",
    "selections": "seleções", "separately": "separadamente", "session": "sessão",
    "set": "definir", "settings": "configurações", "snapshot": "retrato",
    "solution": "solução", "source": "origem", "sources": "origens",
    "spatial": "espacial", "spreadsheet": "planilha", "stage": "etapa", "start": "início",
    "state": "estado", "storing": "armazenamento", "succeeded": "bem-sucedido",
    "suggestions": "sugestões", "supports": "oferece", "tab": "aba", "table": "tabela",
    "tables": "tabelas", "target": "destino", "then": "depois", "there": "há",
    "tolerance": "tolerância", "topology": "topologia", "transient": "transiente",
    "twice": "duas vezes", "types": "tipos", "undo": "desfazer", "undone": "desfeito",
    "update": "atualizar", "use": "usar", "used": "usado", "uses": "usa", "using": "usando",
    "validated": "validado", "validates": "valida", "validation": "validação",
    "vector": "vetorial", "vectors": "vetores", "verification": "verificação",
    "verified": "verificado", "view": "exibição", "viscosity": "viscosidade",
    "want": "deseja", "yet": "ainda", "you": "você", "zoom": "aproximar",
})


_PT_REPLACEMENTS = {
    "HydroSizer Basic Calculation — Stage 6": "Cálculo básico do HydroSizer — Etapa 6",
    "HydroSizer Hazen–Williams Demonstration — Stage 8": "Demonstração Hazen–Williams do HydroSizer — Etapa 8",
    "HydroSizer Darcy–Weisbach Demonstration — Stage 9": "Demonstração Darcy–Weisbach do HydroSizer — Etapa 9",
    "HydroSizer Combined Criteria Demonstration — Stage 10": "Demonstração de critérios combinados do HydroSizer — Etapa 10",
    "HydroSizer Endpoint Pressure Verification — Stage 11": "Verificação de pressão nas extremidades do HydroSizer — Etapa 11",
    "HydroSizer Batch Sizing — Stage 12": "Dimensionamento em lote do HydroSizer — Etapa 12",
    "HydroSizer Safe Apply Plan — Stage 14": "Plano de aplicação segura do HydroSizer — Etapa 14",
    "HydroSizer Data Validation — Stage 5": "Validação de dados do HydroSizer — Etapa 5",
    "HydroSizer — QGIS Environment Diagnostic": "HydroSizer — Diagnóstico do ambiente QGIS",
    "QGISRed Options DBF — read-only inspection": "DBF de opções do QGISRed — inspeção somente leitura",
    "Scope: manual demonstration only; no layer access": "Escopo: somente demonstração manual; sem acesso a camadas",
    "Scope: one manual segment; active catalog products; no layer access": "Escopo: um trecho manual; produtos ativos do catálogo; sem acesso a camadas",
    "Mode: read-only; no attributes or geometries were changed": "Modo: somente leitura; nenhum atributo ou geometria foi alterado",
    "Mode: preview in memory only; no layer or catalog changes": "Modo: prévia somente em memória; sem alterações em camadas ou catálogo",
    "Mode: review only; no layer changes have been made": "Modo: somente revisão; nenhuma camada foi alterada",
    "Original inputs": "Entradas originais",
    "SI conversions": "Conversões para o SI",
    "Calculations": "Cálculos",
    "Equation": "Equação",
    "Equations": "Equações",
    "Inputs": "Entradas",
    "Configuration": "Configuração",
    "Selection strategy": "Estratégia de seleção",
    "Selection order": "Ordem de seleção",
    "Selection": "Seleção",
    "Candidates": "Candidatos",
    "Current limitations": "Limitações atuais",
    "Mapping": "Mapeamento",
    "Resolved endpoints": "Extremidades resolvidas",
    "Margin": "Margem",
    "Product check": "Verificação do produto",
    "Method limitations": "Limitações do método",
    "Run": "Execução",
    "Summary": "Resumo",
    "Results": "Resultados",
    "Safety boundary": "Limite de segurança",
    "Mapped destination fields": "Campos de destino mapeados",
    "Rows": "Linhas",
    "Issues": "Ocorrências",
    "Generated (UTC)": "Gerado (UTC)",
    "Project": "Projeto",
    "Layer summary": "Resumo das camadas",
    "Layers": "Camadas",
    "Warnings": "Alertas",
    "Hydraulic warnings": "Alertas hidráulicos",
    "Inspected directories": "Pastas inspecionadas",
    "Options candidates": "Candidatos a arquivo de opções",
    "Detected settings": "Configurações detectadas",
    "Fields": "Campos",
    "Records shown": "Registros exibidos",
    "Flow magnitude": "Módulo da vazão",
    "Signed SI flow": "Vazão com sinal no SI",
    "Signed flow": "Vazão com sinal",
    "Original flow": "Vazão original",
    "Flow": "Vazão",
    "Internal diameter": "Diâmetro interno",
    "Length attribute": "Atributo de comprimento",
    "Length": "Comprimento",
    "Unit cost": "Custo unitário",
    "Velocity equation": "Equação da velocidade",
    "Velocity": "Velocidade",
    "Segment cost equation": "Equação do custo do trecho",
    "Segment cost": "Custo do trecho",
    "Maximum unit headloss": "Perda de carga unitária máxima",
    "Maximum velocity": "Velocidade máxima",
    "Minimum velocity": "Velocidade mínima",
    "Minimum nominal diameter": "Diâmetro nominal mínimo",
    "Kinematic viscosity": "Viscosidade cinemática",
    "Relative roughness": "Rugosidade relativa",
    "Bresse estimate": "Estimativa de Bresse",
    "Pressure verification": "Verificação de pressão",
    "Catalog priority": "Prioridade do catálogo",
    "Selected catalog ID": "ID selecionado do catálogo",
    "Catalog ID": "ID do catálogo",
    "Product": "Produto",
    "Justification": "Justificativa",
    "Cost": "Custo",
    "reason": "motivo",
    "regime": "regime",
    "priority": "prioridade",
    "allowable pressure": "pressão admissível",
    "Status": "Situação",
    "Controlling criterion": "Critério controlador",
    "controlling criterion": "critério controlador",
    "Failures": "Falhas",
    "Relationship: pipe start/end geometry to node-result points": "Relação: geometria inicial/final da tubulação com pontos de resultado nodal",
    "Pipe layer": "Camada de tubulações",
    "Pipe ID": "ID da tubulação",
    "Initial endpoint": "Extremidade inicial",
    "Final endpoint": "Extremidade final",
    "Node result layer/table": "Camada/tabela de resultados nodais",
    "Node result ID": "ID do resultado nodal",
    "Pipe CRS": "SRC da tubulação",
    "Endpoint tolerance": "Tolerância das extremidades",
    "Initial node": "Nó inicial",
    "Final node": "Nó final",
    "Initial pressure": "Pressão inicial",
    "Final pressure": "Pressão final",
    "Base verification pressure = max(initial, final)": "Pressão-base de verificação = máx(inicial, final)",
    "Mode": "Modo",
    "Safety factor": "Fator de segurança",
    "Additive margin input": "Entrada da margem aditiva",
    "Additive margin SI": "Margem aditiva no SI",
    "Final verification pressure": "Pressão final de verificação",
    "Pressure class": "Classe de pressão",
    "Allowable pressure": "Pressão admissível",
    "Decision: verification pressure is": "Decisão: a pressão de verificação está",
    "within the product rating": "dentro da classe do produto",
    "above the product rating": "acima da classe do produto",
    "Selection mode": "Modo de seleção",
    "Requested pipes": "Trechos solicitados",
    "Processed pipes": "Trechos processados",
    "Cancelled": "Cancelado",
    "Sized with warning": "Dimensionados com alerta",
    "Sized": "Dimensionados",
    "No catalog solution": "Sem solução no catálogo",
    "Insufficient data": "Dados insuficientes",
    "Endpoint pressure check": "Verificação da pressão nas extremidades",
    "Messages": "Mensagens",
    "Included pipes": "Trechos incluídos",
    "Pipes with changes": "Trechos com alterações",
    "Maintained pipes": "Trechos mantidos",
    "Hydraulic method": "Método hidráulico",
    "Project material filter": "Materiais admitidos no projeto",
    "Result layer/table": "Camada/tabela de resultados",
    "Result ID": "ID do resultado",
    "Errors": "Erros",
    "Pipe records": "Registros de tubulações",
    "Result records": "Registros de resultados",
    "Valid pipe IDs": "IDs válidos de tubulações",
    "Valid result IDs": "IDs válidos de resultados",
    "Matched IDs": "IDs correspondentes",
    "Pipes without result": "Tubulações sem resultado",
    "Results without pipe": "Resultados sem tubulação",
    "Title": "Título",
    "File": "Arquivo",
    "Directory": "Pasta",
    "Modified": "Modificado",
    "Total": "Total",
    "Spatial vector layers": "Camadas vetoriais espaciais",
    "Non-spatial tables": "Tabelas não espaciais",
    "Raster layers": "Camadas raster",
    "Other layers": "Outras camadas",
    "Type": "Tipo",
    "Provider": "Provedor",
    "Source": "Origem",
    "Valid": "Válida",
    "Project directory": "Pasta do projeto",
    "Warning": "Alerta",
    "Path": "Caminho",
    "Network base": "Base da rede",
    "Encoding": "Codificação",
    "File size": "Tamanho do arquivo",
    "Records": "Registros",
    "Read-only adapter": "Adaptador somente leitura",
    "Schema recognized": "Esquema reconhecido",
    "Flow units": "Unidades de vazão",
    "Unit system": "Sistema de unidades",
    "Headloss": "Perda de carga",
    "Method": "Método",
    "ADMISSIBLE": "ADMISSÍVEL",
    "REJECTED": "REJEITADO",
    "NOT EVALUATED": "NÃO AVALIADO",
    "INSUFFICIENT DATA": "DADOS INSUFICIENTES",
    "SIZED WITH WARNING": "DIMENSIONADO COM ALERTA",
    "SIZED": "DIMENSIONADO",
    "NO SOLUTION": "SEM SOLUÇÃO",
    "PASS WITH WARNINGS": "APROVADO COM ALERTAS",
    _SUCCESS_STATUS_SOURCE: "APROVADO",
    "FAIL": "REPROVADO",
    "CHANGE": "ALTERAR",
    "KEEP": "MANTER",
    "WARNING": "ALERTA",
    "ERROR": "ERRO",
    "yes": "sim",
    "no": "não",
    "disabled": "desabilitado",
    "enabled": "habilitado",
    "required": "obrigatório",
    "warning": "alerta",
    "all": "todos",
    "selected": "selecionados",
    "<none>": "<nenhum>",
    "<not available>": "<não disponível>",
    "<not provided>": "<não informado>",
    "<not reported>": "<não informado>",
    "<not detected>": "<não detectado>",
    "<not inferred>": "<não inferida>",
    "<not mapped>": "<não mapeado>",
    "<not set>": "<não definido>",
    "<unsaved project>": "<projeto não salvo>",
    "<no layers loaded>": "<nenhuma camada carregada>",
    "<no active catalog products>": "<nenhum produto ativo no catálogo>",
    "currency units": "unidades monetárias",
    "currency/m": "moeda/m",
}


_PT_SENTENCES = {
    "All enabled required criteria; smallest DN; lowest segment cost;": "Todos os critérios obrigatórios habilitados; menor DN; menor custo do trecho;",
    "highest allowable pressure; lowest stable catalog ID.": "maior pressão admissível; menor ID estável do catálogo.",
    "Justification: satisfies every required criterion and ranks first under the configured deterministic selection order.": "Justificativa: atende a todos os critérios obrigatórios e ocupa a primeira posição na ordem de seleção definida.",
    "Batch pressure is resolved automatically from mapped pipe endpoints.": "A pressão do lote é obtida automaticamente nas extremidades mapeadas das tubulações.",
    "Bresse is only an initial diameter estimate, not full validation.": "Bresse é apenas uma estimativa inicial de diâmetro, não uma validação completa.",
    "all active materials": "todos os materiais ativos",
    "sized with warning": "dimensionado com alerta",
    "not admissible": "não admissível",
    "selection order": "ordem de seleção",
    "warning at ": "alerta; limite de ",
    "allowable pressure=": "pressão admissível=",
    "Cost=": "Custo=",
    "Status=": "Situação=",
    "controlling criterion=": "critério controlador=",
    "maximum velocity": "velocidade máxima",
    "minimum velocity": "velocidade mínima",
    "unit headloss": "perda de carga unitária",
    "velocity ": "velocidade ",
    " is below ": " está abaixo de ",
    "No admissible product was found in the active catalog.": "Nenhum produto admissível foi encontrado no catálogo ativo.",
    "No product satisfies all enabled required criteria.": "Nenhum produto atende a todos os critérios obrigatórios habilitados.",
    "Product must be active and hydraulically complete for H-W.": "O produto deve estar ativo e hidraulicamente completo para H-W.",
    "Product must be active and include valid Di and absolute roughness.": "O produto deve estar ativo e conter Di e rugosidade absoluta válidos.",
    "J must be less than or equal to the configured maximum.": "J deve ser menor ou igual ao máximo configurado.",
    "Select smallest nominal diameter; then internal diameter; then ID.": "Selecionar o menor diâmetro nominal; depois o diâmetro interno; por fim o ID.",
    "Velocity and cost are informative, not admissibility criteria.": "Velocidade e custo são informativos, não critérios de admissibilidade.",
    "Results exist only in plugin memory and are cleared on reload.": "Os resultados existem somente na memória do plugin e são apagados ao recarregar.",
    "Cancellation preserves no partial edits because no edits are started.": "O cancelamento não deixa edições parciais porque nenhuma edição é iniciada.",
    "Filtering and inclusion are available in Sizing review.": "A filtragem e a inclusão estão disponíveis na revisão do Dimensionamento.",
    "Apply requires a separate confirmation dialog.": "A aplicação exige uma caixa de confirmação separada.",
    "IDs and old values will be revalidated immediately before edits.": "IDs e valores anteriores serão revalidados imediatamente antes das edições.",
    "Critical failure destroys the edit command and prevents partial apply.": "Uma falha crítica desfaz o comando de edição e impede aplicação parcial.",
    "Successful edits remain pending in the QGIS edit buffer for undo/save.": "As edições bem-sucedidas permanecem no buffer de edição do QGIS para desfazer ou salvar.",
    "Verification uses pressures at the two pipe endpoints.": "A verificação usa as pressões nas duas extremidades da tubulação.",
    "Critical high/low profile points must be represented by nodes.": "Pontos altos ou baixos críticos do perfil devem ser representados por nós.",
    "This is not a transient or water-hammer analysis.": "Esta não é uma análise de transientes ou golpe de aríete.",
    "The displayed node-result state must represent the intended scenario.": "O estado exibido dos resultados nodais deve representar o cenário pretendido.",
    "There is no layer apply action in Stage 13.": "Não há ação de aplicação em camada na Etapa 13.",
    "(catalog ID": "(ID do catálogo",
    "cost=": "custo=",
    "Controlling criterion: pressure": "Critério controlador: pressão",
    "Controlling criterion: unit headloss": "Critério controlador: perda de carga unitária",
    "Controlling criterion: maximum velocity": "Critério controlador: velocidade máxima",
    "Controlling criterion: minimum velocity": "Critério controlador: velocidade mínima",
    "reason:": "motivo:",
    "unit headloss is within the configured limit": "a perda de carga unitária está dentro do limite configurado",
    "unit headloss exceeds the configured limit": "a perda de carga unitária excede o limite configurado",
    "product is inactive": "o produto está inativo",
    "missing ": "ausente: ",
    "Justification: active and complete product;": "Justificativa: produto ativo e completo;",
    "is within the limit and no admissible product has a smaller DN.": "está dentro do limite e nenhum produto admissível possui DN menor.",
    "No pressure check, combined criteria, network iteration, or layer update.": "Não inclui verificação de pressão, critérios combinados, iteração da rede ou atualização de camada.",
    "must be numeric": "deve ser numérico",
    "must be finite": "deve ser finito",
    "must be greater than zero": "deve ser maior que zero",
    "must not be negative": "não pode ser negativo",
    "is required": "é obrigatório",
    "was not found": "não foi encontrado",
    "no longer exists": "não existe mais",
    "has conflicting flow values": "possui valores de vazão conflitantes",
    "has conflicting pressure results": "possui resultados de pressão conflitantes",
    "has no pressure result": "não possui resultado de pressão",
    "unknown unit": "unidade desconhecida",
    "unsupported unit": "unidade não suportada",
    "duplicate IDs": "IDs duplicados",
    "duplicate ID": "ID duplicado",
    "flow must be numeric": "a vazão deve ser numérica",
    "flow must be finite": "a vazão deve ser finita",
    "length must be numeric": "o comprimento deve ser numérico",
    "length must be finite": "o comprimento deve ser finito",
    "diameter must be numeric": "o diâmetro deve ser numérico",
    "diameter must be finite": "o diâmetro deve ser finito",
    "unit cost must be numeric": "o custo unitário deve ser numérico",
    "unit cost must be finite": "o custo unitário deve ser finito",
    "kinematic viscosity must be numeric": "a viscosidade cinemática deve ser numérica",
    "kinematic viscosity must be finite": "a viscosidade cinemática deve ser finita",
    "The pipe layer contains no records.": "A camada de tubulações não contém registros.",
    "The result layer/table contains no records.": "A camada/tabela de resultados não contém registros.",
    "Pipe and result ID fields have incompatible types:": "Os campos de ID da tubulação e do resultado possuem tipos incompatíveis:",
    "Pipe ID is null, empty, or incompatible with its field type.": "O ID da tubulação é nulo, vazio ou incompatível com o tipo do campo.",
    "Result ID is null, empty, or incompatible with its field type.": "O ID do resultado é nulo, vazio ou incompatível com o tipo do campo.",
    "Pipe length must be a finite numeric attribute value.": "O comprimento da tubulação deve ser um atributo numérico finito.",
    "Pipe length must be greater than zero; received": "O comprimento da tubulação deve ser maior que zero; recebido",
    "Flow must be a finite numeric value.": "A vazão deve ser um valor numérico finito.",
    "will retain its sign in records; later sizing will use its absolute value.": "manterá seu sinal nos registros; o dimensionamento usará seu valor absoluto.",
    "Negative flow": "Vazão negativa",
    "Zero flow requires an explicit sizing rule in a later stage.": "A vazão zero exige uma regra explícita de dimensionamento em etapa posterior.",
    "is duplicated.": "está duplicado.",
    "is repeated with equivalent flow.": "está repetido com vazão equivalente.",
    "has no corresponding result.": "não possui resultado correspondente.",
    "has no corresponding pipe.": "não possui tubulação correspondente.",
    "Pipe ID": "ID da tubulação",
    "Result ID": "ID do resultado",
    " — pipe ": " — tubulação ",
    " — result ": " — resultado ",
    "the original flow is negative. Its sign is preserved above; velocity uses the magnitude.": "a vazão original é negativa. O sinal foi preservado acima; a velocidade usa o módulo.",
    "the original flow is zero.": "a vazão original é zero.",
}


def translate_report_text(text: str, locale: object) -> str:
    """Translate presentation-only report text; never alter data structures."""
    if normalize_locale(locale) != "pt_BR" or not text:
        return text
    value_tokens = {
        key: _PT_REPLACEMENTS[key]
        for key in (
            "yes", "no", "all", "selected", "warning", "required",
            "enabled", "disabled", "PASS", "PASS WITH WARNINGS", "FAIL",
        )
    }
    lines = []
    for original_line in str(text).splitlines():
        line = original_line
        for source, target in sorted(
            _PT_SENTENCES.items(), key=lambda item: len(item[0]), reverse=True
        ):
            line = line.replace(source, target)
        for source, target in sorted(
            _PT_REPLACEMENTS.items(), key=lambda item: len(item[0]), reverse=True
        ):
            if source in value_tokens:
                continue
            stripped = line.strip()
            if (
                stripped == source
                or stripped.startswith(source + ":")
                or stripped.startswith(source + " (")
            ):
                offset = line.find(source)
                line = line[:offset] + target + line[offset + len(source):]
            elif source in {
                "ADMISSIBLE", "REJECTED", "NOT EVALUATED", "INSUFFICIENT DATA",
                "SIZED WITH WARNING", "SIZED", "NO SOLUTION", "CHANGE", "KEEP",
                "WARNING", "ERROR",
            }:
                line = line.replace(f"[{source}]", f"[{target}]")
            elif len(source.split()) >= 4 or source.startswith("<"):
                line = line.replace(source, target)
        for source, target in sorted(value_tokens.items(), key=lambda item: len(item[0]), reverse=True):
            line = re.sub(
                rf"(?<=:\s){re.escape(source)}(?=\s|$|\))",
                target,
                line,
                flags=re.IGNORECASE,
            )
            line = re.sub(
                rf"(?<=\(){re.escape(source)}(?=\))",
                target,
                line,
                flags=re.IGNORECASE,
            )
        lines.append(line)
    return "\n".join(lines)


def translate_ui_text(source_text: str) -> str:
    """Translate one registered English Qt message without partial translation."""
    if not source_text:
        return source_text
    return _UI_EXACT_PT.get(source_text, source_text)


def registered_ui_translation(source_text: str) -> Optional[str]:
    """Return a registered translation or ``None`` for Qt fallback."""
    if not source_text:
        return None
    return _UI_EXACT_PT.get(source_text)
