Internationalization

Internationalization

Celena's interface and content are translated through a simple JSON-based localization mechanism.

Language detection

The Celena\Core\I18n\Locale class determines the active language in this priority order:

  1. Query parameter ?lang=en (if the language is in the available list);
  2. cookie celena_lang;
  3. the browser's Accept-Language header;
  4. the default language (option app.locale, e.g. en).

The list of available languages is built automatically from the core/languages/*.json files. Currently these are ru, en, uk, pl, ro.

$active = $locale->detect($request);  // 'en' | 'ru' | 'uk' | …
$locale->remember($active);           // remember in a cookie for a year

Translation files

Strings are stored as JSON and loaded automatically from three places:

core/languages/{lang}.json
modules/<Module>/languages/{lang}.json
plugins/<slug>/languages/{lang}.json

The format is a nested object; keys are flattened with dots:

{
  "landing": {
    "nav": { "services": "Services", "contact": "Contact" }
  }
}

→ available as the key landing.nav.services.

Usage

In a template:

{lang key="landing.nav.services"}
{lang key="greeting" name="{user.name}"}   <!-- :name substitution -->

In PHP:

$t = app(\Celena\Core\I18n\Translator::class);
echo $t->translate('landing.nav.services');
echo $t->translate('greeting', ['name' => 'Anna']);

Fallback

If a key is missing in the current language, it's taken from the fallback language (en); if it's missing there too, the key itself is returned. So an untranslated string never "breaks" the page.

SEO for languages

The template.globals hook sets two variables for each page:

  • {locale} — the current language for the <html lang> attribute;
  • {canonical_self} — the self-referencing canonical: a clean URL for the default language, ?lang=xx for the others.

Alternative language versions are declared via <link rel="alternate" hreflang="…">. A template can disable the default hreflang block by passing no_hreflang="1" and output its own (this is what the documentation section does, limiting the list to three languages).

How to add a language

  1. Create core/languages/<code>.json (e.g. de.json) — the language appears in the available list automatically.
  2. Add the same file in the modules/plugins where translations are needed.
  3. Optionally add an entry to the language switcher in the theme header.

Translating the interface from the admin

The Translations module (the Translations section in the panel) lets you edit UI strings without hand-editing JSON.