PageRenderTime 43ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/mods/_core/languages/classes/LanguageManager.class.php

https://github.com/harriswong/ATutor
PHP | 377 lines | 225 code | 64 blank | 88 comment | 61 complexity | 87b811a48c23ffddd4094952aeaa1fa4 MD5 | raw file
  1. <?php
  2. /************************************************************************/
  3. /* ATutor */
  4. /************************************************************************/
  5. /* Copyright (c) 2002-2010 */
  6. /* Inclusive Design Institute */
  7. /* http://atutor.ca */
  8. /* This program is free software. You can redistribute it and/or */
  9. /* modify it under the terms of the GNU General Public License */
  10. /* as published by the Free Software Foundation. */
  11. /************************************************************************/
  12. // $Id$
  13. require_once(dirname(__FILE__) . '/Language.class.php');
  14. define('AT_LANG_STATUS_EMPTY', 0);
  15. define('AT_LANG_STATUS_INCOMPLETE', 1);
  16. define('AT_LANG_STATUS_COMPLETE', 2);
  17. define('AT_LANG_STATUS_PUBLISHED', 3);
  18. /**
  19. * LanguageManager
  20. * Class for managing available languages as Language Objects.
  21. * @access public
  22. * @author Joel Kronenberg
  23. * @see Language.class.php
  24. * @package Language
  25. */
  26. class LanguageManager {
  27. /**
  28. * This array stores references to all the Language Objects
  29. * that are available in this installation.
  30. * @access private
  31. * @var array
  32. */
  33. var $availableLanguages;
  34. /**
  35. * The fallback language if the DEFAULT_LANGUAGE isn't defined.
  36. * @access private
  37. * @var string
  38. */
  39. var $default_lang = 'en';
  40. /**
  41. * The fallback charachter set if the DEFAULT_CHARSET isn't defined.
  42. * @access private
  43. * @var string
  44. */
  45. // var $default_charset = 'iso-8859-1';
  46. var $default_charset = 'utf-8';
  47. /**
  48. * The number of languages that are available. Does not include
  49. * character set variations.
  50. * @access private
  51. * @var integer
  52. */
  53. var $numLanguages;
  54. /**
  55. * Constructor.
  56. *
  57. * Initializes availableLanguages and numLanguages.
  58. */
  59. function LanguageManager() {
  60. global $db;
  61. $sql = 'SELECT * FROM '.TABLE_PREFIX.'languages ORDER BY native_name';
  62. $result = mysql_query($sql, $db);
  63. while($row = mysql_fetch_assoc($result)) {
  64. if (defined('AT_DEVEL_TRANSLATE') && AT_DEVEL_TRANSLATE) {
  65. $row['status'] = AT_LANG_STATUS_PUBLISHED; // b/c the print drop down checks for it.
  66. }
  67. $this->availableLanguages[$row['language_code']][$row['char_set']] = new Language($row);
  68. }
  69. $this->numLanguages = count($this->availableLanguages);
  70. }
  71. /**
  72. * Returns a valid Language Object based on the given language $code and optional
  73. * $charset, FALSE if it can't be found.
  74. * @access public
  75. * @param string $code The language code of the language to return.
  76. * @param string $charset Optionally, the character set of the language to find.
  77. * @return boolean|Language Returns FALSE if the requested language code and
  78. * character set cannot be found. Returns a Language Object for the
  79. * specified language code and character set.
  80. * @see getMyLanguage()
  81. */
  82. function getLanguage($code, $charset = '') {
  83. if (!$charset) {
  84. if (isset($this->availableLanguages[$code])) {
  85. if (is_array($this->availableLanguages[$code]))
  86. foreach ($this->availableLanguages[$code] as $language)
  87. return $language;
  88. // return current($this->availableLanguages[$code]);
  89. } else {
  90. debug('return false');
  91. return FALSE;
  92. }
  93. }
  94. foreach ($this->availableLanguages[$code] as $language) {
  95. if ($language->getCharacterSet() == $charset) {
  96. return $language;
  97. }
  98. }
  99. return FALSE;
  100. }
  101. /**
  102. * Tries to detect the user's current language preference/setting from (in order):
  103. * _GET, _POST, _SESSION, HTTP_ACCEPT_LANGUAGE, HTTP_USER_AGENT. If no match can be made
  104. * then it tries to detect a default setting (defined in config.inc.php) or a fallback
  105. * setting, false if all else fails.
  106. * @access public
  107. * @return boolean|Language Returns a Language Object matching the user's current session.
  108. * Returns FALSE if a valid Language Object cannot be found
  109. * to match the request
  110. * @see getLanguage()
  111. */
  112. function getMyLanguage() {
  113. global $addslashes, $db;
  114. if (isset($_GET) && !empty($_GET['lang']) && isset($this->availableLanguages[$_GET['lang']])) {
  115. $language = $this->getLanguage($_GET['lang']);
  116. if ($language) {
  117. return $language;
  118. }
  119. }
  120. if (isset($_POST) && !empty($_POST['lang']) && isset($this->availableLanguages[$_POST['lang']])) {
  121. $language = $this->getLanguage($_POST['lang']);
  122. if ($language) {
  123. return $language;
  124. }
  125. }
  126. if (isset($_SESSION) && isset($_SESSION['lang']) && !empty($_SESSION['lang']) && isset($this->availableLanguages[$_SESSION['lang']])) {
  127. $language = $this->getLanguage($_SESSION['lang']);
  128. if ($language) {
  129. return $language;
  130. }
  131. }
  132. if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
  133. // Language is not defined yet :
  134. // try to find out user's language by checking its HTTP_ACCEPT_LANGUAGE
  135. $accepted = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
  136. $acceptedCnt = count($accepted);
  137. reset($accepted);
  138. for ($i = 0; $i < $acceptedCnt; $i++) {
  139. foreach ($this->availableLanguages as $codes) {
  140. foreach ($codes as $language) {
  141. if ($language->isMatchHttpAcceptLanguage($accepted[$i])) {
  142. return $language;
  143. }
  144. }
  145. }
  146. }
  147. }
  148. if (!empty($_SERVER['HTTP_USER_AGENT'])) {
  149. // Language is not defined yet :
  150. // try to find out user's language by checking its HTTP_USER_AGENT
  151. foreach ($this->availableLanguages as $codes) {
  152. foreach ($codes as $language) {
  153. if ($language->isMatchHttpUserAgent($_SERVER['HTTP_USER_AGENT'])) {
  154. return $language;
  155. }
  156. }
  157. }
  158. }
  159. // Didn't catch any valid lang : we use the default settings
  160. if (isset($this->availableLanguages[DEFAULT_LANGUAGE])) {
  161. $language = $this->getLanguage(DEFAULT_LANGUAGE, DEFAULT_CHARSET);
  162. if ($language) {
  163. return $language;
  164. }
  165. }
  166. // fail safe
  167. if (isset($this->availableLanguages[$this->default_lang])) {
  168. $language = $this->getLanguage($this->default_lang, $this->default_charset);
  169. if ($language) {
  170. return $language;
  171. }
  172. }
  173. // else pick one at random:
  174. reset($this->availableLanguages);
  175. $unknown_language = current($this->availableLanguages);
  176. if (!$unknown_language) {
  177. return FALSE;
  178. }
  179. return current($unknown_language);
  180. }
  181. function getAvailableLanguages() {
  182. return $this->availableLanguages;
  183. }
  184. // public
  185. function printDropdown($current_language, $name, $id) {
  186. echo '<select name="'.$name.'" id="'.$id.'">';
  187. foreach ($this->availableLanguages as $codes) {
  188. $language = current($codes);
  189. if ((defined('AT_DEVEL_TRANSLATE') && AT_DEVEL_TRANSLATE) || ($language->getStatus() == AT_LANG_STATUS_PUBLISHED)) {
  190. echo '<option value="'.$language->getCode().'"';
  191. if ($language->getCode() == $current_language) {
  192. echo ' selected="selected"';
  193. }
  194. echo '>'.$language->getNativeName().'</option>';
  195. }
  196. }
  197. echo '</select>';
  198. }
  199. // public
  200. function printList($current_language, $name, $id, $url) {
  201. $delim = false;
  202. foreach ($this->availableLanguages as $codes) {
  203. $language = current($codes);
  204. if ($language->getStatus() == AT_LANG_STATUS_PUBLISHED) {
  205. if ($delim){
  206. echo ' | ';
  207. }
  208. if ($language->getCode() == $current_language) {
  209. echo '<strong>'.$language->getNativeName().'</strong>';
  210. } else {
  211. echo '<a href="'.$url.'lang='.$language->getCode().'">'.$language->getNativeName().'</a> ';
  212. }
  213. $delim = true;
  214. }
  215. }
  216. }
  217. // public
  218. function getNumLanguages() {
  219. return $this->numLanguages;
  220. }
  221. // public
  222. // checks whether or not the language exists/is available
  223. function exists($code, $locale = '') {
  224. if ($locale) {
  225. return isset($this->availableLanguages[$code . AT_LANGUAGE_LOCALE_SEP . $locale]);
  226. }
  227. return isset($this->availableLanguages[$code]);
  228. }
  229. // public
  230. // import language pack from specified file
  231. function import($filename) {
  232. global $languageManager, $msg;
  233. require_once(AT_INCLUDE_PATH.'classes/pclzip.lib.php');
  234. require_once(AT_INCLUDE_PATH.'../mods/_core/languages/classes/LanguagesParser.class.php');
  235. $import_path = AT_CONTENT_DIR . 'import/';
  236. $archive = new PclZip($filename);
  237. if ($archive->extract( PCLZIP_OPT_PATH, $import_path) == 0) {
  238. exit('Error : ' . $archive->errorInfo(true));
  239. }
  240. $language_xml = @file_get_contents($import_path.'language.xml');
  241. $languageParser = new LanguageParser();
  242. $languageParser->parse($language_xml);
  243. $languageEditor = $languageParser->getLanguageEditor(0);
  244. if (($languageEditor->getAtutorVersion() != VERSION)
  245. && (!defined('AT_DEVEL_TRANSLATE') || !AT_DEVEL_TRANSLATE))
  246. {
  247. $msg->addError('LANG_WRONG_VERSION');
  248. }
  249. if (($languageEditor->getStatus() != AT_LANG_STATUS_PUBLISHED)
  250. && ($languageEditor->getStatus() != AT_LANG_STATUS_COMPLETE)
  251. && (!defined('AT_DEVEL_TRANSLATE') || !AT_DEVEL_TRANSLATE))
  252. {
  253. $msg->addError('LANG_NOT_COMPLETE');
  254. }
  255. if ($languageManager->exists($languageEditor->getCode())) {
  256. $msg->addError('LANG_EXISTS');
  257. }
  258. if (!$msg->containsErrors()) {
  259. $languageEditor->import($import_path . 'language_text.sql');
  260. $msg->addFeedback('IMPORT_LANG_SUCCESS');
  261. }
  262. // remove the files:
  263. @unlink($import_path . 'language.xml');
  264. @unlink($import_path . 'language_text.sql');
  265. @unlink($import_path . 'readme.txt');
  266. @unlink($filename);
  267. }
  268. // public
  269. // imports LIVE language from the atutor language database
  270. function liveImport($language_code) {
  271. global $msg;
  272. $zip_file_content = @file_get_contents(AT_LIVE_LANG_PACK_URL.$language_code);
  273. if (!$zip_file_content || substr($zip_file_content, 0, 6) == "Error:") {
  274. $msg->addError(array('REMOTE_ERROR', $zip_file_content));
  275. return;
  276. }
  277. // write the downloaded language pack into a temporary file for pclzip to unpack
  278. $lang_pack_zip = AT_CONTENT_DIR . 'import/'.md5(time()).'.zip';
  279. $fp = fopen($lang_pack_zip, 'w');
  280. fwrite($fp, $zip_file_content);
  281. fclose($fp);
  282. $this->import($lang_pack_zip);
  283. @unlink($lang_pack_zip);
  284. }
  285. function getXML() {
  286. global $db;
  287. $lang_xml = '<?xml version="1.0" encoding="iso-8859-1"?>
  288. <!-- These are ATutor language packs - http://www.atutor.ca-->
  289. <!DOCTYPE languages [
  290. <!ELEMENT language (atutor-version, code, charset, direction, reg-exp, native-name, english-name )>
  291. <!ELEMENT atutor-version (#PCDATA)>
  292. <!ELEMENT code (#PCDATA)>
  293. <!ELEMENT charset (#PCDATA)>
  294. <!ELEMENT direction (#PCDATA)>
  295. <!ELEMENT reg-exp (#PCDATA)>
  296. <!ELEMENT native-name (#PCDATA)>
  297. <!ELEMENT english-name (#PCDATA)>
  298. <!ELEMENT status (#PCDATA)>
  299. <!ATTLIST language code ID #REQUIRED>
  300. ]>
  301. <languages>';
  302. foreach ($this->availableLanguages as $codes) {
  303. foreach ($codes as $language) {
  304. $lang_xml .= $language->getXML(TRUE);
  305. }
  306. }
  307. $lang_xml .= "\r\n".'</languages>';
  308. return $lang_xml;
  309. }
  310. }
  311. ?>