На моём сайте в определенный момент очень остро встал вопрос организации мультиязычности, причём речь шла не о 2-3 языках, а о том, чтобы перевод сайта на другой, абсолютно любой язык мог быть осуществлен за считанные минуты. Информации в сети на эту тему не так много(может я плохо искал?) и мне пришлось думать самому. Хотя моё решение довольно простое и многим может показаться очевидным, я всё равно приведу его, надеюсь кому-нибудь оно будет полезно. Сразу предупреждаю, что необходимо мало-мальское представление о фреймворке kohana 3.
Итак, какие вообще могут быть варианты организации мультиязычности на сайте? Самый простой и очевидный вариант, это создание для каждого языка папки «ru», «en» и т.п. Но это значило бы копирование всех файлов, а если поменяли что-то, меняем во всех 30 папках… О ужас, развивать эту тему может только мазохист, поэтому, естественно, я стал искать другой путь, который бы позволил менять только языковые файлы с переводом.
Очевидно, что необходимо было ввести в роутинг параметр lang, который бы шёл в начале каждого правила:
Route::set('auth', '<lang>/<action>(/<param>)', array('action' => 'login|logout|registration|forgot|start'))
->defaults(array(
'directory' => 'index',
'controller' => 'auth',
));
Route::set('static', '<lang>/<action>(/<uri>)', array('action' => 'page|blog|news|forms|polls'))
->defaults(array(
'directory' => 'index',
'controller' => 'static',
'action' => 'page',
));
Route::set('default', '(<lang>(/<controller>(/<action>(/<param>))))', array('param' => '.+'))
->defaults(array(
'directory' => 'index',
'controller' => 'static',
'action' => 'index',
'lang' => 'ru'
));
Обратите внимание, что последнем роуте я установил lang по дефолту, чтобы можно было открыть домен без указания языка домен/, если бы я этого не сделал, тогда бы пришлось бы всегда дописывать язык домен/ru/, ну или каждый раз выполнять перенаправление.
В основном контроллере в методе before (может это же лучше делать в bootstrap?) я определил константу LANG:
if ( !defined('LANG') ) {
define('LANG', $this->lang());
}
// какой язык в адресе?
$lang_uri = $this->request->param('lang');
// если не совпадает перенаправляем
if ( $lang_uri != LANG ) {
$this->request->redirect(LANG);
}
// подключаем файл перевода
i18n::lang(LANG . '-' . $this->request->controller());
В методе lang я определяю язык пользователя по кукам или ip пользователя. Файл перевода лежит в папке application/i18n/LANG/controller_name.php. Я дробил перевод по контроллерам, можно это сделать по экшенам или вообще всё засунуть в один файл, это уж как вашей душе и потребностям проекта угодно.
Остается только переопределить метод helper'а HTML anchor. Для этого я создал в папке classes файл html с содержимым:
<?php defined('SYSPATH') or die('No direct script access.');
class HTML extends Kohana_HTML {
public static function anchor($uri, $title = NULL, array $attributes = NULL, $protocol = NULL, $index = TRUE)
{
$uri = LANG . '/'. $uri;
return parent::anchor($uri, $title, array $attributes, $protocol, $index);
}
}
Я ВСЕГДА подаю в этот метод адрес без домена и начальной косой черты, если вы не всегда так делаете, то необходимо обработать входящий $uri правильным способом!
Ну вот и всё. Теперь в любом месте любую фразу, которая нуждается в переводе нужно обработать функцией __(). Но, учтите, что вам нужно выбрать базовый язык: если нужного перевода нет, то фраза будет выводиться на этом языке. Кроме этого вам не придется делать файлы перевода для этого языка. Я выбрал в качестве такого языка русский, но думаю перейти на английский.
Я допускаю, что в каких-то местах эта реализация может быть не по фен-шую, но это работает и работает очень гибко. Всем спасибо за внимание.
Автор: olegmar