fuel/core — pull request #1291 by davispuh (2013-01-22 04:02:44+00:00)
Title: Support localized language URLs

### About

This feature allows to make localized URLs. ie.
`http://domain/lang1/controller/method`
`http://domain/lang2/controller/method`

While I've seen other implementations which change Uri class this DOES NOT because it have several issues.

### Implementation

Uri class isn't changed and Lang class is improved properly -> all code is fully backward compatible and everything will work same as before for everyone who don't need such feature. No need to change existing code.

### Usefulness

I'm pretty sure there's people who would love such feature (including me).

And this implementation have several advantages.
* Easy to make same page links for different languages.
* Switching between languages user gets same page (in other language) without redirects.
* Backward compatible
* Lang class supports this feature making it in right place where it should be. And allows routing handle some specific language needs.
* Can be easily customizable if language need to be in other component than first (eg. last). While currently this can't be achieved with config, it's really easy to either directly edit lang class or just overload in app.
* SEO friendly
* Language in URL can be overridden with `Config::set('language',$lang)`

### Usage

To use this feature there are required few code changes, but nothing much.

1. all links which are supposed to be for same language must be replaced with
`Lang::localized($uri)`, eg. `Article`
(Note: currently `localized` doesn't support schema or relative urls, and it expects that uri starts with `/` but it can be implemented if needed, now can do just `'https://domain'.Lang::localized('/blog/article/')`)
2. make links which change language. either use `Lang::localized('/blog/article/','ru')` or directly write `RU`
3. in app `config.php` add available languages `'languages' => Array('en', 'ru')`
4. change `routes.php` config to also include localized routing.

#### `routes.php` config changes explained

Will need routes for both cases when language is included in URI and when isn't.
So will need to add another `_root_` ie. `$routes[$langs]` and all other routes prefixed with `$routes[(({$langs})/)?route]`

There's 4 possible configurations.

##### 1.
SEO friendly. Default language without any prefix. ie. `http://domain/controller` and all other languages `http://domain/lang/controller`. BUT `http://domain/default_lang/controller` returns 404

`config.php`: `'language' => 'en'` // specify which language will be served as default. without included in URL

`routes.php`
```
'welcome/index', // The default route
"({$langs})" => 'welcome/index', // The default route in other language
"(({$langs})/)?hello(/:name)?" => array('welcome/hello', 'name' => 'hello'),
);
```

##### 2.
Default language without any prefix. ie. `http://domain/controller`, BUT `http://domain/default_lang/controller` will still work.

everything same as previous, just without `unset($languages[0]);`

##### 3.
All languages `http://domain/lang/controller`. BUT `http://domain/controller` will return 404. There's exception to `_root_`, it will give default language (language_fallback).

`config.php`: `'language' => ''` // no default language, MUST be in URL
`'language_fallback' => 'en'` // Fallback language if language isn't in URL

`routes.php`
```
'welcome/index', // The default route
"({$langs})" => 'welcome/index', // The default route in other language
"(({$langs})/)?hello(/:name)?" => array('welcome/hello', 'name' => 'hello'),
);
```

##### 4.
Make your own routes, unlimited possibilities. Maybe you don't have some article in that language? No problem, just give in default language or give page informing that it's not available.

### PS

I've been using this feature already some while and it works great :)

Also btw I replaced some code which didn't make any sense...
```
if ($language === null) {
$languages = static::$fallback;
array_unshift($languages, $language ?: \Config::get('language'));
$language = reset($languages);
}
```
firstly it was in several places exactly same and `$languages` wasn't used anywhere only these few lines. And that code part is used only when `$language` is `null`, but `null` is always `false`, so `$languages` always will be with prepended with `Config::get('language')` and so always `$language=Config::get('language')` when `$language` is `null`