I18n: Internationalization and localization

Internationalization (i18n) is the process of developing products in such a way that they can be localized for languages and cultures easily. Localization (l10n), is the process of adapting applications and text to enable their usability in a particular cultural or linguistic market.

This framework comes with buildin English to Finnish translations:

Human language translations: Using The TranslatorInterface

The TranslatorInterface is the base interface for all human language translation related operations in this framework. I supports both basic and plural Gettext style translation.

The translator itself is initialized without any parameters, as any configuration to it is optional. A translator without any translations will do nothing but return all messages verbatim.

A TranslatorInterface object supports both basic and plural Gettext style translation. It has also a method similar to PHP's native vsprintf() function for both basic and plural translations. Additionally the class contain a method for translating a multidimensional array containing singular translatable message strings (plural form is not supported).

A gettext Translator

A Translator object translates given input by using PHP's build in gettext extension.

The underlying technology used in translation is PHP's gettext extension.

Links:

  • PHP code
    1. <?php
    2.  
    3. namespace Sphp\I18n\Gettext;
    4.  
    5. try {
    6.  
    7.   $translator = new Translator('Sphp.Defaults', 'sphp/locale');
    8.   $translator->setLang('fi_FI');
    9. } catch (\Exception $ex) {
    10.   echo $ex;
    11. }
    12.  
    13.         $translator->vsprintf("Please insert atleast %s of the following characters (%s)", [3, "a, b, c, d, e"]),
    14.         $translator->vsprintf("Please insert atleast %s of the following characters (%s)", [1, "a, b, c"]),
    15.         $translator->vsprintfPlural("%d file. Total size: At least %s", "%d files. Total size: At least %s", 3, [3, "20kB"]));
    16. print_r($translator->translateArray(["open", "close", ["save", "delete", "update"]]));
    17.  
    18.         $translator->getPlural("%d directory", "%d directories", 0),
    19.         $translator->getPlural("%d directory", "%d directories", 1),
    20.         $translator->getPlural("%d directory", "%d directories", 2),
    21.         $translator->getPlural("%d directory", "%d directories", -3),
    22.         $translator->getPlural("%d file. Total size: At least %s", "%d files. Total size: At least %s", 3));
    23.  
    24.  
    25.  
    26.  
    Highlighted with GeSHi 1.0.9.1
  • Execution result as highlighted code
    1. string(65) "Syötä vähintään 3 seuraavista vaihtoehdoista (a, b, c, d, e)"
    2. string(59) "Syötä vähintään 1 seuraavista vaihtoehdoista (a, b, c)"
    3. string(46) "3 tiedostoa. Koko yhteensä: vähintään 20kB"
    4. Array
    5. (
    6.     [0] => avaa
    7.     [1] => sulje
    8.     [2] => Array
    9.         (
    10.             [0] => tallenna
    11.             [1] => poista
    12.             [2] => päivitä
    13.         )
    14.  
    15. )
    16. string(13) "%d hakemistoa"
    17. string(12) "%d hakemisto"
    18. string(13) "%d hakemistoa"
    19. string(13) "%d hakemistoa"
    20. string(45) "%d tiedostoa. Koko yhteensä: vähintään %s"
    21.  
    Highlighted with GeSHi 1.0.9.1

A Zend based Translator

A Translator object translates given input with Translators provided by Zend framework

  • PHP code
    1. <?php
    2.  
    3. namespace Sphp\I18n\Zend;
    4. use Sphp\Config\LocaleManager;
    5. $localeManager = new LocaleManager();
    6. $localeManager->setLocale('en_US');
    7. $translator = Translator::fromFilePattern('gettext', 'sphp/locale/', '%s/LC_MESSAGES/Sphp.Defaults.mo', 'Sphp.Defaults')
    8.         ->setUsedDomain('Sphp.Defaults')
    9.         ->setLang('fi_FI');
    10.         $translator->vsprintf('Please insert atleast %s of the following characters (%s)', [3, 'a, b, c, d, e']),
    11.         $translator->vsprintf('Please insert atleast %s of the following characters (%s)', [1, "a, b, c"]),
    12.         $translator->vsprintfPlural('%d file. Total size: At least %s', '%d files. Total size: At least %s', 3, [3, '20kB']));
    13. print_r($translator->translateArray(['open', 'close', ['save', 'delete', 'update']]));
    14.  
    15.         $translator->getPlural('%d directory', "%d directories", 0),
    16.         $translator->getPlural('%d directory', "%d directories", 1),
    17.         $translator->getPlural('%d directory', "%d directories", 2),
    18.         $translator->getPlural('%d directory', "%d directories", -3),
    19.         $translator->getPlural('%d file. Total size: At least %s', '%d files. Total size: At least %s', 3));
    20. $localeManager->restoreLocales();
    Highlighted with GeSHi 1.0.9.1
  • Execution result as highlighted code
    1. string(65) "Syötä vähintään 3 seuraavista vaihtoehdoista (a, b, c, d, e)"
    2. string(59) "Syötä vähintään 1 seuraavista vaihtoehdoista (a, b, c)"
    3. string(46) "3 tiedostoa. Koko yhteensä: vähintään 20kB"
    4. Array
    5. (
    6.     [0] => avaa
    7.     [1] => sulje
    8.     [2] => Array
    9.         (
    10.             [0] => tallenna
    11.             [1] => poista
    12.             [2] => päivitä
    13.         )
    14.  
    15. )
    16. string(13) "%d hakemistoa"
    17. string(12) "%d hakemisto"
    18. string(13) "%d hakemistoa"
    19. string(13) "%d hakemistoa"
    20. string(45) "%d tiedostoa. Koko yhteensä: vähintään %s"
    21.  
    Highlighted with GeSHi 1.0.9.1

Localized verbose messages using Message objects

A Message message provides support for formatted string syntax used in PHP's native vsprintf() function. Additionally arguments used in the formatted string can also be translated to other languages.

When a message object is treated as a string it is translated according to the current settings of its TranslatorInterface object.

  • PHP code
    1. <?php
    2.  
    3. namespace Sphp\I18n\Messages;
    4.  
    5. use Sphp\I18n\Translators;
    6.  
    7. $translator = Translators::instance()->getDefault();
    8.  
    9.  
    10. $singular = Msg::singular("Please insert atleast %s of the following characters (%s)", [2, "a, b, c"], $translator);
    11. $plural = Msg::plural("%s byte", "%s bytes", true, [300], $translator);
    12.  
    13. echo "singular: {$singular->translate()}\n";
    14. echo "plural: {$plural->translate()}\n";
    15.  
    16. $translator->setLang('fi_FI');
    17.  
    18. $plural->setPlural(false)->setArguments([1]);
    19.  
    20. echo "singular: $singular\n";
    21. echo "plural: $plural\n";
    22.  
    23.  
    Highlighted with GeSHi 1.0.9.1
  • Execution result as highlighted code
    1. singular: Please insert atleast 2 of the following characters (a, b, c)
    2. plural: 300 bytes
    3. singular: Syötä vähintään 2 seuraavista vaihtoehdoista (a, b, c)
    4. plural: 1 tavu
    5.  
    Highlighted with GeSHi 1.0.9.1

Translatable collections managing groups of Translatable objects

TranslatableCollectionInterface is is the base interface for all translatable collections.

  • Basic example of translatable collection
    1. <?php
    2.  
    3. namespace Sphp\I18n\Collections;
    4.  
    5. use Sphp\I18n\Translators;
    6. use Sphp\I18n\Messages\Msg;
    7.  
    8. $translator = Translators::instance()->getDefault();
    9. $msg = Msg::singular("%s:%s:%s elapsed", [3, 24, '03'], $translator);
    10. $messageCont1 = (new TranslatableCollection())
    11.         ->append(Msg::singular("%s:%s:%s left", [12, 10, '01'], $translator))
    12.         ->append(Msg::singular("Please insert atleast %s of the following characters (%s)", [2, "a, b, c"], $translator))
    13.         ->append($msg);
    14.  
    15. $translator->setLang('fi_FI');
    16. print_r($messageCont1->translateWith($translator));
    17.  
    18. foreach ($messageCont1 as $m) {
    19.   echo "\n$m";
    20. }
    21.  
    Highlighted with GeSHi 1.0.9.1
  • Execution result as highlighted code
    1. Array
    2. (
    3.     [0] => 12:10:01 jäljellä
    4.     [1] => Syötä vähintään 2 seuraavista vaihtoehdoista (a, b, c)
    5.     [2] => 3:24:03 kulunut
    6. )
    7.  
    8. 12:10:01 jäljellä
    9. Syötä vähintään 2 seuraavista vaihtoehdoista (a, b, c)
    10. 3:24:03 kulunut
    Highlighted with GeSHi 1.0.9.1

TranslatableCollection objects can also be nested easily. extends ArrayAccess and the offset value corresponds this topic.

  • An example of nesting translatable collections
    1. <?php
    2.  
    3. namespace Sphp\I18n\Collections;
    4.  
    5. use Sphp\I18n\Messages\Msg;
    6.  
    7. $translator = \Sphp\I18n\Translators::instance()->get('validation');
    8.  
    9. $c = new TranslatableCollection();
    10.  
    11. $c["group 1"] = (new TranslatableCollection())
    12.         ->append(Msg::singular("Please insert atleast %s of the following characters (%s)", [3, 'a, b, c, d, e, f']))
    13.         ->append(Msg::singular("Please insert a value"));
    14. $c["group 2"] = (new TranslatableCollection())
    15.         ->append(Msg::singular("Please insert a correct email address"))
    16.         ->append(Msg::singular("Please insert alphabets and numbers only"))
    17.         ->append(Msg::plural("%s byte", "%s bytes", true, [300]));
    18. $c["group 3"] = (new TranslatableCollection())
    19.         ->append(Msg::singular("foo%s", ["bar"]));
    20. $translator->setLang("fi_FI");
    21. print_r($c->setTranslator($translator)->toArray());
    22.  
    23.  
    Highlighted with GeSHi 1.0.9.1
  • Execution result as highlighted code
    1. Array
    2. (
    3.     [group 1] => Array
    4.         (
    5.             [0] => Syötä vähintään 3 seuraavista vaihtoehdoista (a, b, c, d, e, f)
    6.             [1] => Syötä jokin arvo
    7.         )
    8.  
    9.     [group 2] => Array
    10.         (
    11.             [0] => Syötä toimiva sähköpostiosoite
    12.             [1] => Syötä ainoastaan kirjaimia ja numeroita
    13.             [2] => 300 bytes
    14.         )
    15.  
    16.     [group 3] => Array
    17.         (
    18.             [0] => foobar
    19.         )
    20.  
    21. )
    22.  
    Highlighted with GeSHi 1.0.9.1

An instance of TranslatablePriorityList is a priority list for handling Translatable objects. It is also a stable priority list.

  • An example of nesting translatable collections
    1. <?php
    2.  
    3. namespace Sphp\I18n\Collections;
    4.  
    5. use Sphp\I18n\Messages\Msg;
    6.  
    7. $list = new TranslatablePriorityList();
    8.  
    9. $translator = \Sphp\I18n\Translators::instance()->getDefault()->setLang("fi_FI");
    10.  
    11. $list->insert(Msg::singular("%s is not valid", ["path"], $translator)->translateArguments(), 1);
    12. $list->insert(Msg::singular("%s is not valid", ["password"], $translator)->translateArguments(), 10);
    13. $list->insert(Msg::singular("%s is not valid", ["host"], $translator)->translateArguments(), 5);
    14.  
    15.  
    16. foreach ($list as $value) {
    17.   echo $value->getFormattedTemplate() . ":\t$value\n";
    18. }
    19. echo "------------------\n";
    20. $list->insert(Msg::singular("%s is not valid", ["Foobar"], $translator)->translateArguments(), 5);
    21.  
    22. foreach ($list as $value) {
    23.   echo $value->getFormattedTemplate() . ":\t$value\n";
    24. }
    25.  
    Highlighted with GeSHi 1.0.9.1
  • Execution result as highlighted code
    1. password is not valid:  salasana ei ole kelvollinen
    2. host is not valid:      isäntä ei ole kelvollinen
    3. path is not valid:      polku ei ole kelvollinen
    4. ------------------
    5. password is not valid:  salasana ei ole kelvollinen
    6. host is not valid:      isäntä ei ole kelvollinen
    7. Foobar is not valid:    Foobar ei ole kelvollinen
    8. path is not valid:      polku ei ole kelvollinen
    9.  
    Highlighted with GeSHi 1.0.9.1

Localized datetime and calendar translations

The DateTime supports following methods for Date and Time localization.

  • PHP code
    1. <?php
    2.  
    3. namespace Sphp\I18n\Datetime;
    4.  
    5. $now = new DateTime();
    6. $lastTuesday = DateTime::fromString('last tuesday');
    7. $date = DateTime::fromFormat('Y-m-d H:i:s', '2009-02-15 15:16:17');
    8.  
    9. echo "$now is " . $now->getWeekdayName() . ' and the week number is ' . $now->getWeekOfYear() . "\n";
    10.  
    11. echo $now->strftime("%A %e %B %G %H:%M:%S %Z\n", 'sv_FI.utf-8') . "\n";
    12. echo $now->strftime("%A %e %B %G %H:%M:%S %Z", 'fi_FI.utf-8') . "\n";
    13.  
    14. echo $date->formatICU('d. MMMM y HH:mm.ss ZZZZ', 'fi_FI.utf-8') . "\n";
    15.  
    16. echo $now->formatICU('d. MMMM y HH:mm.ss ZZZZ', 'fi_FI.utf-8') . "\n";
    17. echo $now->formatICU('d. MMMM y HH:mm.ss, z Q', 'en_US.utf-8') . "\n";
    18. echo $lastTuesday->formatICU('EEEE d.MMMM y HH:mm.s VVVV', 'fi_FI.utf-8') . "\n";
    19. echo $lastTuesday->formatICU('eeee d.MMMM y HH:mm.ss VVVV', 'de-DE.utf-8');
    20.  
    Highlighted with GeSHi 1.0.9.1
  • Execution result as highlighted code
    1. 2020-05-25 15:22:23, EEST is Monday and the week number is 22
    2. måndag 25 maj 2020 15:22:23 EEST
    3.  
    4. maanantai 25 toukokuu 2020 15:22:23 EEST
    5. 15. helmikuuta 2009 15:16.17 UTC+2.00
    6. 25. toukokuuta 2020 15:22.23 UTC+3.00
    7. 25. May 2020 15:22.23, GMT+03:00 2
    8. tiistaina 19.toukokuuta 2020 00:00.0 Aikavyöhyke: Suomi
    9. Dienstag 19.Mai 2020 00:00.00 Finnland Zeit
    Highlighted with GeSHi 1.0.9.1