├── README.md ├── application ├── config │ └── language_editor.php ├── controllers │ └── language.php ├── core │ └── MY_Lang.php ├── language │ ├── english │ │ └── language_lang.php │ └── polish │ │ └── language_lang.php ├── models │ └── model_language.php └── views │ └── language │ ├── dir_list.php │ ├── dir_list_view.php │ ├── edit_lang_file.php │ └── file_list.php ├── css └── style.css └── frontend_translator.sql /README.md: -------------------------------------------------------------------------------- 1 | CodeIgniter Frontend Language Files Editor 2 | ============= 3 | 4 | It's a frontend for editing language files for CodeIgniter 2.x stored in `/application/language` directory. 5 | 6 | WARNING! 7 | ----------- 8 | It's not a good idea to put this files unprotected on production server. 9 | 10 | It's probably ok on localhost when your project is still in development. But **you should implement some authentication** before go live. 11 | 12 | If you use some library for authentication, add one line to contructor in controller like: 13 | 14 | ``` 15 | if(!login){ 16 | show_404(); 17 | } 18 | ``` 19 | 20 | Basic idea 21 | ----------- 22 | 23 | * Using Language Class my files for language are stored in `/my_application_folder/language/` 24 | * I want edit all pairs `key=>value` for languages without opening my file. Add new keys which will be enable for another languages. 25 | * I want to create new languages, new files and copy structure of file to another language while new file is created 26 | * I want to delete languages or files. 27 | * I want to delete one key from all files and from database. 28 | * I want to remove keys from database for file if file does not exist in other languages 29 | * I want to create backup file just in case 30 | * I want to set main language and see translation of it while editing other language 31 | * I want to add comments 32 | 33 | Requirements 34 | ----------- 35 | 36 | Codeigniter 2.x, jQuery, database 37 | 38 | Installation 39 | ----------- 40 | 41 | Grab it from github and extract to corresponding folders. 42 | 43 | Be aware that there is `application/core/MY_Lang.php` file, so if you use i18n for multilanguage or any other library for that purpose most likely you have MY_Lang in that folder already. So be sure that you want to overwrite it. 44 | 45 | How it works 46 | ----------- 47 | 48 | You call it by entering address: `http://yourdomainhere/language/` 49 | 50 | The list of languages are created by folder structure in `/my_application_folder/language/`. 51 | 52 | The list of files are created by content in language directory. Only `.php` files are considered and backup files are excluded. 53 | 54 | When you choose some file for the first time (keys are not in database) you will be asked if you want to add them. 55 | 56 | If there are some differences between keys in file and keys in database we have two options. 57 | 1. Some keys exists in file and not in database - you will be asked if you want to add them. Until than, that keys will not be available in form. Warning! If you save your file before adding those keys, the translation and key will be erased from the file. 58 | 2. Some keys exists in database and not in the file - you will see (NEW!) next to key name. You will see that most likely when new key was added to the file in other language. 59 | 60 | In case anything goes wrong I added copy function which creates backup file so you can restore last file after crash. Better be save than sorry ;o) 61 | 62 | If you delete key from file it is also deleted from other languages and database. 63 | 64 | All translations are escaped by `addslashes` php function. So if you're using `$this->lang->line('key')` and there was some escaping, remember to use `stripslashes` before you echo `$this..`. You could also use `core/My_Lang.php` file which already has it. Then you don't have to worry about that. 65 | 66 | If you have CSRF protection on - remember that it has expire time - so don't edit your files too long ;o) 67 | 68 | I assume that if you want a line break in your translation, you need to add `
` tag. 69 | 70 | This frontend already use language class. All buttons, information etc are already put into `language_lang.php` file so you can translate it into your language. 71 | 72 | Comments 73 | ----------- 74 | 75 | You can add comments to your `key=>translation`. They are stored in database and added as `/* comment */` after saving changes in file. Comments are shared to the same files for different languages. You can disable it in `config/language_editor.php` file. 76 | 77 | Todo 78 | ----------- 79 | 80 | * Switch button between input/textarea for translations 81 | * textarea config - on/off/string length for which textarea will be not input 82 | * line break support - on/off 83 | 84 | 85 | License 86 | ----------- 87 | 88 | MIT 89 | -------------------------------------------------------------------------------- /application/config/language_editor.php: -------------------------------------------------------------------------------- 1 | load->helper(array('url','file','language','form')); //load this helpers if youre not doing it in autoload 24 | $this->load->model(array('model_language')); 25 | $this->load->library(array('session')); //load session if youre not doing it in autoload 26 | $this->load->database(); //load database if youre not doing it in autoload 27 | $this->load->language('language','english'); //you can delete it if you have translation for you language 28 | $this->config->load('language_editor'); 29 | } 30 | 31 | function index(){ 32 | $this->lang_list(); 33 | } 34 | 35 | /** 36 | * Get language list based on directories or files in it. 37 | * 38 | * @return void 39 | */ 40 | function lang_list($dir=FALSE){ 41 | if($dir===FALSE){ 42 | $data['dir'] = $this->model_language->get_languages(); 43 | $this->load->view('language/dir_list',$data); 44 | }else{ 45 | $data['sel_dir']=$dir; 46 | $data['dir'] = $this->model_language->get_languages(); 47 | $data['files'] = $this->model_language->get_list_lfiles($dir); 48 | $this->load->view('language/file_list',$data); 49 | } 50 | } 51 | 52 | /** 53 | * Get list of keys and translations from file. 54 | * Check if all keys from file are in database and show new keys available for translate. 55 | * If there is new keys file must should be saved - until then they are not existing in file. 56 | * 57 | * @return void 58 | */ 59 | function lang_file($l=FALSE,$file=FALSE){ 60 | if($l!==FALSE && $file!==FALSE && is_dir(APPPATH."language/$l/") && file_exists(APPPATH."language/$l/$file")){ 61 | require(APPPATH."language/$l/$file"); 62 | $data = array( 63 | 'lang'=>$lang, 64 | 'language'=>$l, 65 | 'file'=>$file 66 | ); 67 | $data['keys'] = $this->model_language->get_keys_from_db($file); /// get keys for this file 68 | if($this->config->item('comments')==1){ 69 | $data['comments'] = $this->model_language->get_comments_from_db($file); 70 | } 71 | if($data['keys']!==FALSE){ 72 | $data['extra_keys'] = array_diff(array_keys($lang),$data['keys']); ///get keys that are in file but not in database 73 | } 74 | $data['dir'] = $this->model_language->get_languages(); 75 | if($this->config->item('language_pattern')==1 && $l!=$this->config->item('language_pattern_lang') && file_exists(APPPATH."language/{$this->config->item('language_pattern_lang')}/$file")){ 76 | require(APPPATH."language/{$this->config->item('language_pattern_lang')}/$file"); 77 | $data['pattern']=$lang; 78 | } 79 | $this->load->view('language/edit_lang_file',$data); 80 | }else{ 81 | $this->session->set_flashdata('error',$this->lang->line('language_error_dir_not_exist')); 82 | redirect('/language'); 83 | } 84 | } 85 | 86 | /** 87 | * Update keys for file - method most likely trigger when we open file for first time. 88 | * 89 | * @return void 90 | */ 91 | function update_all_keys(){ 92 | if($this->input->post('update')){ ///check if form was submitted 93 | $l = $this->prepare_str($this->input->post('language')); 94 | $file = $this->input->post('filename'); 95 | if(!empty($l) && !empty($file) && is_dir(APPPATH."language/$l/") && file_exists(APPPATH."language/$l/$file")){ ///check if hidden fields are passed and if they exists 96 | require(APPPATH."language/$l/$file"); 97 | if($this->model_language->update_all_keys(array_keys($lang),$file)){ ///insert keys from file into database 98 | $this->session->set_flashdata('msg',$this->lang->line('language_msg_success')); 99 | }else{ 100 | $this->session->set_flashdata('error',$this->lang->line('language_error')); 101 | } 102 | redirect($this->config->item('cms_url')."language/lang_file/$l/$file"); 103 | }else{ 104 | $this->session->set_flashdata('error',$this->lang->line('language_error_dir_not_exist')); 105 | redirect('/language'); 106 | } 107 | }else{ 108 | $this->session->set_flashdata('error',$this->lang->line('language_error_no_direct_access')); 109 | redirect('/language'); 110 | } 111 | } 112 | 113 | /** 114 | * Add extra keys from file - method most likely trigger when there where some keys that were in file but not in database. 115 | * 116 | * @return void 117 | */ 118 | function add_extra_keys(){ 119 | if($this->input->post('add_keys')){ 120 | $l = $this->prepare_str($this->input->post('language')); 121 | $file = $this->input->post('filename'); 122 | if(!empty($l) && !empty($file) && is_dir(APPPATH."language/$l/") && file_exists(APPPATH."language/$l/$file")){ ///check if hidden fields are passed and if they exists 123 | require(APPPATH."language/$l/$file"); 124 | $keys = $this->model_language->get_keys_from_db($file); 125 | if(!is_array($lang) || !is_array($keys)){ 126 | redirect("/language/lang_file/$l/$file"); 127 | } 128 | $extra_keys = array_diff(array_keys($lang),$keys); 129 | if($this->model_language->add_keys($extra_keys,$file)){ 130 | $this->session->set_flashdata('msg',$this->lang->line('language_msg_success')); 131 | }else{ 132 | $this->session->set_flashdata('error',$this->lang->line('language_error')); 133 | } 134 | redirect("/language/lang_file/$l/$file"); 135 | }else{ 136 | $this->session->set_flashdata('error',$this->lang->line('language_error_dir_not_exist')); 137 | redirect('/language'); 138 | } 139 | }else{ 140 | $this->session->set_flashdata('error',$this->lang->line('language_error_no_direct_access')); 141 | redirect('/language'); 142 | } 143 | } 144 | 145 | 146 | /** 147 | * Add one key to database. 148 | * 149 | * @return void 150 | */ 151 | function add_one_key(){ 152 | if($this->input->post('add_key')){ 153 | $l = $this->prepare_str($this->input->post('language')); 154 | $file = $this->input->post('filename'); 155 | if(!empty($l) && !empty($file) && is_dir(APPPATH."language/$l/") && file_exists(APPPATH."language/$l/$file")){ ///check if hidden fields are passed and if they exists 156 | require(APPPATH."language/$l/$file"); 157 | $keys = $this->model_language->get_keys_from_db($file); 158 | $new_key = $this->input->post('key'); 159 | if(!is_array($lang) || !is_array($keys)){ 160 | redirect("/language/lang_file/$l/$file"); 161 | } 162 | if(!in_array($new_key,$keys) && array_key_exists($new_key,$lang)){ ///check if its indeed new key that is in file but not in db 163 | if($this->model_language->add_keys(array($new_key),$file)){ 164 | $this->session->set_flashdata('msg',$this->lang->line('language_msg_success')); 165 | }else{ 166 | $this->session->set_flashdata('error',$this->lang->line('language_error')); 167 | } 168 | }else{ 169 | $this->session->set_flashdata('error',$this->lang->line('language_error')); 170 | } 171 | redirect("/language/lang_file/$l/$file"); 172 | }else{ 173 | $this->session->set_flashdata('error',$this->lang->line('language_error_dir_not_exist')); 174 | redirect('/language'); 175 | } 176 | }else{ 177 | $this->session->set_flashdata('error',$this->lang->line('language_error_no_direct_access')); 178 | redirect('/language'); 179 | } 180 | } 181 | 182 | /** 183 | * Update language file. 184 | * If new keys were added, add them to database so they could be available for another language 185 | * 186 | * @return void 187 | */ 188 | function save_language_file(){ 189 | if($this->input->post('change')){ //check if form was submitted 190 | $l = $this->prepare_str($this->input->post('language')); 191 | $file = $this->input->post('filename'); 192 | if(!empty($l) && !empty($file) && is_dir(APPPATH."language/$l/") && file_exists(APPPATH."language/$l/$file")){ 193 | $f = 'model_language->get_keys_from_db($file); 196 | if(empty($keys)||!is_array($keys)){ 197 | $keys=FALSE; 198 | } 199 | foreach($_POST as $key=>$value){ /// create new array 200 | if($keys!==FALSE&&in_array($key,$keys)){ 201 | if($this->input->post('comment_'.$key)){ 202 | $comments[$key] = $this->input->post('comment_'.$key); 203 | $f .= '/* '.$this->input->post('comment_'.$key).' */'."\n"; 204 | }else{ 205 | $comments[$key] = ''; 206 | } 207 | $f .= '$lang[\''.$key.'\']=\''; ///for language array 208 | $f .= addslashes($this->input->post($key,TRUE)).'\';'."\n"; ///for language array , add escaping " 209 | }elseif($pos=strpos($key,'new_key_')!==FALSE){ /// check if there is new key -> strpos is faster than substr 210 | $new_key = $this->prepare_str(trim($this->input->post($key,TRUE))); 211 | if(!empty($new_key)){ 212 | if(!in_array($new_key,$keys) && !in_array($new_key,$new_keys)){ 213 | if($this->input->post('comment_'.$key)){ 214 | $f .= '/* '.$this->input->post('comment_'.$key).' */'."\n"; 215 | } 216 | $f .= '$lang[\''.$new_key.'\']=\''; ///for language array 217 | $f .= addslashes($this->input->post('new_value_'.substr($key,-1))).'\';'."\n"; ///for language array 218 | $new_keys[]=$new_key; 219 | } 220 | } 221 | } 222 | } 223 | $f.= '/* End of file '.$file.' */'; ///closing tags 224 | ///Before we go on, copy files just in case. 225 | if(!isset($new_keys) || (!empty($new_keys) && is_array($new_keys) && $this->model_language->add_keys($new_keys,$file))){ 226 | if(isset($comments) && !empty($comments)){ 227 | $this->model_language->add_comments($comments,$file); 228 | } 229 | copy(APPPATH."language/$l/$file",APPPATH."language/$l/backup_$file"); 230 | $r = file_put_contents(APPPATH."language/$l/$file",$f,LOCK_EX); ///save language file 231 | if($r){ 232 | $this->session->set_flashdata('msg',$this->lang->line('language_file_saved')); 233 | }else{ 234 | $this->session->set_flashdata('error',$this->lang->line('language_file_not_saved')); 235 | } 236 | }else{ 237 | $this->session->set_flashdata('error',$this->lang->line('language_error_keys_db')); 238 | } 239 | redirect("/language/lang_file/$l/$file"); 240 | }else{ 241 | $this->session->set_flashdata('error',$this->lang->line('language_error_dir_not_exist')); 242 | redirect('/language'); 243 | } 244 | }else{ 245 | $this->session->set_flashdata('error',$this->lang->line('language_error_no_direct_access')); 246 | redirect ('/language'); 247 | } 248 | } 249 | 250 | /** 251 | * Create new file 252 | * If file was created by form - create new empty file. 253 | * If file was created from another file - create copy of it 254 | * 255 | * @return void 256 | */ 257 | function create_file(){ 258 | if($this->input->post('create')){ //check if form was submitted 259 | $l = $this->prepare_str($this->input->post('language')); 260 | $file = $this->input->post('filename'); 261 | $lang_ref = $this->input->post('language_refferer'); 262 | if(!empty($l) && !empty($file)){ 263 | if(substr($file,-9)!='_lang.php'){ 264 | $file = $this->prepare_str($file); 265 | $file = $file.'_lang.php'; 266 | } 267 | if(is_dir(APPPATH."language/$l/") && !file_exists(APPPATH."language/$l/$file")){ 268 | if(!empty($lang_ref) && is_dir(APPPATH."language/$lang_ref/") && file_exists(APPPATH."language/$lang_ref/$file")){ 269 | if(copy(APPPATH."language/$lang_ref/$file",APPPATH."language/$l/$file")){ 270 | $this->session->set_flashdata('msg',$this->lang->line('language_file_created')); 271 | redirect("/language/lang_file/$l/$file"); 272 | }else{ 273 | $this->session->set_flashdata('error',$this->lang->line('language_error_creating_permissions')); 274 | redirect("/language/lang_file/$l/$file"); 275 | } 276 | }else{ 277 | $f = "model_language->get_keys_from_db($file); 279 | if(is_array($keys)){ 280 | foreach($keys as $key){ /// create new array 281 | $f .= '$lang[\''.$key.'\']=\'\';'."\n"; ///for language array 282 | } 283 | }else{ 284 | $f .= "\$lang = array();"."\n"; /// our language array 285 | } 286 | $f.= '/* End of file '.$file.' */'; 287 | if(file_put_contents(APPPATH."language/$l/$file",utf8_encode($f),LOCK_EX)){ 288 | $this->session->set_flashdata('msg','File created.'); 289 | redirect("/language/lang_file/$l/$file"); 290 | }else{ 291 | $this->session->set_flashdata('error',$this->lang->line('language_error_creating_permissions')); 292 | redirect("/language/lang_file/$l/$file"); 293 | } 294 | } 295 | }else{ 296 | $this->session->set_flashdata('error',$this->lang->line('language_error_file_exist')); 297 | redirect("/language/lang_list/$l"); 298 | } 299 | }else{ 300 | $this->session->set_flashdata('error',$this->lang->line('language_error_name_required')); 301 | redirect('/language'); 302 | } 303 | }else{ 304 | $this->session->set_flashdata('error',$this->lang->line('language_error_no_direct_access')); 305 | redirect('/language'); 306 | } 307 | } 308 | 309 | /** 310 | * Create new language 311 | * New directory is created 312 | * 313 | * @return void 314 | */ 315 | function create_new_language(){ 316 | if($this->input->post('create')){ 317 | $l = $this->prepare_str($this->input->post('language')); 318 | if(!empty($l) && !is_dir(APPPATH."language/$l/")){ 319 | $l=$this->prepare_str($l); 320 | if(mkdir(APPPATH."language/$l/")){ 321 | $this->session->set_flashdata('msg',$this->lang->line('language_created')); 322 | redirect("/language/lang_list/$l"); 323 | }else{ 324 | $this->session->set_flashdata('error',$this->lang->line('language_error_creating_dir_permissions')); 325 | redirect('/language/create_new_language'); 326 | } 327 | }else{ 328 | $this->session->set_flashdata('error',$this->lang->line('language_error_exist')); 329 | redirect ('/language'); 330 | } 331 | }else{ 332 | $this->session->set_flashdata('error',$this->lang->line('language_error_no_direct_access')); 333 | redirect ('/language'); 334 | } 335 | } 336 | 337 | /** 338 | * Delete language 339 | * Directory and all files in it are deleted 340 | * 341 | * @return void 342 | */ 343 | function delete_language(){ 344 | if($this->input->post('delete')){ //check if form was submitted 345 | $l = $this->prepare_str($this->input->post('language')); 346 | if(!empty($l) && is_dir(APPPATH."language/$l/")){ 347 | if(delete_files(APPPATH."language/$l/", TRUE) && rmdir(APPPATH."language/$l/")){ 348 | $this->session->set_flashdata('msg',$this->lang->line('language_msg_deleted')); 349 | }else{ 350 | $this->session->set_flashdata('error',$this->lang->line('language_error_delete_permissions')); 351 | } 352 | }else{ 353 | $this->session->set_flashdata('error',$this->lang->line('language_langdir_not_exist')); 354 | } 355 | }else{ 356 | $this->session->set_flashdata('error',$this->lang->line('language_error_no_direct_access')); 357 | } 358 | redirect('/language'); 359 | } 360 | 361 | /** 362 | * Delete language file from specified language 363 | * 364 | * @return void 365 | */ 366 | function delete_language_file(){ 367 | if($this->input->post('delete')){ //check if form was submitted 368 | $l = $this->prepare_str($this->input->post('language')); 369 | $file = $this->input->post('filename'); 370 | $file = preg_replace('/[^a-zA-Z0-9-_.]*/','',$file); 371 | if(!empty($l) && !empty($file) && is_dir(APPPATH."language/$l/") && file_exists(APPPATH."language/$l/$file")){ 372 | if(unlink(APPPATH."language/$l/$file")){ 373 | $this->model_language->delete_keys($file); 374 | $this->session->set_flashdata('msg',$this->lang->line('language_file_deleted')); 375 | }else{ 376 | $this->session->set_flashdata('error',$this->lang->line('language_error_delete_file_permissions')); 377 | } 378 | }else{ 379 | $this->session->set_flashdata('error',$this->lang->line('language_error_dir_not_exist')); 380 | } 381 | redirect("/language/lang_list/$l"); 382 | }else{ 383 | $this->session->set_flashdata('error',$this->lang->line('language_error_no_direct_access')); 384 | } 385 | redirect('/language'); 386 | } 387 | 388 | /** 389 | * Delete key from database and all files. Call by AJAX. 390 | * 391 | * @return void 392 | */ 393 | function remove_key(){ 394 | if(!$this->input->is_ajax_request()){ 395 | redirect('/language'); 396 | }else{ 397 | $del_key=substr($this->input->post('key'),4); 398 | $file=$this->input->post('filename'); 399 | $file = preg_replace('/[^a-zA-Z0-9-_.]*/','',$file); 400 | $l = $this->prepare_str($this->input->post('language')); 401 | if(!empty($l) && !empty($file) && is_dir(APPPATH."language/$l/") && file_exists(APPPATH."language/$l/$file")){ 402 | $in_lang = $this->model_language->file_in_language($file); 403 | if(is_array($in_lang)){ 404 | foreach($in_lang as $in){ 405 | unset($lang); 406 | if($this->config->item('comments')==1){ 407 | $comments = $this->model_language->get_comments_from_db($file); 408 | } 409 | require(APPPATH."language/$in/$file"); 410 | if(array_key_exists($del_key,$lang)){ 411 | $f = '$val){ /// create new array 413 | if($key_lang!=$del_key){ 414 | if(isset($comments) && array_key_exists($key_lang,$comments) && !empty($comments[$key_lang])){ 415 | $f .= '/* '.$comments[$key_lang].' */'."\n"; 416 | } 417 | $f .= '$lang[\''.$key_lang.'\']=\''; ///for language array 418 | $f .= addslashes($val).'\';'."\n"; ///for language array , add escaping " 419 | } 420 | } 421 | $f.= '/* End of file '.$file.' */'; ///closing tags 422 | copy(APPPATH."language/$in/$file",APPPATH."language/$in/backup_$file"); 423 | file_put_contents(APPPATH."language/$in/$file",$f,LOCK_EX); 424 | } 425 | } 426 | } 427 | $this->model_language->delete_one_key($del_key,$file); 428 | echo json_encode(array('response'=>TRUE,'msg'=>$this->lang->line('language_key_deleted'))); 429 | }else{ 430 | echo json_encode(array('response'=>FALSE,'msg'=>$this->lang->line('language_error_dir_not_exist'))); 431 | } 432 | } 433 | } 434 | 435 | /** 436 | * Prepare string by removing unwanted signs 437 | * 438 | * @param string 439 | * @return string0tring 440 | */ 441 | function prepare_str($string){ 442 | $from = array('ą','ć','ę','ł','ó','ń','ś','ż','ź',' '); ///polish signs 443 | $to = array('a','c','e','l','o','n','s','z','z','_'); ///signs to replace 444 | $out = preg_replace('/[^a-zA-Z0-9-_]*/','',str_ireplace($from, $to, strtolower($string))); ///prepare, remove spaces, replace 445 | return strtolower($out); 446 | } 447 | 448 | } 449 | -------------------------------------------------------------------------------- /application/core/MY_Lang.php: -------------------------------------------------------------------------------- 1 | language[$line])) ? FALSE : $this->language[$line]; 16 | 17 | // Because killer robots like unicorns! 18 | if ($value === FALSE) 19 | { 20 | log_message('error', 'Could not find the language line "'.$line.'"'); 21 | } 22 | 23 | return is_array($value) ? $value : stripslashes($value); 24 | } 25 | 26 | } 27 | 28 | /* End of file MY_Lang.php */ 29 | /* Location: ./application/core/MY_Lang.php */ 30 | -------------------------------------------------------------------------------- /application/language/english/language_lang.php: -------------------------------------------------------------------------------- 1 | WARNING! If you don\'t add them now they will be removed from this file after saving your changes. The translation will be also gone.'; 15 | $lang['language_keys_db_warning']='It seems that some keys are not in database. Do you want to add them?'; 16 | $lang['language_add_all_keys']='Add all keys'; 17 | $lang['language_keys_file_warning']='WARNING! If you don\'t add them now they will be removed from the file after saving your changes.'; 18 | $lang['language_show_keys']='Show me those keys'; 19 | $lang['language_add_this_key']='Add this key'; 20 | $lang['language_delete_key']='Delete key for good'; 21 | $lang['language_add_new_key']='Add new key'; 22 | $lang['language_save_changes']='Save changes'; 23 | $lang['language_delete_file']='Delete file from this language'; 24 | $lang['language_no_files']='No files for this language'; 25 | $lang['language_file_label']='File'; 26 | $lang['language_lang_label']='Language'; 27 | $lang['language_langfile_not_exist']='File does not exists for '; 28 | $lang['language_error_dir_not_exist']='Language directory or file does not exists'; 29 | $lang['language_msg_success']='Success'; 30 | $lang['language_error']='Error'; 31 | $lang['language_error_no_direct_access']='No direct access allowed'; 32 | $lang['language_file_saved']='File saved'; 33 | $lang['language_file_not_saved']='File not saved'; 34 | $lang['language_error_keys_db']='There was a problem with saving new keys in database. File not saved.'; 35 | $lang['language_file_created']='File created'; 36 | $lang['language_error_creating_permissions']='There was a problem with creating new file. Check permissions for folders.'; 37 | $lang['language_error_file_exist']='Language directory does not exist or file exists'; 38 | $lang['language_error_name_required']='Language name and filename are required'; 39 | $lang['language_created']='Language created'; 40 | $lang['language_error_creating_dir_permissions']='There was a problem with creating new directory for language. Check permissions for folders.'; 41 | $lang['language_error_exist']='Language exists'; 42 | $lang['language_msg_deleted']='Language deleted'; 43 | $lang['language_error_delete_permissions']='There was a problem with deleting directory for language. Check permissions for folders.'; 44 | $lang['language_langdir_not_exist']='Language directory does not exist'; 45 | $lang['language_file_deleted']='Language file deleted'; 46 | $lang['language_error_delete_file_permissions']='There was a problem with deleting file for language. Check permissions.'; 47 | $lang['language_key_deleted']='Key deleted'; 48 | $lang['language_confirm_file_delete']='Are you sure you want to delete this file from this language?'; 49 | $lang['language_sh_comments']='Show/hide comments'; 50 | $lang['language_home_link']='Home'; 51 | $lang['language_file_list_link']='File list'; 52 | $lang['language_create_file_link']='Create new file'; 53 | $lang['language_new_lang_info']='Enter name for new language'; 54 | /* End of file language_lang.php */ -------------------------------------------------------------------------------- /application/language/polish/language_lang.php: -------------------------------------------------------------------------------- 1 | OSTRZEŻENIE! Jeśli nie dodasz ich teraz, zostaną one usunięte z pliku po zapisaniu formularza. Tłumaczenia jeśli istniały, również zostaną usunięte.'; 15 | $lang['language_keys_db_warning']='Wygląda na to, że niektórych kluczy nie ma w bazie. Czy chcesz je dodać?'; 16 | $lang['language_add_all_keys']='Dodaj wszystkie klucze'; 17 | $lang['language_keys_file_warning']='OSTRZEŻENIE! Jeśli nie dodasz ich teraz zostaną usunięte z pliku po zapisaniu formularza.'; 18 | $lang['language_show_keys']='Pokaż te klucze'; 19 | $lang['language_add_this_key']='Dodaj ten klucz'; 20 | $lang['language_delete_key']='Usuń klucz na zawsze'; 21 | $lang['language_add_new_key']='Dodaj nowy klucz'; 22 | $lang['language_save_changes']='Zapisz zmiany'; 23 | $lang['language_delete_file']='Usuń plik z tego języka'; 24 | $lang['language_no_files']='Brak plików dla tego języka'; 25 | $lang['language_file_label']='Plik'; 26 | $lang['language_lang_label']='Język'; 27 | $lang['language_langfile_not_exist']='Nie istnieje plik dla '; 28 | $lang['language_error_dir_not_exist']='Folder języka lub plik nie istnieje'; 29 | $lang['language_msg_success']='Sukces'; 30 | $lang['language_error']='Błąd'; 31 | $lang['language_error_no_direct_access']='Bezpośredni dostęp zabroniony'; 32 | $lang['language_file_saved']='Plik zapisany'; 33 | $lang['language_file_not_saved']='Plik nie zapisany'; 34 | $lang['language_error_keys_db']='Wystąpił problem z zapisem kluczy w bazie. Plik nie zapisany.'; 35 | $lang['language_file_created']='Plik utworzony'; 36 | $lang['language_error_creating_permissions']='Wystąpił problem podczas tworzenia pliku. Sprawdź uprawnienia dla folderów.'; 37 | $lang['language_error_file_exist']='Folder języka nie istnieje lub plik istnieje'; 38 | $lang['language_error_name_required']='Nazwa języka i pliku wymagane'; 39 | $lang['language_created']='Język został utworzony'; 40 | $lang['language_error_creating_dir_permissions']='Wystąpił problem podczas tworzenia folderu dla języka. Sprawdź uprawnienia.'; 41 | $lang['language_error_exist']='Język istnieje'; 42 | $lang['language_msg_deleted']='Język usunięty'; 43 | $lang['language_error_delete_permissions']='Wystąpił problem podczas usuwania folderu języka. Sprawdź uprawnienia.'; 44 | $lang['language_langdir_not_exist']='Folder języka nie istnieje'; 45 | $lang['language_file_deleted']='Plik języka został usunięty'; 46 | $lang['language_error_delete_file_permissions']='Wystąpił problem podczas usuwania pliku dla języka. Sprawdź uprawnienia.'; 47 | $lang['language_key_deleted']='Klucz usunięty'; 48 | $lang['language_confirm_file_delete']='Czy jesteś pewien że chcesz usunąć ten plik z wybranego języka?'; 49 | $lang['language_sh_comments']='Pokaż/ukryj komentarze'; 50 | $lang['language_home_link']='Główna'; 51 | $lang['language_file_list_link']='Lista plików'; 52 | $lang['language_create_file_link']='Utwórz nowy plik'; 53 | $lang['language_new_lang_info']='Wprowadź nazwę dla nowego języka'; 54 | /* End of file language_lang.php */ -------------------------------------------------------------------------------- /application/models/model_language.php: -------------------------------------------------------------------------------- 1 | get_count_lfiles($filename); 29 | $i++; 30 | } 31 | } 32 | return (!empty($files))?$files:FALSE; 33 | } 34 | 35 | /** 36 | * Get list of files from language directory 37 | * 38 | * @param string 39 | * @return array 40 | */ 41 | function get_list_lfiles($dir){ 42 | if(!is_dir(APPPATH."language/$dir/")){ 43 | return FALSE; 44 | } 45 | $dir = APPPATH."language/$dir/"; 46 | $dh = opendir($dir); 47 | while (false !== ($filename = readdir($dh))) { 48 | if($filename!=='.' && $filename!=='..' && !is_dir($dir.$filename) && pathinfo($filename, PATHINFO_EXTENSION)=='php' && substr($filename,0,7)!='backup_'){ 49 | $files[] = $filename; 50 | } 51 | } 52 | return (!empty($files))?$files:FALSE; 53 | } 54 | 55 | /** 56 | * Get number of files from language directory 57 | * 58 | * @param string 59 | * @return int 60 | */ 61 | function get_count_lfiles($dir){ 62 | if(!is_dir(APPPATH."language/$dir/")){ 63 | return FALSE; 64 | } 65 | $dir = APPPATH."language/$dir/"; 66 | $dh = opendir($dir); 67 | $i=0; 68 | while (false !== ($filename = readdir($dh))) { 69 | if($filename!=='.' && $filename!=='..' && !is_dir($dir.$filename) && pathinfo($filename, PATHINFO_EXTENSION)=='php' && substr($filename,0,7)!='backup_'){ 70 | $i++; 71 | } 72 | } 73 | return (int)$i; 74 | } 75 | 76 | /** 77 | * Get list of languages where file exist 78 | * 79 | * @param string 80 | * @return array 81 | */ 82 | function file_in_language($file){ 83 | $lang = $this->get_languages(); 84 | if($lang!==FALSE){ 85 | foreach($lang as $l){ 86 | $names = get_filenames(APPPATH."language/{$l['dir']}/"); 87 | if(in_array($file,$names)){ 88 | $in_lang[]=$l['dir']; 89 | } 90 | } 91 | return $in_lang; 92 | } 93 | return FALSE; 94 | } 95 | 96 | /** 97 | * Get list of keys for file from database 98 | * 99 | * @param string 100 | * @return array 101 | */ 102 | function get_keys_from_db($file){ 103 | $this->db->select('key as `keys`'); 104 | $r = $this->db->get_where('language_keys', array('filename' => $file)); 105 | if($r->num_rows()){ 106 | $result=$r->result(); 107 | foreach($result as $row){ 108 | $tab[]=$row->keys; 109 | } 110 | } 111 | return (!empty($row)) ? $tab : FALSE; 112 | } 113 | 114 | /** 115 | * Get list of keys for file from database 116 | * 117 | * @param string 118 | * @return array 119 | */ 120 | function get_comments_from_db($file){ 121 | $this->db->select('key as `keys`,comment'); 122 | $r = $this->db->get_where('language_keys', array('filename' => $file)); 123 | if($r->num_rows()){ 124 | $result=$r->result(); 125 | foreach($result as $row){ 126 | $tab[$row->keys]=$row->comment; 127 | } 128 | } 129 | return (!empty($row)) ? $tab : FALSE; 130 | } 131 | 132 | /** 133 | * Update all keys in database, by removing previous and adding new. 134 | * 135 | * @param array 136 | * @param string 137 | * @return bool 138 | */ 139 | function update_all_keys($keys,$file){ 140 | $this->delete_all_keys($file); 141 | return $this->add_keys($keys,$file); 142 | } 143 | 144 | /** 145 | * Add keys to database 146 | * 147 | * @param array 148 | * @param string 149 | * @return bool 150 | */ 151 | function add_keys($keys,$file){ 152 | if(!is_array($keys)){ 153 | return FALSE; 154 | } 155 | foreach ($keys as $k){ 156 | $data[] = array( 157 | 'key'=>$k, 158 | 'filename'=>$file 159 | ); 160 | } 161 | $this->db->insert_batch('language_keys',$data); 162 | return ($this->db->affected_rows()) ? TRUE : FALSE; 163 | } 164 | 165 | 166 | /** 167 | * Delete keys from database if file does not exists in any language 168 | * 169 | * @param string 170 | * @return bool 171 | */ 172 | function delete_keys($file){ 173 | $lang = $this->get_languages(); 174 | if($lang!==FALSE){ 175 | foreach($lang as $l){ 176 | $names = get_filenames(APPPATH."language/{$l['dir']}/"); 177 | if(in_array($file,$names)){ 178 | return FALSE; 179 | } 180 | } 181 | if($this->delete_all_keys($file)){ 182 | return TRUE; 183 | }else{ 184 | return FALSE; 185 | } 186 | } 187 | } 188 | 189 | /** 190 | * Delete keys from database 191 | * 192 | * @param string 193 | * @return bool 194 | */ 195 | function delete_all_keys($file){ 196 | $this->db->delete('language_keys',array('filename'=>$file)); 197 | return ($this->db->affected_rows()) ? TRUE : FALSE; 198 | } 199 | 200 | function delete_one_key($key,$file){ 201 | $this->db->delete('language_keys',array('filename'=>$file,'key'=>$key)); 202 | return ($this->db->affected_rows()) ? TRUE : FALSE; 203 | } 204 | 205 | function add_comments($com,$file){ 206 | if(!is_array($com)){ 207 | return FALSE; 208 | } 209 | $this->db->trans_start(); 210 | foreach ($com as $k=>$c){ 211 | $this->db->where('key', $k); 212 | $this->db->where('filename', $file); 213 | $this->db->update('language_keys',array('comment'=>$c)); 214 | } 215 | $this->db->trans_complete(); 216 | return ($this->db->trans_status()) ? TRUE : FALSE; 217 | } 218 | 219 | } 220 | /* End of file model_language.php */ 221 | -------------------------------------------------------------------------------- /application/views/language/dir_list.php: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 21 | 22 | 23 |
24 | session->flashdata('error')){ ?> 25 |
26 | session->flashdata('error');?> 27 |
28 | session->flashdata('msg')){ ?> 29 |
30 | session->flashdata('msg');?> 31 |
32 | 33 | load->view('language/dir_list_view'); ?> 34 |
35 | Created by Eliza Witkowska 36 |
37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /application/views/language/dir_list_view.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |

lang->line('language_title');?>

4 | 14 |

15 | 16 |

lang->line('language_create_lang');?>

17 |
18 | 19 |
20 | 21 | 22 | 23 |
24 | 25 |
26 |
27 | -------------------------------------------------------------------------------- /application/views/language/edit_lang_file.php: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 59 | 60 | 61 |
62 | session->flashdata('error')){ ?> 63 |
64 | session->flashdata('error');?> 65 |
66 | session->flashdata('msg')){ ?> 67 |
68 | session->flashdata('msg');?> 69 |
70 | 71 | 84 |
85 | load->view('language/dir_list_view'); 87 | } ?> 88 |
89 | 1){ ?> 90 |
91 |

lang->line('language_edit_file_info');?>

92 |
    93 | 95 | 96 |
  • 97 | 98 |
  • lang->line('language_langfile_not_exist').$d['dir'];?>
    99 | 100 | 101 | 102 | 103 | 104 | 105 |
  • 106 | 109 |
110 |
111 | 112 |
113 | 114 |
115 |
lang->line('language_first_time_info');?>
116 | 117 |
118 | 119 |
120 | 121 |
122 | 123 |

lang->line('language_first_time_warning');?>

124 |
125 | 127 |
128 |
129 |

lang->line('language_keys_db_warning');?>

130 | 131 |
132 | 133 | 134 | 135 |
136 | 137 |

lang->line('language_keys_file_warning');?>

138 | lang->line('language_show_keys');?> 139 |
140 | 157 |
158 | 159 |
160 | config->item('comments')==1) { ?>lang->line('language_sh_comments');?>
161 | 162 |
163 | 164 | 165 |
166 | 167 | 168 | '.$pattern[$key].'

'; 170 | }?> 171 | 172 | 173 |
config->item('comments_show')==1) ? '' : ' style="display:none;"';?>> 174 | 175 |
176 | 177 |
178 |
179 | 180 | 181 |
182 |
183 |
184 | 185 | 186 | 187 | 188 | 189 |
190 |
191 | Created by Eliza Witkowska 192 |
193 |
194 | 195 | 196 | -------------------------------------------------------------------------------- /application/views/language/file_list.php: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 25 | 26 | 27 |
28 | session->flashdata('error')){ ?> 29 |
30 | session->flashdata('error');?> 31 |
32 | session->flashdata('msg')){ ?> 33 |
34 | session->flashdata('msg');?> 35 |
36 | 37 | 50 | load->view('language/dir_list_view'); 52 | } ?> 53 | 54 |
55 | 65 |
66 | 67 |
lang->line('language_no_files');?>
68 | 69 |
70 | Created by Eliza Witkowska 71 |
72 |
73 | 74 | 75 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Document : style.css 3 | Author : Eliza Witkowska (http://codebusters.pl/en/) 4 | Description: Stylesheet for CodeIgniter frontend language files editor. 5 | */ 6 | * { 7 | margin: 0px 0px; 8 | padding: 0px 0px; 9 | border:none; 10 | color: #606260; 11 | list-style:none; 12 | } 13 | 14 | body 15 | { 16 | font-size: 12px; 17 | background:#d5dad5; 18 | font-family: Tahoma, Geneva, sans-serif; 19 | } 20 | #wrapper{width:900px; margin:0 auto;} 21 | a{text-decoration:none;} 22 | li,.clear {clear:both;} 23 | li a,.box.language,.left{float:left;} 24 | li form input[type="submit"],.box.files,.right{float:right;} 25 | input[type="submit"],input[type="button"]{background-color:#F3F3EE; border:1px solid #CCCDC9; font-size:10px; border-radius:5px; -moz-border-radius:5px; -webkit-border-radius:5px; padding:1px 6px; cursor:pointer;} 26 | .box,.error,.msg{background:#f3f3ee; border:1px solid #cccdc9; -webkit-box-shadow: 1px 1px 1px #d8ddd8; -moz-box-shadow: 1px 1px 1px #d8ddd8; box-shadow: 1px 1px 1px #d8ddd8; display:block; padding:15px; margin-bottom:10px;border-radius:15px; -moz-border-radius:15px; -webkit-border-radius:15px; margin:10px;} 27 | .box.language{width:235px; line-height:200%;} 28 | .box.language .no-float input[type="submit"]{float:none; margin-left:0px;} 29 | .box.language.listyle ul li{list-style:disc outside; margin-left:15px;} 30 | .box li form input[type="submit"]{margin-left:10px;} 31 | .box li{padding: 5px 0;} 32 | .box.files li{border-bottom:1px solid #e8eedd;} 33 | .box.files {width: 560px;} 34 | .msg{background-color:#ccee97 !important; font-weight: bold;} 35 | .error{background: #d44545 !important; color: #ffffff; font-weight: bold;} 36 | input[type="text"],textarea{background: #f8f8f3;border: 1px solid #CCCDC9; padding: 4px; border-radius:5px; -moz-border-radius:5px; -webkit-border-radius:5px; font-size: 12px; color:#333333;} 37 | #create_file_form,#new_lang_form{margin-top:10px; border-top:1px dashed; padding-top:10px;} 38 | .row{margin-top:10px; border-bottom:1px dashed #cccddd; padding-bottom:10px;} 39 | .row input[type="text"],textarea{width:545px;} 40 | .row input[type="text"].comment{width:400px;} 41 | .row .comments label{padding-top:4px; margin-right:5px;} 42 | .row .comments{margin-top:5px;} 43 | .row .comments label,.row .comments input[type="text"]{color:#999;} 44 | .row label{margin-bottom:5px; display:block; color:#437394; font-weight:bold;} 45 | small{color:red;} 46 | .delete_key{margin-bottom:5px; margin-right:5px;} 47 | .pattern{margin-bottom:7px; color:#8b9297;} 48 | -------------------------------------------------------------------------------- /frontend_translator.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `language_keys` ( 2 | `key` VARCHAR(255) NOT NULL, 3 | `filename` VARCHAR(255) NOT NULL, 4 | `comment` VARCHAR(255) NOT NULL 5 | ) 6 | COLLATE='utf8_general_ci' 7 | ENGINE=InnoDB; --------------------------------------------------------------------------------