5. Language and reading direction #
← Themes · Contents · Cross-cutting features →
The components carry interface labels of their own: context menus, dialog buttons, dockable panel actions, toolbar tooltips… Those strings are translated by the library, without you having to supply them.
5.1 Choosing the language #
The language is global to the process. Set it once in the application object, before the first window opens:
// open event of the application object
PBT_SetLanguage("fr")
| Code | Language |
|---|---|
en | English (default) |
fr | French |
de | German |
it | Italian |
es | Spanish |
pt | Portuguese |
The dictionary is injected before the first render of each component: no English label flashes before the translation appears. Switching on the fly is possible — every open component is relabeled immediately.
// Language switch from a menu in the application
PBT_SetLanguage("de")
A language cannot be set component by component: an application displays one language at a time. This is a deliberate choice (interface consistency), unlike the theme, which can be overridden locally.
5.2 Adapting a label: of_set_translation #
You are not locked into the dictionaries we ship. of_set_translation(key, text) overrides an interface string, taking priority over the language dictionary:
// Business vocabulary: say "panes" rather than "panels"
uo_dock.of_set_translation("dock.float", "Detach the pane")
uo_dock.of_set_translation("dock.autohide", "Hide the pane")
uo_dock.of_set_translation("dock.closePanel", "Close the pane")
Two use cases:
- Adapting the vocabulary to your application's business domain ("panes" rather than "panels", "branches" rather than "groups").
- Serving a language we do not ship: set your own translations key by key, in whatever language you need, from your own translation table.
// Feed a custom language from your own translation repository
uo_dock.of_set_translation("dock.float", of_traduire("DOCK_DETACHER"))
uo_dock.of_set_translation("dock.show", of_traduire("DOCK_AFFICHER"))
The override is set on the instance; it is cancelled by of_reset().
Key families #
Keys follow the <domain>.<name> pattern. The main families:
| Prefix | Covers |
|---|---|
dock.* | Dockable panels: float, hide, close |
toolbar.* | Toolbar: move the bar, overflow |
tab.* | Tabs: close |
tile.* · tilesbox.* | Tiles: sizes, "no tile" message |
ribbon.* | Ribbon: collapse, expand |
mb.* | Message box: standard buttons, show / hide the password |
webbrowser.* | Web browser: context menu (back, forward, reload) |
picture.* | Picture: pan hint |
sb.* | Status bar: its name for screen readers |
color.* | Color picker: OK / Cancel |
💡 To find the exact key behind a label, open the demo application in English and then in another language: the string that changes is the one from the dictionary. The complete key list ships with the library.
5.3 Reading direction: left-to-right / right-to-left #
For languages written from right to left (Arabic, Hebrew), a single call flips the whole application:
// open event of the application object
PBT_SetFlowDirection("rtl") // "ltr" by default
What this changes in every component, present and future:
- the natural alignment of text and labels;
- the order of columns, tabs and toolbar buttons;
- the side of icons, expand arrows and chevrons;
- the side of scroll bars and side panels;
- the direction of drop-down menus and popups.
// Switch on the fly
PBT_SetFlowDirection("ltr")
Like the theme and the language, the reading direction is injected before the first render: a component created after the switch is born in the right direction.
⚠️ The reading direction only applies to PBToolboxAI components. The native PowerBuilder controls on your windows (edit fields, DataWindows) remain your responsibility.
5.4 Writing RTL-ready code #
Mirroring is automatic for the layout. It cannot be for the values you set yourself: if you hard-code "left", it will be on the left in both reading directions.
That is why every placement property in the library uses logical values rather than physical ones:
| Logical value | In left → right writing | In right → left writing |
|---|---|---|
start | on the left | on the right |
end | on the right | on the left |
They are exposed as constants, to be read on the object you are assigning the value to:
// Text alignment, position of a banner...
uo_titre.is_align = uo_titre.ALIGN_START
uo_onglets.is_position = uo_onglets.POSITION_START
The families involved: ALIGN_START / ALIGN_END (statictext, statusbar, picture), POSITION_START / POSITION_END (tab, dockcontainer), MARQUEE_START / MARQUEE_END (statictext).
The old physical values
"left"and"right"are still accepted everywhere: your existing code keeps working exactly as before. They are simply frozen — they will not flip inrtl.
The two deliberate exceptions #
Some placements have no "start of reading": they stay physical, and that is intentional.
- Toaster — a toast is a system window anchored to a corner of the screen.
POSITION_BOTTOM_RIGHTdesignates a physical corner, not the end of a line of text. - Drawing surfaces — org chart, flow diagram, node graph, image cropping: there you place elements at
x/ycoordinates. A Cartesian plane does not flip with the language; only the labels inside it follow the reading direction.
5.5 Summary #
| Setting | Scope | Where to call it |
|---|---|---|
PBT_SetLanguage (string as_lang) | Whole process | open of the application object |
of_set_translation (string as_clé, string as_texte) | One instance | After the component is created |
PBT_SetFlowDirection (string as_sens) | Whole process | open of the application object |
The three global settings — theme, language and reading direction — are set together, in the same place:
// open event of the application object
PBT_SetLicense(gs_titulaire, gs_cle_licence)
PBT_SetDefaultTheme("fluent-light")
PBT_SetLanguage("fr")
PBT_SetFlowDirection("ltr")
PBT_Warmup()
Open(w_principale)