parent
c091dacfc2
commit
d94f9d9829
97
README.md
97
README.md
|
@ -1,24 +1,26 @@
|
|||
# Kohana Multilang Module
|
||||
# Kohana Multilang Module 2.0
|
||||
|
||||
!!! NEW VERSION 2.0 !!!
|
||||
|
||||
Multilingual module for Kohana PHP Framework, version 3.1
|
||||
|
||||
Partly based on this module https://github.com/GeertDD/kohana-lang
|
||||
|
||||
## Features
|
||||
|
||||
* Language segment in uri
|
||||
* Language segment in uri. Can be optional for the default language
|
||||
* Works with normal routes
|
||||
* Custom routes for each language (localization or parameters)
|
||||
* Auto language detection or cookie
|
||||
* Language selection menu
|
||||
* Custom routes for each language
|
||||
* Auto language detection for the homepage (headers then cookie)
|
||||
* Language selector menu
|
||||
|
||||
## Usage
|
||||
|
||||
### Configuration
|
||||
|
||||
return array(
|
||||
'default' => 'en', // The default language code
|
||||
'cookie' => 'lang', // The cookie name
|
||||
'default' => 'en', // The default language code
|
||||
'cookie' => 'lang', // The cookie name
|
||||
'hide_default' => FALSE, // Hide the language code for the default language
|
||||
'auto_detect' => TRUE, // Auto detect the user language on the homepage
|
||||
/**
|
||||
* The allowed languages
|
||||
* For each language, you need to give a code (2-5 chars) for the key,
|
||||
|
@ -47,23 +49,26 @@ Partly based on this module https://github.com/GeertDD/kohana-lang
|
|||
|
||||
### Example
|
||||
|
||||
If you try to access `http://www.domain.tld/`, the module will redirect it to `http://www.domain.tld/en/` for example.
|
||||
If you try to access `http://www.domain.tld/`, the module will redirect it to `http://www.domain.tld/en/` if the hide_default option is set to FALSE.
|
||||
|
||||
Let's say we have a product page, with kohana 3 we'd have something like :
|
||||
|
||||
Route::set('product.details', 'products/<product_id>-<product_slug>', array(
|
||||
'product_id' => '[0-9]+',
|
||||
'product_slug' => '.+',
|
||||
))->defaults(array(
|
||||
'controller' => 'product',
|
||||
'action' => 'details',
|
||||
'product_id' => NULL,
|
||||
'product_slug' => '',
|
||||
));
|
||||
Route::set('product.details', 'products/<product_id>-<product_slug>', array(
|
||||
'product_id' => '[0-9]+',
|
||||
'product_slug' => '.+',
|
||||
))->defaults(array(
|
||||
'controller' => 'product',
|
||||
'action' => 'details',
|
||||
'product_id' => NULL,
|
||||
'product_slug' => '',
|
||||
));
|
||||
|
||||
|
||||
|
||||
If you try to access `http://www.domain.tld/products/12-my-product`, it will redirect to `http://www.domain.tld/en/products/12-my-product`.
|
||||
Now, I'm on the same page in french `http://www.domain.tld/fr/products/12-my-product`, but I'd like to translate it and set `produits` instead of `products`. You can use the `Routes` object (notice the S at the end) to set multiple routes for each language.
|
||||
You can access `http://www.domain.tld/products/12-my-product` with this one.
|
||||
Now, I want this url in french too, like that: `http://www.domain.tld/fr/products/12-my-product`.
|
||||
You can use the `Routes` object (notice the S at the end) to set multiple routes for each language.
|
||||
Let's take a look:
|
||||
|
||||
Routes::set('product.details', array(
|
||||
'en' => 'products/<product_id>-<product_slug>',
|
||||
|
@ -78,27 +83,29 @@ Now, I'm on the same page in french `http://www.domain.tld/fr/products/12-my-pro
|
|||
'product_slug' => '',
|
||||
));
|
||||
|
||||
This creates 2 routes named `en.products.details` and `fr.products.details`. The default language (english here) is required. If we have a third language like `de`, it will use `en`. The thing is, both url `http://www.domain.tld/fr/products/12-my-product` and `http://www.domain.tld/en/produits/12-my-product` will still work. To make sure this is not an issue, you should use reverse routing everywhere. With `Route::get('product/details')->uri(array('product_id' => 12, 'product_slug' => 'my_product'))`, you'll get the complete uri with the current user language code. To get another language, just pass a second parameter to `Route::get('product/details', 'en')`.
|
||||
This creates 2 routes named `en.products.details` and `fr.products.details`. The default language (english here) is required. If we have a third language like german with `de`, it will use the default uri, english here.
|
||||
It is highly recommanded to use reverse routing! With `Route::get('product/details')->uri(array('product_id' => 12, 'product_slug' => 'my_product'))`, you'll get the complete uri with the current user language code. To get another language, just pass a second parameter to `Route::get('product/details', 'en')`.For the routes than dont need any language code, you can keep the normal kohana syntax.
|
||||
If you wanna create a route for only one language, you're gonna have to pass a 4th parameter:
|
||||
|
||||
Now, I got a controller that serves CSS files, I obviously don't need any language specified. To prevent the normal behaviour, just pass `FALSE` as the third parameter to `Route::set` like this :
|
||||
|
||||
Route::set('file.css', 'static/css/<action>.css', array(
|
||||
'action' => '[^/.]+',
|
||||
), FALSE)->defaults(array(
|
||||
'controller' => 'css',
|
||||
'action' => NULL,
|
||||
Route::set('product.made-in-france', 'produits/fabrique-en-france', NULL, 'fr')
|
||||
->defaults(array(
|
||||
'controller' => 'product',
|
||||
'action' => 'made_in_france',
|
||||
));
|
||||
|
||||
If you access `http://www.domain.tld/static/css/custom_page.css`, it will not redirect and `Route::get('file.css.custom')->uri(array('action' => 'categories'))` will not return the uri with a language code.
|
||||
|
||||
And then to get it `Route::get('fr.product.made-in-france')` or `Route::get('product.made-in-france', 'fr)`.
|
||||
|
||||
The default route is particular and its declaration is set in init.php. Since it doesnt need any translations and has a different behaviour (we wanna keep the trailing slash), we create a custom route that alows all the languages.
|
||||
|
||||
|
||||
### Language selector menu
|
||||
|
||||
`Multilang::selector($current)` returns a menu to select the language. It will keep the same page. The `current` parameter adds the current language in the menu or not.
|
||||
`Multilang::selector($current)` returns a menu to select the language. It will keep the same page if routes are available for the other languages. The `current` parameter adds the current language in the menu.
|
||||
You can change the view file `multilang/selector.php`.
|
||||
|
||||
### Misc
|
||||
|
||||
To access the current language, you can use `Request::$lang`.
|
||||
To get the current language, you can use `Request::$lang`.
|
||||
|
||||
### Input
|
||||
|
||||
|
@ -107,24 +114,6 @@ If you have any suggestions, found a bug or anything, feel free to share.
|
|||
|
||||
### How it works
|
||||
|
||||
See https://github.com/GeertDD/kohana-lang
|
||||
|
||||
#### The URI does not contain a language code
|
||||
|
||||
If somebody visits `http://www.domain.tld/page`, without a language, the best default language will be found and the user will be redirected to the same URL *with* that language prepended. To find the best language, the following elements are taken into account (in this order):
|
||||
|
||||
1. a language cookie (set during a previous visit);
|
||||
2. the HTTP Accept-Language header;
|
||||
3. a hard-coded default language.
|
||||
|
||||
#### The URI contains a language code
|
||||
|
||||
1. The language code is chopped off before the request and stored in `Request::$lang`.
|
||||
2. `I18n::$lang` is set to the correct target language (from config).
|
||||
3. The correct locale is set (from config).
|
||||
4. A cookie with the language code is set.
|
||||
5. Normal request processing continues.
|
||||
|
||||
It is important to be aware that the *language part is completely chopped off* of the URI. When normal request processing continues it, it does so with a URI without language. This means that **your routes must not contain a language code. Also, you can create HMVC subrequests without having to worry about adding the current language to the URI.
|
||||
|
||||
The one thing we still need to take care of then, is that any generated URLs should contain the language. An extension of `URL::site` is created for this. A third argument, `$lang`, is added to `URL::site`. By default, the current language is used (`Request::$lang`). You can also provide another language key as a string, or set the argument to `FALSE` to generate a URL without language.
|
||||
We change the Request to force the detection of a language on the site root. Then if a route is found, we get the language from it with its 'lang' parameter and we initialize.
|
||||
Each route created with a language code gets another parameter: `lang`. A uri like `products/details` will become `<lang>/products/details`.
|
||||
But since every multilingual route is unique (except default), the regex part allows only one language code. So we have `array('lang' => 'en')` instead of having something like `array('lang' => '(en|fr|de')`. We could have directly the language code in the uri like `en/products/details` but the lang parameter allows us to easily retrieve the route language and works better with the default route.
|
|
@ -119,12 +119,13 @@ class Multilang_Core {
|
|||
{
|
||||
// We juste need to change the language parameter
|
||||
$route = Request::initial()->route();
|
||||
|
||||
$params['lang'] = NULL;
|
||||
if(!Kohana::config('multilang.hide_default') || Kohana::config('multilang.default') !== $lang)
|
||||
{
|
||||
$params['lang'] = $lang;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -31,23 +31,25 @@ class Multilang_Request extends Kohana_Request {
|
|||
if(!Kohana::$is_cli)
|
||||
{
|
||||
// If we don't hide the default language, we must look for a language code for the root uri
|
||||
if(Kohana::config('multilang.auto_detect') && $uri === TRUE && Request::detect_uri() === '')
|
||||
if(Request::detect_uri() === '' && Kohana::config('multilang.auto_detect') && $uri === TRUE)
|
||||
{
|
||||
$lang = Multilang::find_user_language();
|
||||
|
||||
// Use the default server protocol
|
||||
$protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
|
||||
$lang = Multilang::find_user_language();
|
||||
if(!Kohana::config('multilang.hide_default') || $lang != Kohana::config('multilang.default'))
|
||||
{
|
||||
// Use the default server protocol
|
||||
$protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
|
||||
|
||||
// Redirect to the root URI, but with language prepended
|
||||
header($protocol.' 302 Found');
|
||||
header('Location: '.URL::base(TRUE, TRUE).$lang.'/');
|
||||
exit;
|
||||
// Redirect to the root URI, but with language prepended
|
||||
header($protocol.' 302 Found');
|
||||
header('Location: '.URL::base(TRUE, TRUE).$lang.'/');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$request = parent::factory($uri, $cache, $injected_routes);
|
||||
|
||||
// If the default language is hidden, we manually set it
|
||||
// If the default language is hidden, we manually set it
|
||||
if(Kohana::config('multilang.hide_default') && $request->param('lang') === NULL)
|
||||
{
|
||||
Request::$lang = Kohana::config('multilang.default');
|
||||
|
@ -55,8 +57,8 @@ class Multilang_Request extends Kohana_Request {
|
|||
else
|
||||
{
|
||||
Request::$lang = $request->param('lang');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Multilang::init();
|
||||
return $request;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ return array(
|
|||
* For each language, you need to give a code (2-5 chars) for the key,
|
||||
* the 5 letters i18n language code, the locale and the label for the auto generated language selector menu.
|
||||
*/
|
||||
/*
|
||||
'languages' => array(
|
||||
'en' => array(
|
||||
'i18n' => 'en_US',
|
||||
|
@ -34,4 +35,5 @@ return array(
|
|||
'label' => 'deutsch',
|
||||
),
|
||||
),
|
||||
*/
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue