flightphp / core

An extensible micro-framework for PHP
https://docs.flightphp.com
MIT License
2.62k stars 409 forks source link

Multilanguage routing #39

Closed kamov closed 11 years ago

kamov commented 11 years ago

Hi,

Could you help to understand how to create a multilingual site with Flight?

For example, I want my site to have such languages: en (default), de, fr, it, .... Language identifier is presented in URL: http://example.com/de/hello/ But the default language ('en' for this example) has not to be presented in URL. An URL http://example.com/hello/ means English page.

How it is better to achieve this?

Thanks

knusperpixel commented 11 years ago

The docs (http://flightphp.com/learn#routing) say that "You can pass execution on to the next matching route by returning true from your callback function".

So I would think, something like this should work:

// Setup possible languages
Flight::set('possible_languages', array('en', 'de', 'fr', 'it'));

// Set default language if not present in url
Flight::set('language', 'en');

// Setup route to check the language
Flight::route('(/@lang:[a-z]{2})', function($language){

    // Check if valid language
    if (in_array($language, Flight::get('possible_languages'))) {

        // Set language
        Flight::set('language', $language);

        // Continue to next route
        return true;
    }
});

// define all other routes
kamov commented 11 years ago

Fabulous! I will try.

Thank you.

kamov commented 11 years ago

Hi,

I try use your code, and the problem is that next route is not found.

I change a bit the code and now seem work.

Check below:

Flight::set('possible_languages', array('en', 'de', 'fr', 'it'));// Setup possible languages
Flight::set('language', 'en');// Set default language if not present in url
// Setup route to check the language - add here /[a-z]+ because is not found the next route
Flight::route('(/@lang:[a-z]{2}/[a-z]+)', function($lang){ 
    // Check if valid language
    if (in_array($lang, Flight::get('possible_languages'))) {
        // Set language
        Flight::set('language', $lang);
        // Continue to next route
        return true;
    }
});
/* Others Routing */
Flight::route('/[a-z]{2}/login', array('AuthController','login')); // added [a-z]{2}

URL: www.example.com/it/login => work fine, firstly is load first route, then second route

What do you think?

Bye

sah-comp commented 11 years ago

Following the suggested code i have found that i have to add a piece of (/[0-9a-z]+) in the default language route for every segment of my URLs i use later on.

Shouldn't it be possible to write:

Flight::route('(/@language:[a-z]{2})(/*)', function($language) {});

instead of

Flight::route('(/@language:[a-z]{2})(/[0-9a-z]+)(/[0-9a-z]+)', function($language) {});

Here is my routes.php so far. It works as expected, but if a want to add a route for e.g. /editor/@type/@action(@id) i will have to add (/[0-9a-z]+) to my language setter route as many times as my urls may get deep?!

/**
 * Change the default language.
 */
Flight::route('(/@language:[a-z]{2})(/[0-9a-z]+)(/[0-9a-z]+)', function($language) {
    error_log('set lang...' . $language);
    if (in_array($language, Flight::get('possible_languages'))) {
        Flight::set('language', $language);   
    }
    return true;
});

/**
 * Route the root to our welcome controller.
 */
Flight::route('(/[a-z]{2})/', array('Controller_Welcome', 'index'));

/**
 * Route to the system controller.
 */
Flight::route('(/[a-z]{2})/admin', array('Controller_Admin', 'index'));
Flight::route('(/[a-z]{2})/admin/index', array('Controller_Admin', 'index'));

/**
 * Show a 404 error page if no route has jumped in yet.
 */
Flight::map('notFound', function() {
    Flight::render('404', array(), 'content');
    Flight::render('html5', array(
        'language' => Flight::get('language'),
        'title' => I18n::__('notfound_head_title')
    ));
});
kamov commented 11 years ago

I have the same problem, I also need add /[a-z]{2}/ to any routes...

Not find yet a solution.

I hope @mikecao can help

Otherwise with .htaccess can be fixed in some way.

mikecao commented 11 years ago

Unfortunately you will need to add the language detection /[a-z]{2}/ to all your routes because it exists as part of the url. What you can do is use name parameters so you don't have to create so many custom routes:

Flight::route('(/@lang:[a-z]{2})/@page', function($lang, $page){
    if (!empty($lang)) {
        // Set language
    }

    // Load page controller
});

@sah-comp There was a bug in the router code. With the latest commit f64774881fdd810ec4d32b3001e0fa32d761a5e2 you should now be able to do:

Flight::route('/@lang:[a-z]{2}/*', function($lang){
    // Set language
});
sah-comp commented 11 years ago

For me this is the fix.

I can now use the following as my first route:

Flight::route('(/@language:[a-z]{2})(/*)', function($language) {
     // set the language...
     return true;
});

//other routes with optional language code follow...

Thanks so much.

fatihmert commented 9 years ago

Hello,

I guess, I'm late :/ but I don't want create new commit. My lang route func that like; (but doesn't work, flifhtphp show to 404 error)

Flight::route('(/@lang:[a-z]{2})',function($lang){
    foreach (glob("lang/*.php") as $dosya) {
        if(basename($dosya,".php") == $lang){
            Flight::set('lang',$lang);
            return true;
        }
    }
});

include("lang/".Flight::get('lang').".php");

Flight::route('/',function(){
    echo "Hello";
});
mikecao commented 9 years ago

@fatihmert Your use of include it will run immediately where that line is, which is before Flight even starts up.