0

I'm new to Kohana, using version 3.3.3.1, I'm trying to build a simple dynamic site with the content/pages stored in mySQL DB. The site should have multiple languages. I tried searching everywhere for a good solution/module but I couldn't find anything that works with latest version of Kohana. I tried also this: https://github.com/shockiii/kohana-multilang but it's not working on the latest kohana.

I want to put the language in URL like this (and possibly hide the parameter for the default language):

http://www.domain.com/topics/page-name-here.html   -- this would be default EN
http://www.domain.com/de/test/some-page-name-here.html
http://www.domain.com/fr/category/other-page-name-here.html

In my bootstrap.php I have the following route (before adding the language logic):

Route::set('page', '(<category>)(/<pagename>.html)', array(
    'category' => '.*', 
    'pagename' => '.*'))
    ->defaults(array(
                'controller' => 'Page',
                'action' => 'index',
)); 

I want to have all this multi-language logic inside a module if possible. But I read about overriding the Request, URL, Route, and other classes to be able to do that.

What is the best way I can do this? What should I do/change and where to start?

I know this is more a general question, but any help or guidance is greatly appreciated.

Thanks very much!

2 Answers2

0

I found a great module that is working with Kohana 3.3.3: https://github.com/creatoro/flexilang

0

1) add <lang> into routes in bootstrap.php:

Route::set('default', '((<lang>)(/)(<controller>)(/<action>(/<id>)))', array('lang' => "({$langs_abr})",'id'=>'.+'))
    ->defaults(array(
        'lang'          => $default_lang,
        'controller'    => 'Welcome',
        'action'        => 'index',
    ));

- define $default_lang somehow - I use siteconfig.php file placed inside application/config -see below.

2) Extend/redefine factory method in Request Controller:

<?php defined('SYSPATH') or die('No direct script access.');

class Request extends Kohana_Request {
    /**
     * Main request singleton instance. If no URI is provided, the URI will
     * be automatically detected using PATH_INFO, REQUEST_URI, or PHP_SELF.
     *
     * @param   string   URI of the request
     * @return  Request
     */
    public static function factory( $uri = TRUE,$client_params = array(), $allow_external = TRUE, $injected_routes = array())
    {

        $instance = parent::factory($uri);

        $index_page     = Kohana::$index_file;
        $siteconfig     = Model_Siteconfig::load();
        $lang_uri_abbr  = $siteconfig['lang_uri_abbr'];
        $default_lang   = $siteconfig['language_abbr'];
        $lang_ignore    = $siteconfig['lang_ignore'];

        $ignore_urls    = $siteconfig['ignore_urls'];

        /* get the lang_abbr from uri segments */
        $segments = explode('/',$instance->detect_uri());

        $uri_detection  = array_intersect($segments, $ignore_urls);

        if(empty($uri_detection))
        {

            $lang_abbr = isset($segments[1]) ? $segments[1]:'';

            /* get current language */
            $cur_lang = $instance->param('lang',$default_lang);

            /* check for invalid abbreviation */
            if( ! isset($lang_uri_abbr[$lang_abbr]))
            {       
                /* check for abbreviation to be ignored */
                if ($cur_lang != $lang_ignore) {
                    /* check and set the default uri identifier */
                    $index_page .= empty($index_page) ? $default_lang : "/$default_lang";

                    /* redirect after inserting language id */
                    header('Location: '.URL::base().$index_page . $instance->detect_uri());
                    die();
                }
            }
        }

        return $instance;

    }
}

I use "siteconfig" array with language definitions:

array(
        'language_abbr'     => 'cs',
        'lang_uri_abbr'     => array("cs" => "Ĩesky", "en" => "english"),
        'lang_ignore'       => 'it', 
)

3) Extend/redefine "redirect" method in Controller class for automatic language adding:

<?php defined('SYSPATH') or die('No direct script access.');

class Controller extends Kohana_Controller {

    /**
     * Issues a HTTP redirect.
     *
     * Proxies to the [HTTP::redirect] method.
     *
     * @param  string  $uri   URI to redirect to
     * @param  int     $code  HTTP Status code to use for the redirect
     * @throws HTTP_Exception
     */
    public static function redirect($uri = '', $code = 302)
    {
        $lng = Request::current()->param('lang');
        return HTTP::redirect( (string) '/'.$lng.$uri, $code);
    }
}

If You would use HTML class (for templates for example), you should probably redefine some other methods like "anchor" for creating anchors with automatic language adding:

<?php defined('SYSPATH') OR die('No direct script access.');

class HTML extends Kohana_HTML {

    /**
     * Create HTML link anchors. Note that the title is not escaped, to allow
     * HTML elements within links (images, etc).
     *
     *     echo HTML::anchor('/user/profile', 'My Profile');
     *
     * @param   string  $uri        URL or URI string
     * @param   string  $title      link text
     * @param   array   $attributes HTML anchor attributes
     * @param   mixed   $protocol   protocol to pass to URL::base()
     * @param   boolean $index      include the index page
     * @return  string
     * @uses    URL::base
     * @uses    URL::site
     * @uses    HTML::attributes
     */
    public static function anchor($uri, $title = NULL, array $attributes = NULL, $protocol = NULL, $index = FALSE)
    {

        //default language
        $lng = Request::current()->param('lang');

        if ($title === NULL)
        {
            // Use the URI as the title
            $title = $uri;
        }

        if ($uri === '')
        {
            // Only use the base URL
            $uri = URL::base($protocol, $index).$lng;
        }
        else
        {
            if (strpos($uri, '://') !== FALSE)
            {
                if (HTML::$windowed_urls === TRUE AND empty($attributes['target']))
                {
                    // Make the link open in a new window
                    $attributes['target'] = '_blank';
                }
            }
            elseif ($uri[0] !== '#')
            {
                // Make the URI absolute for non-id anchors
                $uri = URL::site($lng.$uri, $protocol, $index);
            }
        }

        // Add the sanitized link to the attributes
        $attributes['href'] = $uri;

        return '<a'.HTML::attributes($attributes).'>'.$title.'</a>';
    }

}
leosek
  • 16
  • 3