(created at: March 17, 2015; last update: December 7, 2015)
Well… This is getting rather complicated… After we’ve “personalized” the controllers and methods for a multilanguage site, it’s time to make sure we won’t do something wrong once we start developing it. So why not set everything that is related to the language inside our MY_Controller.
We will retrieve the languages from our language_model we’ve created in Step 4.1 – Create the admin area for a multilanguage site in CodeIgniter. We will use the language slug as a key in order to identify the language. Also, we will need ‘language_directory’, which will help us identify the language file inside ‘application/language’ directory. ‘Default’ will simply tell us if that particular language is the default language (1 = default). We need to find out if the language is the default language because we don’t need that language’s slug to pe appended to our urls if it’s the default language.
Now, let me show you MY_Controller, and after that I will explain you what were my thoughts. Bare in mind that this is a continuation of what we’ve already written in our MY_Controller file:
class MY_Controller extends CI_Controller { protected $data = array(); protected $langs = array(); protected $default_lang; protected $current_lang; function __construct() { parent::__construct(); // First of all let's see what languages we have and also get the default language $this->load->model('language_model'); $available_languages = $this->language_model->get_all(); if(isset($available_languages)) { foreach($available_languages as $lang) { $this->langs[$lang->slug] = array('id'=>$lang->id,'slug'=>$lang->slug,'language_directory'=>$lang->language_directory,'language_code'=>$lang->language_code,'default'=>$lang->default); if($lang->default == '1') $this->default_lang = $lang->slug; } } // Verify if we have a language set in the URL; $lang_slug = $this->uri->segment(1); // If we do, and we have that languages in our set of languages we store the language slug in the session if(isset($lang_slug) && array_key_exists($lang_slug, $this->langs)) { $this->current_lang = $lang_slug; $_SESSION['set_language'] = $lang_slug; } // If not, we look to see if the language session variable is set elseif(isset($_SESSION['set_language'])) { $this->current_lang = $_SESSION['set_language']; } // If not, we set the language session to the default language else { $this->current_lang = $this->default_lang; $_SESSION['set_language'] = $this->default_lang; } // Now we store the languages as a $data key, just in case we need them in our views $this->data['langs'] = $this->langs; // Also let's have our current language in a $data key $this->data['current_lang'] = $this->langs[$this->current_lang]; // For links inside our views we only need the lang slug. If the current language is the default language we don't need to append the language slug to our links if($this->current_lang != $this->default_lang) { $this->data['lang_slug'] = $this->current_lang.'/'; } else { $this->data['lang_slug'] = ''; } $this->data['page_title'] = 'CI App'; $this->data['page_description'] = 'CI_App'; $this->data['before_head'] = ''; $this->data['before_body'] = ''; } protected function render($the_view = NULL, $template = 'master') { if($template == 'json' || $this->input->is_ajax_request()) { header('Content-Type: application/json'); echo json_encode($this->data); } elseif(is_null($template)) { $this->load->view($the_view,$this->data); } else { $this->data['the_view_content'] = (is_null($the_view)) ? '' : $this->load->view($the_view, $this->data, TRUE); $this->load->view('templates/' . $template . '_view', $this->data); } } }
Ok…
As you can see, we’ve started by defining some properties: the $langs, the $current_lang, and the $default_lang. The $langs property will contain the languages we’ve talked about earlier. The $current_lang will hold the current language data, and the $default_lang will contain data regarding the default language. Inside the comments starting with line … I left you something that we will use later, after we’ve added the languages module inside our admin area.
Now… according to the inline comments you can see that we will search for the slug inside the urls. If there is a slug and that slug exists in our defined languages array, we will set the $current_lang property to the slug. Also, we will keep that in our session, so make sure you’ve autoloaded the sessions library.
We will pass all our defined languages to a $this->data[‘langs’] so that it will be available to our views. Who knows, maybe later we will create a menu where we will allow the visitors to select the language. Also we will pass the view the current language.
I’ve made a $this->data[‘lang_slug’] because we need to be brief when we will create links. This way, when we will create links we will simply do something like: echo site_url($lang_slug.’/controller/method’);
If the site were to be in the default language, that won’t affect our links.
Hey there!
Your approach of how to implement a multilingual CI website is awesome! Congrats.
Let me just ask you if have you ever tried to implement it using the CI_Lang library, instead of store your language keys and translations on database?
Cheers,
Rogério.
That’s exactly the point with MY_Controller. What I did in MY_Controller is exactly for being used with the CI_Lang. Now we can use the language library to retrieve whatever we want.
For example, we can have a single view of a page for two or more than two languages. As you can see, at line 41 we’ve defined $this->data[‘current_lang’]. That is an array containing all the data needed to work with the current language (the language that the visitor selected).
We start by creating a language file, let’s say blog_lang.php, inside the application/language/english, application/language/french or whatever other languages we might have. Then, in the constructor of the controllers, or even in the MY_Controller, we load that language file with:
$language = $_SESSION[‘set_language’];
$idiom = $this->langs[$language][‘language_directory’];
$this->lang->load(‘blog’, $idiom);
And after that, in the views we simply replace our strings with what we’ve defined inside the language files. Instead of writing:
echo ‘This is a great page’;
…we write:
echo $this->lang->line(‘the_teaser’);
And we define the ‘the_teaser’ in every language file:
$lang[‘the_teaser’] = ‘This is a great page’;
This way, when the visitor changes the language, he will be served with that line in his language.
I guess I need to do another tutorial after this one, don’t I?
“I guess I need to do another tutorial after this one, don’t I?”
It would be greta to better understanding 🙂
Missing single-quote on line #19 (just before language_directory means this version of MY_Controller will never work.
Shown:
$this->langs[$lang->slug] = array(‘id’=>$lang->id,’slug’=>$lang->slug,language_directory’=>$lang->language_directory,’language_code’=>$lang->language_code,’default’=>$lang->default);
Should be:
$this->langs[$lang->slug] = array(‘id’=>$lang->id,’slug’=>$lang->slug,’language_directory’=>$lang->language_directory,’language_code’=>$lang->language_code,’default’=>$lang->default);
Thank you for noticing.
Hi ,
I’m developping a multilingual site using your tutorial. Thanks.
I have created my owns libraries, everything works correctly till I use ajax. The ajax method works correctly and do what i want, but “regenerate” the session variable with default language.
For example, if I choose English, everything is ok, and load the langs files properly, but when i try to comment o rate (ajax), the libraries load the langs files again and the session variable contain the default language.
i read this, but i’m can’t find the solution.
http://www.codeigniter.com/userguide3/libraries/sessions.html?highlight=ajax#a-note-about-concurrency
Could you help me out?
Thanks in advance.
I’ve changed the MY_Controller a bit. I hope this helps.
May I ask you for a full project with all files, if it’s possible please.