PageRenderTime 26ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/frontend/core/engine/language.php

https://github.com/janmoesen/forkcms
PHP | 432 lines | 198 code | 60 blank | 174 comment | 20 complexity | 231370298df188d6f8bf8881580ff85b MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of Fork CMS.
  4. *
  5. * For the full copyright and license information, please view the license
  6. * file that was distributed with this source code.
  7. */
  8. /**
  9. * This class will store the language-dependant content for the frontend.
  10. *
  11. * @author Tijs Verkoyen <tijs@sumocoders.be>
  12. */
  13. class FrontendLanguage
  14. {
  15. /**
  16. * Locale arrays
  17. *
  18. * @var array
  19. */
  20. private static $act = array(), $err = array(), $lbl = array(), $msg = array();
  21. /**
  22. * The possible languages
  23. *
  24. * @var array
  25. */
  26. private static $languages = array('active' => array(), 'possible_redirect' => array());
  27. /**
  28. * Build the language files
  29. *
  30. * @param string $language The language to build the locale-file for.
  31. * @param string $application The application to build the locale-file for.
  32. */
  33. public static function buildCache($language, $application)
  34. {
  35. $db = FrontendModel::getDB();
  36. // get types
  37. $types = $db->getEnumValues('locale', 'type');
  38. // get locale for backend
  39. $locale = (array) $db->getRecords(
  40. 'SELECT type, module, name, value
  41. FROM locale
  42. WHERE language = ? AND application = ?
  43. ORDER BY type ASC, name ASC, module ASC',
  44. array((string) $language, (string) $application)
  45. );
  46. // init var
  47. $json = array();
  48. // start generating PHP
  49. $value = '<?php' . "\n";
  50. $value .= '/**' . "\n";
  51. $value .= ' *' . "\n";
  52. $value .= ' * This file is generated by Fork CMS, it contains' . "\n";
  53. $value .= ' * more information about the locale. Do NOT edit.' . "\n";
  54. $value .= ' * ' . "\n";
  55. $value .= ' * @author Fork CMS' . "\n";
  56. $value .= ' * @generated ' . date('Y-m-d H:i:s') . "\n";
  57. $value .= ' */' . "\n";
  58. $value .= "\n";
  59. // loop types
  60. foreach($types as $type)
  61. {
  62. // default module
  63. $modules = array('core');
  64. // continue output
  65. $value .= "\n";
  66. $value .= '// init var' . "\n";
  67. $value .= '$' . $type . ' = array();' . "\n";
  68. // loop locale
  69. foreach($locale as $i => $item)
  70. {
  71. // types match
  72. if($item['type'] == $type)
  73. {
  74. // new module
  75. if(!in_array($item['module'], $modules))
  76. {
  77. $value .= '$' . $type . '[\'' . $item['module'] . '\'] = array();' . "\n";
  78. $modules[] = $item['module'];
  79. }
  80. // parse
  81. if($application == 'backend')
  82. {
  83. $value .= '$' . $type . '[\'' . $item['module'] . '\'][\'' . $item['name'] . '\'] = \'' . str_replace('\"', '"', addslashes($item['value'])) . '\';' . "\n";
  84. $json[$type][$item['module']][$item['name']] = $item['value'];
  85. }
  86. else
  87. {
  88. $value .= '$' . $type . '[\'' . $item['name'] . '\'] = \'' . str_replace('\"', '"', addslashes($item['value'])) . '\';' . "\n";
  89. $json[$type][$item['name']] = $item['value'];
  90. }
  91. // unset
  92. unset($locale[$i]);
  93. }
  94. }
  95. }
  96. $value .= "\n";
  97. $value .= '?>';
  98. // store
  99. SpoonFile::setContent(constant(mb_strtoupper($application) . '_CACHE_PATH') . '/locale/' . $language . '.php', $value);
  100. // get months
  101. $monthsLong = SpoonLocale::getMonths(FRONTEND_LANGUAGE, false);
  102. $monthsShort = SpoonLocale::getMonths(FRONTEND_LANGUAGE, true);
  103. // get days
  104. $daysLong = SpoonLocale::getWeekDays(FRONTEND_LANGUAGE, false, 'sunday');
  105. $daysShort = SpoonLocale::getWeekDays(FRONTEND_LANGUAGE, true, 'sunday');
  106. // build labels
  107. foreach($monthsLong as $key => $value) $json['loc']['MonthLong' . SpoonFilter::ucfirst($key)] = $value;
  108. foreach($monthsShort as $key => $value) $json['loc']['MonthShort' . SpoonFilter::ucfirst($key)] = $value;
  109. foreach($daysLong as $key => $value) $json['loc']['DayLong' . SpoonFilter::ucfirst($key)] = $value;
  110. foreach($daysShort as $key => $value) $json['loc']['DayShort' . SpoonFilter::ucfirst($key)] = $value;
  111. // store
  112. SpoonFile::setContent(constant(mb_strtoupper($application) . '_CACHE_PATH') . '/locale/' . $language . '.json', json_encode($json));
  113. }
  114. /**
  115. * Get an action from the language-file
  116. *
  117. * @param string $key The key to get.
  118. * @return string
  119. */
  120. public static function getAction($key)
  121. {
  122. // redefine
  123. $key = SpoonFilter::toCamelCase((string) $key);
  124. // if the action exists return it,
  125. if(isset(self::$act[$key])) return self::$act[$key];
  126. // otherwise return the key in label-format
  127. return '{$act' . $key . '}';
  128. }
  129. /**
  130. * Get all the actions
  131. *
  132. * @return array
  133. */
  134. public static function getActions()
  135. {
  136. return self::$act;
  137. }
  138. /**
  139. * Get the active languages
  140. *
  141. * @return array
  142. */
  143. public static function getActiveLanguages()
  144. {
  145. // validate the cache
  146. if(empty(self::$languages['active']))
  147. {
  148. // grab from settings
  149. $activeLanguages = (array) FrontendModel::getModuleSetting('core', 'active_languages');
  150. // store in cache
  151. self::$languages['active'] = $activeLanguages;
  152. }
  153. // return from cache
  154. return self::$languages['active'];
  155. }
  156. /**
  157. * Get the prefered language by using the browser-language
  158. *
  159. * @param bool[optional] $forRedirect Only look in the languages to redirect?
  160. * @return string
  161. */
  162. public static function getBrowserLanguage($forRedirect = true)
  163. {
  164. // browser language set
  165. if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && strlen($_SERVER['HTTP_ACCEPT_LANGUAGE']) >= 2)
  166. {
  167. // get languages
  168. $redirectLanguages = self::getRedirectLanguages();
  169. // prefered languages
  170. $acceptedLanguages = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
  171. $browserLanguages = array();
  172. foreach($acceptedLanguages as $language)
  173. {
  174. $qPos = strpos($language, 'q=');
  175. $weight = 1;
  176. if($qPos !== false)
  177. {
  178. $endPos = strpos($language, ';', $qPos);
  179. $weight = ($endPos === false) ? (float) substr($language, $qPos + 2) : (float) substr($language, $qPos + 2, $endPos);
  180. }
  181. $browserLanguages[$language] = $weight;
  182. }
  183. // sort by weight
  184. arsort($browserLanguages);
  185. // loop until result
  186. foreach(array_keys($browserLanguages) as $language)
  187. {
  188. // redefine language
  189. $language = substr($language, 0, 2); // first two characters
  190. // find possible language
  191. if($forRedirect)
  192. {
  193. // check in the redirect-languages
  194. if(in_array($language, $redirectLanguages)) return $language;
  195. }
  196. }
  197. }
  198. // fallback
  199. return SITE_DEFAULT_LANGUAGE;
  200. }
  201. /**
  202. * Get an error from the language-file
  203. *
  204. * @param string $key The key to get.
  205. * @return string
  206. */
  207. public static function getError($key)
  208. {
  209. // redefine
  210. $key = SpoonFilter::toCamelCase((string) $key);
  211. // if the error exists return it,
  212. if(isset(self::$err[$key])) return self::$err[$key];
  213. // otherwise return the key in label-format
  214. return '{$err' . $key . '}';
  215. }
  216. /**
  217. * Get all the errors
  218. *
  219. * @return array
  220. */
  221. public static function getErrors()
  222. {
  223. return self::$err;
  224. }
  225. /**
  226. * Get a label from the language-file
  227. *
  228. * @param string $key The key to get.
  229. * @return string
  230. */
  231. public static function getLabel($key)
  232. {
  233. // redefine
  234. $key = SpoonFilter::toCamelCase((string) $key);
  235. // if the error exists return it,
  236. if(isset(self::$lbl[$key])) return self::$lbl[$key];
  237. // otherwise return the key in label-format
  238. return '{$lbl' . $key . '}';
  239. }
  240. /**
  241. * Get all the labels
  242. *
  243. * @return array
  244. */
  245. public static function getLabels()
  246. {
  247. return self::$lbl;
  248. }
  249. /**
  250. * Get a message from the language-file
  251. *
  252. * @param string $key The key to get.
  253. * @return string
  254. */
  255. public static function getMessage($key)
  256. {
  257. // redefine
  258. $key = SpoonFilter::toCamelCase((string) $key);
  259. // if the error exists return it,
  260. if(isset(self::$msg[$key])) return self::$msg[$key];
  261. // otherwise return the key in label-format
  262. return '{$msg' . $key . '}';
  263. }
  264. /**
  265. * Get all the messages
  266. *
  267. * @return array
  268. */
  269. public static function getMessages()
  270. {
  271. return self::$msg;
  272. }
  273. /**
  274. * Get the redirect languages
  275. *
  276. * @return array
  277. */
  278. public static function getRedirectLanguages()
  279. {
  280. // validate the cache
  281. if(empty(self::$languages['possible_redirect']))
  282. {
  283. // grab from settings
  284. $redirectLanguages = (array) FrontendModel::getModuleSetting('core', 'redirect_languages');
  285. // store in cache
  286. self::$languages['possible_redirect'] = $redirectLanguages;
  287. }
  288. // return
  289. return self::$languages['possible_redirect'];
  290. }
  291. /**
  292. * Set locale
  293. *
  294. * @param string[optional] $language The language to load, if not provided we will load the language based on the URL.
  295. * @param bool[optional] $force Force the language, so don't check if the language is active.
  296. */
  297. public static function setLocale($language = null, $force = false)
  298. {
  299. // redefine
  300. $language = ($language !== null) ? (string) $language : FRONTEND_LANGUAGE;
  301. // validate language
  302. if(!$force && !in_array($language, self::getActiveLanguages())) throw new FrontendException('Invalid language (' . $language . ').');
  303. // validate file, generate it if needed
  304. if(!SpoonFile::exists(FRONTEND_CACHE_PATH . '/locale/en.php')) self::buildCache('en', 'frontend');
  305. if(!SpoonFile::exists(FRONTEND_CACHE_PATH . '/locale/' . $language . '.php')) self::buildCache($language, 'frontend');
  306. // init vars
  307. $act = array();
  308. $err = array();
  309. $lbl = array();
  310. $msg = array();
  311. // set English translations, they'll be the fallback
  312. require FRONTEND_CACHE_PATH . '/locale/en.php';
  313. self::$act = (array) $act;
  314. self::$err = (array) $err;
  315. self::$lbl = (array) $lbl;
  316. self::$msg = (array) $msg;
  317. // overwrite with the requested language's translations
  318. require FRONTEND_CACHE_PATH . '/locale/' . $language . '.php';
  319. self::$act = array_merge(self::$act, (array) $act);
  320. self::$err = array_merge(self::$err, (array) $err);
  321. self::$lbl = array_merge(self::$lbl, (array) $lbl);
  322. self::$msg = array_merge(self::$msg, (array) $msg);
  323. }
  324. }
  325. /**
  326. * FL (some kind of alias for FrontendLanguage)
  327. *
  328. * @author Tijs Verkoyen <tijs@sumocoders.be>
  329. */
  330. class FL extends FrontendLanguage
  331. {
  332. /**
  333. * Get an action from the language-file
  334. *
  335. * @param string $key The key to get.
  336. * @return string
  337. */
  338. public static function act($key)
  339. {
  340. return FrontendLanguage::getAction($key);
  341. }
  342. /**
  343. * Get an error from the language-file
  344. *
  345. * @param string $key The key to get.
  346. * @return string
  347. */
  348. public static function err($key)
  349. {
  350. return FrontendLanguage::getError($key);
  351. }
  352. /**
  353. * Get a label from the language-file
  354. *
  355. * @param string $key The key to get.
  356. * @return string
  357. */
  358. public static function lbl($key)
  359. {
  360. return FrontendLanguage::getLabel($key);
  361. }
  362. /**
  363. * Get a message from the language-file
  364. *
  365. * @param string $key The key to get.
  366. * @return string
  367. */
  368. public static function msg($key)
  369. {
  370. return FrontendLanguage::getMessage($key);
  371. }
  372. }