Skip to the content
Documentation
Help Start
Reading in:
  • German: 9,059 of 9,059 pages
About the help in other languages
All help pages

Tutorial: internationalize a theme

Step by step, make every text of a theme translatable: i18n in templates with a context, placeholders, a translation.ts per language in the extension, TranslationExtensions, locale-aware dates and numbers, right-to-left…

Download as PDF

Address: https://doc.exponential.earth/exphelp/viewer/help/designers/theme-design/tutorial-internationalize-a-theme.md

On this page

Tutorial: internationalize a theme

This tutorial is for designers who want their theme in more than one language. You will make every visible text of the design translatable and ship a German translation. Allow one to two hours for a small theme.

Contents

  1. Step 1: every text through i18n
  2. Step 2: placeholders, not concatenation
  3. Step 3: the translation file
  4. Step 4: tell the siteaccess to read it
  5. Step 5: dates, numbers and direction
  6. Step 6: caches and checks

Step 1: every text through i18n

Every text a template prints goes through the i18n operator with a context, a name that groups the texts of one area. Use design/<your theme>/<area>:

<a class="skip-link" href="#main">{'Skip to main content'|i18n( 'design/mytheme/pagelayout' )}</a>
<button type="button">{'Menu'|i18n( 'design/mytheme/pagelayout' )}</button>

Also attribute values (title, aria-label, alt of design images, placeholder): wash them when they go into an attribute, |i18n( ... )|wash. See The i18n operator.

Step 2: placeholders, not concatenation

Word order differs between languages. Put variable parts into the sentence as placeholders:

{'Page %current of %total'|i18n( 'design/mytheme/navigator',, hash( '%current', $page, '%total', $pages ) )}

The second parameter (empty here) is a comment for translators.

Step 3: the translation file

extension/mytheme/translations/ger-DE/translation.ts:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="ger-DE" sourcelanguage="en">
<context>
    <name>design/mytheme/pagelayout</name>
    <message>
        <source>Skip to main content</source>
        <translation>Zum Inhalt springen</translation>
    </message>
    <message>
        <source>Menu</source>
        <translation>Menü</translation>
    </message>
</context>
<context>
    <name>design/mytheme/navigator</name>
    <message>
        <source>Page %current of %total</source>
        <translation>Seite %current von %total</translation>
    </message>
</context>
</TS>

The starter theme's translations/ger-DE/translation.ts has exactly this form. The source must match the template text character for character. A text without a translation is shown in English.

Step 4: tell the siteaccess to read it

The kernel reads share/translations/ and the extensions listed in site.ini [RegionalSettings] TranslationExtensions[]. In the extension's siteaccess settings (as the media and starter themes do):

# extension/mytheme/settings/siteaccess/<siteaccess>/site.ini.append.php
[RegionalSettings]
TranslationExtensions[]=mytheme

The siteaccess's [RegionalSettings] Locale (for example ger-DE) chooses the language.

Step 5: dates, numbers and direction

  • Dates and numbers through l10n: {$date|l10n( 'shortdate' )}, {$amount|l10n( 'number' )} (Dates, numbers and l10n).
  • lang and dir on <html> from $site (Right-to-left designs).
  • Leave room: German and French texts are often a third longer than English. Buttons and menus must wrap or grow.

Step 6: caches and checks

php bin/php/ezcache.php --clear-id=translation
./console exp:ezchecktranslation ger-DE    # statistics for one translation
  • To do: Open every page type in each language: no English left in the design's own texts.
  • To do: Long translations do not break buttons or menus at 375 px.
  • To do: The translation.ts file is valid XML (xmllint --noout).

Become an Exponential Partner

Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.

Something wrong on this page? Report an error

Documentation license

This documentation is free documentation, licensed under the GNU Free Documentation License 1.3 or later.

Exponential Copyright © 1998-2026 Exponential Foundation and 7x