2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4 // +----------------------------------------------------------------------+
5 // | Akelos Framework - http://www.akelos.org |
6 // +----------------------------------------------------------------------+
7 // | Copyright (c) 2002-2006, Akelos Media, S.L. & Bermi Ferrer Martinez |
8 // | Released under the GNU Lesser General Public License, see LICENSE.txt|
9 // +----------------------------------------------------------------------+
12 * @package ActiveSupport
13 * @subpackage I18n-L10n
14 * @author Bermi Ferrer <bermi a.t akelos c.om>
15 * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org
16 * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html>
19 if(!defined('AK_AVAILABLE_LOCALES')){
20 define('AK_AVAILABLE_LOCALES',AK_FRAMEWORK_LANGUAGE
);
23 require_once(AK_LIB_DIR
.DS
.'AkObject.php');
25 defined('AK_FRAMEWORK_LANGUAGE') ?
null : define('AK_FRAMEWORK_LANGUAGE', 'en');
27 class AkLocaleManager
extends AkObject
30 var $available_locales = array(AK_FRAMEWORK_LANGUAGE
=>array(AK_FRAMEWORK_LANGUAGE
));
31 var $browser_lang = array(AK_FRAMEWORK_LANGUAGE
);
35 if(AK_AVAILABLE_LOCALES
== 'auto'){
36 $this->available_locales
= $this->_getAvailableLocales();
37 }elseif(AK_AVAILABLE_LOCALES
!= 'en'){
38 $this->available_locales
= $this->_parseLocaleConfigString(AK_AVAILABLE_LOCALES
);
42 function _getAvailableLocales()
44 static $available_locales;
46 if(empty($available_locales)){
47 $available_locales = array();
48 $d = dir(AK_CONFIG_DIR
.DS
.'locales');
49 while (false !== ($entry = $d->read())) {
50 if (preg_match('/\\.php$/', $entry)){
51 $locale = str_replace('.php','',$entry);
52 $available_locales[$locale] = array($locale);
58 return $available_locales;
61 function _parseLocaleConfigString($locale_settings)
63 $locale_settings = trim(str_replace(' ','',$locale_settings));
64 $locale_settings = str_replace(array(';','(',')'), array(',','~','',''),$locale_settings);
65 $available_locales = strstr($locale_settings,',') ?
explode(',',$locale_settings) : array($locale_settings);
67 foreach ($available_locales as $locale_string){
68 if(strstr($locale_string,'~')){
69 $tmp_arr = explode('~',$locale_string);
70 $locale_string = $tmp_arr[0];
71 $locale_alias = array($locale_string);
72 if(strstr($tmp_arr[1],'|')){
73 $locale_alias = array_merge($locale_alias, explode('|',$tmp_arr[1]));
75 $locale_alias = array_merge($locale_alias, array($tmp_arr[1]));
78 $locale_alias = array($locale_string);
82 $locales[trim($locale_string)] = $locale_alias;
88 function getBrowserLanguages()
90 $browser_accepted_languages = str_replace('-','_', strtolower(preg_replace('/q=[0-9\.]+,*/','',@$_SERVER['HTTP_ACCEPT_LANGUAGE'])));
91 $browser_languages = (array_diff(split(';|,',$browser_accepted_languages.','), array('')));
92 if(empty($browser_languages)){
93 return array($this->_getDefaultLocale());
95 return array_unique($browser_languages);
99 function getDefaultLanguageForUser()
101 $browser_languages = $this->getBrowserLanguages();
103 // First run for full locale (en_us, en_uk)
104 foreach ($browser_languages as $browser_language){
105 if(isset($this->available_locales
[$browser_language])){
106 return $browser_language;
110 // Second run for only language code (en, es)
111 foreach ($browser_languages as $browser_language){
112 if($pos = strpos($browser_language,'_')){
113 $browser_language = substr($browser_language,0, $pos);
114 if(isset($this->available_locales
[$browser_language])){
115 return $browser_language;
119 return $this->_getDefaultLocale();
122 function _getDefaultLocale()
124 $available_locales = $this->available_locales
;
125 $default_locale = array_shift($available_locales);
126 return is_array($default_locale) ?
$default_locale[0] : $default_locale;
130 function getUsedLanguageEntries($lang_entry = null, $controller = null)
132 static $_locale_entries = array();
134 if(isset($controller)){
135 $_locale_entries[$controller][$lang_entry] = $lang_entry;
137 $_locale_entries[$lang_entry] = $lang_entry;
140 if(!isset($lang_entry)){
141 return $_locale_entries;
146 * @todo Refactor this method
148 function updateLocaleFiles()
150 $new_core_entries = array();
151 $new_controller_entries = array();
152 $new_controller_files = array();
153 $used_entries = AkLocaleManager
::getUsedLanguageEntries();
154 require(AK_CONFIG_DIR
.DS
.'locales'.DS
.AK_FRAMEWORK_LANGUAGE
.'.php');
155 $core_dictionary = $dictionary;
156 $controllers_dictionaries = array();
158 foreach ($used_entries as $k=>$v){
159 // This is a controller file
161 if(!isset($controllers_dictionaries[$k])){
163 $module_lang_file = AK_APP_DIR
.DS
.'locales'.DS
.$controller.DS
.AK_FRAMEWORK_LANGUAGE
.'.php';
164 if(is_file($module_lang_file)){
165 require($module_lang_file);
166 $controllers_dictionaries[$controller] = array_merge((array)$dictionary, (array)$v);
167 $existing_controllers_dictionaries[$controller] = (array)$dictionary;
169 $controllers_dictionaries[$controller] = (array)$v;
170 $new_controller_files[$controller] = $module_lang_file;
174 if(!isset($core_dictionary[$k])){
175 $new_core_entries[$k] = $k;
180 $dictionary_file = '';
181 foreach ($new_controller_files as $controller=>$file_name){
182 $dictionary_file = "<?php\n\n// File created on: ".date("Y-m-d G:i:s",Ak
::time())."\n\n\$dictionary = array();\n\n";
183 foreach ($controllers_dictionaries[$controller] as $k=>$entry){
184 $entry = str_replace("'","\\'",$entry);
185 $dictionary_file .= "\n\$dictionary['$entry'] = '$entry';";
187 unset($controllers_dictionaries[$controller]);
188 $dictionary_file .= "\n\n\n?>";
189 Ak
::file_put_contents($file_name,$dictionary_file);
193 foreach ((array)$controllers_dictionaries as $controller => $controller_entries){
194 $dictionary_file = '';
195 foreach ($controller_entries as $entry){
196 if($entry == '' ||
isset($existing_controllers_dictionaries[$controller][$entry])) {
199 $entry = str_replace("'","\\'",$entry);
200 $dictionary_file .= "\n\$dictionary['$entry'] = '$entry';";
202 if($dictionary_file != ''){
203 $original_file = Ak
::file_get_contents(AK_APP_DIR
.DS
.'locales'.DS
.$controller.DS
.AK_FRAMEWORK_LANGUAGE
.'.php');
204 $original_file = rtrim($original_file,"?> \n\r");
205 $new_entries = "\n\n// ".date("Y-m-d G:i:s",Ak
::time())."\n\n".$dictionary_file."\n\n\n?>\n";
206 $dictionary_file = $original_file.$new_entries;
207 Ak
::file_put_contents(AK_APP_DIR
.DS
.'locales'.DS
.$controller.DS
.AK_FRAMEWORK_LANGUAGE
.'.php', $dictionary_file);
209 foreach (Ak
::langs() as $lang){
210 if($lang != AK_FRAMEWORK_LANGUAGE
){
211 $lang_file = @Ak
::file_get_contents(AK_APP_DIR
.DS
.'locales'.DS
.$controller.DS
.$lang.'.php');
212 if(empty($lang_file)){
213 $dictionary_file = $original_file;
215 $lang_file = rtrim($lang_file,"?> \n\r");
216 $dictionary_file = $lang_file;
218 Ak
::file_put_contents(AK_APP_DIR
.DS
.'locales'.DS
.$controller.DS
.$lang.'.php', $dictionary_file.$new_entries);
225 $dictionary_file = '';
226 foreach ($new_core_entries as $core_entry){
227 if($core_entry == '') {
230 $core_entry = str_replace("'","\\'",$core_entry);
231 $dictionary_file .= "\n\$dictionary['$core_entry'] = '$core_entry';";
233 if($dictionary_file != ''){
234 $original_file = Ak
::file_get_contents(AK_CONFIG_DIR
.DS
.'locales'.DS
.AK_FRAMEWORK_LANGUAGE
.'.php');
235 $original_file = rtrim($original_file,"?> \n\r");
236 $new_entries = "\n\n// ".date("Y-m-d G:i:s",Ak
::time())."\n\n".$dictionary_file."\n\n\n?>\n";
237 $dictionary_file = $original_file.$new_entries;
238 Ak
::file_put_contents(AK_CONFIG_DIR
.DS
.'locales'.DS
.AK_FRAMEWORK_LANGUAGE
.'.php', $dictionary_file);
239 foreach (Ak
::langs() as $lang){
240 if($lang != AK_FRAMEWORK_LANGUAGE
){
241 $lang_file = Ak
::file_get_contents(AK_CONFIG_DIR
.DS
.'locales'.DS
.$lang.'.php');
242 if(empty($lang_file)){
243 $dictionary_file = str_replace("\$locale['description'] = 'English';","\$locale['description'] = '$lang';", $original_file);
245 $lang_file = rtrim($lang_file,"?> \n\r");
246 $dictionary_file = $lang_file;
248 Ak
::file_put_contents(AK_CONFIG_DIR
.DS
.'locales'.DS
.$lang.'.php', $dictionary_file.$new_entries);
257 * The following functions are for handling i18n when using url based interfaces
261 function initApplicationInternationalization(&$Request)
263 if(!defined('AK_APP_LOCALES')){
264 define('AK_APP_LOCALES',join(',',array_keys($this->available_locales
)));
266 $lang = $this->_getLocaleForRequest($Request);
268 $this->rememberNavigationLanguage($lang);
270 $Request->_request
['lang'] = $lang;
271 $Request->lang
= $lang;
275 * Returns an array which locales enabled on the public website.
276 * In order to define available languages you must define AK_PUBLIC_LOCALES
277 * which a comma-separated list of locales
281 function getPublicLocales()
283 static $public_locales;
284 if(empty($public_locales)){
285 $public_locales = defined('AK_PUBLIC_LOCALES') ?
286 Ak
::toArray(AK_PUBLIC_LOCALES
) :
287 array_keys($this->available_locales
);
289 return $public_locales;
292 function _getLocaleForRequest(&$Request)
294 $lang = $this->getNavigationLanguage();
296 if($url_locale = $this->getLangFromUrl($Request)){
297 $lang = $this->getLocaleFromAlias($url_locale);
300 if(!$this->_canUseLocaleOnCurrentRequest($lang, $Request)){
301 $lang = array_shift($this->getPublicLocales());
302 }elseif (empty($lang)){
303 $lang = array_shift($this->getPublicLocales());
306 // This way we store on get_url_locale and on lang the value of $lang on
307 // a static variable for accessing it application wide
308 empty($url_locale) ?
null : Ak
::get_url_locale($url_locale);
314 function _canUseLocaleOnCurrentRequest($lang, &$Request)
316 return in_array($lang, $this->getPublicLocales());
320 function getLangFromUrl(&$Request)
324 if(isset($Request->lang
)){
325 return $Request->lang
;
328 if(isset($Request->ak
)){
329 $regex_arr = array();
332 foreach ($this->available_locales
as $lang=>$aliases){
333 foreach ($aliases as $alias){
334 $regex_arr[] = '('.$alias.')(\/){1}';
337 $regex = '/^('.join('|',$regex_arr).'){1}/';
339 if (preg_match($regex, trim($Request->ak
,'/').'/', $match)){
340 $lang = trim($match[0],'/');
342 unset($Request->_request
['ak'], $Request->ak
);
344 $Request->ak
= $Request->_request
['ak'] = ltrim(substr_replace(trim($Request->ak
,'/'),'',0,strlen($lang)), '/');
351 $lang = isset($Request->lang
) ?
$Request->lang
: $lang;
356 function rememberNavigationLanguage($lang)
358 if(isset($_SESSION) && !empty($lang)){
359 $_SESSION['lang'] = $lang;
363 function getNavigationLanguage()
365 if(!isset($_SESSION['lang'])){
366 $this->browser_lang
= $this->getDefaultLanguageForUser();
367 return $this->getDefaultLanguageForUser();
369 return $_SESSION['lang'];
373 function getLocaleFromAlias($alias)
375 foreach ($this->available_locales
as $locale=>$locale_arr){
376 if(in_array($alias,$locale_arr)){