Internationalization (i18n) in PHP: from basics to modern solutions
Internationalization (i18n) is the process of designing software so that it can be easily adapted to various languages and regions without changing the code. In PHP, there are several approaches to implementing i18n, from built-in functions to powerful libraries. In this article, we will cover the main tools and best practices.
Why is internationalization needed?
The main goal of i18n is to separate interface text from code. This allows you to:
- Add new languages without changing application logic
- Support multiple locales (date, number, currency formats)
- Simplify the translation process for translators
- Comply with regional standards (e.g., phone number format)
Built-in support: gettext
PHP offers a powerful gettext mechanism for working with translations. This is a classic approach used in most Linux systems.
Installation and configuration
Make sure the gettext extension is installed. In most Linux distributions, it is available by default. For Windows, you may need to enable php_gettext.dll in php.ini.
Creating translation files
First, create a directory for locales. A typical structure:
locale/ ru_RU/ LC_MESSAGES/ messages.po messages.mo en_US/ LC_MESSAGES/ messages.po messages.mo.po (Portable Object) files are text files with translations. Example content of messages.po for Russian:
msgid "Welcome"msgstr "Добро пожаловать"
msgid "Hello, %s!"msgstr "Здравствуйте, %s!"Compile the .po file into a binary .mo file using the msgfmt utility:
msgfmt locale/ru_RU/LC_MESSAGES/messages.po -o locale/ru_RU/LC_MESSAGES/messages.moUsage in code
Example PHP script with gettext:
<?php// Set locale and domain$locale = 'ru_RU';putenv("LANG=$locale");setlocale(LC_ALL, $locale);bindtextdomain('messages', __DIR__ . '/locale');textdomain('messages');
// String translationecho gettext('Welcome'); // Outputs "Добро пожаловать"echo _('Hello, %s!', 'Иван'); // Outputs "Здравствуйте, Иван!"?>The _() function is a shortcut for gettext(). For translation with placeholders, use sprintf():
echo sprintf(_('Hello, %s!'), $username);Modern approach: symfony/translation
For large projects, it is more convenient to use the symfony/translation library. It offers a more flexible interface, support for different formats (YAML, XLIFF, JSON), and easy integration with frameworks.
Installation via Composer
composer require symfony/translationUsage example
<?phprequire_once __DIR__ . '/vendor/autoload.php';
use Symfony\\Component\\Translation\\Translator;use Symfony\\Component\\Translation\\Loader\\ArrayLoader;
$translator = new Translator('ru_RU');$translator->addLoader('array', new ArrayLoader());
// Add translations directly (for demonstration)$translator->addResource('array', [ 'Welcome' => 'Добро пожаловать', 'Hello %name%' => 'Здравствуйте, %name%',], 'ru_RU');
// Switch to English$translator->setLocale('en_US');$translator->addResource('array', [ 'Welcome' => 'Welcome', 'Hello %name%' => 'Hello, %name%',], 'en_US');
// Usageecho $translator->trans('Welcome'); // "Welcome"echo $translator->trans('Hello %name%', ['%name%' => 'John']); // "Hello, John"?>Working with YAML files
Create a file messages.ru.yaml: