(created at: February 6, 2015; last update: September 14, 2015)
Before creating a multilanguage site we need to make sure we have the administration area of the languages. So, in the dashboard we will create a controller named languages, that will take care of administering the languages.
The table
First of all let’s create a table with the languages.
CREATE TABLE `languages` ( `id` int NOT NULL AUTO_INCREMENT PRIMARY KEY, `language_name` varchar(100) NOT NULL, `language_directory` varchar(100) NOT NULL, `slug` varchar(10) NOT NULL, `language_code` varchar(20), `default` tinyint(1) NOT NULL DEFAULT '0' ) COMMENT='' ENGINE='MyISAM' COLLATE 'utf8_general_ci';
Some explaining:
- language_name will be the language name;
- language_directory will be the language directory that will be found inside the application/language directory
- slug will be the URL slug for the language;
- language_code will be the language code that will appear in the html page.
The controller
Now let’s create the Languages.php file inside application/controllers/admin/ directory:
<?php defined('BASEPATH') OR exit('No direct script access allowed'); class Languages extends Admin_Controller { function __construct() { parent::__construct(); $this->load->library('form_validation'); $this->load->model('language_model'); } public function index() { } public function create() { } public function update() { } public function delete() { } }
The model
We will create a Language_model.php inside application/models directory:
<?php defined('BASEPATH') OR exit('No direct script access allowed'); class Language_model extends CI_Model { public function __construct() { parent::__construct(); } public function get_all() { } public function get_by_id() { } public function create() { } public function update() { } public function delete() { } }
The workings
The index() method of languages controller
This method will display all the languages that have been added
public function index() { $this->data['languages'] = $this->language_model->get_all(); $this->render('admin/languages/index_view'); }
The index() method requests a get_all() method from the Language_model. So let’s go to our model and create the method:
public function get_all($where = NULL) { if(isset($where)) { $this->db->where($where); } $this->db->order_by('language_name','ASC'); $query = $this->db->get('languages'); if($query->num_rows()>0) { return $query->result(); } return FALSE; }
The application/views/admin/languages/index_view.php:
<?php defined('BASEPATH') OR exit('No direct script access allowed');?> <div class="container" style="margin-top:60px;"> <div class="row"> <div class="col-lg-12"> <a href="<?php echo site_url('admin/languages/create');?>" class="btn btn-primary">Add language</a> </div> </div> <div class="row"> <div class="col-lg-12" style="margin-top: 10px;"> <?php echo '<table class="table table-hover table-bordered table-condensed">'; echo '<tr><td>ID</td><td>Language name</td></td><td>Slug</td><td>Language directory</td><td>Language code</td><td>Default</td><td>Operations</td></tr>'; if(!empty($languages)) { foreach($languages as $lang) { echo '<tr>'; echo '<td>'.$lang->id.'</td><td>'.$lang->language_name.'</td><td>'.$lang->slug.'</td><td>'.$lang->language_directory.'</td><td>'.$lang->language_code.'</td>'; echo '<td>'; echo ($lang->default == '1') ? '<span class="glyphicon glyphicon-ok"></span>' : ' '; echo '</td>'; echo '<td>'.anchor('admin/languages/update/'.$lang->id,'<span class="glyphicon glyphicon-pencil"></span>').' '.anchor('admin/languages/delete/'.$lang->id,'<span class="glyphicon glyphicon-remove"></span>').'</td>'; echo '</tr>'; } } echo '</table>'; ?> </div> </div> </div>
The create() method of languages controller
public function create() { $this->form_validation->set_rules('language_name', 'Language name','trim|required|is_unique[languages.language_name]'); $this->form_validation->set_rules('language_slug','Slug','trim|alpha_dash|required|is_unique[languages.slug]'); $this->form_validation->set_rules('language_directory', 'Language directory','trim|required'); $this->form_validation->set_rules('language_code','Language code','trim|alpha_dash|required|is_unique[languages.language_code]'); $this->form_validation->set_rules('default','Default','trim|in_list[0,1]'); if($this->form_validation->run()===FALSE) { $this->render('admin/languages/create_view'); } else { $new_language = array( 'language_name' => $this->input->post('language_name'), 'slug' => $this->input->post('language_slug'), 'language_directory' => $this->input->post('language_directory'), 'language_code' => $this->input->post('language_code'), 'default' => $this->input->post('default') ); $this->session->set_flashdata('message', 'Language added successfully'); if (!$this->language_model->create($new_language)) { $this->session->set_flashdata('message', 'There was an error inserting the new language'); } redirect('admin/languages', 'refresh'); } }
The create() method of language_model:
public function create($data) { if($data['default']=='1') { $this->db->where('default', '1'); $this->db->update('languages', array('default'=>'0')); } return $this->db->insert('languages',$data); }
The application/views/admin/languages/create_view.php:
<?php defined('BASEPATH') OR exit('No direct script access allowed');?> <div class="container" style="margin-top:60px;"> <div class="row"> <div class="col-lg-4 col-lg-offset-4"> <h1>Add language</h1> <?php echo form_open('',array('class'=>'form-horizontal'));?> <div class="form-group"> <?php echo form_label('Language name','language_name'); echo form_error('language_name'); echo form_input('language_name',set_value('language_name'),'class="form-control"'); ?> </div> <div class="form-group"> <?php echo form_label('Language slug','language_slug'); echo form_error('language_slug'); echo form_input('language_slug',set_value('language_slug'),'class="form-control"'); ?> </div> <div class="form-group"> <?php echo form_label('Language directory','language_directory'); echo form_error('language_directory'); echo form_input('language_directory',set_value('language_directory'),'class="form-control"'); ?> </div> <div class="form-group"> <?php echo form_label('Language code','language_code'); echo form_error('language_code'); echo form_input('language_code',set_value('language_code'),'class="form-control"'); ?> </div> <div class="form-group"> <?php echo form_label('Default language','default'); echo form_dropdown('default',array('0' => 'Not default', '1'=>'Default'),set_value('default',0),'class="form-control"'); ?> </div> <?php echo form_submit('submit', 'Add language', 'class="btn btn-primary btn-lg btn-block"');?> <?php echo form_close();?> </div> </div> </div>
The update() method of the languages controller:
public function update($language_id = NULL) { $this->form_validation->set_rules('language_name', 'Language name','trim|required'); $this->form_validation->set_rules('language_slug','Slug','trim|alpha_dash|required'); $this->form_validation->set_rules('language_directory','Language directory','trim|required'); $this->form_validation->set_rules('language_code','Language code','trim|alpha_dash|required'); $this->form_validation->set_rules('default','Default','trim|in_list[0,1]'); $this->form_validation->set_rules('language_id','Language ID','trim|integer'); $language_id = isset($language_id) ? (int) $language_id : (int) $this->input->post('language_id'); if($this->form_validation->run()===FALSE) { $language = $this->language_model->get_by_id($language_id); if($language!==FALSE) { $this->data['language'] = $language; $this->render('admin/languages/edit_view'); } else { $this->session->set_flashdata('message', 'The ID for the language doesn\'t exist'); redirect('admin/languages', 'refresh'); } } else { $new_data = array( 'language_name' => $this->input->post('language_name'), 'slug' => $this->input->post('language_slug'), 'language_directory' => $this->input->post('language_directory'), 'language_code' => $this->input->post('language_code'), 'default' => $this->input->post('default') ); $this->session->set_flashdata('message', 'Language updated successfuly'); if (!$this->language_model->update($language_id, $new_data)) { $this->session->set_flashdata('message', 'There was an error in updating the language'); } redirect('admin/languages', 'refresh'); } }
…the get_by_id() method of the language_model
public function get_by_id($id = NULL) { if(isset($id) && is_int($id)) { $this->db->where('id',$id); $query = $this->db->get('languages'); if($query->num_rows()==1) { return $query->row(); } } return FALSE; }
…and the update() method of the language_model:
public function update($language_id, $data) { if($data['default']=='1') { $this->db->where('default', '1'); $this->db->update('languages', array('default'=>'0')); } $this->db->where('id',$language_id); return $this->db->update('languages',$data); }
…and the application/views/admin/languages/edit_view.php:
<?php defined('BASEPATH') OR exit('No direct script access allowed');?> <div class="container" style="margin-top:60px;"> <div class="row"> <div class="col-lg-4 col-lg-offset-4"> <h1>Edit language</h1> <?php echo form_open('',array('class'=>'form-horizontal'));?> <div class="form-group"> <?php echo form_label('Language name','language_name'); echo form_error('language_name'); echo form_input('language_name',set_value('language_name',$language->language_name),'class="form-control"'); ?> </div> <div class="form-group"> <?php echo form_label('Language slug','language_slug'); echo form_error('language_slug'); echo form_input('language_slug',set_value('language_slug',$language->slug),'class="form-control"'); ?> </div> <div class="form-group"> <?php echo form_label('Language directory','language_directory'); echo form_error('language_directory'); echo form_input('language_directory',set_value('language_directory',$language->language_directory),'class="form-control"'); ?> </div> <div class="form-group"> <?php echo form_label('Language code','language_code'); echo form_error('language_code'); echo form_input('language_code',set_value('language_code',$language->language_code),'class="form-control"'); ?> </div> <div class="form-group"> <?php echo form_label('Default language','default'); echo form_dropdown('default',array('0' => 'Not default', '1'=>'Default'),set_value('default',$language->default),'class="form-control"'); ?> </div> <?php echo form_error('language_id');?> <?php echo form_hidden('language_id',$language->id);?> <?php echo form_submit('submit', 'Edit language', 'class="btn btn-primary btn-lg btn-block"');?> <?php echo form_close();?> </div> </div> </div>
The delete() method of the languages controller:
public function delete($language_id) { if(($language = $this->language_model->get_by_id($language_id)) && $language->default == '1') { $this->session->set_flashdata('message','I can\'t delete a default language. First set another default language.'); } elseif($this->language_model->delete($language_id) === FALSE) { $this->session->set_flashdata('message', 'There was an error in deleting the language'); } else { $this->session->set_flashdata('message', 'Language deleted successfuly'); } redirect('admin/languages','refresh'); }
And the delete() method of language_model:
public function delete($language_id) { return $this->db->delete('languages', array('id'=>$language_id)); }
Cool. The easy part is done. After this we will have to see how we can pass the language slug to our controllers when someone is accessing a link.
Obviously (but better to ask…who knows? 🙂 ), language_model.php inside application/models should be Language_model.php (capitalize just the first L), right?
Great and useful tutorial, of course.
Right
I think you forgot to mention the codes included with this function
public function get_by_id()
{
}
When you try to edit a language in the dashboard, an error is raised: “The ID for the language doesn’t exist”
In your Languages Controller inside the update function, you have a condition where the cuirrent language is equal or not to the ID of the language that has to be updated. If the condition is met, you will be redirected to the edit view of the language, otherwise, you cannot alter that language.
Good tutorial by the way. This is new and updated and I’m learning so much with this. I was wondering If you can make a tutorial about migrations in CI 3
Wow… a lot of bugs in my tutorials. Thank you for taking the time to notice the errors and report them to me. Just did a new update. As thank you, I will create a tutorial about migrations just for you. 🙂
this line seems to be wrong…
echo form_input(‘language_directory’,set_value(‘language_directory’,$language->directory),’class=”form-control”‘);
correct
echo form_input(‘language_directory’,set_value(‘language_directory’,$language->language_directory),’class=”form-control”‘);
🙂
You are right. Thank you.
Thanks for this very detailed tutorial. It works just fine. Anyway when I try to post the empty form (just to trigger the validation) I am still getting the error messages in English while I have the default language set to Dutch.
I just did this in the Admin_controller (as you do in the Public_Controller, which works just finein the public area):
$language = $this->data[‘current_lang’];
$idiom = $language[‘language_directory’];
$this->load->language(‘form_validation_lang’,$idiom);
But with any success.
Do you have any tip for me? I will appreciate it.
Hello. You need to get the translation files for form validation. Those are specific to CodeIgniter. You can find the translation files in here: https://github.com/bcit-ci/codeigniter3-translations
Thanks for your reply. I have the translation already installed. I just want to show the validations according to the current language.
Try this before setting the validation rules… don’t know if it works… $this->config->set_item(‘language’, ‘dutch’);
Hi avenirer,
This works! Of course you really don’t want to hard code the current language. So I need to get the current language in the controller.
In my Admin controller I have done:
$language = $this->data[‘current_lang’];
$idiom = $language[‘language_directory’];
echo $idiom;
If I echo the $idiom I get as expected ‘dutch’.
In the Groups controller I do:
$this->config->set_item(‘language’, $idiom);
But I got ‘undefined variable’ $idiom.
Thanks for your help.
If you look in a previous tutorial you will see that I passed the language in a session variable in MY_Controller, which is extended by Admin_Controller. So you can get that language from the session. Also, regarding your $idiom problem, of course you cannot access it, because you defined it in another class. Search Google for “accessing variables properties from classes php” (or something in these lines)
Thanks for your help. I have chosen to set:
$this->config->set_item(‘language’, $idiom);
directly in the Admin controller so I don’t have to set this in all my controllers or models.
It looks that this works just fine (for me).
I am coming from Laravel, so I am fighting a little bit with Codeigniter.
Thanks again for your help and for this tutorial (the best out there so far).