chore: [DHIS2-21969] Refine configurable terminology label support - #4700
chore: [DHIS2-21969] Refine configurable terminology label support#4700henrikmv wants to merge 27 commits into
Conversation
…_plural-custom-terminology-note-relationship-attribute
…_plural-custom-terminology-note-relationship-attribute
…_display-custom-teminology
|
| const defaults: Record<CustomLabelKey, () => string> = { | ||
| enrollment: () => i18n.t('enrollment'), | ||
| event: () => i18n.t('event'), | ||
| programStage: () => i18n.t('program stage'), | ||
| note: () => i18n.t('note'), | ||
| relationship: () => i18n.t('relationship'), | ||
| attribute: () => i18n.t('attribute'), | ||
| orgUnit: () => i18n.t('organisation unit'), | ||
| followUp: () => i18n.t('follow-up'), | ||
| }; |
There was a problem hiding this comment.
🟡 Plural wording requests fall back to singular words
When a plural term is requested but the server or configuration provides no plural custom label, the singular default word is returned (defaults[key]() at src/core_modules/capture-core/metaData/helpers/customLabels/useLabel.ts:29), so plural places in the interface can read "1 event"-style singular wording such as "event" instead of "events".
Impact: Users on servers that do not provide plural terminology (or programs without plural labels configured) can see grammatically wrong singular words where a plural is expected.
How the plural resolution path degrades to the singular default
resolveLabel in src/core_modules/capture-core/metaData/helpers/customLabels/customLabels.ts:43-55 now returns undefined when plural is requested and the plural field (displayEventsLabel, displayProgramStagesLabel, displayEnrollmentsLabel) is not present on the program/stage. Those plural fields are only fetched when the server supports customTerminologyPlurals (version ≥ 43) — see src/core_modules/capture-core/metaDataStoreLoaders/programs/quickStoreOperations/storePrograms.ts:178-196. So on pre-43 servers resolveLabel(..., { plural: true }) is always undefined, and resolve() falls back to defaults[key](), which only contains singular terms (i18n.t('event'), i18n.t('program stage'), i18n.t('enrollment'), …) with no plural variant. Previously resolveLabel fell back to the singular custom field for plural requests, which at least preserved the configured terminology. A plural default map (or i18n plural forms) is needed alongside the singular defaults.
Prompt for agents
In src/core_modules/capture-core/metaData/helpers/customLabels/useLabel.ts the `defaults` map only provides singular translations (e.g. i18n.t('event')). `resolve()` falls back to this map whenever `resolveLabel` returns undefined, which now happens for every plural request on servers below version 43 (plural fields such as displayEventsLabel are not requested there, see storePrograms.ts buildFieldsParam) and for any program that has not configured a plural label. As a result `getTermLabel(programId, 'event', { plural: true })` yields the singular word 'event'. Consider adding plural default translations (a second map or i18n.t with a count/plural form) and selecting them when options.plural is true, and/or deciding whether the removed fallback to the singular custom label should be reinstated for plural requests so configured terminology is not lost on older servers.
Was this helpful? React with 👍 or 👎 to provide feedback.
| header={ | ||
| <div className={classes.header}> | ||
| <span>{i18n.t('Stages and Events')}</span> | ||
| <span>{i18n.t('Program stages and events')}</span> |
There was a problem hiding this comment.
🔍 Renamed UI strings break existing Cypress assertions
"Stages and Events" is now rendered as "Program stages and events", but cypress/e2e/WidgetsForEnrollmentPages/WidgetEnrollmentNote/index.js:6 asserts cy.contains('Stages and Events'). Similarly, cypress/e2e/ScopeSelector/ScopeSelector.js:287 asserts cy.contains('Choose a stage for a new event'), which was renamed in src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/ProgramStageSelector/ProgramStageSelector.container.tsx:106. These e2e specs will fail until updated.
Was this helpful? React with 👍 or 👎 to provide feedback.




DHIS2-21969
This PR refactors the custom terminology system to support configurable labels from the DHIS2 backend. The key changes are:
Unified label API: Replaces
getProgramLabel,getStageLabel,useTrackedEntityTypeLabel,useProgramLabel,useStageLabelwith two functions:getTermLabel(programId, key, options)— usable anywhereuseTermLabel(key, options)— React hook that readsprogramIdfrom Redux Both resolve custom labels from stage → program hierarchy, falling back to translated defaults.Feature-gated plural fields: Plural terminology fields (
displayEnrollmentsLabel,displayProgramStagesLabel,displayEventsLabel) are only requested from the API when the backend supports them (version ≥ 43).i18n correctness: Module-level
i18n.t()calls are moved to function/render scope so translations resolve at call time, not import time — required for dynamic terminology to work.String updates: "Stage" → "Program stage" across UI strings.