
Give every interface word a shared home
Labels belong to the application’s language tree rather than being scattered through screens. Components and resource interfaces request the words for their own context.
That keeps a field, action or recurring control consistently named and makes another language available without duplicating the screen. The application supplies the supported languages and reviewed wording.
Example — One control, two languages
The carousel’s next action reads “Next slide” in English and uses its French bundle when the language changes. Its button and interaction remain the same.
For engineers
The carousel is a concrete example of the runtime contract:
const { tComponent, isReady } = useI18n({
component: FrontendComponentType.LOW_LEVEL_CAROUSEL,
})
const previousLabel = tComponent(FrontendComponentType.LOW_LEVEL_CAROUSEL, 'previousSlide')
if (!isReady) return null
The hook requests the component’s subtree. isReady prevents showing a key while that request is still loading. The returned text is placed in the control’s screen-reader label.
The corresponding current English bundle is:
export const labels = {
"components": {
"LOW_LEVEL_CAROUSEL": {
"previousSlide": "Previous slide",
"nextSlide": "Next slide"
}
}
} as const;
The generated file lives under backend-api/src/engine/i18n/components. The backend serves label trees; it does not invoke language generation during a user request. I18nProvider loads core sections initially, requests other sections or keys as needed, and merges the configured fallback language beneath the active language.
Select the helper that matches the meaning
Use component helpers for component-owned words and resource/field/operation helpers for business interfaces. Register shared enums through registerCommonEnum so recurring values have one named vocabulary; field-specific overrides remain a separate choice.
A custom component must request and render its labels just like a preset. Avoid deriving a user-facing label from an identifier: it loses the authored meaning and cannot replace translation. A missing translation should be corrected in the owning language bundle and generation inputs, not patched by a second string in the screen.