Doc updated

Small fixes
This commit is contained in:
Sebastien Guibert 2011-06-26 19:54:27 +02:00
parent c091dacfc2
commit d94f9d9829
4 changed files with 61 additions and 67 deletions

View File

@ -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 Multilingual module for Kohana PHP Framework, version 3.1
Partly based on this module https://github.com/GeertDD/kohana-lang
## Features ## Features
* Language segment in uri * Language segment in uri. Can be optional for the default language
* Works with normal routes * Works with normal routes
* Custom routes for each language (localization or parameters) * Custom routes for each language
* Auto language detection or cookie * Auto language detection for the homepage (headers then cookie)
* Language selection menu * Language selector menu
## Usage ## Usage
### Configuration ### Configuration
return array( return array(
'default' => 'en', // The default language code 'default' => 'en', // The default language code
'cookie' => 'lang', // The cookie name '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 * The allowed languages
* For each language, you need to give a code (2-5 chars) for the key, * 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 ### 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 : 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( Route::set('product.details', 'products/<product_id>-<product_slug>', array(
'product_id' => '[0-9]+', 'product_id' => '[0-9]+',
'product_slug' => '.+', 'product_slug' => '.+',
))->defaults(array( ))->defaults(array(
'controller' => 'product', 'controller' => 'product',
'action' => 'details', 'action' => 'details',
'product_id' => NULL, 'product_id' => NULL,
'product_slug' => '', '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`. You can access `http://www.domain.tld/products/12-my-product` with this one.
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. 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( Routes::set('product.details', array(
'en' => 'products/<product_id>-<product_slug>', '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' => '', '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('product.made-in-france', 'produits/fabrique-en-france', NULL, 'fr')
->defaults(array(
Route::set('file.css', 'static/css/<action>.css', array( 'controller' => 'product',
'action' => '[^/.]+', 'action' => 'made_in_france',
), FALSE)->defaults(array(
'controller' => 'css',
'action' => NULL,
)); ));
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 ### 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`. You can change the view file `multilang/selector.php`.
### Misc ### Misc
To access the current language, you can use `Request::$lang`. To get the current language, you can use `Request::$lang`.
### Input ### Input
@ -107,24 +114,6 @@ If you have any suggestions, found a bug or anything, feel free to share.
### How it works ### How it works
See https://github.com/GeertDD/kohana-lang 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`.
#### The URI does not contain a language code 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.
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.

View File

@ -119,12 +119,13 @@ class Multilang_Core {
{ {
// We juste need to change the language parameter // We juste need to change the language parameter
$route = Request::initial()->route(); $route = Request::initial()->route();
$params['lang'] = NULL;
if(!Kohana::config('multilang.hide_default') || Kohana::config('multilang.default') !== $lang) if(!Kohana::config('multilang.hide_default') || Kohana::config('multilang.default') !== $lang)
{ {
$params['lang'] = $lang; $params['lang'] = $lang;
} }
} }
else else
{ {

View File

@ -31,23 +31,25 @@ class Multilang_Request extends Kohana_Request {
if(!Kohana::$is_cli) if(!Kohana::$is_cli)
{ {
// If we don't hide the default language, we must look for a language code for the root uri // 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(); $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'; // 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 // Redirect to the root URI, but with language prepended
header($protocol.' 302 Found'); header($protocol.' 302 Found');
header('Location: '.URL::base(TRUE, TRUE).$lang.'/'); header('Location: '.URL::base(TRUE, TRUE).$lang.'/');
exit; exit;
}
} }
} }
$request = parent::factory($uri, $cache, $injected_routes); $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) if(Kohana::config('multilang.hide_default') && $request->param('lang') === NULL)
{ {
Request::$lang = Kohana::config('multilang.default'); Request::$lang = Kohana::config('multilang.default');
@ -55,8 +57,8 @@ class Multilang_Request extends Kohana_Request {
else else
{ {
Request::$lang = $request->param('lang'); Request::$lang = $request->param('lang');
} }
Multilang::init(); Multilang::init();
return $request; return $request;
} }

View File

@ -17,6 +17,7 @@ return array(
* For each language, you need to give a code (2-5 chars) for the key, * 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. * the 5 letters i18n language code, the locale and the label for the auto generated language selector menu.
*/ */
/*
'languages' => array( 'languages' => array(
'en' => array( 'en' => array(
'i18n' => 'en_US', 'i18n' => 'en_US',
@ -34,4 +35,5 @@ return array(
'label' => 'deutsch', 'label' => 'deutsch',
), ),
), ),
*/
); );