Dictionary
The dictionary is the shared catalog of per-column metadata. One file (config/dictionary.toml) defines:
- Entries — per-column metadata: label, format, rule, per-language label translations.
- Enums — named enumerations with translatable labels.
- Lookups — references to a query that resolves a
code → label.
A query's columns hint references an entry; the SQL connector resolves the label / format / rule at result time in the request's language. The React grid then renders the localized label, ✓ / ✗ for booleans, the enum label, or — via services/lookups.useLookupBatch — the lookup label after a one-shot per-session fetch.
At a glance
Entries
Per-column metadata. Each entry pins:
| Field | Description |
|---|---|
label | Default English label. |
l | Per-language labels ({ fr = "...", de = "..." }). |
format | UI-interpreted format: date, datetime, amount, percent, string, number, boolean, …. |
rules | Display rule — BOOLEAN / ENUM / LOOKUP (or one of the form-layer rules — see below). |
rules_values / default | Optional rule-specific configuration (e.g. boolean true_value, default value on form add). |
[entries.USER_STATUS]
label = "Status"
format = "string"
rules = "ENUM"
[entries.USER_STATUS.l]
fr = "Statut"
de = "Status"
An entry may sit at the top level (shared across every connector) or under [connectors.<conn>.entries.<key>] (specific to one connector — useful when the same column name carries a different meaning in different sources). Resolution checks the per-connector entry first, then falls back to the shared top-level one.
A column hint dd = "USER_STATUS" lifts the entry onto the query column. dd = "" opts out — the column is left untranslated. A label on the column itself overrides the dictionary's.
Enums
A static code → label table with translations.
[enums.USER_STATUS]
label = "User status"
values = [
{ value = "Y", label = "Active", l = { fr = "Actif" } },
{ value = "N", label = "Inactive", l = { fr = "Inactif" } },
]
Resolved at result time. The cell renders the active language's label; the per-column filter offers the multi-select picker over the same values; the form widget is a SearchSelect.
Lookups
A reference to a query whose value / label columns resolve the cell.
[lookups.CITY]
description = "Cities"
connector = "myapp" # falls back to the calling connector when omitted
query = "cities_get"
value = "ID"
label = "NAME"
group = "REGION" # optional secondary grouping
A column with rules = "LOOKUP" pointing at a lookup id is resolved by:
- the grid: one shared
useLookupBatchfetch per session — cell renderscode — label; - the form widget: a
SearchSelectwithuseLookupTables, narrowed at call time bylookup_param_bindsif any.
Display rules vs form-layer rules
| Rule | Owner | Effect |
|---|---|---|
BOOLEAN | Display | Cell renders ✓ / ✗. rules_values.true_value declares which raw value counts as true (default "Y"). |
ENUM | Display | Cell renders the localized label. Column filter and form widget pull the value list from [enums.<id>]. |
LOOKUP | Display | Cell renders code — label from [lookups.<id>]. Form widget narrows by lookup_param_binds. |
SEQUENCE | Form | Pulls the next sequence value on add. |
SYSDATE / CURRENT_DATE | Form | Seeds today on add. |
LOGIN | Form | Seeds the caller's username on add. |
PASSWORD | Form | Marks the input as a password and triggers crypto handling on save. |
Display rules ship on Column.rule so the grid can render without a second round-trip. Form-layer rules are applied by ScreenDialog when the modal form opens — they wait for Screens.
i18n
Every API request carries X-Liberty-Lang (the current react-i18next language). The SQL connector resolves the label and the rule in that language; the React grid renders labels already localized. A missing translation falls back to the label (English).
The dictionary itself declares its default language:
default_language = "en"
Tips & best practices
- Define entries shared across connectors at the top level. A
USER_STATUSthat means the same thing everywhere belongs under[entries.USER_STATUS]once. Reach for the per-connector override only when the meaning differs. - Keep
labelshort. It is what the grid header shows. Long titles belong indescriptionon the query, which surfaces as the TableView's panel title. rules = "ENUM"should not be aLOOKUPin disguise. When the value list is small and known at config time, useENUM. When the list comes from a table that changes at runtime, useLOOKUP. The cell renders the same — the input editor changes (static vs. live).- A column with no
ddstill works. The grid renders the raw cursor type. Useddwhen there is a real reason: a localized label, a boolean / enum / lookup rule, a non-default format.