В первую очередь хочу сказать спасибо за комментарии. Думаю данная тема будет еще для многих актуальна, так как периодически получаю от пользователей хабры сообщения в скайп, помочь в создании «модуля» мультиязычности.
Данный пост полностью переписан, так как на данный момент использую совершенно другой подход к разработки мультиязычности для CodeIgniter 3. Также пост максимально короткий с примером и кратким описанием.
В общем, со временем и более детальным изучением данного фреймворка, пришел к выводу — мультиязычность нужно делать в роутере.
Логика мультиязычности, до боли проста. Одна функция в обновленный MY_Router.php которая добавит в начало всех правил — языки сайта. После работы функции, CodeIgniter 3 будет работать с новым списком route. Получится примерно так :)
Было
Станет
Но для начала, создадим файл c настройками, где будем хранить доступные языки сайта и установим язык по-умолчанию config/localize_config.php
Беремся расширять стандартный system/core/Router.php.
Создаем в каталоге application/core файл MY_Router.php Если вы используете HMVC, вам нужно сначала загрузить его Router.php
В начало MY_Router.php добавьте следующий блок кода
2) После этого, создаем уже расширение класса CI_Router или если с HMVC MX_Router
3) А теперь самое интересное. Нам нужно расширить стандартную функцию CI_Router -> _set_routing. Возможно от версии к версии эта функция будет меняться разработчиками CI, советую просто разобраться в этих строчках, чтобы после любого обновления фреймворка, ваш файл MY_Routing был в актуальном состоянии. Тем более вам нужно добавить всего 1 строчку.
Итак начнем, копируем из system/core/Router.php функцию (метод) _set_routing и вставляем в наш созданный класс MY_Routing.
находим строчки, после которой функция подгрузила routes.php
и включаем в этот участок кода нашу строку для изменения полученных роутеров.
4) А вот и сама функция которая переделает наши правила под понимание различных языков.
Теперь ваш сайт будет понимать ссылки vashsite.com/by, vashsite.com/ru или vashsite.com (с использованием языка по-умолчанию).
Вы всегда имеете возможность получить выбранный язык (by,ru,.....kz) используя ниже описанную переменную в своих контроллерах или моделях.
Дальше уже дело за вашей фантазией как работать с user_lang :) всё что нужно, у вас уже есть.
Готовый вариант на bitbucket.org
Данный пост полностью переписан, так как на данный момент использую совершенно другой подход к разработки мультиязычности для CodeIgniter 3. Также пост максимально короткий с примером и кратким описанием.
Решение проблемы
В общем, со временем и более детальным изучением данного фреймворка, пришел к выводу — мультиязычность нужно делать в роутере.
Принцип работы мультиязычности
Логика мультиязычности, до боли проста. Одна функция в обновленный MY_Router.php которая добавит в начало всех правил — языки сайта. После работы функции, CodeIgniter 3 будет работать с новым списком route. Получится примерно так :)
Было
$route['default_controller'] = "pages/index";
$route['pages/(.+)'] = 'pages/index/$1';
$route['news/(.+)'] = 'news/view/$1';
Станет
$route['default_controller'] = "pages/index";
$route['(by|ru|kz|en)/pages/(.+)'] = 'pages/index/$2';
$route['(by|ru|kz|en)/news/(.+)'] = 'news/view/$2';
Но для начала, создадим файл c настройками, где будем хранить доступные языки сайта и установим язык по-умолчанию config/localize_config.php
<?php defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Настройки локализации сайта.
*
* default_key => язык сайта по умолчанию
* list => список доступных языков
*
* @author Sergey Makhlenko
* @version 1.0
*/
$config['ROUTE_LOCALIZE'] = array(
'default_key' => 1, // Язык по-умолчанию, указывается ключ из массива "list" (0 -> by, 1 -> ru, .... 4 -> en)
'list' => array('by', 'ru', 'kz', 'ua', 'en'), // Доступные языки для сайта
);
Беремся расширять стандартный system/core/Router.php.
Расширяем CI_Router (MX_Router)
Создаем в каталоге application/core файл MY_Router.php Если вы используете HMVC, вам нужно сначала загрузить его Router.php
В начало MY_Router.php добавьте следующий блок кода
<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
// load the MX_Router class
if ( file_exists(APPPATH."third_party/MX/Router.php") ) {
require APPPATH."third_party/MX/Router.php";
}
....
2) После этого, создаем уже расширение класса CI_Router или если с HMVC MX_Router
class MY_Router extends CI_Router {
/**
* Language user or default language
* Язык пользователя или язык по-умолчанию
*/
public $user_lang = '';
/**
* Class constructor
*
* Run the route mapping function.
*
* @param array $routing
* @return void
*/
public function __construct($routing = NULL)
{
parent::__construct();
}
...
}
3) А теперь самое интересное. Нам нужно расширить стандартную функцию CI_Router -> _set_routing. Возможно от версии к версии эта функция будет меняться разработчиками CI, советую просто разобраться в этих строчках, чтобы после любого обновления фреймворка, ваш файл MY_Routing был в актуальном состоянии. Тем более вам нужно добавить всего 1 строчку.
Итак начнем, копируем из system/core/Router.php функцию (метод) _set_routing и вставляем в наш созданный класс MY_Routing.
находим строчки, после которой функция подгрузила routes.php
.....
if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))
{
include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');
}
// Validate & get reserved routes
if (isset($route) && is_array($route))
{
// Тут мы допишем нашу строку...
.....
и включаем в этот участок кода нашу строку для изменения полученных роутеров.
// Update Routing Localize
$this->__localize_init($route);
4) А вот и сама функция которая переделает наши правила под понимание различных языков.
/**
* Append to routing localize lang
*
* @param array $route Route is config/routes.php
* @return array
*/
private function __localize_init( &$route = array() ) {
// Loader config localize
if (file_exists(APPPATH.'config/localize_config.php'))
{
include(APPPATH.'config/localize_config.php');
$localize = $config['ROUTE_LOCALIZE'];
} else {
return FALSE;
}
/* --------------------------------------------------------- */
// Check config localize
if ( !isset($localize) or !isset($localize['list']) ) {
return FALSE;
}
if ( !isset($localize['default_key']) ) {
$localize['default_key'] = 0;
}
$localize['default_key'] = intval($localize['default_key']);
/* --------------------------------------------------------- */
// Language join list
$lang_list = implode('|', $localize['list']);
// Create new route list
foreach ( $route as $key => $item ) {
$_route[$key] = $item;
if ( $key == 'default_controller' ) {
$_route['('.$lang_list.')'] = $route['default_controller'];
$_route['('.$lang_list.')/(.+)'] = '$2';
}
}
/* --------------------------------------------------------- */
// Check default language
if ( isset( $localize['list'][ $localize['default_key'] ] ) ) {
$this->user_lang = $localize['list'][ $localize['default_key'] ];
}
// User select language
if ( array_search( $this->uri->segment(1), $localize['list'] ) !== FALSE ) {
$this->user_lang = $this->uri->segment(1);
}
$route = $_route;
}
Вот и всё!
Теперь ваш сайт будет понимать ссылки vashsite.com/by, vashsite.com/ru или vashsite.com (с использованием языка по-умолчанию).
Вы всегда имеете возможность получить выбранный язык (by,ru,.....kz) используя ниже описанную переменную в своих контроллерах или моделях.
$this->router->user_lang;
Дальше уже дело за вашей фантазией как работать с user_lang :) всё что нужно, у вас уже есть.
Готовый вариант на bitbucket.org