2 /************************************************************************/
4 /************************************************************************/
5 /* Copyright (c) 2002-2008 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/
6 /* Adaptive Technology Resource Centre / University of Toronto */
9 /* This program is free software. You can redistribute it and/or */
10 /* modify it under the terms of the GNU General Public License */
11 /* as published by the Free Software Foundation. */
12 /************************************************************************/
15 require_once(dirname(__FILE__) . '/Language.class.php');
17 define('AT_LANG_STATUS_EMPTY', 0);
18 define('AT_LANG_STATUS_INCOMPLETE', 1);
19 define('AT_LANG_STATUS_COMPLETE', 2);
20 define('AT_LANG_STATUS_PUBLISHED', 3);
24 * Class for managing available languages as Language Objects.
26 * @author Joel Kronenberg
27 * @see Language.class.php
30 class LanguageManager {
33 * This array stores references to all the Language Objects
34 * that are available in this installation.
38 var $availableLanguages;
41 * The fallback language if the DEFAULT_LANGUAGE isn't defined.
45 var $default_lang = 'en';
48 * The fallback charachter set if the DEFAULT_CHARSET isn't defined.
52 // var $default_charset = 'iso-8859-1';
53 var $default_charset = 'utf-8';
56 * The number of languages that are available. Does not include
57 * character set variations.
66 * Initializes availableLanguages and numLanguages.
68 function LanguageManager() {
71 $sql = 'SELECT * FROM '.TABLE_PREFIX.'languages ORDER BY native_name';
72 $result = mysql_query($sql, $db);
73 while($row = mysql_fetch_assoc($result)) {
74 if (defined('AT_DEVEL_TRANSLATE') && AT_DEVEL_TRANSLATE) {
75 $row['status'] = AT_LANG_STATUS_PUBLISHED; // b/c the print drop down checks for it.
77 $this->availableLanguages[$row['language_code']][$row['char_set']] = new Language($row);
79 $this->numLanguages = count($this->availableLanguages);
84 * Returns a valid Language Object based on the given language $code and optional
85 * $charset, FALSE if it can't be found.
87 * @param string $code The language code of the language to return.
88 * @param string $charset Optionally, the character set of the language to find.
89 * @return boolean|Language Returns FALSE if the requested language code and
90 * character set cannot be found. Returns a Language Object for the
91 * specified language code and character set.
92 * @see getMyLanguage()
94 function getLanguage($code, $charset = '') {
96 if (isset($this->availableLanguages[$code])) {
97 return current($this->availableLanguages[$code]);
103 foreach ($this->availableLanguages[$code] as $language) {
104 if ($language->getCharacterSet() == $charset) {
112 * Tries to detect the user's current language preference/setting from (in order):
113 * _GET, _POST, _SESSION, HTTP_ACCEPT_LANGUAGE, HTTP_USER_AGENT. If no match can be made
114 * then it tries to detect a default setting (defined in config.inc.php) or a fallback
115 * setting, false if all else fails.
117 * @return boolean|Language Returns a Language Object matching the user's current session.
118 * Returns FALSE if a valid Language Object cannot be found
119 * to match the request
122 function getMyLanguage() {
123 global $addslashes, $db;
125 if (isset($_GET) && !empty($_GET['lang']) && isset($this->availableLanguages[$_GET['lang']])) {
126 $language = $this->getLanguage($_GET['lang']);
133 if (isset($_POST) && !empty($_POST['lang']) && isset($this->availableLanguages[$_POST['lang']])) {
134 $language = $this->getLanguage($_POST['lang']);
141 if (isset($_SESSION) && isset($_SESSION['lang']) && !empty($_SESSION['lang']) && isset($this->availableLanguages[$_SESSION['lang']])) {
142 $language = $this->getLanguage($_SESSION['lang']);
148 if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
150 // Language is not defined yet :
151 // try to find out user's language by checking its HTTP_ACCEPT_LANGUAGE
152 $accepted = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
153 $acceptedCnt = count($accepted);
155 for ($i = 0; $i < $acceptedCnt; $i++) {
156 foreach ($this->availableLanguages as $codes) {
157 foreach ($codes as $language) {
158 if ($language->isMatchHttpAcceptLanguage($accepted[$i])) {
166 if (!empty($_SERVER['HTTP_USER_AGENT'])) {
168 // Language is not defined yet :
169 // try to find out user's language by checking its HTTP_USER_AGENT
170 foreach ($this->availableLanguages as $codes) {
171 foreach ($codes as $language) {
172 if ($language->isMatchHttpUserAgent($_SERVER['HTTP_USER_AGENT'])) {
179 // Didn't catch any valid lang : we use the default settings
180 if (isset($this->availableLanguages[DEFAULT_LANGUAGE])) {
181 $language = $this->getLanguage(DEFAULT_LANGUAGE, DEFAULT_CHARSET);
189 if (isset($this->availableLanguages[$this->default_lang])) {
190 $language = $this->getLanguage($this->default_lang, $this->default_charset);
197 // else pick one at random:
198 reset($this->availableLanguages);
200 $unknown_language = current($this->availableLanguages);
202 if (!$unknown_language) {
206 return current($unknown_language);
209 function getAvailableLanguages() {
210 return $this->availableLanguages;
214 function printDropdown($current_language, $name, $id) {
215 echo '<select name="'.$name.'" id="'.$id.'">';
217 foreach ($this->availableLanguages as $codes) {
218 $language = current($codes);
219 if ((defined('AT_DEVEL_TRANSLATE') && AT_DEVEL_TRANSLATE) || ($language->getStatus() == AT_LANG_STATUS_PUBLISHED)) {
220 echo '<option value="'.$language->getCode().'"';
221 if ($language->getCode() == $current_language) {
222 echo ' selected="selected"';
224 echo '>'.$language->getNativeName().'</option>';
231 function printList($current_language, $name, $id, $url) {
234 foreach ($this->availableLanguages as $codes) {
235 $language = current($codes);
237 if ($language->getStatus() == AT_LANG_STATUS_PUBLISHED) {
243 if ($language->getCode() == $current_language) {
244 echo '<strong>'.$language->getNativeName().'</strong>';
246 echo '<a href="'.$url.'lang='.$language->getCode().'">'.$language->getNativeName().'</a> ';
255 function getNumLanguages() {
256 return $this->numLanguages;
260 // checks whether or not the language exists/is available
261 function exists($code, $locale = '') {
263 return isset($this->availableLanguages[$code . AT_LANGUAGE_LOCALE_SEP . $locale]);
265 return isset($this->availableLanguages[$code]);
269 // import language pack from specified file
270 function import($filename) {
271 global $languageManager, $msg;
273 $import_path = AT_CONTENT_DIR . 'import/';
275 $archive = new PclZip($filename);
276 if ($archive->extract( PCLZIP_OPT_PATH, $import_path) == 0) {
277 exit('Error : ' . $archive->errorInfo(true));
280 $language_xml = @file_get_contents($import_path.'language.xml');
282 $languageParser = new LanguageParser();
283 $languageParser->parse($language_xml);
284 $languageEditor = $languageParser->getLanguageEditor(0);
286 if (($languageEditor->getAtutorVersion() != VERSION)
287 && (!defined('AT_DEVEL_TRANSLATE') || !AT_DEVEL_TRANSLATE))
289 $msg->addError('LANG_WRONG_VERSION');
292 if (($languageEditor->getStatus() != AT_LANG_STATUS_PUBLISHED)
293 && ($languageEditor->getStatus() != AT_LANG_STATUS_COMPLETE)
294 && (!defined('AT_DEVEL_TRANSLATE') || !AT_DEVEL_TRANSLATE))
296 $msg->addError('LANG_NOT_COMPLETE');
299 if ($languageManager->exists($languageEditor->getCode())) {
300 $msg->addError('LANG_EXISTS');
303 if (!$msg->containsErrors()) {
304 $languageEditor->import($import_path . 'language_text.sql');
305 $msg->addFeedback('IMPORT_LANG_SUCCESS');
309 @unlink($import_path . 'language.xml');
310 @unlink($import_path . 'language_text.sql');
311 @unlink($import_path . 'readme.txt');
316 // imports LIVE language from the atutor language database
317 function liveImport($language_code) {
320 $tmp_lang_db = mysql_connect(AT_LANG_DB_HOST, AT_LANG_DB_USER, AT_LANG_DB_PASS);
321 // set database connection using utf8
322 mysql_query("SET NAMES 'utf8'", $tmp_lang_db);
325 /* AT_ERROR_NO_DB_CONNECT */
326 echo 'Unable to connect to db.';
329 if (!mysql_select_db('dev_atutor_langs', $tmp_lang_db)) {
330 echo 'DB connection established, but database "dev_atutor_langs" cannot be selected.';
334 $sql = "SELECT * FROM languages_SVN WHERE language_code='$language_code'";
335 $result = mysql_query($sql, $tmp_lang_db);
337 if ($row = mysql_fetch_assoc($result)) {
338 $row['reg_exp'] = addslashes($row['reg_exp']);
339 $row['native_name'] = addslashes($row['native_name']);
340 $row['english_name'] = addslashes($row['english_name']);
342 $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)";
343 $result = mysql_query($sql, $db);
345 $sql = "SELECT * FROM language_text_SVN WHERE language_code='$language_code'";
346 $result = mysql_query($sql, $tmp_lang_db);
348 $sql = "REPLACE INTO ".TABLE_PREFIX."language_text VALUES ";
349 while ($row = mysql_fetch_assoc($result)) {
350 $row['text'] = addslashes($row['text']);
351 $row['context'] = addslashes($row['context']);
352 $sql .= "('{$row['language_code']}', '{$row['variable']}', '{$row['term']}', '{$row['text']}', '{$row['revised_date']}', '{$row['context']}'),";
354 $sql = substr($sql, 0, -1);
355 mysql_query($sql, $db);
362 $lang_xml = '<?xml version="1.0" encoding="iso-8859-1"?>
363 <!-- These are ATutor language packs - http://www.atutor.ca-->
365 <!DOCTYPE languages [
366 <!ELEMENT language (atutor-version, code, charset, direction, reg-exp, native-name, english-name )>
367 <!ELEMENT atutor-version (#PCDATA)>
368 <!ELEMENT code (#PCDATA)>
369 <!ELEMENT charset (#PCDATA)>
370 <!ELEMENT direction (#PCDATA)>
371 <!ELEMENT reg-exp (#PCDATA)>
372 <!ELEMENT native-name (#PCDATA)>
373 <!ELEMENT english-name (#PCDATA)>
374 <!ELEMENT status (#PCDATA)>
375 <!ATTLIST language code ID #REQUIRED>
380 foreach ($this->availableLanguages as $codes) {
381 foreach ($codes as $language) {
382 $lang_xml .= $language->getXML(TRUE);
386 $lang_xml .= "\r\n".'</languages>';