PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/AkLocaleManager.php

http://akelosframework.googlecode.com/
PHP | 388 lines | 337 code | 30 blank | 21 comment | 27 complexity | 71fb991962019bf44bf9a14e5ba1dc1a MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. // +----------------------------------------------------------------------+
  4. // | Akelos Framework - http://www.akelos.org |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 2002-2006, Akelos Media, S.L. & Bermi Ferrer Martinez |
  7. // | Released under the GNU Lesser General Public License, see LICENSE.txt|
  8. // +----------------------------------------------------------------------+
  9. /**
  10. * @package AkelosFramework
  11. * @subpackage I18n-L10n
  12. * @author Bermi Ferrer <bermi a.t akelos c.om>
  13. * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org
  14. * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html>
  15. */
  16. if(!defined('AK_AVAILABLE_LOCALES')){
  17. define('AK_AVAILABLE_LOCALES',AK_FRAMEWORK_LANGUAGE);
  18. }
  19. require_once(AK_LIB_DIR.DS.'AkObject.php');
  20. defined('AK_FRAMEWORK_LANGUAGE') ? null : define('AK_FRAMEWORK_LANGUAGE', 'en');
  21. class AkLocaleManager extends AkObject
  22. {
  23. var $available_locales = array(AK_FRAMEWORK_LANGUAGE=>array(AK_FRAMEWORK_LANGUAGE));
  24. var $browser_lang = array(AK_FRAMEWORK_LANGUAGE);
  25. function init()
  26. {
  27. if(AK_AVAILABLE_LOCALES == 'auto'){
  28. $this->available_locales = $this->_getAvailableLocales();
  29. }elseif(AK_AVAILABLE_LOCALES != 'en'){
  30. $this->available_locales = $this->_parseLocaleConfigString(AK_AVAILABLE_LOCALES);
  31. }
  32. }
  33. function _getAvailableLocales()
  34. {
  35. static $available_locales;
  36. Ak::profile(__CLASS__.'::'.__FUNCTION__);
  37. if(empty($available_locales)){
  38. $available_locales = array();
  39. $d = dir(AK_CONFIG_DIR.DS.'locales');
  40. while (false !== ($entry = $d->read())) {
  41. if (preg_match('/\\.php$/', $entry)){
  42. $locale = str_replace('.php','',$entry);
  43. $available_locales[$locale] = array($locale);
  44. }
  45. }
  46. $d->close();
  47. }
  48. return $available_locales;
  49. }
  50. function _parseLocaleConfigString($locale_settings)
  51. {
  52. Ak::profile(__CLASS__.'::'.__FUNCTION__);
  53. $locale_settings = trim(str_replace(' ','',$locale_settings));
  54. $locale_settings = str_replace(array(';','(',')'), array(',','~','',''),$locale_settings);
  55. $available_locales = strstr($locale_settings,',') ? explode(',',$locale_settings) : array($locale_settings);
  56. $locales = array();
  57. foreach ($available_locales as $locale_string){
  58. if(strstr($locale_string,'~')){
  59. $tmp_arr = explode('~',$locale_string);
  60. $locale_string = $tmp_arr[0];
  61. $locale_alias = array($locale_string);
  62. if(strstr($tmp_arr[1],'|')){
  63. $locale_alias = array_merge($locale_alias, explode('|',$tmp_arr[1]));
  64. }else{
  65. $locale_alias = array_merge($locale_alias, array($tmp_arr[1]));
  66. }
  67. }else {
  68. $locale_alias = array($locale_string);
  69. }
  70. $locales[trim($locale_string)] = $locale_alias;
  71. }
  72. return $locales;
  73. }
  74. function getBrowserLanguages()
  75. {
  76. $browser_accepted_languages = str_replace('-','_', strtolower(preg_replace('/q=[0-9\.]+,*/','',@$_SERVER['HTTP_ACCEPT_LANGUAGE'])));
  77. $browser_languages = (array_diff(split(';|,',$browser_accepted_languages.','), array('')));
  78. if(empty($browser_languages)){
  79. return array($this->_getDefaultLocale());
  80. }
  81. return array_unique($browser_languages);
  82. }
  83. function getDefaultLanguageForUser()
  84. {
  85. $browser_languages = $this->getBrowserLanguages();
  86. // First run for full locale (en_us, en_uk)
  87. foreach ($browser_languages as $browser_language){
  88. if(isset($this->available_locales[$browser_language])){
  89. return $browser_language;
  90. }
  91. }
  92. // Second run for only language code (en, es)
  93. foreach ($browser_languages as $browser_language){
  94. if($pos = strpos($browser_language,'_')){
  95. $browser_language = substr($browser_language,0, $pos);
  96. if(isset($this->available_locales[$browser_language])){
  97. return $browser_language;
  98. }
  99. }
  100. }
  101. return $this->_getDefaultLocale();
  102. }
  103. function _getDefaultLocale()
  104. {
  105. $available_locales = $this->available_locales;
  106. $default_locale = array_shift($available_locales);
  107. return is_array($default_locale) ? $default_locale[0] : $default_locale;
  108. }
  109. function getUsedLanguageEntries($lang_entry = null, $controller = null)
  110. {
  111. static $_locale_entries = array();
  112. if(isset($controller)){
  113. $_locale_entries[$controller][$lang_entry] = $lang_entry;
  114. } else {
  115. $_locale_entries[$lang_entry] = $lang_entry;
  116. }
  117. if(!isset($lang_entry)){
  118. return $_locale_entries;
  119. }
  120. }
  121. /**
  122. * @todo Refactor this method
  123. */
  124. function updateLocaleFiles()
  125. {
  126. $new_core_entries = array();
  127. $new_controller_entries = array();
  128. $new_controller_files = array();
  129. $used_entries = AkLocaleManager::getUsedLanguageEntries();
  130. require(AK_CONFIG_DIR.DS.'locales'.DS.AK_FRAMEWORK_LANGUAGE.'.php');
  131. $core_dictionary = $dictionary;
  132. $controllers_dictionaries = array();
  133. foreach ($used_entries as $k=>$v){
  134. // This is a controller file
  135. if(is_array($v)){
  136. if(!isset($controllers_dictionaries[$k])){
  137. $controller = $k;
  138. $module_lang_file = AK_APP_DIR.DS.'locales'.DS.$controller.DS.AK_FRAMEWORK_LANGUAGE.'.php';
  139. if(is_file($module_lang_file)){
  140. require($module_lang_file);
  141. $controllers_dictionaries[$controller] = array_merge((array)$dictionary, (array)$v);
  142. $existing_controllers_dictionaries[$controller] = (array)$dictionary;
  143. }else{
  144. $controllers_dictionaries[$controller] = (array)$v;
  145. $new_controller_files[$controller] = $module_lang_file;
  146. }
  147. }
  148. }else {
  149. if(!isset($core_dictionary[$k])){
  150. $new_core_entries[$k] = $k;
  151. }
  152. }
  153. }
  154. $dictionary_file = '';
  155. foreach ($new_controller_files as $controller=>$file_name){
  156. $dictionary_file = "<?php\n\n// File created on: ".date("Y-m-d G:i:s",Ak::time())."\n\n\$dictionary = array();\n\n";
  157. foreach ($controllers_dictionaries[$controller] as $k=>$entry){
  158. $entry = str_replace("'","\\'",$entry);
  159. $dictionary_file .= "\n\$dictionary['$entry'] = '$entry';";
  160. }
  161. unset($controllers_dictionaries[$controller]);
  162. $dictionary_file .= "\n\n\n?>";
  163. Ak::file_put_contents($file_name,$dictionary_file);
  164. }
  165. // Module files
  166. foreach ((array)$controllers_dictionaries as $controller => $controller_entries){
  167. $dictionary_file = '';
  168. foreach ($controller_entries as $entry){
  169. if($entry == '' || isset($existing_controllers_dictionaries[$controller][$entry])) {
  170. continue;
  171. }
  172. $entry = str_replace("'","\\'",$entry);
  173. $dictionary_file .= "\n\$dictionary['$entry'] = '$entry';";
  174. }
  175. if($dictionary_file != ''){
  176. $original_file = Ak::file_get_contents(AK_APP_DIR.DS.'locales'.DS.$controller.DS.AK_FRAMEWORK_LANGUAGE.'.php');
  177. $original_file = rtrim($original_file,"?> \n\r");
  178. $new_entries = "\n\n// ".date("Y-m-d G:i:s",Ak::time())."\n\n".$dictionary_file."\n\n\n?>\n";
  179. $dictionary_file = $original_file.$new_entries;
  180. Ak::file_put_contents(AK_APP_DIR.DS.'locales'.DS.$controller.DS.AK_FRAMEWORK_LANGUAGE.'.php', $dictionary_file);
  181. foreach (Ak::langs() as $lang){
  182. if($lang != AK_FRAMEWORK_LANGUAGE){
  183. $lang_file = @Ak::file_get_contents(AK_APP_DIR.DS.'locales'.DS.$controller.DS.$lang.'.php');
  184. if(empty($lang_file)){
  185. $dictionary_file = $original_file;
  186. }else{
  187. $lang_file = rtrim($lang_file,"?> \n\r");
  188. $dictionary_file = $lang_file;
  189. }
  190. Ak::file_put_contents(AK_APP_DIR.DS.'locales'.DS.$controller.DS.$lang.'.php', $dictionary_file.$new_entries);
  191. }
  192. }
  193. }
  194. }
  195. // Core locale files
  196. $dictionary_file = '';
  197. foreach ($new_core_entries as $core_entry){
  198. if($core_entry == '') {
  199. continue;
  200. }
  201. $core_entry = str_replace("'","\\'",$core_entry);
  202. $dictionary_file .= "\n\$dictionary['$core_entry'] = '$core_entry';";
  203. }
  204. if($dictionary_file != ''){
  205. $original_file = Ak::file_get_contents(AK_CONFIG_DIR.DS.'locales'.DS.AK_FRAMEWORK_LANGUAGE.'.php');
  206. $original_file = rtrim($original_file,"?> \n\r");
  207. $new_entries = "\n\n// ".date("Y-m-d G:i:s",Ak::time())."\n\n".$dictionary_file."\n\n\n?>\n";
  208. $dictionary_file = $original_file.$new_entries;
  209. Ak::file_put_contents(AK_CONFIG_DIR.DS.'locales'.DS.AK_FRAMEWORK_LANGUAGE.'.php', $dictionary_file);
  210. foreach (Ak::langs() as $lang){
  211. if($lang != AK_FRAMEWORK_LANGUAGE){
  212. $lang_file = Ak::file_get_contents(AK_CONFIG_DIR.DS.'locales'.DS.$lang.'.php');
  213. if(empty($lang_file)){
  214. $dictionary_file = str_replace("\$locale['description'] = 'English';","\$locale['description'] = '$lang';", $original_file);
  215. }else{
  216. $lang_file = rtrim($lang_file,"?> \n\r");
  217. $dictionary_file = $lang_file;
  218. }
  219. Ak::file_put_contents(AK_CONFIG_DIR.DS.'locales'.DS.$lang.'.php', $dictionary_file.$new_entries);
  220. }
  221. }
  222. }
  223. }
  224. /**
  225. * The following functions are for handling i18n when using url based interfaces
  226. */
  227. function initApplicationInternationalization(&$Request)
  228. {
  229. if(!defined('AK_APP_LOCALES')){
  230. define('AK_APP_LOCALES',join(',',array_keys($this->available_locales)));
  231. }
  232. $lang = $this->_getLocaleForRequest($Request);
  233. $this->rememberNavigationLanguage($lang);
  234. $Request->_request['lang'] = $lang;
  235. $Request->lang = $lang;
  236. }
  237. /**
  238. * Returns an array which locales enabled on the public website.
  239. * In order to define available languages you must define AK_PUBLIC_LOCALES
  240. * which a comma-separated list of locales
  241. *
  242. * @return array
  243. */
  244. function getPublicLocales()
  245. {
  246. static $public_locales;
  247. if(empty($public_locales)){
  248. $public_locales = defined('AK_PUBLIC_LOCALES') ?
  249. Ak::toArray(AK_PUBLIC_LOCALES) :
  250. array_keys($this->available_locales);
  251. }
  252. return $public_locales;
  253. }
  254. function _getLocaleForRequest(&$Request)
  255. {
  256. $lang = $this->getNavigationLanguage();
  257. if($url_locale = $this->getLangFromUrl($Request)){
  258. $lang = $this->getLocaleFromAlias($url_locale);
  259. }
  260. if(!$this->_canUseLocaleOnCurrentRequest($lang, $Request)){
  261. $lang = array_shift($this->getPublicLocales());
  262. }elseif (empty($lang)){
  263. $lang = array_shift($this->getPublicLocales());
  264. }
  265. // This way we store on get_url_locale and on lang the value of $lang on
  266. // a static variable for accessing it application wide
  267. empty($url_locale) ? null : Ak::get_url_locale($url_locale);
  268. Ak::lang($lang);
  269. return $lang;
  270. }
  271. function _canUseLocaleOnCurrentRequest($lang, &$Request)
  272. {
  273. return in_array($lang, $this->getPublicLocales());
  274. }
  275. function getLangFromUrl(&$Request)
  276. {
  277. $lang = false;
  278. if(isset($Request->lang)){
  279. return $Request->lang;
  280. }
  281. if(isset($Request->ak)){
  282. $regex_arr = array();
  283. $match = false;
  284. foreach ($this->available_locales as $lang=>$aliases){
  285. foreach ($aliases as $alias){
  286. $regex_arr[] = '('.$alias.')(\/){1}';
  287. }
  288. }
  289. $regex = '/^('.join('|',$regex_arr).'){1}/';
  290. if (preg_match($regex, trim($Request->ak,'/').'/', $match)){
  291. $lang = trim($match[0],'/');
  292. if(empty($lang)){
  293. unset($Request->_request['ak'], $Request->ak);
  294. }else{
  295. $Request->ak = $Request->_request['ak'] = ltrim(substr_replace(trim($Request->ak,'/'),'',0,strlen($lang)), '/');
  296. }
  297. }else {
  298. return false;
  299. }
  300. }
  301. $lang = isset($Request->lang) ? $Request->lang : $lang;
  302. return $lang;
  303. }
  304. function rememberNavigationLanguage($lang)
  305. {
  306. if(isset($_SESSION) && !empty($lang)){
  307. $_SESSION['lang'] = $lang;
  308. }
  309. }
  310. function getNavigationLanguage()
  311. {
  312. if(!isset($_SESSION['lang'])){
  313. $this->browser_lang = $this->getDefaultLanguageForUser();
  314. return $this->getDefaultLanguageForUser();
  315. }else{
  316. return $_SESSION['lang'];
  317. }
  318. }
  319. function getLocaleFromAlias($alias)
  320. {
  321. foreach ($this->available_locales as $locale=>$locale_arr){
  322. if(in_array($alias,$locale_arr)){
  323. return $locale;
  324. }
  325. }
  326. return false;
  327. }
  328. }
  329. ?>