feat(i18n): traduzir ui/components e coordinators (fase 2 de 3) - #462
Merged
Conversation
Migra model_diagnostics_panel, global_model_configuration_panel e o model_diagnostics_coordinator que emite o texto dos messagebox que eles disparam -- separa-los deixaria metade de cada dialogo em portugues. - "Ambos" era comparado com == no coordinator a partir do combobox do painel: vira ui/sentinels.both_models_label(), como os demais rotulos que sao exibidos e testados em modulos diferentes. - Os quatro dicionarios de rotulos do painel global (_TARGET_LABELS e companhia) viram funcoes; um dict montado no corpo do modulo congela a traducao no import. - O alias aceito no prompt de alvo passa a ser comparado sem acentos, de modo que "aquario" e "aquário" continuam valendo sem carregar um literal acentuado. - `_` deixou de ser usado como descarte de tupla nos tres arquivos: ali ele sombreava o gettext dentro da propria funcao. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e 2)
config_editor, canvas/zone_editor e zone_controls -- os tres painieis que
o operador usa para definir zona e regra de ROI.
Dois defeitos de i18n corrigidos de passagem, ambos do tipo que degrada
em silencio:
- `show_aquarium_selector` procurava o frame de acoes de desenho pelo
texto exibido (`"Desenho" in child.cget("text")`). Traduzido o rotulo,
a busca falharia e o seletor de aquario cairia no fallback sem avisar.
Agora ancora no proprio widget (`self.drawing_actions_frame`).
- `_` era usado como descarte de tupla em `save_arena`/`discard_arena`,
sombreando o gettext dentro da mesma funcao -- o ruff (F823) pegou.
Constantes de corpo de modulo/classe viram funcoes:
SEG_OVERLAP_MISSING_MASKS_WARNING, _BGR_COLOR_MAP (e o alias em
canvas_manager) e _HIERARCHY_LABEL_MAP.
Os nomes de cor de color_selection_dialog ficam para a fase 3; as duas
listas nao se comparam por igualdade, so exibem.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Phase 2/3 of the GUI i18n migration, converting ui/components/** and the coupled model_diagnostics_coordinator to use runtime gettext resolution (no import-time translation), while fixing a couple of “display text used as logic” hazards (sentinel label + widget anchoring) that would silently break once translated.
Changes:
- Migrates multiple UI components and
model_diagnostics_coordinatorfrom Portuguese literals to_()calls, with{msgid: pt_BR_literal}pairs recorded undersrc/zebtrack/locales/_pairs/. - Introduces/extends i18n-safe sentinels and function-based label maps to prevent “translated in one module, compared in another” failures.
- Updates UI tests and the migrated-paths gate to reflect English-as-source behavior.
Reviewed changes
Copilot reviewed 21 out of 22 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tests/ui/components/test_zone_editor_selection.py | Updates assertion to match new English status message on arena-save failure. |
| tests/ui/components/test_zone_controls_widget.py | Updates assertions for translated UI strings (English source) in zone controls. |
| tests/ui/components/test_model_diagnostics_panel.py | Updates assertion for translated project-weight summary string. |
| tests/i18n/test_no_untranslated_literals.py | Extends MIGRATED_PATHS to include newly migrated modules. |
| src/zebtrack/ui/sentinels.py | Adds both_models_label() sentinel to share a translated-but-compared label across modules. |
| src/zebtrack/ui/components/zone_controls.py | Converts UI strings to _(), removes text-based widget matching, and adds runtime label mapping for context menu. |
| src/zebtrack/ui/components/model_diagnostics_panel.py | Converts panel strings to _(), centralizes engine names, and uses the shared “Both” sentinel in the combobox. |
| src/zebtrack/ui/components/global_model_configuration_panel.py | Converts labels/prompts to _(), replaces import-time dict constants with functions, and adds accent-folding helper for target input. |
| src/zebtrack/ui/components/config_editor.py | Converts warning constant to a function to avoid import-time translation; migrates additional UI strings to _(). |
| src/zebtrack/ui/components/canvas/zone_editor.py | Converts dialog/status strings to _() and moves BGR color-name map to a runtime function for i18n safety. |
| src/zebtrack/ui/components/canvas_manager.py | Removes class alias to the now-removed ZoneEditor._BGR_COLOR_MAP. |
| src/zebtrack/coordinators/model_diagnostics_coordinator.py | Converts coordinator-emitted messagebox/status/report strings to _() and uses the shared “Both” sentinel for branching. |
| src/zebtrack/locales/_pairs/pr2-zone-editor.json | Records msgid→original-PT pairs for zone_editor.py. |
| src/zebtrack/locales/_pairs/pr2-zone-controls.json | Records msgid→original-PT pairs for zone_controls.py. |
| src/zebtrack/locales/_pairs/pr2-sentinels.json | Records msgid→original-PT pairs for sentinels.py (adds “Both”). |
| src/zebtrack/locales/_pairs/pr2-model-diagnostics-panel.json | Records msgid→original-PT pairs for model_diagnostics_panel.py. |
| src/zebtrack/locales/_pairs/pr2-model-diagnostics-coordinator.json | Records msgid→original-PT pairs for model_diagnostics_coordinator.py. |
| src/zebtrack/locales/_pairs/pr2-global-model-configuration-panel.json | Records msgid→original-PT pairs for global_model_configuration_panel.py. |
| src/zebtrack/locales/_pairs/pr2-config-editor.json | Records msgid→original-PT pairs for config_editor.py. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
Colapsa a duplicata de PROJECT_STATUS_META: gui.py carregava uma copia
byte-identica da tabela do validation_manager e nao a usava. Sobra um
acessor so, `validation_manager.project_status_meta()`, funcao porque um
dict de corpo de modulo congela a traducao no import.
Outros pontos:
- `icon, _ = PROJECT_STATUS_META[...]` sombreava o gettext dentro das
funcoes que agora chamam `_()`; virou `icon, _label`.
- `validate_positive_integer(field_name="valor")` tinha o default no
proprio parametro -- avaliado no import. Passa a `None` e resolve
`_("value")` no corpo.
- "Nao informado" passa a sair de `sentinels.not_reported_label()`, que
ja existia para esse mesmo valor.
- Os IDs de agrupamento continuam em portugues de proposito: "Sem Dia",
"Sem Grupo" e "Dia_N" sao espaco de chave, nao rotulo. So o
`day_label` do placeholder passou a usar `day_prefix()`, que
`resolve_day_display` ja aceita nos dois idiomas.
- Dois msgids colidiam com traducoes diferentes entre lotes
("Confirm Deletion", "No video selected"); foram separados para que
cada sitio preserve o literal que substituiu.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ao ao vivo
dialog_coordinator, video_processing_coordinator e
live_camera_session_coordinator -- os tres que emitem o texto dos
messagebox disparados pelos paineis ja migrados.
- `LIVE_PROFILE_DISPLAY_DEFAULT` era constante de modulo; virou
`live_profile_display_default()`.
- O helper de exibicao de dia continua ACEITANDO os prefixos "Dia_"/"Dia "
que a metadata gravada contem, e passa a RENDERIZAR com `day_prefix()`.
- Tres msgids colidiam entre lotes com traducoes diferentes
("Processing", "Analysis in Progress", alem dos dois do commit
anterior); cada sitio ficou com um msgid proprio para preservar o
literal que substituiu.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Colapsa a segunda duplicata prevista: ANALYSIS_PROFILE_TOOLTIP existia em analysis_controls e analysis_display com textos JA divergentes -- o do display tinha uma frase a mais nomeando o fallback. Sobra um acessor so, `ui/components/analysis_profile.analysis_profile_tooltip()`, com o texto mais completo dos dois. Outras constantes de corpo de modulo/classe viraram funcoes: `_BADGE_STYLES` (zone_context_panel) e `AQUARIUM_COLORS` (multi_aquarium_overlay, mais o alias em canvas_manager). analysis_view_controller entrou junto porque monta o mesmo rotulo de perfil que os dois paineis exibem. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Fecha o pacote: `src/zebtrack/coordinators` inteiro entra em MIGRATED_PATHS como um caminho so, no lugar dos quatro arquivos avulsos. Mais tres sitios em que `_` era sombreado -- todos pegos por ferramenta, nenhum por leitura: - `for _ in range(5)` em live_calibration_coordinator (ruff F402); - `_ = arduino_enabled` em recording_session_coordinator, o idioma de "parametro deliberadamente nao usado", que rebindava o gettext para o resto da funcao -- justo a funcao que monta as mensagens de recusa do gatilho externo (mypy: "bool not callable"); - `_, roi_index, roi_name` ja corrigido no lote anterior. Tags de proveniencia e chaves de dicionario ficam em portugues de proposito: 'auto', 'manual', 'arena', 'camera', 'frame', 'cobaia', 'single_video'. Sao comparadas, nao exibidas. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
arduino_bindings_panel, arduino_dashboard e weight_hardware_manager -- o painel de comandos por zona, o dashboard de status e o resumo de pesos/GPU do painel de projeto. Tres constantes de corpo de modulo viraram funcoes (DISCLAIMER, NOTE_NO_ARDUINO, CONFLICT_WARNING -> disclaimer(), note_no_arduino(), conflict_warning()); nenhuma era importada de fora do modulo. Dois defeitos corrigidos de passagem, ambos do tipo que degrada em silencio depois da traducao: - `update_gpu_hardware_display` ramificava por `"CPU" in gpu_name`, ou seja, pelo proprio texto exibido. Traduzido o rotulo, o ramo escolhido passaria a depender do idioma. Agora um booleano `accelerator_found` carrega a informacao, e a fidelidade do caso `cuda_available=True` com `torch.cuda.is_available()=False` (que mantinha "CPU apenas") foi preservada. - `handle_request_weight_type` comparava a entrada digitada contra a lista fixa ["seg", "segmentation", "segmentacao"]. O prompt agora e traduzido, entao a lista virou casamento por prefixo -- aceita as tres grafias sem depender do idioma instalado. Reaproveitados os msgids ja existentes de "No Project Loaded", "Segmentation", "Detection", "Enabled", "Disabled" e "Error" em vez de criar duplicatas com traducao divergente. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Os seis modulos de ui/components/project_views: helpers de formatacao,
construtor da arvore de relatorios, acoes de geracao e de artefato, e os
dois tree managers. O pacote entra inteiro em MIGRATED_PATHS.
Um bug JA ATIVO no main, encontrado ao migrar:
`navigate_to_processing_reports_tab` procurava a aba pelo texto exibido
(`"Processamento e Relatorios" in tab_text`). A aba passou a ser criada
com `_("Processing and Reports")` na fase 1 (ui/builders), entao a busca
nunca mais casou -- e o unico sintoma era um log.warning, com a aba
simplesmente nao abrindo. Agora ambos os sitios (video_selector_tree_-
manager e project_initializer) selecionam
`gui.processing_reports_tab_frame`, que nao depende de idioma.
Outros pontos:
- `_HIERARCHY_LABELS` era um ClassVar com "grupo"/"dia"/"sujeito" no
corpo da classe: virou a funcao `hierarchy_label()`. O valor alimenta
`target_kind`, que o dialog_manager interpola dentro de mensagem ja
traduzida.
- `for _ in range(3)` em `delete_all_unified_reports` sombreava o
gettext: virou `_attempt`.
- `format_status_label` usa dois msgids simples em vez de ngettext --
os arquivos de pares nao carregam formas plurais, e nenhum outro
sitio do projeto usa ngettext.
- Status da coluna da arvore: "Processado"/"Pendente" viraram
`_("Processed")`/`_("Not processed")`. O msgid "Pending" ja existe
mapeado para "Pendentes" (rotulo de card, plural), e reusa-lo poria
o plural numa coluna de linha unica.
- Dois textos de "excluir arquivos do disco" que diferiam so por
"do disco"/"no disco" foram unificados num msgid so.
- `roi_template_var != "Nenhum"` foi deixado como esta: e comparacao
com valor armazenado, nao texto exibido, e hoje nada grava "Nenhum".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ento project_model_configuration_panel e behavioral_config_widget -- os dois formularios que o pesquisador usa para definir pesos por projeto e os parametros de tigmotaxia/geotaxia. `WEIGHT_INHERIT_LABEL` era constante de corpo de classe e virou a funcao `weight_inherit_label()`. Ela e um caso especial: o texto e exibido no dropdown E comparado com `!=` para decidir se o slot tem override. Como os dois lados agora chamam a mesma funcao, o sentinela continua casando qualquer que seja o idioma -- o que NAO aconteceria se so o lado exibido fosse traduzido. `lambda *_: ...` em `_build_slot_override_controls` virava um `_` local dentro da lambda; renomeado para `*_a` agora que o modulo importa o gettext. O mapa perspectiva-exibida -> valor-persistido do behavioral_config_widget ja era construido em tempo de execucao a partir de uma unica lista, entao traduzir os rotulos nao desalinha `_perspective_mapping` de `_perspective_reverse`; os valores gravados seguem "top_down"/"lateral". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Os rotulos das abas do notebook, os botoes do painel de controle e todo o
texto que o StateSynchronizer escreve na barra de status e no cabecalho de
analise (metadados, tarefa em andamento, resumo de interacao social).
`update_analysis_task_status` removia o prefixo redundante do passo com
`step_text.lower().startswith("etapa:")` -- ramo por texto exibido. O
produtor (`core/video/progress_notifier`) ainda escreve "Etapa: ", mas vai
para o ingles numa fase seguinte; agora o strip aceita os dois prefixos,
entao nenhuma das duas ordens de migracao deixa "Etapa: Etapa: ..." na
tela.
`tests/test_analysis_metadata_display.py` reimplementa a mao os dois
formatos que o StateSynchronizer produz, e uma das asserts compara com
`_default_analysis_metadata_text()` de verdade -- a copia migrou junto,
senao o teste passaria a comparar portugues com ingles.
Msgids reaproveitados em vez de duplicados: "Detection Model Status",
"Settings", "No analysis in progress.", "No task in progress.",
"Individual: {value}", "Group: {value}", "Day: {value}" e
"▶️ Start Recording". O LabelFrame "Processamento" do control_panel usa
"Video Processing" porque "Processing" ja esta mapeado para "Processando"
(gerundio), que nao serve como titulo de secao.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
video_frame_manager, event_handler, renderer e polygon_drawing_service --
o caminho que carrega o frame no canvas, o menu de contexto dos vertices e
as mensagens de conclusao de arena/ROI.
Mais um `_` sombreado que so o ruff (F823) enxergou:
`h, w, _ = frame.shape` em `display_roi_frame`, na mesma funcao que abre
quatro dialogos de erro. Renomeado para `_channels`.
Msgids reaproveitados: "No Video Selected", "ROI Name", "Error Loading" e
"Could not load the selected video.\n{path}".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
roi_template_manager, zone_edit_guard e validators/config_validator -- a biblioteca de templates, o dialogo que impede sair da aba com desenho por concluir, e as mensagens de validacao numerica do editor de configuracao. Msgids reaproveitados de lotes anteriores em vez de duplicados: "Video not selected", "Template applied", "Confirm Deletion", "Error applying the template", "Import ROI Template into the Library", "ROI Templates", "All files", "Import error", "Template imported", "Overlap fraction must be between 0 and 1", "Window length must be odd and at least 3." e "Polyorder must be at least 1." -- varios deles ja existiam porque dialog_manager e validation_manager exibem as mesmas frases. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ultimo lote: processing_reports, project_overview, single_video_workflow,
event_dispatcher e project_initializer. Com ele o scanner reporta ZERO
literais em src/zebtrack/ui/components.
MIGRATED_PATHS deixa de crescer arquivo a arquivo nesse pacote: as ~30
entradas de ui/components/* viram uma unica "src/zebtrack/ui/components".
Assim um arquivo NOVO no pacote ja nasce coberto pelo ratchet, em vez de
ficar de fora ate alguem lembrar de acrescenta-lo a lista.
Os seis cards de status de processing_reports e project_overview eram duas
copias literais da mesma tabela; agora as duas chamam os msgids que o
validation_manager ja usava ("Pending", "Processing", "With data",
"Completed", "Failed"), entao os rotulos nao podem mais divergir entre as
duas abas.
`_describe_roi_rule` montava a frase da regra de ROI por concatenacao de
fragmentos; virou um msgid por caso mais um molde final, que e o que
permite ao tradutor reordenar a sentenca.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fase 2 de 3 da internacionalização, seguindo a fase 1 mergeada em #461.
O PR #461 já foi mergeado, então esta fase abre um PR próprio a partir do
merge dele.
Escopo
src/zebtrack/ui/components/**esrc/zebtrack/coordinators/**— juntos depropósito: os coordinators emitem o texto dos messagebox que os components
disparam, e separá-los deixaria metade de cada diálogo traduzido.
O literal português é a tradução: cada par vai para
src/zebtrack/locales/_pairs/pr2-*.json, então o diff do.poé o inversoexato do diff do fonte.
Landed até agora
model_diagnostics_panel,global_model_configuration_panel,model_diagnostics_coordinatorconfig_editor,canvas/zone_editor,zone_controlsDefeitos corrigidos de passagem
Ambos do tipo que a tradução quebraria em silêncio:
"Ambos"era comparado com==entre o combobox do painel dediagnóstico e o coordinator. Virou
ui/sentinels.both_models_label(),o mesmo padrão dos outros rótulos que são exibidos num módulo e testados
noutro.
show_aquarium_selectorramificava pelo texto exibido(
"Desenho" in child.cget("text")). Traduzido o rótulo, o seletor deaquário cairia no fallback sem avisar. Agora ancora no próprio widget.
_usado como descarte de tupla sombreava o gettext dentro da mesmafunção (ruff F823).
Constantes de corpo de módulo/classe viraram funções, conforme
tests/i18n/test_no_import_time_translation.py.Verificação
ruff check .,mypy .,pytest -qepytest -m gui -n0verdes a cadacommit;
update_translations.pyreporta All catalogues are complete.Cada pacote migrado entra em
MIGRATED_PATHSno mesmo commit.🤖 Generated with Claude Code