From 407e889c3aedcffa96b62380743ef35c8285165c Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sun, 21 Feb 2010 11:27:50 +0000 Subject: [PATCH] added language detection functionality --- codepot/etc/codepot.ini.in | 6 +- codepot/src/codepot/config/Makefile.am | 1 + codepot/src/codepot/config/Makefile.in | 1 + codepot/src/codepot/config/autoload.php | 4 +- codepot/src/codepot/config/config.php | 2 +- codepot/src/codepot/config/lang_detect.php | 33 ++ codepot/src/codepot/controllers/source.php | 2 +- codepot/src/codepot/libraries/Lang_detect.php | 287 ++++++++++++++++++ codepot/src/codepot/libraries/Makefile.am | 3 +- codepot/src/codepot/libraries/Makefile.in | 3 +- codepot/src/codepot/models/logmodel.php | 1 - codepot/src/config.php.in | 2 +- 12 files changed, 335 insertions(+), 10 deletions(-) create mode 100644 codepot/src/codepot/config/lang_detect.php create mode 100644 codepot/src/codepot/libraries/Lang_detect.php diff --git a/codepot/etc/codepot.ini.in b/codepot/etc/codepot.ini.in index 6e16127c..a53fe69c 100644 --- a/codepot/etc/codepot.ini.in +++ b/codepot/etc/codepot.ini.in @@ -31,9 +31,11 @@ ldap_userid_format = "${userid}" ldap_password_format = "${password}" ;------------------------------------------------------------------------------ -; language to use +; default langage to use. set it to 'auto' to detect it automatically. +; available languages are: +; english, korean, indonesian ;------------------------------------------------------------------------------ -lang = "english" +language = "auto" ;------------------------------------------------------------------------------ ; When set to yes, viewing pages require a user to sign in. diff --git a/codepot/src/codepot/config/Makefile.am b/codepot/src/codepot/config/Makefile.am index f68b56c6..e992f55b 100644 --- a/codepot/src/codepot/config/Makefile.am +++ b/codepot/src/codepot/config/Makefile.am @@ -7,6 +7,7 @@ www_DATA = \ doctypes.php \ hooks.php \ index.html \ + lang_detect.php \ mimes.php \ routes.php \ smileys.php \ diff --git a/codepot/src/codepot/config/Makefile.in b/codepot/src/codepot/config/Makefile.in index 71b9bde2..2cc28752 100644 --- a/codepot/src/codepot/config/Makefile.in +++ b/codepot/src/codepot/config/Makefile.in @@ -170,6 +170,7 @@ www_DATA = \ doctypes.php \ hooks.php \ index.html \ + lang_detect.php \ mimes.php \ routes.php \ smileys.php \ diff --git a/codepot/src/codepot/config/autoload.php b/codepot/src/codepot/config/autoload.php index 4c891e60..ea08f8b1 100644 --- a/codepot/src/codepot/config/autoload.php +++ b/codepot/src/codepot/config/autoload.php @@ -39,7 +39,7 @@ | $autoload['libraries'] = array('database', 'session', 'xmlrpc'); */ -$autoload['libraries'] = array('database'); +$autoload['libraries'] = array('database', 'lang_detect'); /* @@ -79,7 +79,7 @@ $autoload['plugin'] = array(); | */ -$autoload['config'] = array(); +$autoload['config'] = array('lang_detect'); /* diff --git a/codepot/src/codepot/config/config.php b/codepot/src/codepot/config/config.php index 965f6505..5d66aa6b 100644 --- a/codepot/src/codepot/config/config.php +++ b/codepot/src/codepot/config/config.php @@ -69,7 +69,7 @@ $config['url_suffix'] = ""; | than english. | */ -$config['language'] = "english"; +$config['language'] = 'english'; /* |-------------------------------------------------------------------------- diff --git a/codepot/src/codepot/config/lang_detect.php b/codepot/src/codepot/config/lang_detect.php new file mode 100644 index 00000000..24f508e7 --- /dev/null +++ b/codepot/src/codepot/config/lang_detect.php @@ -0,0 +1,33 @@ + 'english', + 'ko' => 'korean', + 'id' => 'indonesian' +); + +// define the default language code. This language MUST be supported! +$config['lang_default'] = 'en'; + +// the selected language code. Is set by the language detection +$config['lang_selected'] = 'en'; + +// Language cookie parameters: +// 'lang_cookie_name' = the name you want for the cookie +// 'lang_expiration' = the number of SECONDS you want the language to be +// remembered. by default 2 years. +// Set zero for expiration when the browser is closed. +$config['lang_cookie_name'] = 'lang_select_language'; +$config['lang_expiration'] = 63072000; + +?> diff --git a/codepot/src/codepot/controllers/source.php b/codepot/src/codepot/controllers/source.php index df8f51ca..9db21829 100644 --- a/codepot/src/codepot/controllers/source.php +++ b/codepot/src/codepot/controllers/source.php @@ -19,7 +19,7 @@ class Source extends Controller $this->load->model (CODEPOT_LOGIN_MODEL, 'login'); $this->load->library ('Language', 'lang'); - $this->lang->load ('common', CODEPOT_LANG); + $this->lang->load ('common', CODEPOT_LANG); } function home ($projectid = '', $subdir = '', $rev = SVN_REVISION_HEAD) diff --git a/codepot/src/codepot/libraries/Lang_detect.php b/codepot/src/codepot/libraries/Lang_detect.php new file mode 100644 index 00000000..b91cc559 --- /dev/null +++ b/codepot/src/codepot/libraries/Lang_detect.php @@ -0,0 +1,287 @@ + 'english', +| 'en_us' => 'english', +| 'de' => 'german', +| 'es' => 'spanish' +| ); +| $config['lang_default'] = 'en'; +| $config['lang_selected'] = 'en'; +| +| Full language codes such as en_uk, de_at are supported. If there is no +| configuration entry for them, their base language, i.e. en, de, etc. is used. +| If no match was found, the configured default language is taken. +| +| The selected ISO language code is included as URI segment in all links that +| are generated by the site_url function of the MY_Config class. Additionally +| a cookie is set that stores the selected code for a longer time period. +| The cookie can be configured by the following configuration values (all +| other cookie parameters are taken from the standard CodeIgniter +| configuration items): +| $config['lang_cookie_name'] = 'xxx_language'; +| $config['lang_expiration'] = 63072000; // 2 years +| +| @package CodeIgniter +| @subpackage Libraries +| @category I18N +| @copyright Copyright (C) 2007 Roland Blochberger +| @author Roland Blochberger +| +| @inpiredFrom Code Igniter Mini-App, Language Detect Library by George Dunlop +| @inpiredlink http://mini-app.peccavi.com +| +| +| This library is free software; you can redistribute it and/or +| modify it under the terms of the GNU Lesser General Public +| License as published by the Free Software Foundation; either +| version 2.1 of the License, or (at your option) any later version. +| +| This library is distributed in the hope that it will be useful, +| but WITHOUT ANY WARRANTY; without even the implied warranty of +| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +| Lesser General Public License for more details. +| +| You should have received a copy of the GNU Lesser General Public +| License along with this library; if not, write to the Free Software +| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +| +*/ +// Lang_detect Version +define('LANG_DETECT_VERSION', '1.1.0'); + +class Lang_detect +{ + var $obj; + // make config item available locally + var $lang_avail; + // the user's language (directory name) + var $lang_dir = ''; + + /** + * Constructor + */ + function Lang_detect() + { + $this->obj =& get_instance(); + // get list of supported languages + $this->lang_avail = $this->obj->config->item('lang_avail'); + + if (empty($this->lang_dir)) + { + $this->lang_dir = $this->detectLanguage(); + if (!defined('CODEPOT_LANG')) + { + if (strcasecmp(CODEPOT_LANGUAGE, 'auto') == 0) + define ('CODEPOT_LANG', $this->lang_dir); + else + define ('CODEPOT_LANG', CODEPOT_LANGUAGE); + } + } + log_message('debug', __CLASS__." class ".LANG_DETECT_VERSION." initialized (using $this->lang_dir)"); + } + + // -------------------------------------------------------------------- + + /** + * determine user's language. + * Use either the URI segment's or the cookie's language code or + * determine the best match of the browser's languages with the + * available languages. + * If no match s found, the configured default language is taken. + * + * @return language directory name, e.g 'english' + */ + function detectLanguage() + { + $language = false; + +/* + // obtain language code from URI segment if available + $langu = $this->_uri_lang_detect(); + if ($langu !== false) + { + // check the URI's language code + $language = $this->_checkLang($langu); + if ($language !== false) + { + $lang = $langu; + //log_message('debug', __CLASS__.".detectLanguage(): Use URI segment language: $langu ($language)"); + } + } + + // if a language cookie available get its sanitized info + $langc = $this->obj->input->cookie($this->obj->config->item('cookie_prefix').$this->obj->config->item('lang_cookie_name'), true); + if ($langc !== false) + { + if (($language !== false) && ($langu !== $langc)) + { + // URI has valid language but cookie has wrong language: + // update cookie + $this->_set_lang_cookie($langu); + } + if ($language === false) + { + // invalid or no URI language code: check the cookie's language + $language = $this->_checkLang($langc); + if ($language !== false) + { + $lang = $langc; + //log_message('debug', __CLASS__.".detectLanguage(): Use cookie language: $langc ($language)"); + } + } + } +*/ + + if ($language === false) + { + // no cookie/URI language code: check browser's languages + $accept_langs = $this->obj->input->server('HTTP_ACCEPT_LANGUAGE'); + if ($accept_langs !== false) + { + //explode languages into array + $accept_langs = strtolower($accept_langs); + $accept_langs = explode(",", $accept_langs); + //log_message('debug', __CLASS__.".detectLanguage(): browser languages: ".print_r($accept_langs, true)); + // check all of them + foreach ($accept_langs as $lang) + { + //log_message('debug', __CLASS__.".detectLanguage(): Check lang: $lang"); + // remove all after ';' + $pos = strpos($lang,';'); + if ($pos !== false) + { $lang = substr($lang,0,$pos); } + // get CI language directory + $language = $this->_checkLang($lang); + // finish search if we support that language + if ($language !== false) + { + // set cookie + $this->_set_lang_cookie($lang); + //log_message('debug', __CLASS__.".detectLanguage(): Use browser language: $lang ($language)"); + break; + } + } + } + } + + if ($language === false) + { + // no base language available or no browser language match: use default + $lang = $this->obj->config->item('lang_default'); + // XXX Of course the default language has to be supported! + $language = $this->lang_avail[$lang]; + // set cookie + $this->_set_lang_cookie($lang); + //log_message('debug', __CLASS__.".detectLanguage(): Use default language: $lang ($language)"); + } + +/* + // set the configuration for the CI_Language class + $this->obj->config->set_item('language', $language); +*/ + + // store the language code too + $this->obj->config->set_item('lang_selected', $lang); + //log_message('debug', __CLASS__.".detectLanguage(): Use language: $lang ($language)"); + return $language; + } + + // -------------------------------------------------------------------- + + /** + * set the language cookie. + * + * @access private + * @param string $lang the language code, e.g. en + */ + function _set_lang_cookie($lang) + { + //log_message('debug', __CLASS__."._set_lang_cookie($lang)"); + if (!function_exists('set_cookie')) + { + $this->obj->load->helper('cookie'); + } + set_cookie($this->obj->config->item('lang_cookie_name'), + $lang, + $this->obj->config->item('lang_expiration'), + $this->obj->config->item('cookie_domain'), + $this->obj->config->item('cookie_path'), + $this->obj->config->item('cookie_prefix')); + } + + // -------------------------------------------------------------------- + + /** + * fetch language code from URI segment if available. + * + * @access private + * @return mixed the language code; or FALSE if not found. + */ + function _uri_lang_detect() + { + // search the language code in the uri segments + $_n = $this->obj->uri->total_segments(); + for ($_s = $_n; $_s > 0; $_s--) + { + $_seg = $this->obj->uri->segment($_s); + // the uri segment with the language code has the prefix 'l_' + if (!empty($_seg) && (strpos($_seg, 'l_') === 0)) + { + // extract the language code + return substr($_seg, 2); + } + } + return false; + } + + // -------------------------------------------------------------------- + + /** + * determine language directory + * + * @param string $lang language code, e.g. en_uk + * @return string language directory or false if not found. + * updates the $lang parameter! + */ + function _checkLang(&$lang) + { + //log_message('debug', __CLASS__."._checkLang($lang) trys '$lang'"); + if (!array_key_exists($lang, $this->lang_avail)) + { + if (strlen($lang) == 2) + { + // we had already the base language: not found so give up + //log_message('debug', __CLASS__."._checkLang($lang) '$lang' not available!"); + return false; + } + else + { + // try base language + $lang = substr($lang, 0, 2); + //log_message('debug', __CLASS__."._checkLang($lang) trys '$lang'"); + if (!array_key_exists($lang, $this->lang_avail)) + { + // calculated base language also not found: give up + //log_message('debug', __CLASS__."._checkLang($lang) '$lang' not available!"); + return false; + } + } + } + // get CI language directory + //log_message('debug', __CLASS__."._checkLang($lang) uses '$lang'"); + return $this->lang_avail[$lang]; + } +} + diff --git a/codepot/src/codepot/libraries/Makefile.am b/codepot/src/codepot/libraries/Makefile.am index 42128436..4dc5fade 100644 --- a/codepot/src/codepot/libraries/Makefile.am +++ b/codepot/src/codepot/libraries/Makefile.am @@ -1,7 +1,8 @@ wwwdir=$(WWWDIR)/codepot/libraries www_DATA = \ converter.php \ - index.html + index.html \ + Lang_detect.php EXTRA_DIST = $(www_DATA) diff --git a/codepot/src/codepot/libraries/Makefile.in b/codepot/src/codepot/libraries/Makefile.in index 1840e540..c4185446 100644 --- a/codepot/src/codepot/libraries/Makefile.in +++ b/codepot/src/codepot/libraries/Makefile.in @@ -164,7 +164,8 @@ top_srcdir = @top_srcdir@ wwwdir = $(WWWDIR)/codepot/libraries www_DATA = \ converter.php \ - index.html + index.html \ + Lang_detect.php EXTRA_DIST = $(www_DATA) all: all-am diff --git a/codepot/src/codepot/models/logmodel.php b/codepot/src/codepot/models/logmodel.php index 8effbf33..a17a0643 100644 --- a/codepot/src/codepot/models/logmodel.php +++ b/codepot/src/codepot/models/logmodel.php @@ -52,7 +52,6 @@ class LogModel extends Model $commits[$count]['repo'] = $repo; $commits[$count]['rev'] = $rev; - $log = @svn_log ( 'file:///'.CODEPOT_SVNREPO_DIR."/{$repo}", $rev, $rev, 1,SVN_DISCOVER_CHANGED_PATHS); diff --git a/codepot/src/config.php.in b/codepot/src/config.php.in index 58027f7b..df5b628d 100644 --- a/codepot/src/config.php.in +++ b/codepot/src/config.php.in @@ -15,7 +15,7 @@ function load_ini ($file) $xcfgs = array ( array ('default_banner', 'string', '@PACKAGE@'), array ('default_siteid', 'string', 'default'), - array ('lang', 'string', 'english'), + array ('language', 'string', 'auto'), array ('always_require_signin', 'boolean', FALSE), array ('enable_websvn', 'boolean', FALSE),