2 /************************************************************************/
4 /************************************************************************/
5 /* Copyright (c) 2002-2010 */
6 /* Inclusive Design Institute */
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 /************************************************************************/
14 require_once(dirname(__FILE__) . '/Language.class.php');
16 define('AT_LANG_STATUS_EMPTY', 0);
17 define('AT_LANG_STATUS_INCOMPLETE', 1);
18 define('AT_LANG_STATUS_COMPLETE', 2);
19 define('AT_LANG_STATUS_PUBLISHED', 3);
23 * Class for managing available languages as Language Objects.
25 * @author Joel Kronenberg
26 * @see Language.class.php
29 class LanguageManager {
32 * This array stores references to all the Language Objects
33 * that are available in this installation.
37 var $availableLanguages;
40 * The fallback language if the DEFAULT_LANGUAGE isn't defined.
44 var $default_lang = 'en';
47 * The fallback charachter set if the DEFAULT_CHARSET isn't defined.
51 // var $default_charset = 'iso-8859-1';
52 var $default_charset = 'utf-8';
55 * The number of languages that are available. Does not include
56 * character set variations.
65 * Initializes availableLanguages and numLanguages.
67 function LanguageManager() {
70 $sql = 'SELECT * FROM '.TABLE_PREFIX.'languages ORDER BY native_name';
71 $result = mysql_query($sql, $db);
72 while($row = mysql_fetch_assoc($result)) {
73 if (defined('AT_DEVEL_TRANSLATE') && AT_DEVEL_TRANSLATE) {
74 $row['status'] = AT_LANG_STATUS_PUBLISHED; // b/c the print drop down checks for it.
76 $this->availableLanguages[$row['language_code']][$row['char_set']] = new Language($row);
78 $this->numLanguages = count($this->availableLanguages);
83 * Returns a valid Language Object based on the given language $code and optional
84 * $charset, FALSE if it can't be found.
86 * @param string $code The language code of the language to return.
87 * @param string $charset Optionally, the character set of the language to find.
88 * @return boolean|Language Returns FALSE if the requested language code and
89 * character set cannot be found. Returns a Language Object for the
90 * specified language code and character set.
91 * @see getMyLanguage()
93 function getLanguage($code, $charset = '') {
95 if (isset($this->availableLanguages[$code])) {
96 if (is_array($this->availableLanguages[$code]))
97 foreach ($this->availableLanguages[$code] as $language)
99 // return current($this->availableLanguages[$code]);
101 debug('return false');
106 foreach ($this->availableLanguages[$code] as $language) {
107 if ($language->getCharacterSet() == $charset) {
115 * Tries to detect the user's current language preference/setting from (in order):
116 * _GET, _POST, _SESSION, HTTP_ACCEPT_LANGUAGE, HTTP_USER_AGENT. If no match can be made
117 * then it tries to detect a default setting (defined in config.inc.php) or a fallback
118 * setting, false if all else fails.
120 * @return boolean|Language Returns a Language Object matching the user's current session.
121 * Returns FALSE if a valid Language Object cannot be found
122 * to match the request
125 function getMyLanguage() {
126 global $addslashes, $db;
128 if (isset($_GET) && !empty($_GET['lang']) && isset($this->availableLanguages[$_GET['lang']])) {
129 $language = $this->getLanguage($_GET['lang']);
136 if (isset($_POST) && !empty($_POST['lang']) && isset($this->availableLanguages[$_POST['lang']])) {
137 $language = $this->getLanguage($_POST['lang']);
144 if (isset($_SESSION) && isset($_SESSION['lang']) && !empty($_SESSION['lang']) && isset($this->availableLanguages[$_SESSION['lang']])) {
145 $language = $this->getLanguage($_SESSION['lang']);
151 if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
153 // Language is not defined yet :
154 // try to find out user's language by checking its HTTP_ACCEPT_LANGUAGE
155 $accepted = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
156 $acceptedCnt = count($accepted);
158 for ($i = 0; $i < $acceptedCnt; $i++) {
159 foreach ($this->availableLanguages as $codes) {
160 foreach ($codes as $language) {
161 if ($language->isMatchHttpAcceptLanguage($accepted[$i])) {
169 if (!empty($_SERVER['HTTP_USER_AGENT'])) {
171 // Language is not defined yet :
172 // try to find out user's language by checking its HTTP_USER_AGENT
173 foreach ($this->availableLanguages as $codes) {
174 foreach ($codes as $language) {
175 if ($language->isMatchHttpUserAgent($_SERVER['HTTP_USER_AGENT'])) {
182 // Didn't catch any valid lang : we use the default settings
183 if (isset($this->availableLanguages[DEFAULT_LANGUAGE])) {
184 $language = $this->getLanguage(DEFAULT_LANGUAGE, DEFAULT_CHARSET);
192 if (isset($this->availableLanguages[$this->default_lang])) {
193 $language = $this->getLanguage($this->default_lang, $this->default_charset);
200 // else pick one at random:
201 reset($this->availableLanguages);
203 $unknown_language = current($this->availableLanguages);
205 if (!$unknown_language) {
209 return current($unknown_language);
212 function getAvailableLanguages() {
213 return $this->availableLanguages;
217 function printDropdown($current_language, $name, $id) {
218 echo '<select name="'.$name.'" id="'.$id.'">';
220 foreach ($this->availableLanguages as $codes) {
221 $language = current($codes);
222 if ((defined('AT_DEVEL_TRANSLATE') && AT_DEVEL_TRANSLATE) || ($language->getStatus() == AT_LANG_STATUS_PUBLISHED)) {
223 echo '<option value="'.$language->getCode().'"';
224 if ($language->getCode() == $current_language) {
225 echo ' selected="selected"';
227 echo '>'.$language->getNativeName().'</option>';
234 function printList($current_language, $name, $id, $url) {
237 foreach ($this->availableLanguages as $codes) {
238 $language = current($codes);
240 if ($language->getStatus() == AT_LANG_STATUS_PUBLISHED) {
246 if ($language->getCode() == $current_language) {
247 echo '<strong>'.$language->getNativeName().'</strong>';
249 echo '<a href="'.$url.'lang='.$language->getCode().'">'.$language->getNativeName().'</a> ';
258 function getNumLanguages() {
259 return $this->numLanguages;
263 // checks whether or not the language exists/is available
264 function exists($code, $locale = '') {
266 return isset($this->availableLanguages[$code . AT_LANGUAGE_LOCALE_SEP . $locale]);
268 return isset($this->availableLanguages[$code]);
272 // import language pack from specified file
273 function import($filename) {
274 global $languageManager, $msg;
276 require_once(AT_INCLUDE_PATH.'classes/pclzip.lib.php');
277 require_once(AT_INCLUDE_PATH.'../mods/_core/languages/classes/LanguagesParser.class.php');
279 $import_path = AT_CONTENT_DIR . 'import/';
281 $archive = new PclZip($filename);
282 if ($archive->extract( PCLZIP_OPT_PATH, $import_path) == 0) {
283 exit('Error : ' . $archive->errorInfo(true));
286 $language_xml = @file_get_contents($import_path.'language.xml');
288 $languageParser = new LanguageParser();
289 $languageParser->parse($language_xml);
290 $languageEditor = $languageParser->getLanguageEditor(0);
292 if (($languageEditor->getAtutorVersion() != VERSION)
293 && (!defined('AT_DEVEL_TRANSLATE') || !AT_DEVEL_TRANSLATE))
295 $msg->addError('LANG_WRONG_VERSION');
298 if (($languageEditor->getStatus() != AT_LANG_STATUS_PUBLISHED)
299 && ($languageEditor->getStatus() != AT_LANG_STATUS_COMPLETE)
300 && (!defined('AT_DEVEL_TRANSLATE') || !AT_DEVEL_TRANSLATE))
302 $msg->addError('LANG_NOT_COMPLETE');
305 if ($languageManager->exists($languageEditor->getCode())) {
306 $msg->addError('LANG_EXISTS');
309 if (!$msg->containsErrors()) {
310 $languageEditor->import($import_path . 'language_text.sql');
311 $msg->addFeedback('IMPORT_LANG_SUCCESS');
315 @unlink($import_path . 'language.xml');
316 @unlink($import_path . 'language_text.sql');
317 @unlink($import_path . 'readme.txt');
322 // imports LIVE language from the atutor language database
323 function liveImport($language_code) {
326 $zip_file_content = @file_get_contents(AT_LIVE_LANG_PACK_URL.$language_code);
328 if (!$zip_file_content || substr($zip_file_content, 0, 6) == "Error:") {
329 $msg->addError(array('REMOTE_ERROR', $zip_file_content));
333 // write the downloaded language pack into a temporary file for pclzip to unpack
334 $lang_pack_zip = AT_CONTENT_DIR . 'import/'.md5(time()).'.zip';
335 $fp = fopen($lang_pack_zip, 'w');
336 fwrite($fp, $zip_file_content);
339 $this->import($lang_pack_zip);
340 @unlink($lang_pack_zip);
346 $lang_xml = '<?xml version="1.0" encoding="iso-8859-1"?>
347 <!-- These are ATutor language packs - http://www.atutor.ca-->
349 <!DOCTYPE languages [
350 <!ELEMENT language (atutor-version, code, charset, direction, reg-exp, native-name, english-name )>
351 <!ELEMENT atutor-version (#PCDATA)>
352 <!ELEMENT code (#PCDATA)>
353 <!ELEMENT charset (#PCDATA)>
354 <!ELEMENT direction (#PCDATA)>
355 <!ELEMENT reg-exp (#PCDATA)>
356 <!ELEMENT native-name (#PCDATA)>
357 <!ELEMENT english-name (#PCDATA)>
358 <!ELEMENT status (#PCDATA)>
359 <!ATTLIST language code ID #REQUIRED>
364 foreach ($this->availableLanguages as $codes) {
365 foreach ($codes as $language) {
366 $lang_xml .= $language->getXML(TRUE);
370 $lang_xml .= "\r\n".'</languages>';