Skip to content

Localization & Internationalization

Total CMS provides comprehensive support for localizing dates, numbers, currencies, and relative time strings. This guide covers the supported languages and how to use localization features in your Twig templates.

The default locale is configured in Settings > General > Locale. This affects all date, number, and currency formatting throughout your site.

The following languages have full localization support, including translated relative time strings:

LanguageLocale CodeExample Relative Time
Arabicar_SA”منذ شهرين”
Czechcs_CZ”před 2 měsíci”
Danishda_DK”for 2 måneder siden”
Dutchnl_NL”2 maanden geleden”
English (US)en_US”2 months ago”
English (UK)en_GB”2 months ago”
English (Canada)en_CA”2 months ago”
English (Australia)en_AU”2 months ago”
English (Singapore)en_SG”2 months ago”
French (France)fr_FR”il y a 2 mois”
French (Canada)fr_CA”il y a 2 mois”
Germande_DE”vor 2 Monaten”
Hungarianhu_HU”2 hónapja”
Italianit_IT”2 mesi fa”
Japaneseja_JP”2 か月前”
Khmer (Cambodia)km_KH”2 months ago” *
Norwegianno_NO”for 2 måneder siden”
Polishpl_PL”2 miesiące temu”
Portuguese (Brazil)pt_BR”há 2 meses”
Portuguese (Portugal)pt_PT”há 2 meses”
Russianru_RU”2 месяца назад”
Spanish (Spain)es_ES”hace 2 meses”
Spanish (Mexico)es_MX”hace 2 meses”
Turkishtr_TR”2 ay önce”
Ukrainianuk_UA”2 місяці тому”
Vietnamesevi_VN”2 tháng trước”
Chinese (Simplified)zh_CN”2 个月前”

* Khmer has partial support - date/number formatting works but relative time falls back to English.

For sites with multiple languages, you can change the locale dynamically within your templates.

Use cms.locale.set() at the top of your template to change the locale for all subsequent formatting:

{# Set locale based on page language #}
{{ cms.locale.set('de_DE') }}
{# All formatting now uses German #}
{{ post.date|dateRelative }}
{# Output: "vor 2 Monaten" #}
{{ cms.locale.get() }}
{# Output: "de_DE" #}

If your content has a language field, you can set the locale dynamically:

{# Assuming page.locale contains the locale code #}
{{ cms.locale.set(page.locale) }}
<article>
<h1>{{ page.title }}</h1>
<time>{{ page.date|dateRelative }}</time>
</article>

The dateRelative filter displays dates in a human-readable relative format:

{{ post.date|dateRelative }}
{# Output varies by locale: #}
{# en_US: "2 months ago" #}
{# de_DE: "vor 2 Monaten" #}
{# fr_FR: "il y a 2 mois" #}
{# ja_JP: "2 か月前" #}

Use format_date for locale-aware date formatting:

{# Short format #}
{{ post.date|format_date('short') }}
{# en_US: "12/31/25" #}
{# de_DE: "31.12.25" #}
{# Medium format #}
{{ post.date|format_date('medium') }}
{# en_US: "Dec 31, 2025" #}
{# de_DE: "31.12.2025" #}
{# Long format #}
{{ post.date|format_date('long') }}
{# en_US: "December 31, 2025" #}
{# de_DE: "31. Dezember 2025" #}
{# Full format #}
{{ post.date|format_date('full') }}
{# en_US: "Wednesday, December 31, 2025" #}
{# de_DE: "Mittwoch, 31. Dezember 2025" #}

Use format_datetime for both date and time:

{{ post.date|format_datetime('medium', 'short') }}
{# en_US: "Dec 31, 2025, 3:30 PM" #}
{# de_DE: "31.12.2025, 15:30" #}
{{ post.date|format_time('short') }}
{# en_US: "3:30 PM" #}
{# de_DE: "15:30" #}

Numbers are formatted according to locale conventions:

{{ 1234567.89|format_number }}
{# en_US: "1,234,567.89" #}
{# de_DE: "1.234.567,89" #}
{# fr_FR: "1 234 567,89" #}
{{ 0.1525|format_percent_number }}
{# en_US: "15%" #}
{# de_DE: "15 %" #}
{{ 1234567|format_scientific_number }}
{# Output: "1.234567E6" #}
{{ 42|format_spellout_number }}
{# en_US: "forty-two" #}
{# de_DE: "zwei­und­vierzig" #}

Currencies are formatted with proper symbols and decimal placement:

{{ 99.99|format_currency('USD') }}
{# en_US: "$99.99" #}
{# de_DE: "99,99 $" #}
{{ 99.99|format_currency('EUR') }}
{# en_US: "€99.99" #}
{# de_DE: "99,99 €" #}
{{ 99.99|format_currency('JPY') }}
{# ja_JP: "¥100" (no decimals for Yen) #}
{{ 99.99|format_currency('SGD') }}
{# en_SG: "S$99.99" #}
{{ 'US'|country_name }}
{# en_US: "United States" #}
{# de_DE: "Vereinigte Staaten" #}
{# ja_JP: "アメリカ合衆国" #}
{{ 'de'|language_name }}
{# en_US: "German" #}
{# de_DE: "Deutsch" #}
{# fr_FR: "allemand" #}
{{ 'EUR'|currency_name }}
{# en_US: "Euro" #}
{# de_DE: "Euro" #}
{# ja_JP: "ユーロ" #}
{{ 'USD'|currency_symbol }}
{# Output: "$" #}
{{ 'America/New_York'|timezone_name }}
{# en_US: "Eastern Time" #}
{# de_DE: "Nordamerikanische Ostküstenzeit" #}

Here’s a complete example of a multilingual blog post template:

{# Set locale from page content #}
{{ cms.locale.set(post.locale|default('en_US')) }}
<article class="blog-post" lang="{{ post.locale|default('en_US')|slice(0,2) }}">
<header>
<h1>{{ post.title }}</h1>
<div class="meta">
<time datetime="{{ post.date|date('c') }}">
{{ post.date|format_date('long') }}
</time>
<span class="relative-time">
({{ post.date|dateRelative }})
</span>
</div>
</header>
<div class="content">
{{ post.content|raw }}
</div>
{% if post.price %}
<div class="price">
{{ post.price|format_currency(post.currency|default('USD')) }}
</div>
{% endif %}
</article>

Available format options for format_date, format_datetime, and format_time:

OptionDescriptionExample (en_US)
noneNo output-
shortAbbreviated”12/31/25”
mediumStandard”Dec 31, 2025”
longFull month name”December 31, 2025”
fullComplete with weekday”Wednesday, December 31, 2025”