Internationalization (i18n) in PHP: gettext library and modern approaches

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

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.mo


Usage 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/translation


Usage 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:

Recommendations