Інтэрнацыяналізацыя ў
Zend Framework 2

Ben Scholzen
Архітэктар праграмнага забеспячэння і кансультант

About myself

Ben Scholzen is …

  • Freelancing Software Architect & Consultant
  • Author and maintainer of core components in Zend Framework
  • Open Source Contributor

Getting terms right

  • Internationalization (i18n):
    Designing your application to be able to be adapted to various languages and regions.
  • Localization (L10n):
    Adding information for a specific locale or region.
  • Locale:
    A short identifier which can include language, region and additionally a character encoding.
  • Character set:
    A subset of characters (Unicode, Latin, …).
  • Character encoding:
    Specification about how to encode characters in memory (UTF-8, ASCII, …).
  • Collation:
    Comparision method for characters.

How a locale is build up

de-CH.utf-8 (old style: de_CH.utf-8)

  • de: the language of the locale (German)
  • CH: the region of the locale (Switzerland)
  • utf-8: the encoding of the locale

What Zend Framework 2 provides

  • A translator with integration into various components
  • View helpers for formatting numbers, currencies and dates
  • Validators for numbers, post codes and alphanumeric strings
  • Filters for numbers and alphanumeric strings

The base: ext/intl

  • All i18n components make use of the intl extension
  • Default locale can be set via \Locale::setDefault()
  • If no locale is set, the system default is used

The basics of translations

Making your information available for everyone

How the translator works

  • Designed to work similar to gettext
  • Handles multiple text domains per locale
  • Provides functionally to handle plurals

Text domains

  • Each provided by an individual source (e.g. a file)
  • Contain a mapping of message IDs and their translation
  • Provide plural rules for ordinal numbers

Loaders provided with the Translator

  • Gettex
  • PHP arrays
  • More to come (TMX, XLIFF, …)

Loading methods for translations

  • Individual files per text domain and locale
  • File patterns per text domain
  • Remote sources per text domain

How plural definitions work

nplurals=5; plural=n==1 ? 0 : n==2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4
  • nplurals defines the number of plural forms available in the language
  • plural defines how to find out which plural form to use
    • Syntax is the same C
    • Expression is parsed internally, not used via eval()
    • Available variables: n (number to resolve)
    • Available operators: +, -, *, /, %, &&, ||, !, ?: <, >, <=, >=, !=, ==
    • Parantheses also work
    • Boolean operations return 1 or 0

A simple translation file

return array(
    '' => array(
        'plural_forms' => 'nplurals=2; plural=n!=1'
    'bacon' => 'speck',
    '%d house' => array(
        'Ein Haus',
        '%d Häuser'

Setting up your translator

use Zend\I18n\Translator\Translator;

$translator = new Translator::factory(array(
    'locale' => 'de_DE',
    'files' => array(
            'type' => 'phparray',
            'filename' => 'languages/de-DE.php'

Translating your strings

Simple string:

echo $translator->translate('bacon'); // speck

String with plural form:

$houses = 5;

    $translator->translatePlural('%d house', '%d houses', $houses),
); // 5 Häuser

Translations in your views

<?php echo $this->translate('bacon'); ?>
<?php printf(
    $this->translatePlural('%d house', '%d houses', $number),
); ?>

Switchting your text domain

Switch text domain for a single call

<?php echo $this->translate('bacon', 'module-b'); ?>

Switch text domain for all following calls

<?php $this->plugin('translate')->setTranslatorTextDomain('module-b'); ?>

Switchting the locale for the translation

<?php echo $this->translate('bacon', null, 'fr-FR'); ?>

Handling many translations within a module

use Zend\I18n\Translator\Translator;

$translator = new Translator::factory(array(
    'locale' => 'de_DE',
    'patterns' => array(
            'type'     => 'phparray',
            'base_dir' => 'translations',
            'pattern'  => '%s.php'

Handlings dates

Working with dates everyone can understand

Many date formats

Dates in Zend Framework 2

  • Date handling via \DateTime
  • Formatting and parsing through \IntlDateFormatter
  • View helper wrapping around \IntlDateFormatter

Setting a locale

  • By default, the standard Locale in \Locale is used
  • Alternatively, a specific locale can be passed as last parameter to the date format view helper.

Setting a timezone

  • By default, the standard timezone of the system is used

How to format dates in your views

<?php echo $this->dateFormat(
    $dateType, // Optional, default: NONE
    $timeType, // Optional, default: NONE
    $locale    // Optional
); ?>

What the view helper takes

  • Date may be a unix timestamp (an integer), a \DateTime object or an array
  • Both the date and time format may be one of the following constants:
    • \IntlDateFormatter::NONE: Do not include this element
    • \IntlDateFormatter::FULL: Completely specified style (Tuesday, April 12, 1952 AD or 3:30:42pm PST)
    • \IntlDateFormatter::LONG: Long style (January 12, 1952 or 3:30:32pm)
    • \IntlDateFormatter::MEDIUM: Medium style (Jan 12, 1952)
    • \IntlDateFormatter::SHORT: Most abbreviated style, only essential data (12/13/52 or 3:30pm)

Using \IntlDateFormatter directly

$formatter = new \IntlDateFormatter(
    /*, $timezone*/

$formattedDate = $formatter->format($date);

Parsing localized dates

  • Parsing is always done via intl extension
  • Parse method returns a unix timestamp
$formatter = new \IntlDateFormatter(/* … */);
$timestamp = $formatter->parse($formattedDate);
$date      = new \DateTime('@' . $timestamp);

Numbers and currencies

Keeping data readable (and writable) for anyone

Helpers in Zend Framework

  • Date handling via \DateTime
  • Formatting and parsing through \NumberFormatter
  • View helpers and filters wrapping around \NumberFormatter

Setting a locale

  • By default, the standard Locale in \Locale is used
  • Alternatively, a specific locale can be passed as last parameter to the number and currency format view helpers.

How to format numbers and currencies in your views

<?php echo $this->numberFormat(
    $formatStyle, // Optional, default: DECIMAL
    $formatType,  // Optional, default: TYPE_DEFAULT
    $locale       // Optional
); ?>
<?php echo $this->currencyFormat(
    $currencyCode, // Optional, default: not set
    $showDecimals, // Optional, default: true
    $locale        // Optional
); ?>

Format types and format styles for number formatting

Setting defaults for the number formatter


Setting defaults for the currency formatter


Using \NumberFormatter directly

$formatter = new \NumberFormatter(

$formattedNumber = $formatter->format($number);

Parsing localized numbers

  • Parsing is either done via intl extension or filter
$formatter = new \NumberFormatter(/* … */);
$number    = $formatter->parse($formattedNumber);
$filter = new \Zend\I18n\Filter\NumberFormat($locale, $type, $style);
$number = $filter->filter($formattedNumber);

The Intl extension

More cool features


  • Provides locale dependent comparision methods
  • Allows sorting strings based on collation


  • Normalizes strings to a specific base form


  • Formats data into messages
  • Similar to printf, but locale based


  • Retrieves CLDR information about a locale


  • Checks if a string containts confusable or suspicious characters


  • Transliterates stings from one encoding to another


Whatever you wanna know.