Internationalization & Localization: Text Files, Overrides, Translation Pipelines, and Runtime Interpolation
This article extends the basic Qbix Text & View architecture by introducing a cohesive, production-ready internationalization system. Unlike the ad-hoc approaches used in many ecosystems — Linux .po files, Apple .strings, iOS/macOS .lproj bundles — the Qbix Platform provides a structured, layered, override-friendly, machine-translatable, and plugin-aware model for managing all text across your application.
All of this is expressed using simple JSON trees, combined by the same Q_Tree system that powers Config, Streams, Views, and Permissions.
Separation of Text by Plugin and Domain
Each plugin ships its own text bundle:
Users/text/email/en.json
Users/text/content/en.json
Communities/text/content/en.json
MyApp/text/content/en.json
This structure allows:
- modular internationalization
- plugin reuse across multiple apps
- translation sharing across apps
- app-level overrides without forking plugins
- shipping machine translations immediately, fixing them later
Each JSON file is simply a tree of keys mapping to language strings, which may contain placeholders.
Placeholders & Safe Interpolation
Strings support positional and named placeholders:
"ThankForPayment": "Thank you for your payment to {{call 'publisher.displayName'}}"
"SeeYou": "See you at {{1}}!"
"ResetLink": "Click <a href='{{2}}'>here</a> to reset your passphrase."
Placeholders can refer to:
-
{{0}},{{1}},{{2}}… positional parameters -
{{foo.bar.baz}}objects inside$fields, usingQ::getObject -
{{call 'publisher.displayName'}}custom code callbacks
Google-Translate-Safe Placeholders
The translation pipeline rewrites placeholders temporarily, preventing Google Translate from mangling them. For example:
{{1}} → __QBIX_PLACEHOLDER_1__
After translation, placeholders are restored.
This makes automated translation safe.
The Translation Pipeline (translate.php)
The Qbix CLI includes a translation utility that:
- identifies all text bundles across core, plugins, and your app
- maintains caches of previous translations
- does not retranslate files unless explicitly asked
- handles batch export/import
- preserves all placeholders
- provides targeted translation of specific paths
Key Capabilities
1. First-Pass Machine Translation
./translate.php --app
./translate.php --plugin Users
This produces all missing locales using Google Translate (or any configured provider).
2. Retain Manual Translator Work
By default, translations are only generated once.
To redo them:
./translate.php --retranslate Users/text/email
./translate.php --retranslate foo\/bar/baz
Slash-escaping lets you precisely target subtrees.
3. Incremental Translation Workflow
Perfect for:
- shipping apps quickly with machine translations
- letting real translators “clean up” later
- reducing cost by translating only updated/added strings
- adding new locales on demand
Runtime Loading of Text
All strings are loaded through Q_Text::get() and rendered via Q::interpolate() or Q::text().
Q::interpolate($expression, $fields)
-
Accepts:
-
a raw string
-
or
[textName, pathArray]tuple, which will:- load it via
Q_Text::get() -
apply overrides from config (
Q/text/override)
- load it via
-
-
Replaces placeholders using either:
- positional parameters
- or associative structures, even with dotted paths
-
Supports nested objects using
Q::getObject()
Q::text($expression)
Same as Q::interpolate, but also applies HTML escaping.
Used for safely inserting text into views.
Overriding Text (Two Mechanisms)
Qbix supports overrides at multiple levels: core → plugins → your app.
1. In-File Overrides Using @override
Your app’s text file can contain:
"@override": {
"Users/content": {
"login": {
"prompt": "Let friends recognize you:"
}
},
"Communities/content": {
"events": {
"MakeReservation": "Request to Join"
}
}
}
During translation:
- overrides generate proper per-language files
- overrides cascade into all languages
- no need to edit plugin files
Internally uses Q_Tree->merge().
Works both server-side and client-side.
Path-Based Overrides via Config
The second override mechanism works via:
"Q": {
"text": {
"Hebrews": {
"dashboard.php": ["Hebrews/content"],
"content": {
"activate.php": ["Users/content", "Hebrews/content"],
"*": ["Hebrews/content"]
},
"email": {
"*": ["Hebrews/email"]
}
},
"Communities": {
"controls": {
"eventReservation.php": ["Communities/content", "Hebrews/content"]
}
}
}
}
Whenever Qbix renders a view (PHP, Handlebars, or custom):
Q::view($template, $fields)
The system:
- Looks up the template in the
Q/textmapping. - Loads additional text bundles.
- Merges all relevant text trees.
- Makes them available during that view render.
This allows:
- view-specific text overrides
- entire locale-specific content packs
- community-specific language variants
- theming and rebranding per domain/app
Client-Side Text Loading
The client mirrors the server model.
Calling:
Q.Text.get("MyApp/content")
fetches text bundles from backend, merges overrides automatically, and makes them available for client-side rendering and interpolation.
This guarantees:
- consistent text across PHP, JS, Handlebars
- single source of truth
- ability to override text without editing templates
- uniform behavior across plugins
Why This System Works Better Than Existing Standards
Most systems use one of the following:
-
GNU gettext (
.po) — brittle placeholders, difficult merging -
Apple
.strings— flat key–value, no hierarchy, hard to organize - JSON catalogs in JS frameworks — no merging, no plugin inheritance
- Ad-hoc YAML or PHP arrays — inconsistent, hard to machine translate
Qbix solves all of these by providing:
- structured trees (nested JSON)
- built-in merging and overrides
- plugin-aware hierarchy
- app-level layer on top
- safe placeholder processing
- integration with views
- client/server uniformity
- automated translation pipeline
- machine-translation bootstrap with human refinement
It is the first system designed from the ground up for:
Modular apps, plugin ecosystems, and multi-tenant deployments.
Example Use Cases
1. Apps with 15–50 Languages
Ship instantly with machine translations, hire translators only where adoption takes off.
2. Multi-Tenant Communities
Each community can introduce language overrides that reflect its culture or terminology.
3. Plugin Marketplaces
Third-party plugin authors ship translations for their own components without interfering with apps.
4. Rebranding & White-Labeling
Domains can override text for branding without touching plugin or app code.
5. Advanced Dynamic Views
Templates automatically load the text bundles they need, based on config.
Bringing It All Together
By combining:
- text files per plugin
- safe placeholder interpolation
- a layered override model
- a flexible translation pipeline
- config-based text injection
- unified client/server loading
…the Qbix Platform provides a robust internationalization architecture far beyond traditional systems. It solves the real-world needs of:
- large apps
- modular plugins
- multi-community systems
- machine translation bootstrapping
- human refinement workflows
- deeply nested views & UI components
Your app can ship globally from day one — while keeping translation costs low, maintainability high, and overrides simple.