11: Translations
Phlo uses the lang resource for multilingual view text and translation. In views, you write static text preferably with the compact language shorthand. You write source text in your own language; the examples below use Dutch (nl) as the source language.
11.1: View shorthand
The standard form for static translatable text in a view is:
view:
<p>{nl: Hallo wereld}</p>
The language code before the colon is the source language of the text. If %app->lang is the same language, the text is shown as is. If the active language differs, %lang uses the translation cache and schedules missing translations asynchronously.
The shorthand is for static text only. Everything between the colon and the closing brace becomes a single string argument: {nl: Hallo wereld} compiles to {{ nl('Hallo wereld') }}, so there is no placeholder or argument syntax inside it.
For dynamic values, call the nl() / en() function in an expression instead. These take sprintf-style arguments:
view($name):
<p>{{ nl('Hallo %s', $name) }}</p>
The %s lives in the translated source string (so the cache key stays stable), and the argument is substituted after translation. Use the shorthand for static text and the function when you need to interpolate.
11.2: Helpers in code
The current lang resource provides global helper functions for Dutch and English:
method title => nl('Welkom')
method intro => en('Build compact full-stack apps')
These helpers are useful in methods, props or controller code. In views, the shorthand usually stays clearer:
view:
<h1>{nl: Welkom}</h1>
<p>{en: Build compact full-stack apps}</p>11.3: Active language
The active language lives on %app->lang. A route can set it before the view is rendered:
route both GET $lang:nl,en=nl guide {
%app->lang = $lang
view($this)
}
In links you can use %lang as an object value to display or process the current language.
11.4: Translation cache
Translations are loaded per language from langs/ via %INI(%app->lang, langs). Missing entries are translated asynchronously based on their hash and read from the cache later.
The core methods are:
%lang->translation('nl', 'Hallo wereld')
%lang->translate('nl', 'en', 'Hallo wereld')
Use translation() for normal app rendering with caching and async backfill. Use translate() only when you deliberately want to perform a single direct translation.
11.5: Translation instructions
The lang resource feeds an AI translator, and you can steer it. The instructions property is extra context the translator receives with every translation: your domain, your terminology, and rules about what must stay verbatim. An app injects it with a build mod:
prop %lang.instructions = 'Documentation for the Phlo language. Keep keywords like route, view and prop in English. Keep common English technical terms (best practices, deployment, release) untranslated where that reads naturally, and prefer natural phrasing over forced, over-literal translation.'
Without instructions the translator works from the text alone. Use them to keep proper names and keywords intact and to avoid stilted translations of terms that are already common in the target language. The default is void. The same instructions also reach markdown documentation translated through the docs machinery, which reads %lang->instructions.
11.6: Best practices
- Use
{nl: ...}and{en: ...}in views for static text; usenl()/en()for anything with arguments. - Use
nl()anden()in PHP/Phlo code outside views. - Set
%app->langearly, in the route or a central controller. - Keep source text stable; changed text gets a new hash.
- Set
%lang.instructionsso the translator keeps your terminology and avoids forced translations. - Document only language helpers that actually exist as resource functions.