The localization system in Kodall provides a robust, dynamic, and multi-tenant translation mechanism for low-code applications. Instead of hardcoding user-facing strings (like titles, column headers, actions, inputs, menus, or dashboard items) directly in configurations, Kodall references localization keys. These keys are resolved to translated text at runtime based on the user's active locale.
ui_i18n)At the core of the localization system is the ui_i18n entity. It stores the mapping between localization labels (keys) and their corresponding translations in different languages.
| Property | Type | Description |
|---|---|---|
key | integer | Primary key of the translation record. |
label | string | The unique identifier/key used in views (e.g., system.ui.view_edit.title_new or entity.product.ui.title). |
value | string | The default/fallback value used when no locale-specific translation is found. |
value_en | string | English translation value. |
value_ro | string | Romanian translation value. |
value_de | string | German translation value. |
id_organization | integer (FK) | Optional. Restricts the translation override to a specific organization. |
id_business_unit | integer (FK) | Optional. Restricts the translation override to a specific business unit. |
id_user | integer (FK) | Optional. Restricts the translation override to a specific user. |
date_created | datetime | Timestamp of record creation. |
date_updated | datetime | Timestamp of last record update. |
When configuring user interface elements, user-facing name or title fields are populated with localization tokens instead of literal strings.
A localization token follows the format:
${i18n.your_label_here}
A developer or a system workflow registers a key in the ui_i18n database table. For example, registering entity.product.ui.title with the default value Product.
The component (view, column, action, menu, or input) is saved with the token ${i18n.entity.product.ui.title} as its title.
When a user requests the component, the frontend application detects the ${i18n....} format. It looks up the current user's active locale (e.g., German de) and queries the ui_i18n table for that label, resolving it to the value in value_de. If no translation exists, it falls back to the default value.
When the Create UI Entity action is run on a database entity, it automatically configures all localization rules and records for the generated views. Instead of prompting for manual translation setup, the action reads the entity structure and registers the keys programmatically in the background.
For every generated UI element, the action:
id_product_category or product_category to a sentence-case display name).ui_i18n table for the corresponding key. If the key does not exist, it inserts a new ui_i18n record.${i18n.entity.product.ui.title}) in its database fields.The system organizes localization keys into a strict hierarchical taxonomy under two root namespaces: entity and system.
entity:
[entityName]:
ui:
title # General UI title of the entity
property:
[propertyName] # Titles for fields, columns, and relationships
system:
ui:
view_edit:
title_new # General edit view prefix for creating a record (e.g. "Add")
title_edit # General edit view prefix for modifying a record (e.g. "Edit")
[specific-edit] # Other edit-specific actions or UI prompts
view_search:
[specific-search] # Search-specific grid controls or prompts
This hierarchical convention was chosen for several critical architectural reasons:
entity and system prevents naming collisions. System labels (such as general actions like "Add", "Edit", or "Search") are isolated from entity schema property names, allowing each entity to define fields independently."entity." + entityName + ".ui.title""entity." + entityName + ".property." + propertyName${i18n.system.ui.view_edit.title_new} ${i18n.entity.product.ui.title}."Add Product" in English or "Adăugare Produs" in Romanian. The system doesn't need to define separate full-sentence labels for every entity.entity.invoice.property.).Dynamic translation tokens are utilized across every layer of the user interface:
${i18n.entity.[entityName].ui.title}.${i18n.entity.[entityName].property.[propertyName]}.ui_action) or detail forms (ui_entity_action) use translation keys for their label text (e.g., ui_action.name = "${i18n.action.invoice.send}").ui_action_item.title = "${i18n.action.invoice.send.email_address}").menu_node) and individual sub-items (menu_node_item) reference localization labels for their display names (e.g., ${i18n.menu.sales}).${i18n.menu.item.inventory}) in their string responses, allowing the client interface to resolve and translate the text on the fly.ui_i18n database table, meaning translation text can be modified instantly by administrators on a live system without changing configurations, files, or executing build pipelines.id_organization, id_business_unit, and id_user keys, which allow translations to be scoped:
entity.account.ui.title translates to Account.Patient.Search Views
The search view displays data in a table with functions for adding, editing, deleting and filtering.
Organizations
The Organizations allows to divide all the users in as many as need categories. Through this, all the rows that are created in the platform are created with the current user id, user business unit and user organization as well. Using organizations allows us to set a specific security on it.