PHP Internationalization: How to Make a Website in All World Languages

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

Why PHP Internationalization Is Not Just "Word Translation"

\n\n

Imagine: you wrote a cool PHP project. It works, delights users, and generates profit. But one day, you notice in your statistics that 30% of traffic is from Germany, 15% from Japan, and 10% from the UAE. Your site only speaks Russian. Users leave without finding the "Buy" button in their language.

\n\n

Does this sound familiar? Internationalization (i18n) of PHP applications is not just about replacing words in a template. It is an architectural approach that allows your code to "understand" culture, currency, dates, and even text direction (left-to-right or right-to-left).

\n\n

In this article, we will break down how to turn a regular PHP site into a multilingual platform using native tools and best practices. You will learn how gettext in PHP works, how localization differs from internationalization, and how to avoid pitfalls with pluralization.

\n\n

i18n vs l10n: What's the Difference (and Why It Matters)

\n\n

Before writing code, let's agree on terms. Internationalization (i18n) is preparing the code for translation: extracting strings, working with number, date, and currency formats. Localization (l10n) is the actual process of translation and adaptation for a specific region.

\n\n

A simple analogy: internationalization is building a house with empty rooms where you can place any furniture. Localization is arranging the furniture according to the tastes of a specific resident.

\n\n

For a PHP developer, this means: do not hardcode strings! Never. Even if the site is currently only in Russian. Every phrase should be wrapped in a translation function.

\n\n

Technology Stack for i18n in PHP

\n\n

The PHP ecosystem has several powerful tools. We will look at two main approaches: the classic gettext and the modern ICU MessageFormat via the intl extension.

\n\n

1. Gettext — The Grandfather of Multilingualism

\n\n

Gettext in PHP is the de facto standard for many CMS (WordPress, Drupal). It uses .po and .mo files to store translations. Pros: simplicity, support for plural forms, integration with Poedit.

\n\n

2. ICU MessageFormat — For Complex Logic

\n\n

The PHP intl extension (Internationalization) provides the MessageFormatter and NumberFormatter classes. This is the choice for projects that require complex templates with case, gender, and number selection.

\n\n

3. Wrapper Libraries

\n
    \n
  • symfony/translation — a Symfony component, works with YAML/XLIFF as well as gettext.
  • \n
  • laravel-localization — for Laravel (mcamara/laravel-localization package).
  • \n
  • zend-i18n — for Laminas (formerly Zend Framework).
  • \n
\n\n

Practice: Setting Up gettext in PHP from Scratch

\n\n

Let's say we have a simple script index.php that outputs a greeting. Let's make it multilingual.

\n\n

Step 1. Prepare the Code

\n\n

Wrap all strings in the _() function (an alias for gettext()):

\n\n
<?php\n// index.php\necho _("Welcome to our site!");\n\n$items = 5;\n// For plural forms, use ngettext\necho ngettext("%d item", "%d items", $items);\n?>
\n\n

Step 2. Generate the .pot File

\n\n

Install gettext on the server or use xgettext:

\n\n
xgettext -o locales/messages.pot index.php --from-code=UTF-8
\n\n

Step 3. Create the Translation

\n\n

Copy messages.pot to locales/ru_RU/LC_MESSAGES/messages.po and edit it:

\n\n
msgid "Welcome to our site!"\nmsgstr "Добро пожаловать на наш сайт!"\n\nmsgid "%d item"\nmsgid_plural "%d items"\nmsgstr[0] "%d товар"\nmsgstr[1] "%d товаров"
\n\n

Step 4. Compilation and

Blogs

Book Recommendations