Skip to content

Localization

QUIQQER packages use locale.xml for translated text in PHP, JavaScript, templates, package metadata, permissions, console tools, mail texts, and backend interfaces.

Translations are grouped by package. A package usually uses its Composer package name as the locale group, for example quiqqer/bricks.

Declare Translations

Create locale.xml in the package root.

xml
<?xml version="1.0" encoding="UTF-8"?>
<locales>
    <groups name="vendor/package" datatype="php,js">
        <locale name="package.title">
            <de><![CDATA[Pakettitel]]></de>
            <en><![CDATA[Package title]]></en>
        </locale>
    </groups>
</locales>

Use CDATA for translation text. This avoids XML escaping problems when the translation contains punctuation, placeholders, or markup.

Locale Groups

Use one group per package and data target.

xml
<groups name="quiqqer/bricks" datatype="php,js">
    <locale name="package.title">
        <de><![CDATA[QUIQQER - Baustein Modul / Bricks]]></de>
        <en><![CDATA[QUIQQER - Bricks Module]]></en>
    </locale>
</groups>

The datatype attribute controls where translations are available:

ValueUse
phpPHP/runtime translations.
jsJavaScript translations.
php,jsTranslations needed in both PHP and JavaScript.

Choose the narrowest target that fits the usage. Backend JavaScript labels need js or php,js; server-side exceptions and mail texts can stay PHP-only.

Naming Translation Keys

Use descriptive names that match the feature area.

Common patterns:

  • package.title
  • package.description
  • permission.vendor.package.action
  • exception.feature.reason
  • message.feature.result
  • console.ToolName.desc
  • console.ToolName.help.argumentName

Examples:

xml
<locale name="permission.quiqqer.bricks.create">
    <de><![CDATA[Darf Bausteine erstellen.]]></de>
    <en><![CDATA[Can create blocks.]]></en>
</locale>

<locale name="brick.content.title">
    <de><![CDATA[Bausteine: Inhalt]]></de>
    <en><![CDATA[Bricks: Content]]></en>
</locale>

Placeholders

Translations can contain placeholders in square brackets. Pass replacement values when reading the translation.

xml
<locale name="message.brick.saved">
    <de><![CDATA[Baustein [brickId] wurde gespeichert.]]></de>
    <en><![CDATA[Brick [brickId] was saved.]]></en>
</locale>
php
$message = QUI::getLocale()->get('vendor/package', 'message.brick.saved', [
    'brickId' => $brickId
]);

HTML Text

Use html="true" when a translation intentionally contains HTML.

xml
<locale name="message.address.invalid" html="true">
    <de><![CDATA[Bitte füllen Sie <strong>[field]</strong> aus.]]></de>
    <en><![CDATA[Please fill in <strong>[field]</strong>.]]></en>
</locale>

Only use HTML translations where the rendering context expects HTML. Do not use HTML translations for plain CLI output, log messages, or attributes.

Read Translations In PHP

Use QUI::getLocale()->get() for the current runtime language.

php
$title = QUI::getLocale()->get('vendor/package', 'package.title');

Pass placeholders as the third argument:

php
$text = QUI::getLocale()->get('vendor/package', 'message.brick.saved', [
    'brickId' => $brickId
]);

Use getByLang() when code needs translations for a specific language, for example when creating default records for all available languages.

php
$title = QUI::getLocale()->getByLang($language, 'vendor/package', 'package.title');

Read Translations In JavaScript

Use the Locale module in browser code.

js
require(['Locale'], function (Locale) {
    const title = Locale.get('vendor/package', 'package.title');
});

Pass replacements as an object:

js
Locale.get('vendor/package', 'message.brick.saved', {
    brickId: brickId
});

Use Translations In XML

Package metadata can reference locale entries instead of hard-coding text.

xml
<title>
    <locale group="vendor/package" var="package.title"/>
</title>

This pattern is common in package.xml for package titles and descriptions.

Use Translations In Templates

Smarty templates can use the locale function.

smarty
{locale group="vendor/package" var="package.title"}

Practical Checklist

Before adding translations:

  • Use the package name as locale group.
  • Keep keys descriptive and grouped by feature area.
  • Use php, js, or php,js based on actual usage.
  • Add all languages supported by the package.
  • Use placeholders instead of concatenating translated sentences.
  • Mark HTML translations with html="true" only when HTML is intended.
  • Reuse the same locale keys in PHP, JavaScript, XML, and templates where they describe the same text.

Released under GPL-3.0-or-later.