Поддержка многоязычности

Компонент Phalcon\Translate поможет в создании многоязычных приложений. Приложения, использующие этот компонент, отображают содержимое на разных языках, основываясь на выборе пользователя из поддерживаемых приложением.

Адаптеры

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

АдаптерОписание
Phalcon\Translate\Adapter\NativeArray Использует массивы PHP для хранения сообщений. Это лучший вариант с точки зрения производительности.

Фабрика

Загружает адаптер используя параметр adapter:

<?php

use Phalcon\Translate\Factory;

$options = [
    'locale'        => 'de_DE.UTF-8',
    'defaultDomain' => 'translations',
    'directory'     => '/path/to/application/locales',
    'category'      => LC_MESSAGES,
    'adapter'       => 'gettext',
];

$translate = Factory::load($options);

Использование компонента

Строки перевода хранятся в файлах. Структура этих файлов может варьироваться в зависимости от используемого адаптера. Phalcon дает вам свободу в организации ваших строк перевода. Простая структура может быть:

app/messages/en.php
app/messages/es.php
app/messages/fr.php
app/messages/zh.php

Каждый файл содержит массив переводов в виде ключ/значение. Для каждого файла перевода ключи уникальны. Тот же массив используется в разных файлах, где ключи остаются неизменными, а значения содержат переведенные строки в зависимости от каждого языка.

<?php

// app/messages/en.php
$messages = [
    'hi'      => 'Hello',
    'bye'     => 'Good Bye',
    'hi-name' => 'Hello %name%',
    'song'    => 'This song is %song%',
];
<?php

// app/messages/fr.php
$messages = [
    'hi'      => 'Bonjour',
    'bye'     => 'Au revoir',
    'hi-name' => 'Bonjour %name%',
    'song'    => 'La chanson est %song%',
];

Реализация механизма перевода в вашем приложении тривиальна, но зависит от того, как вы хотите его реализовать. Вы можете использовать автоматическое определение языка из браузера пользователя, или вы можете предоставить выбор языка пользователю.

Простым способом определения языка пользователя является анализ содержимого $_SERVER ['HTTP_ACCEPT_LANGUAGE'] или, если хотите, получить к нему доступ напрямую, вызывая $this->request->getBestLanguage() из действия / контроллера:

<?php

use Phalcon\Mvc\Controller;
use Phalcon\Translate\Adapter\NativeArray;

class UserController extends Controller
{
    protected function getTranslation()
    {
        // Получение оптимального языка из браузера
        $language = $this->request->getBestLanguage();
        $messages = [];

        $translationFile = 'app/messages/' . $language. '.php';

        // Проверить, есть ли у нас файл перевода для этого языка
        if (file_exists($translationFile)) {
            require $translationFile;
        } else {
            // Возврат к некоторому по умолчанию
            require 'app/messages/en.php';
        }

        // Возврат объекта перевода $messages происходит из
        // инструкции require выше
        return new NativeArray(
            [
                'content' => $messages,
            ]
        );
    }

    public function indexAction()
    {
        $this->view->name = 'Mike';
        $this->view->t    = $this->getTranslation();
    }
}

Метод _getTranslation() доступен для всех действий, требующих перевода. Переменная $t передается в представления, и с ней мы можем переводить строки в этом слое:

<!-- welcome -->
<!-- String: hi => 'Hello' -->
<p><?php echo $t->_('hi'), ' ', $name; ?></p>

Метод _() возвращает переведенные строки на основе индекса, переданного функции. Некоторым строкам необходимо включить заполнители для рассчитанных данных, т. е. Hello %name%. Эти заполнители могут быть заменены переданными параметрами в методе _(). Прошедшие параметры представлены в виде массива key / value, где ключ соответствует имени заполнителя, а значение - фактические данные, подлежащие замене:

<!-- welcome -->
<!-- String: hi-name => 'Hello %name%' -->
<p><?php echo $t->_('hi-name', ['name' => $name]); ?></p>

Некоторые приложения используют многоязычный URL-адрес, например http://www.mozilla.org/**es-ES**/firefox/. Реализовать такую схему в приложении на Phalcon можно используя компонент Router.

Реализация выше удобна, но она требует наличия базового контроллера для реализации getTranslation() и возвращения компонента Phalcon\Translate\Adapter\NativeArray. Кроме того, компонент должен быть передан в представление, как в примере выше, в виде переменной $t.

Вы всегда можете реализовать эту функциональность в своём собственном классе и зарегистрировать его в DI:

<?php

use Phalcon\Mvc\User\Component;
use Phalcon\Translate\Adapter\NativeArray;

class Locale extends Component
{
    public function getTranslator()
    {
        // Получение оптимального языка из браузера
        $language = $this->request->getBestLanguage();

        /**
         * Здесь мы используем JSON-файлы для хранения переводов. 
         * Помните, вам необходимо убедиться, что файл существует! 
         */
        $translations = json_decode(
            file_get_contents('app/messages/' . $language. '.json'),
            true
        );

        // Возвращение объекта работы с переводом
        return new NativeArray(
            [
                'content' => $translations,
            ]
        );
    }
}

Таким образом, вы можете использовать этот компонент в контроллерах:

<?php

use Phalcon\Mvc\Controller;

class MyController extends Controller
{
    public function indexAction()
    {
        $name = 'Майк';
        $text = $this->locale->_('hi-name', ['name' => $name]);

        $this->view->text = $text;
    }
}

или напрямую в представлении

<?php echo $locale->_('hi-name', ['name' => 'Майк']);

Реализация собственных адаптеров

Интерфейс Phalcon\Translate\AdapterInterface должен быть реализован для создания собственных адаптеров перевода или расширения существующих:

<?php

use Phalcon\Translate\AdapterInterface;

class MyTranslateAdapter implements AdapterInterface
{
    /**
     * Конструктор адаптера
     *
     * @param array $options
     */
    public function __construct(array $options);

    /**
     * @param  string     $translateKey
     * @param  array|null $placeholders
     * @return string
     */
    public function t($translateKey, $placeholders = null);

    /**
     * Возвращает перевод строки по ключу
     *
     * @param   string $translateKey
     * @param   array $placeholders
     * @return  string
     */
    public function _(string $translateKey, $placeholders = null): string;

    /**
     * Возвращает перевод, связанный с заданным ключом
     *
     * @param   string $index
     * @param   array $placeholders
     * @return  string
     */
    public function query(string $index, $placeholders = null): string;

    /**
     * Проверяет существование перевода ключа во внутреннем массиве
     *
     * @param   string $index
     * @return  bool
     */
    public function exists(string $index): bool;
}

Для этих компонентов доступно больше адаптеров. Phalcon Incubator