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 /************************************************************************/
12 // $Id: LanguageManager.class.php 8919 2009-11-16 18:07:32Z cindy $
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 $import_path = AT_CONTENT_DIR . 'import/';
278 $archive = new PclZip($filename);
279 if ($archive->extract( PCLZIP_OPT_PATH, $import_path) == 0) {
280 exit('Error : ' . $archive->errorInfo(true));
283 $language_xml = @file_get_contents($import_path.'language.xml');
285 $languageParser = new LanguageParser();
286 $languageParser->parse($language_xml);
287 $languageEditor = $languageParser->getLanguageEditor(0);
289 if (($languageEditor->getAtutorVersion() != VERSION)
290 && (!defined('AT_DEVEL_TRANSLATE') || !AT_DEVEL_TRANSLATE))
292 $msg->addError('LANG_WRONG_VERSION');
295 if (($languageEditor->getStatus() != AT_LANG_STATUS_PUBLISHED)
296 && ($languageEditor->getStatus() != AT_LANG_STATUS_COMPLETE)
297 && (!defined('AT_DEVEL_TRANSLATE') || !AT_DEVEL_TRANSLATE))
299 $msg->addError('LANG_NOT_COMPLETE');
302 if ($languageManager->exists($languageEditor->getCode())) {
303 $msg->addError('LANG_EXISTS');
306 if (!$msg->containsErrors()) {
307 $languageEditor->import($import_path . 'language_text.sql');
308 $msg->addFeedback('IMPORT_LANG_SUCCESS');
312 @unlink($import_path . 'language.xml');
313 @unlink($import_path . 'language_text.sql');
314 @unlink($import_path . 'readme.txt');
319 // imports LIVE language from the atutor language database
320 function liveImport($language_code) {
323 $tmp_lang_db = mysql_connect(AT_LANG_DB_HOST, AT_LANG_DB_USER, AT_LANG_DB_PASS);
324 // set database connection using utf8
325 mysql_query("SET NAMES 'utf8'", $tmp_lang_db);
328 /* AT_ERROR_NO_DB_CONNECT */
329 echo 'Unable to connect to db.';
332 if (!mysql_select_db('dev_atutor_langs', $tmp_lang_db)) {
333 echo 'DB connection established, but database "dev_atutor_langs" cannot be selected.';
337 $sql = "SELECT * FROM languages_SVN WHERE language_code='$language_code'";
338 $result = mysql_query($sql, $tmp_lang_db);
340 if ($row = mysql_fetch_assoc($result)) {
341 $row['reg_exp'] = addslashes($row['reg_exp']);
342 $row['native_name'] = addslashes($row['native_name']);
343 $row['english_name'] = addslashes($row['english_name']);
345 $sql = "REPLACE INTO ".TABLE_PREFIX."languages VALUES ('{$row['language_code']}', '{$row['char_set']}', '{$row['direction']}', '{$row['reg_exp']}', '{$row['native_name']}', '{$row['english_name']}', 3)";
346 $result = mysql_query($sql, $db);
348 $sql = "SELECT * FROM language_text_SVN WHERE language_code='$language_code'";
349 $result = mysql_query($sql, $tmp_lang_db);
351 $sql = "REPLACE INTO ".TABLE_PREFIX."language_text VALUES ";
352 while ($row = mysql_fetch_assoc($result)) {
353 $row['text'] = addslashes($row['text']);
354 $row['context'] = addslashes($row['context']);
355 $sql .= "('{$row['language_code']}', '{$row['variable']}', '{$row['term']}', '{$row['text']}', '{$row['revised_date']}', '{$row['context']}'),";
357 $sql = substr($sql, 0, -1);
358 mysql_query($sql, $db);
365 $lang_xml = '<?xml version="1.0" encoding="iso-8859-1"?>
366 <!-- These are ATutor language packs - http://www.atutor.ca-->
368 <!DOCTYPE languages [
369 <!ELEMENT language (atutor-version, code, charset, direction, reg-exp, native-name, english-name )>
370 <!ELEMENT atutor-version (#PCDATA)>
371 <!ELEMENT code (#PCDATA)>
372 <!ELEMENT charset (#PCDATA)>
373 <!ELEMENT direction (#PCDATA)>
374 <!ELEMENT reg-exp (#PCDATA)>
375 <!ELEMENT native-name (#PCDATA)>
376 <!ELEMENT english-name (#PCDATA)>
377 <!ELEMENT status (#PCDATA)>
378 <!ATTLIST language code ID #REQUIRED>
383 foreach ($this->availableLanguages as $codes) {
384 foreach ($codes as $language) {
385 $lang_xml .= $language->getXML(TRUE);
389 $lang_xml .= "\r\n".'</languages>';