Skip to content

Adds Portuguese (Brazil) translations and add translation persistence feature + code couple more terms to i18n - #60

Merged
paynejd merged 33 commits into
OpenConceptLab:mainfrom
filiperochalopes:feature/translation-pt-br-i18n
Oct 7, 2026
Merged

paynejd merged 33 commits into
OpenConceptLab:mainfrom
filiperochalopes:feature/translation-pt-br-i18n

Conversation

@filiperochalopes

Copy link
Copy Markdown
Contributor

TL;DR: Adds Portuguese (Brazil) locale + i18n for event feed types & object types (refs ocl_issues#2866). Activity feed items like "Created Source Version", "Updated Collection" are now translatable instead of hardcoded EN.


Changes

Area Files Description
PT-BR locale src/i18n/locales/pt-BR/translations.json (new, 1159 lines) Full UI translation: common, dashboard, auth, concept, mapping, repository, org, user, search, import, clone, quota, etc.
Locale registration src/common/constants.js, src/i18n/config.js Added pt-BR to LANGUAGES and i18n resources
Event/Object type i18n src/i18n/locales/en/translations.json (+18), src/i18n/locales/pt-BR/translations.json Added common.event_types & common.object_types keys
Feed components src/components/common/Events.jsx, src/components/dashboard/DashboardEvents.jsx Now use t() for event types & object types with defaultValue fallback

Key Translation Decisions

EN Key PT-BR Note
Source Source Kept as-is (domain term for collection/repo type)
Source Version Versão do Source "do Source" not "da Fonte" per domain convention
Collection Coleção
Collection Version Versão da Coleção
Organization Organização
Concept Conceito
Mapping Mapeamento
Repository Repositório
Event types (created/updated/released/deleted/joined/source) Criado/Atualizado/Publicado/Excluído/Entrou/Fonte

Verification

npm run build && npm run lint
  • Language switcher → Português (Brasil) renders full UI in PT-BR
  • Dashboard → Activity Feed shows translated event types & object types
  • Events component (repo pages) same behavior
  • Unknown keys fall back to EN key (no crash)
  • EN locale unchanged (keys added to en/translations.json)

- Add pt-BR translation catalog with all English keys translated
- Register pt-BR in i18n config
- Add pt-BR to LANGUAGES in constants.js
- Add event_types and object_types to common translations (en and pt-BR)
- Update Events.jsx and DashboardEvents.jsx to translate event_type and referenced_object.type from API
* Implement the PT-BR locale configuration and language persistence logic

* Add translations for event and object types to both en and pt-BR locales

* Update event and object display components to utilize translated types
* Refactor event component to use targeted internationalization strings based on user ownership

* Added necessary translations for activity states in English, Spanish, Portuguese (Brazil), and Chinese locales
* Update Portuguese (Brazil) translations for user state changes, including followed and unfollowed states
* Updated Portuguese (Brazil) translations for event types in the i18n localization files

* Ensured that the translated terms accurately reflect the action (e.g., "Criou" instead of "Criado" for event creation)

@paynejd paynejd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obrigado, Filipe! This is a careful, high-quality translation. The placeholders and tags all check out, and the 332 strings shared with the Mapper are translated identically.

Claude and Codex reviewed this independently, then checked each other's findings. The inline comments are one-click suggestions in three kinds:

  • Bug: a clear error (typo, untranslated word, broken key, code regression). Please apply.
  • Assembled text: the problem only shows on screen. The code joins your fragments, or inserts names and labels into them, so you couldn't have seen these from the catalog. Each comment quotes what the user sees today and after the suggestion. All of them can be fixed in the catalog now; the wording is yours.
  • Second opinion: a judgment call. You decide.

Other notes:

  • CI: the Eslint check fails on "Português (Brasil)". The one-click fix is on constants.js.
  • Rebase (optional): 11 strings landed on main after you branched (e.g. common.error, concept.success_retired). They show in English until translated. Translations would be welcome, but they don't block the merge.
  • Code-side fixes: some sentences need code changes before they can read naturally (raw English resource types inside sentences, relative dates). We'll handle those in OpenConceptLab/ocl_issues#2877, so there's nothing for you to do there.
  • Glossary: we're starting a cross-language glossary of OCL terms in the design system (OpenConceptLab/ocl_issues#2878), and you decide the Portuguese terms. None of these questions block the merge:
    • Source / Coleção: keeping "Source" while translating Collection, Organization and Repository looks like a sound rule: translate names with a clear cognate, and keep the one whose translation would be ambiguous ("Fonte"). We'll document it that way unless you'd rather change it.
    • Retired = "Aposentado" (with Unretire = "Reativar"): would "Inativo" or "Descontinuado" read better to Brazilian terminology users?
    • Locale: "Localidade" or "Idioma"? And should labels use title case or sentence case?

Comment thread src/common/constants.js Outdated
Comment thread src/i18n/locales/pt-BR/translations.json Outdated
Comment thread src/components/common/Events.jsx Outdated
Comment thread src/i18n/locales/pt-BR/translations.json Outdated
Comment thread src/i18n/locales/en/translations.json Outdated
Comment thread src/i18n/locales/pt-BR/translations.json Outdated
Comment thread src/i18n/locales/pt-BR/translations.json Outdated
Comment thread src/i18n/locales/pt-BR/translations.json Outdated
Comment thread src/i18n/locales/pt-BR/translations.json Outdated
Comment thread src/i18n/locales/pt-BR/translations.json Outdated

@paynejd paynejd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex review record (codex-cli 0.160.0; oclweb3 07c8260, oclmap b05133c). One combined review covers both PRs, so the same record is posted on oclweb3#60 and oclmap#90. The actionable items are the inline suggestions in the review above. This record also lists items that were later downgraded (pass 2) or moved to OpenConceptLab/ocl_issues#2877, so nothing here needs action beyond that review.

Pass 1: independent review (coverage, language, i18n & code)

Summary

  • oclweb3#60: request changes. Fix the stored-zh menu crash, missing catalog key, and event sentence construction before merging.
  • oclmap#90: request changes. Complete catalog coverage, correct a few clear language errors, align feature names, and separate dependency churn.
  • OCL Web covers 1,040/1,041 branch English keys and 1,014/1,026 current-main keys. Mapper covers 750/752 branch keys and 748/759 current-main keys.
  • Both catalogs have zero interpolation-variable mismatches, tag mismatches, or empty strings. Neither English catalog defines plural-suffix keys.
  • Of 332 shared keys with identical branch English, 331 have identical Portuguese translations; the remaining difference is OCL Web’s misspelled key.
  • The translations are broadly coherent Brazilian Portuguese. “Source” is consistently retained in OCL Web; its retention is a maintainer glossary decision, not a translation error.
  • Language persistence generally works, but document language and formatting do not consistently follow it. Mapper’s lockfile additionally changes 68 dependency versions.
  • Review was read-only. Dependencies are absent, so lint/build execution was not possible; neither project defines npm run lint—the script is npm run eslint.

oclweb3#60

Coverage

Counts use unique, flattened string keys.

Comparison English keys Covered Missing Portuguese-only
PR branch 1,041 1,040 1 1
Current origin/main 1,026 1,014 12 27

Branch missing key — high confidence: src/i18n/locales/pt-BR/translations.json:574 names the key repo.repo_summary_is_calculando. Rename it repo.repo_summary_is_calculating, preserving its translated value. src/components/repos/RepoSummary.jsx:66 requests the English key, so the current translation is unreachable.

Missing against current main, grouped by section:

Section Missing keys
announcement pricing_label
common error
concept form.id_auto_assign_back, form.id_live_at, form.id_optional_sequential, form.id_optional_uuid, success_retired, success_unretired
org success_delete
reference unresolved
repo auto_id_manual_short, repo_summary_is_calculating

These missing entries have no Portuguese PR-head line. Their insertion sections begin at pt-BR/translations.json:2, :260, :419, :506, :867, and :1112. High confidence: translate the 11 main additions and repair the existing typo; fallback avoids missing-key failures but does not satisfy full translation coverage.

Portuguese-only keys:

  • Against branch English: only repo.repo_summary_is_calculando.
  • Against main: that typo; user.own_recent_activity, user.recent_activity_of; and these PR additions:
    • common.event_types.{created,updated,released,deleted,followed,unfollowed,joined,source}
    • common.object_types.{Source,Collection,Source Version,Collection Version,Organization,Concept,Mapping,Repository}
    • common.event_object_types with the same eight object names.

The 26 legitimate additions will cease being extras when the PR’s English changes merge.

Identical-to-English values: 46. None is a clear accidental untranslated sentence.

Classification Keys
Deliberate Source terminology common.event_types.source, common.object_types.Source, reference.source, reference.sources, reference.group_sources, repo.source, sort.source
Identifiers, formats, literal displays common.id, common.uid, common.json, repo.ids, repo.auto_id_uuid, repo.version.form.id.label, repo.external_export_file_types, repo.reindex_dialog_title, repo.processing_stage_caption, repo.clear_processing_title, sort.a_z, sort.z_a, sort.num_asc, sort.num_desc
Technical FHIR parameter names repo.version.expansion_form.parameters_fields.{activeOnly,includeDesignations,includeDefinition,excludeNested,excludeNotForUI,excludePostCoordinated,exclude-system,system-version,check-system-version,force-system-version}.label
Portuguese cognates/accepted technical terms common.status, concept.namespace, reference.intensional, reference.extensional, repo.experimental, repo.meta, repo.code_system, repo.valueset, repo.concept_map, repo.changelog, repo.stage_changelog, repo.mapper, user.avatar, url_registry.global, import.args

“Changelog”, “Namespace”, and “Args” could receive more accessible labels, but they are glossary choices, not high-confidence omissions.

Structural checks: zero variable mismatches, zero Trans/HTML tag mismatches, zero empty values. Neither catalog has _one, _other, _zero, _two, _few, or _many keys. Existing explicit singular/plural strings remain present.

Use of added English keys:

  • common.event_types and common.event_object_types: used dynamically in Events.jsx:29–31 and DashboardEvents.jsx:29–43.
  • user.own_recent_activity, user.recent_activity_of: used in Events.jsx:111.
  • common.object_types is unused; en/translations.json:61 adds an unused parallel object-name catalog. High confidence: remove it or use it deliberately.
  • common.event_types.source has no explicit consumer; the dynamic lookup would use it only if the API supplied event_type: "Source".

Nearby English UI remaining — high confidence:

PR-head location Current output Suggested output Reason
Events.jsx:24–26 Server description + site title Localized whole-event message No-object events bypass translation.
Events.jsx:59; DashboardEvents.jsx:67 Moment fromNow(), e.g. “a day ago” Portuguese relative time OCL Web never synchronizes Moment with UI language.
src/components/users/UserProfile.jsx:104 Joined {date} Entrou em {date} through an i18n key Adjacent profile UI remains hardcoded English.

Language

Locations below refer to src/i18n/locales/pt-BR/translations.json.

Line/key Current string Suggested string Confidence / reason
910, user.last_name Último Nome Sobrenome High: “last name” means family name in this form.
878, org.org_have_not_created_public_repos_suffix não criaram nenhum repositório público não criou nenhum repositório público High: OrgOverview.jsx:17 prefixes one organization’s name.
322, concept.ai_assistant_not_configured Assistente de IA não está configurado… O Assistente de IA do OCL não está configurado… High: restore the required OCL feature brand; English already omits it.
990, url_registry.resolve_success_with_entry …usando uma entrada no <2/> Registro …usando uma entrada no Registro <2/> High: with the Global component this renders “Global Registro”.
992–993, registry failure messages …no <0/> Registro… …no Registro <0/>… High: same English noun-order carryover.
1146, 1155, quota Auto Match messages Correspondência Automática Auto Match if the feature name is invariant Medium: internally consistent translation, but the stated product name is “Auto Match”; confirm the branding policy.

Register is coherent: infinitives for actions (“Salvar”, “Excluir”, “Buscar”), você forms for instructions. Mixing these functions is appropriate. Capitalization varies between sentence case and title case, generally following English; standardizing it is optional.

There is no “Fonte” anywhere in this catalog, including event_types: common.event_types.source is "Source". Repository is sometimes abbreviated “Repo”; that is an internal terminology inconsistency rather than a mistranslation.

i18n & code

Stored Chinese crashes the user menu — high confidence.

  • src/i18n/config.js:9,16–17 accepts stored "zh".
  • src/common/constants.js:3–6 excludes Chinese from LANGUAGES.
  • src/components/users/UserMenu.jsx:31,86 obtains undefined, then evaluates selectedLanguage.name.
  • Suggestion: either include Chinese in the selector or restrict accepted persisted languages to selector entries; also guard the lookup. The application can initialize in Chinese, but opening the menu throws.

Event fragments need complete sentence keys — high confidence. Current construction is in Events.jsx:29–31 and DashboardEvents.jsx:29–43.

Every referenced-object combination is exactly the following verb + noun phrase. The two tables describe the complete catalog-defined Cartesian product, including combinations the API may never emit.

event_type Portuguese fragment
Created Criou
Updated Atualizou
Released Publicou
Deleted Excluiu
Followed Passou a seguir
Unfollowed Deixou de seguir
Joined Entrou
Source Source
referenced_object.type Portuguese fragment
Source um Source
Collection uma Coleção
Source Version uma Versão do Source
Collection Version uma Versão da Coleção
Organization uma Organização
Concept um Conceito
Mapping um Mapeamento
Repository um Repositório

Thus “Criou uma Coleção” and “Passou a seguir um Source” work. “Entrou uma Organização” does not: use “Entrou em uma Organização”. Every Joined/object combination lacks the required preposition. The Source event row mechanically produces “Source um Source”, etc.; verify whether that event type is real before maintaining it.

For no referenced object:

  • Dashboard: verb + getSiteTitle(), defaulting to OCL. Joined renders “Entrou OCL”; use “Entrou no OCL”, or “Ingressou em {{site}}” for a configurable site name.
  • Profile timeline: retains API description, appending the site title only for Joined. An API description "Joined" renders “Joined OCL”.
  • Unknown event/object types retain raw English API values.

Suggestion: event-specific complete messages, with object/site interpolation and explicit gender/preposition handling. The new recent-activity heading already correctly adopts this approach.

Spanish/Chinese event behavior: neither receives the new event catalogs, so both fall back to English.

  • Profile referenced-object events gain English articles: formerly “Created Collection”, now “Created a Collection”.
  • Dashboard formerly combined lowercase API labels with translated common.a/an; now it renders English “Created a Collection” / “Created an Organization”.
  • No-object dashboard verbs change from raw lowercase to English catalog capitalization.
  • Recent-activity headings improve: proper Spanish and Chinese whole phrases replace English possessive concatenation.

Persistence and formatting:

Location Finding / suggestion Confidence
config.js:11–28,53 Valid stored selections survive reload; blocked storage and missing window are caught. No competing language detector or lng persistence was found. Storage remains origin-specific; equal keys do not share language across different hosts. High; fine
config.js:52 i18n.languages = SUPPORTED_LANGUAGES overwrites the selected language’s resolution hierarchy. Remove it; use supportedLngs for supported locales. High
public/index.html:2 <html lang="en"> remains English. Update it at initialization and on language change. High
common/constants.js:10–12; common/utils.js:26–28 Dates retain M/D/YYYY and 12-hour formatting. Number calls generally use toLocaleString() without the selected locale. High

The i18n.languages assignment does not itself make Portuguese translations fall back to English. i18next’s translator computes its lookup hierarchy separately; changeLanguage also resets languages. The assignment corrupts public hierarchy state and is unnecessary, but claiming it reverses ordinary translation lookup would be incorrect. i18next translator, language-change implementation.

Other fragment problems — high confidence: DeleteEntityDialog.jsx:33–41 combines resource labels with "este {{resourceType}}" and "o {{resourceType}} inteiro" from the new catalog. Collection expansion deletion can produce “este Expansão de Coleção”; some callers pass raw English resource types. Use resource-specific messages or gender-neutral wording. The Portuguese confirmation title also adds ?, while the component appends the ID and another ?.

Lint/build: no obvious import or JSON syntax failure. Medium-confidence lint concern: constants.js:6 introduces "Português (Brasil)" into a file governed by an English spell-check rule; neither word is allowlisted. Verify and narrowly exempt language display names. No lint/build pass is claimed.

oclmap#90

Coverage

Comparison English keys Covered Missing Portuguese-only
PR branch 752 750 2 0
Current origin/main 759 748 11 2

Missing against branch — high confidence:

  • map_project.preview_limit_title_scispacy
  • map_project.preview_limit_body_scispacy_no_count

English entries are at src/i18n/locales/en/translations.json:532,550; Portuguese insertion anchors are pt-BR/translations.json:530,546.

Suggested translations:

  • ScispaCy LOINC ainda não está disponível
  • A correspondência ScispaCy LOINC não está disponível para sua conta. Solicite mais acesso abaixo.

Missing against main, grouped by section:

Section Missing keys
announcement pricing_link_label
map_project algorithm_throttled, auto_match_rows_throttled, preview_limit_body_scispacy_no_count, preview_limit_title_scispacy, rerank_step, row_throttled, search_failed, search_throttled, waiting_for_capacity, waiting_for_capacity_short

The nine main-only additions have no Portuguese PR-head line. High confidence: add translations when updating the branch; English fallback currently covers the gaps.

Extras against main: only user.own_recent_activity, user.recent_activity_of, which this PR also adds to English.

Identical-to-English values: 11, all plausible deliberate keeps:

common.id, common.ok, common.json, concept.namespace, repo.source, repo.experimental, user.avatar, url_registry.global, map_project.source, map_project.lookup_configuration_token, map_project.bridge_canonical_short.

No high-confidence accidental untranslated English sentence.

Structural checks: zero variable mismatches, zero tag mismatches, zero empty strings, and no plural-suffix keys on either side.

Duplicate JSON member — high confidence: pt-BR/translations.json:563,719 repeats map_project.proposed_successfully, identically "Proposto com sucesso.". Remove one. Parsing succeeds and the value is unchanged, but duplicate members obscure maintenance. Counts above count it once.

Unused new keys — high confidence: pt-BR/translations.json:342–343 and corresponding English entries add user.own_recent_activity / user.recent_activity_of; neither is used anywhere in Mapper’s code. The earlier reviewer’s observation is correct. Remove them unless a consumer is added.

Nearby English UI sample — high confidence: src/components/map-projects/ProjectLogs.jsx:170 renders {log.user} at {date}. Suggested: a complete localized message, e.g. {{user}} em {{date}}. The PR touches catalogs/configuration rather than these components; this is existing visible English, not newly introduced English.

Language

Locations below refer to src/i18n/locales/pt-BR/translations.json.

Line/key Current string Suggested string Confidence / reason
327, user.last_name Último Nome Sobrenome High: family-name field.
303, organization suffix não criaram nenhum repositório público não criou nenhum repositório público High: singular organization subject; shared with OCL Web.
440, concurrent_requests Requisições Concurrentes Requisições concorrentes or Requisições simultâneas High: “Concurrentes” is misspelled Portuguese.
629, source_code Código Fonte Código de origem High: MappingDecisionResult.jsx:126 labels the terminology’s source-side code, not software source code.
555, preview_limit_notify_me Notifique-me quando planos lançarem Notifique-me quando os planos forem lançados High: plans are launched; they do not launch something.
748, algo_canonical_url_description URL canônica do code system que este algoritmo corresponde… URL canônica do sistema de códigos no qual este algoritmo busca correspondências… High: incorrect verb construction and unclear matching target.
386, 388–389, registry messages …no <n/> Registro… …no Registro <n/>… High: same noun-order problem as OCL Web.
482, Auto Match and related messages Correspondência Automática Auto Match if invariant Medium: coherent localization; needs an explicit branding decision.

OCL AI Assistant branding — high confidence: generic “Assistente de IA” appears at lines 427, 501, 515, 522, 524, 531, 547, 548, 683, 754. Add “do OCL” when naming the feature. Lines 672–673 already correctly retain OCL. These omissions largely mirror omissions in English; fix the source wording too.

Prohibited “AI recommendations” wording — high confidence: lines 499, 520–521, 692, 760–761 use “Recomendado por IA”, “Recomendações de IA”, or “recomendações de mapeamento com IA”. Suggested wording should name the feature or its output, for example:

  • Sugerido pelo Assistente de IA do OCL
  • Análise do Assistente de IA do OCL para…
  • A análise do Assistente de IA do OCL falhou — clique para tentar novamente

Again, these faithfully reproduce problematic English branding; they are not independent mistranslations.

Register broadly follows the same appropriate infinitive/instruction pattern as OCL Web. Capitalization is uneven but not a blocker. “Bridge”, “ponte”, and “bridge” vary within Mapper; agree on one human-facing term while retaining API identifiers.

i18n & code

  • Persistence — high confidence, generally fine: config.js:11–28,54 validates stored values and catches storage failures. All four accepted languages exist in Mapper’s selector. No competing detector or language-storage implementation was found.
  • Hierarchy assignment — high confidence: config.js:53 has the same unnecessary i18n.languages overwrite discussed above; remove it. Ordinary translation fallback remains English.
  • Moment restoration gap — high confidence: UserMenu.jsx:34–35 calls both changeLanguage(locale) and moment.locale(locale) on manual selection. config.js:33 restores i18next language on reload without restoring Moment. Thus persisted Portuguese UI can have English relative dates until language is selected again. Synchronize both at startup and on every language change.
  • Document/formatting — high confidence: public/index.html:2 remains lang="en"; common/constants.js:12–14 fixes US date/time patterns; number formatting is not tied to UI selection.
  • Interface versus content language — checked: the PR does not change input-language, name-locale, target terminology, or assistant-output locale selection. Keep those independent.

Unrelated dependency changes — high confidence: package-lock.json:3,9 updates root metadata from 1.0.0-beta to 1.0.11-beta, matching the existing package.json. That metadata correction is reasonable. However, the same diff changes 68 shared package versions, adds no package paths, and removes node_modules/body-parser/node_modules/qs. Examples include Babel parser, webpack, ws, undici-types, and the jsonjoy packages.

Suggestion: retain only the root metadata correction if needed; move dependency refresh to a separate dependency PR with install/build/test validation. The churn is not demonstrably unsafe, but its safety is unverified and unrelated to pt-BR.

No obvious new JavaScript/JSON syntax problem was found. Dependencies are absent; no executable lint/build verification was performed.

Cross-app consistency

There are 332 shared keys whose branch English values are identical. 331 Portuguese values match exactly. There are no differing Portuguese values where both apps contain the correctly named shared key.

Shared key oclweb3 oclmap Recommendation
repo.repo_summary_is_calculating Missing; translation exists under repo_summary_is_calculando at line 574 Resumo do repositório está sendo calculado, por favor verifique novamente após algum tempo. at line 289 Repair OCL Web’s key; the actual wording already matches.

Canonical-term inventory:

Term oclweb3 oclmap Recommendation
Source Source / Sources Source / Sources Agree explicitly on retention or localization.
Source Version Versão do Source; versão de Source Versão do Source de Origem/Destino is not independently cataloged Use agreed Source term consistently; do not invent absent Mapper labels.
Collection Coleção Coleção Keep.
Collection Version Versão da Coleção No standalone equivalent Keep when introduced.
Organization Organização Organização Keep; repair singular verb agreement.
Repository Repositório / Repo Repositório / Repo Prefer Repositório in visible prose.
Concept Conceito Conceito / Conceitos Keep.
Mapping Mapeamento Mapeamento / Mapeamentos Keep.
Reference Referência “referências” in collection-save help Keep; means collection membership expression, not citation.
Expansion Expansão No canonical expansion label Keep.
Release / Released Publicar / Publicado / versões publicadas Status de Publicação / versões publicadas Keep; agree on gender for standalone state labels.
HEAD HEAD No explicit HEAD label Preserve identifier; explain as working version where needed.
Retired Aposentado / aposentados Aposentado / aposentados Acceptable choice; document inactive-status meaning.
Map Type Tipo de mapeamento Tipo de mapeamento Keep.
Concept Class Classe do Conceito / Classes de Conceito Same Keep; normalize capitalization if desired.
Datatype Tipo de Dado / Tipo de dado Same Keep; optionally standardize “tipo de dados”.
Locale Localidade Localidade; idioma in code help Distinguish locale/content language from interface language.
Mapping / Mapper project Projeto de Mapeamento Projeto de Mapeamento / projeto do Mapper Distinguish resource name from branded app attribution.
Auto Match Correspondência Automática in quota messages Correspondência Automática throughout Decide whether translated names are allowed; otherwise retain Auto Match.
Candidate No candidate feature terminology Candidato Keep.
Target repository No corresponding feature label Repositório de Destino Keep.
OCL AI Assistant Assistente de IA do OCL; one generic omission Assistente de IA do OCL plus multiple generic omissions Always retain OCL when naming the feature.

Canonical terms: options and how to document them

Keeping “Source” is defensible, especially for technical users moving between the UI, API, and /sources/ URLs. “Fonte” is ambiguous: it can mean provenance, information source, or a typeface. “do Source” is not inherently a grammatical error—a borrowed resource name can take masculine gender by association with “repositório”—but it may sound less natural to newcomers and needs an explicit glossary rule.

Maintainer options:

  1. Source / Coleção: retain the PR’s choice. Define “Source” as an OCL terminology repository and document masculine gender and “Sources” plural.
  2. Fonte / Coleção: more fully localized, with feminine agreement: “uma Fonte”, “Versão da Fonte”. Explain that this is an OCL resource, not generic provenance.
  3. Repositório de terminologia / Coleção: clearer on first use, with “Source” in help text for API correspondence. Avoid equating every Source directly with FHIR CodeSystem.

Brazilian FHIR material supports retaining CodeSystem/ValueSet identifiers while explaining them in Portuguese, but it does not establish “Source” as standard Brazilian terminology. RNDS publishes both TabelaSUS CodeSystem resources and ValueSet resources with Portuguese displays. Brazilian HL7 documentation similarly mixes Portuguese descriptions with canonical resource identifiers. HL7 Brasil example. This favors preserving interoperability identifiers; it does not require untranslated OCL resource labels.

SNOMED CT Brasil, LOINC, and TabelaSUS should remain named terminologies, not be relabeled “Fontes” as proper names. Also, a Coleção can contain concepts and mappings; avoid defining it simply as a ValueSet.

Concrete documentation proposal: record an approved glossary in the OCL design-system documentation, e.g. docs/i18n/pt-BR-glossary.md, and link it from both repositories’ localization guidance. Each entry should include:

  • English term, approved pt-BR term, gender and plural.
  • Resource meaning versus ordinary prose meaning.
  • Example complete sentences, especially events and deletion confirmations.
  • Protected feature names: OCL AI Assistant and Auto Match.
  • Separate definitions for interface language, terminology locale, and assistant output language.

Use Filipe’s review for final language approval and maintainer approval for branding/resource names. Add a read-only catalog check for missing keys, duplicate members, placeholders/tags, and shared-key divergence. No documentation was edited.

Things you checked and found fine

  • pt-BR is imported, registered, and added as Português (Brasil) in both selectors.
  • English remains configured as fallback.
  • Every existing matching key preserves interpolation variables and Trans/HTML tags.
  • No empty Portuguese values or missing plural-suffix counterparts.
  • New OCL Web recent-activity headings correctly handle Portuguese, Spanish, and Chinese word order.
  • No European-Portuguese vocabulary issue rose to high-confidence severity.
  • No unexpected Source/Fonte alternation exists in OCL Web. Mapper’s “Código Fonte” is a separate source-code context error.
  • Both working trees remained clean; no files were modified.
Pass 2: reconciliation with Claude's review

Pass 2 checked the second reviewer's findings (A) and the points where it disagreed with pass 1 (B):
A1 CI spellcheck failure · A2 name escaping in the recent-activity heading · A3 dashboard verb capitalization · A4 real event types, missing User, "Entrou em" · A5 processing-banner agreement · A6 Error 403 sentence · A7 allowance → "cota" · A8 "delete" → "exclua" · A9 Mapper "Excluir" vs Delete · A10 "graciosamente" · A11 Elasticsearch name · A12 "buscar por" · A13 hardship note · A14 "Importações" · A15 "mais específico" · A16 "salvo {{time}}" · A17 minor wording.
B1 stored-zh severity · B2 i18n.languages overwrite · B3 "Aposentado" · B4 overall verdicts · B5 Source / Coleção rule.

A. Claude-only findings

  • A1 — NUANCE: The spellcheck configuration confirms the missing exemptions and proposed fix, but I could not retrieve CI run 37136671460 to verify its failure independently.
  • A2 — AGREE: The new heading interpolates names with escaping enabled by i18next’s defaults, producing literal entities in React; the existing per-call exemption fixes the regression.
  • A3 — AGREE: The dashboard replaced lowercase event prose with capitalized catalog fragments, introducing mid-sentence capitalization in both languages.
  • A4 — NUANCE: The backend confirms the six event constants and user references, while the catalog lacks User; “Entrou em” fixes organization events, but site joins need separate wording, and I did not re-query production counts.
  • A5 — AGREE: RepoHome supplies plural resource labels, so “A lista de {{resource}} exibida aqui pode estar incompleta” fixes agreement consistently.
  • A6 — AGREE: The actual link label produces “Ir voltar,” and the proposed sentence composes correctly with both links.
  • A7 — AGREE: These strings describe quantitative allowances, making “cota” more precise than “permissão.”
  • A8 — AGREE: “delete” is untranslated English here, and “exclua” matches the Portuguese instruction.
  • A9 — NUANCE: “Excluir” can legitimately mean exclusion, but its collision with deletion warrants clarification; “Desconsiderar” is a defensible Mapper-specific choice for Filipe to approve.
  • A10 — AGREE: “Parando graciosamente” misrepresents graceful shutdown, whereas “Encerrando com segurança” conveys the intended operation.
  • A11 — AGREE: The adjacent description explicitly identifies Elasticsearch, so preserving that product name corrects “Busca Elástica.”
  • A12 — AGREE: Both strings precede a search term, for which “buscar … por” is the appropriate construction.
  • A13 — NUANCE: The current wording is awkward, but “orçamento de projeto” loses the English grant-funding distinction; revise the sentence while preserving that meaning.
  • A14 — AGREE: “Importações” is the appropriate Portuguese noun and matches the catalog’s terminology.
  • A15 — AGREE: In this terminology-and-cascade context, “conceito mais específico” expresses narrower scope more naturally than “mais estreito.”
  • A16 — AGREE: Controls supplies fromNow() text, so removing “em” prevents “salvo em há 5 minutos.”
  • A17 — AGREE: The catalog supports these corrections: “de Origem,” “Ver membros,” “Sources de origem e de destino,” and feminine “Nenhuma” for “Decisão.”

B. Disagreements

  • B1 — AGREE: Separate origins prevent Mapper storage from supplying zh to TBv3 through normal usage, so the real crash merits a low-severity defensive guard.
  • B2 — AGREE: Main already overwrites i18n.languages, making removal optional cleanup rather than a blocker introduced by these PRs.
  • B3 — NUANCE: Keep “Aposentado” acceptable and raise a nonblocking glossary question, without treating the cited external terminology as independently verified in this pass.
  • B4 — AGREE: Require focused corrections for introduced defects and unrelated lockfile churn, while moving broader coverage, formatting, branding, and glossary work to follow-ups.
  • B5 — AGREE: Retaining masculine “Source” while translating transparent resource names is defensible; document the convention and resolve capitalization and Bridge/Ponte outliers with Filipe.

Net changes to my pass-1 report

  • Downgrade the stored-zh crash to low, nonblocking.
  • Reclassify the hierarchy overwrite as pre-existing optional cleanup.
  • Withdraw full catalog coverage, existing branding omissions, and broader formatting work as merge requirements.
  • Replace hypothetical event combinations with backend-supported cases; add missing User coverage and dashboard capitalization.
  • Add the escaping regression and verified sentence defects; retain the lint concern, with CI confirmation unavailable.
  • Narrow Mapper’s verdict to a small correction list, with broader terminology decisions deferred.
  • No files modified.

@paynejd

paynejd commented Oct 7, 2026

Copy link
Copy Markdown
Member

Codex review, pass 3 (codex-cli 0.161.0, commit f49e926)

Verdict: clean, no new findings. 23 of 24 earlier items are resolved or declined. One assembled-text item is still open: common.for is still "para", so the search placeholder reads 'Buscar Conceitos para "malária"'. That's a wording call for the author, not a defect.

findings.json
{
  "reviewer": "codex-cli 0.161.0",
  "perspective": "defects",
  "mode": "verify",
  "commit": "f49e9262",
  "verdict": "clean",
  "prior": [
    {"id": "P1", "status": "resolved"},
    {"id": "P2", "status": "resolved"},
    {"id": "P3", "status": "resolved"},
    {"id": "P4", "status": "resolved"},
    {"id": "P5", "status": "resolved"},
    {"id": "P6", "status": "resolved"},
    {"id": "P7", "status": "resolved"},
    {"id": "P8", "status": "resolved"},
    {"id": "P9", "status": "resolved"},
    {"id": "P10", "status": "resolved"},
    {"id": "P11", "status": "resolved"},
    {"id": "P12", "status": "unresolved"},
    {"id": "P13", "status": "resolved"},
    {"id": "P14", "status": "resolved"},
    {"id": "P15", "status": "resolved"},
    {"id": "P16", "status": "resolved"},
    {"id": "P17", "status": "resolved"},
    {"id": "P18", "status": "resolved"},
    {"id": "P19", "status": "resolved"},
    {"id": "P20", "status": "resolved"},
    {"id": "P21", "status": "resolved"},
    {"id": "P22", "status": "resolved"},
    {"id": "P23", "status": "resolved"},
    {"id": "P24", "status": "resolved"}
  ],
  "findings": []
}

@paynejd paynejd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Obrigado, Filipe! All the bugs and assembled-text fixes are in, CI is green, and Codex's pass 3 is clean. Your pt-BR decisions are now recorded on the live Localization guide.

One optional wording point: common.for is still "para", so the search placeholder reads 'Buscar Conceitos para "malária"'. "por" reads more naturally to us, but it's your call. The code-side assembly fixes come next in OpenConceptLab/ocl_issues#2877.

@paynejd
paynejd merged commit df8e8ec into OpenConceptLab:main Oct 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants