Punic: Localize Dates, Numbers, Locations and More in PHP

There are a number of ways to handle localization of content in PHP. You can use PHP's built-in GetText support, or a third party library like Zend\i18n. But what about localized content that isn't strictly translation? Things like

  • Currencies
  • Date and Time
  • Country and Territory Names
  • Regular Number Formats
  • Phone Number Formats

When creating a truly multilingual app, these are every bit as important to deal with as strict translations. Fortunately, a new PHP library makes handling these a snap.


When Concrete5 introduced its multilingual support it used Zend_Translate for translation, and Zend_Locale for localization. It was Zend_Locale that handled the above tasks, and it did a good job of it. It shipped with a ton of XML files that specified different number formats, names of languages in different languages and more.

When we shipped version 7 of Concrete5 we wanted to switch to version 2 of the Zend Framework for all included Zend Framework libraries. Unfortunately, Zend_Locale was never added to ZF2. We could have relied on built-in Intl support in PHP, but this wouldn't get us all the functionality that we had in the previous versions of Concrete5, and the Intl extension has some known issues. What we really wanted was an updated, maintained PHP library, built with namespaces and composer readiness, that could do the job.

Enter Punic

Unfortunately, we couldn't find one that met our standards – so we had to write it ourselves. Or rather, an enterprise, incredibly helpful community member – mlocati – wrote it for us.


You can include Punic in your problems easily with composer.

"require": {
    "punic/punic": "1.*"

It's also available for download from GitHub.


Here are some examples of Punic in action. It's shockingly easy to use.


use \Punic\Unit;

// This will output `2 Millisekunden`
echo Unit::format(2, 'millisecond', 'long', 'de');

// This will output `2 ms`
echo Unit::format(2, 'millisecond', 'short', 'en');


use \Punic\Data,

// This will print `Schweizer Hochdeutsch (Schweiz)` without specifying a second parameter for Language::getName
echo Language::getName('de_CH');

// This will print `alto tedesco svizzero (Svizzera)` because the value in the second parameter of getName isn't a valid locale
echo Language::getName('de_CH', 'et_INVALID');


use \Punic\Territory;

// This will output `United States`
echo Territory::getName('US', 'en');

// Prints a list of all countries, indexed by the territory code
$countries = Territory::getCountries();

// Prints a list of all continents
$continents = Territory::getContinents();

// Prints a list of all countries group by continents
$continentsAndCountries = Territory::getContinentsAndCountries();


There's more that Punic can do. If you ever need to localize dates, currencies or phone numbers, or display countries and territories in alternate languages, this is the library for you. It's included and heavily use in Concrete5, but like any good modern PHP library, it can be used anywhere.

Loading Conversation