На данный момент локализация присутствует в библиотеке Hlogin - для авторизации пользователей. Можно посмотреть, как это устроено там. Но из-за специфики библиотеки не все функции оттуда могут вам пригодиться. Поэтому здесь описание простой локализации для фреймворка через пользовательскую функцию (но можно переделать и через DI), которую вы можете адаптировать под свои нужды.
Локализация
В зависимости от предпочтений вы можете назвать функцию как угодно, но желательно кратко. Здесь мы рассмотрим формат t(...);. Видел еще использование как символа нижнее подчеркивание, но на одном хостинге у меня с этим была проблема, так что нижнее подчеркивание не рекомендую как функцию.
Во фреймворке HLEB2 есть возможность добавлять файлы со своими функциями, они будут инициализированы до основного пользовательского кода. Возможно, что вы уже используете такой файл и нужно будет добавить функцию в него, но если нет, в файле конфигурации config/system.php найдите настройку custom.function.files и добавьте в массив значение '/app/functions.php'. После этого создайте файл для собственных функций в папке app со следующим кодом:
<?php
// Файл app/functions.php
if (!function_exists('t')) {
/**
* Локализация по ключу $key.
* Поддерживает подмену подстрок по принципу {%name%} из именованного массива $params.
*/
function t(string $key, array $params = [], ?string $lang = null): string
{
return \App\Translations::t($key, $params, $lang);
}
}
Далее нам понадобится класс Translations в той-же папке app.
<?php
// Файл app/Translations.php
declare(strict_types=1);
namespace App;
use Hleb\Static\Settings;
use InvalidArgumentException;
class Translations
{
public const RU = 'ru';
public const EN = 'en';
private static array $sources = [];
/**
* Локализация по ключу $key.
* Поддерживает подмену подстрок по принципу {%name%} из именованного массива $params.
*/
public static function t(string $key, array $params = [], ?string $lang = null): string
{
// Попытка определить язык из первой части url, get-параметра (lang) или сессии (LANG), иначе дефолтный из конфига.
$lang = $lang ?? Settings::getAutodetectLang();
$languages = config('main', 'allowed.languages');
if (!in_array($lang, $languages)) {
throw new InvalidArgumentException("Language `{$lang}` is not supported or not defined.");
}
if (empty(self::$sources[$lang])) {
self::$sources[$lang] = require_once hl_path("@/config/i18n/$lang.php");
}
$result = self::$sources[$lang][$key] ?? $key;
if ($params) {
$replacements = [];
foreach ($params as $name => $value) {
$replacements['{%'.$name.'%}'] = (string)$value;
}
$result = strtr($result, $replacements);
}
return $result;
}
}
Теперь добавим в папку config/il18n/ файлы переводов, например для русского ru.php и английского en.php. Так как поддерживаются только два эти языка, нужно оставить в настройке allowed.languages конфигурации /config/main.php только их.
<?php
// Файл config/i18n/ru.php
return [
'hello_world' => 'Привет, Мир!',
'unique_visits' => 'Зафиксировано {%count%} уникальных посещений',
// ...
];
<?php
// Файл config/i18n/en.php
return [
'hello_world' => 'Hello, World!',
'unique_visits' => '{%count%} unique visits were recorded',
// ...
];
Используется это так в коде (предполагается, что в стандартных шаблонах фреймворка):
use App\Translations;
echo t('hello_world'); // Автоопределяемый язык
echo t('unique_visits', ['count' => 120]); // Автоопределяемый язык
echo t('unique_visits', ['count' => 120], Translations::RU);
Здесь еще важно указать нужный параметр по умолчанию, когда язык не удалось определить - это настройка default.lang в конфигурации config/main.php.
Расширенная интернационализация
Указанной выше локализации хватит для большинства приложений, однако, если у вас очень много переводов, то можно разбить локализацию на логические части и подгружать файлы только из определенной подпапки, соответственно в функции t() нужно добавить аргумент с указанием этой части.
Также для преобразования дат и прочего в тексте предназначено расширение https://www.php.net/manual/ru/book.intl.php intl в PHP, но его подключение и использование выходит за рамки этого вопроса.
Локализация для Twig
Начиная с v2.1.18 версии фреймворка можно добавить функцию для поддержки в Twig. Для этого добавлен параметр в common раздел, в котором надо указать функцию t().
'twig.allowed.functions' => ['csrf_token', 'url', 't'],
После этого она будет доступна в Twig-шаблонах.