Управление русской локалью в URL на PHP: от index.php до роутинга

Раздел: Веб-разработка на PHP -> Структура index.php

Основные подходы к обработке русской локали в URL через index.php

Как организовать поддержку русской локали, когда URL содержит её в начале пути, например /ru/index.php или /ru/категория/товар?

Наиболее эффективное решение - использовать единую точку входа index.php в связке с URL rewriting. Это позволяет отделить логику выбора локали от физической структуры файлов. Алгоритм:

  1. Все запросы направляются на index.php через .htaccess (Apache) или аналогичный механизм.
  2. В index.php из $_SERVER['REQUEST_URI'] извлекается первый сегмент пути (например, ru).
  3. Если сегмент соответствует одному из поддерживаемых языков (включая ru), устанавливается локаль, а сегмент удаляется из дальнейшего маршрута. Если сегмент отсутствует или невалиден, применяется локаль по умолчанию.
  4. Оставшаяся часть пути передаётся внутреннему роутеру или подключается соответствующий контроллер.

Ниже приведён пример реализации.


<?php
// index.php - front controller
$uri = $_SERVER['REQUEST_URI'];
$path = parse_url($uri, PHP_URL_PATH);
$segments = explode('/', trim($path, '/'));

// Поддерживаемые локали
$supportedLocales = ['ru', 'en', 'de'];
$defaultLocale = 'ru';

$locale = $defaultLocale;
$route = $path;

if (count($segments) > 0 && in_array($segments[0], $supportedLocales)) {
    $locale = array_shift($segments);
    $route = '/' . implode('/', $segments);
}

// Установка локали
setlocale(LC_ALL, $locale . '_RU.UTF-8');
putenv('LANG=' . $locale . '_RU.UTF-8');

// Дальнейшая маршрутизация по $route
// ...

Index php url ru (url index.php с русской локалью)

Этот подход чистый, легко расширяемый и не требует изменения структуры URL при добавлении новых языков.

Типичные ошибки:

  • Забывают удалить сегмент с локалью из пути, из-за чего маршрутизатор пытается найти контроллер с именем ru.
  • Не проверяют, что локаль действительно поддерживается - тогда нужно либо возвращать 404, либо перенаправлять на дефолтную.
  • Игнорируют кодировку: setlocale может не сработать, если не установлены соответствующие локали в системе (проверка через locale -a).

Вариант с параметром запроса: index.php?lang=ru

Простой способ - читать локаль из GET-параметра. Это не требует перезаписи URL, но такие адреса менее дружественны для SEO.


<?php
$lang = $_GET['lang'] ?? 'ru';
if (!in_array($lang, ['ru', 'en'])) $lang = 'ru';
setlocale(LC_ALL, $lang . '_RU.UTF-8');

Проблема: параметр lang может конфликтовать с другими GET-параметрами. Кроме того, этот способ плохо поддерживается поисковыми системами для многоязычных сайтов.

Вариант с поддоменом: ru.example.com

Локаль определяется по имени поддомена. В index.php нужно проанализировать $_SERVER['HTTP_HOST'].


<?php
$host = $_SERVER['HTTP_HOST'];
if (strpos($host, 'ru.') === 0) {
    $locale = 'ru';
} elseif (strpos($host, 'en.') === 0) {
    $locale = 'en';
} else {
    $locale = 'ru';
}
// далее установка локали

Сложность: требуется настройка DNS и веб-сервера для каждого поддомена. Также необходимо правильно обрабатывать куки сессии между поддоменами.

Вариант с HTTP-заголовком Accept-Language

Автоматическое определение локали по заголовку браузера. Не зависит от URL, но не даёт пользователю явно выбрать язык через ссылку.


<?php
$acceptLang = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '';
preg_match('/(ru|en)/i', $acceptLang, $matches);
$locale = $matches[1] ?? 'ru';
setlocale(LC_ALL, $locale . '_RU.UTF-8');

Этот метод лучше использовать как резервный, а не основной, так как он не даёт пользователю явно зафиксировать выбор языка в URL.

Расширенные примеры кода с пояснениями

Полный index.php с роутингом, поддержкой русской локали и многоязычными текстами

Пример

<?php
// index.php
// 1. Определение локали
$locale = detectLocale();
setLocale($locale);

// 2. Загрузка языкового файла
$translations = include "lang/{$locale}.php";

// 3. Маршрутизация
$path = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
// удаляем сегмент с локалью, если он есть
$segments = explode('/', $path);
if (in_array($segments[0], ['ru','en','de'])) {
    array_shift($segments);
}
$controller = $segments[0] ?? 'home';
$action = $segments[1] ?? 'index';

// 4. Подключение контроллера
$controllerFile = "controllers/{$controller}.php";
if (file_exists($controllerFile)) {
    require $controllerFile;
    $class = 'Controller\\' . ucfirst($controller);
    $obj = new $class($translations);
    $obj->$action();
} else {
    http_response_code(404);
    echo $translations['404'];
}

function detectLocale() {
    $uri = $_SERVER['REQUEST_URI'];
    $segments = explode('/', trim(parse_url($uri, PHP_URL_PATH), '/'));
    $supported = ['ru','en','de'];
    if (count($segments) > 0 && in_array($segments[0], $supported)) {
        return $segments[0];
    }
    // fallback: проверяем куку, сессию, Accept-Language
    return $_COOKIE['lang'] ?? $_SESSION['lang'] ?? 'ru';
}

function setLocale($locale) {
    putenv('LC_ALL=' . $locale . '_RU.UTF-8');
    setlocale(LC_ALL, $locale . '_RU.UTF-8');
    // Для mb_ функций
    mb_internal_encoding('UTF-8');
    mb_language('uni');
}

Теперь пример языкового файла lang/ru.php:

Пример

<?php
return [
    'welcome'    => 'Добро пожаловать',
    '404'        => 'Страница не найдена',
    'date_format'=> 'd.m.Y',
    'currency'   => 'руб.',
];

Вывод результата: при обращении к /ru/home/index вызывается контроллер Home, метод index, который использует массив $translations для вывода текста на русском.

Пример .htaccess для перенаправления всех запросов на index.php

Пример

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]

Этот код заставляет сервер обрабатывать любые URL (кроме существующих файлов и папок) через index.php. Без этого правила /ru/catalog вернёт 404, так как физической папки ru нет.

Пример настройки русской локали для дат

Пример

<?php
setlocale(LC_TIME, 'ru_RU.UTF-8');
echo strftime('%A %d %B %Y', time());
// Вывод: пятница 14 марта 2025
пятница 14 марта 2025

Если локаль не установлена, strftime вернёт английские названия.

Пример обработки ошибок кодировки при работе с русскими URL

Пример

<?php
// Если в URL встречаются кириллические символы (например, /ru/товар)
// необходимо правильно декодировать их из UTF-8
$uri = urldecode($_SERVER['REQUEST_URI']);
// Далее работа с $uri

Без декодирования русские буквы в URL будут выглядеть как процентные последовательности (%D1%82%D0%BE%D0%B2%D0%B0%D1%80).

Пример использования константы для локали

Пример

<?php
define('CURRENT_LOCALE', detectLocale());
// после этого константу можно использовать в любом файле

Такой подход упрощает доступ к активной локали без глобальных переменных.

URL index.php с русской локалью - comments

En
Index php url ru (php)