Multilanguage Support Solution

From: Date: Mon, 30 Sep 2002 08:29:40 +0000
Subject: Multilanguage Support Solution
Groups: php.smarty.dev 
Request: Send a blank email to php-smarty-dev+get-284@lists.php.net to get a copy of this message
I've already posted this on the Wiki sites. But here It is again for discussion ;-) I would really like to know if this is a good approach to solve the common multilanguage problem. Classes to make Smarty templates multilanguage Author: André Rabold The following class subclasses smarty to add multilanguage support 1.. require_once ("Smarty.class.php"); 2.. 3.. $_NG_LANGUAGE_ = null; 4.. 5.. /** 6.. * smarty_prefilter_i18n() 7.. * This function takes the XML language file, and rips it into the template 8.. * You Must register this function with smarty like: 9.. * 10.. * @param $tpl_source 11.. * @return 12.. **/ 13.. function smarty_prefilter_i18n($tpl_source, &$smarty) { 14.. global $_NG_LANGUAGE_; 15.. $_NG_LANGUAGE_ = $smarty->_tpl_vars["_NG_LANGUAGE_"]; 16.. if (!is_object($_NG_LANGUAGE_)) { 17.. die("Error loading Multilanguage Support"); 18.. } 19.. $smarty->compile_id = $_LANG_; 20.. // Now replace the matched language strings with the entry in the file 21.. $return = preg_replace_callback('/##(.+?)##/', '_compile_lang', $tpl_source); 22.. unset($_NG_LANGUAGE_); 23.. return $return; 24.. } 25.. 26.. /** 27.. * _compile_lang 28.. * Called by smarty_prefilter_i18n function it processes every language 29.. * identifier, and inserts the language string in its place. 30.. * 31.. */ 32.. function _compile_lang($key) { 33.. global $_NG_LANGUAGE_; 34.. return $_NG_LANGUAGE_->getTranslation($key[1]); 35.. } 36.. 37.. 38.. class smartyML extends Smarty { 39.. var $language; 40.. 41.. function smartyML ($locale="") { 42.. $this->Smarty(); 43.. 44.. // Multilanguage Support 45.. // use $smarty->language->setLocale() to change the language of your template 46.. // $smarty->loadTranslationTable() to load custom translation tables 47.. $this->language = new ngLanguage($locale); // create a new language object 48.. $this->register_prefilter("smarty_prefilter_i18n"); 49.. } 50.. 51.. function fetch($_smarty_tpl_file, $_smarty_cache_id = null, $_smarty_compile_id = null, $_smarty_display = false) { 52.. $this->assign("_NG_LANGUAGE_", $this->language); // this is a bad workaround to use the language object in our prefilter 53.. return Smarty::fetch( $_smarty_tpl_file, $_smarty_cache_id, $_smarty_compile_id, $_smarty_display ); 54.. } 1.. 2.. class ngLanguage { 3.. var $_translationTable; // currently loaded translation table 4.. var $_supportedLanguages; // array of all supported languages 5.. var $_defaultLocale; // the default language 6.. var $_currentLanguage; // currently loaded language 7.. var $_languageTable; // array of language to file associations 8.. var $_loadedTranslationTables; // array of all loaded translation tables 9.. 10.. function ngLanguage($locale="") { 11.. $this->_languageTable = Array( 12.. "de" => "deu", 13.. "en" => "eng", 14.. "en-us" => "eng", 15.. "en-gb" => "eng" 16.. ); // to be continued ... 17.. $this->_translationTable = Array(); 18.. $this->_loadedTranslationTables = Array(); 19.. foreach ($this->_languageTable as $lang) 20.. $this->_translationTable[$lang] = Array(); 21.. 22.. if (strval($locale) == "") 23.. $locale = $this->getHTTPAcceptLanguage(); 24.. if (strval($locale) == "") 25.. $locale = "en_US"; 26.. $this->_defaultLocale = $locale; 27.. 28.. $path = "languages/".$this->_languageTable[$locale]."/global.lng"; 29.. $this->_loadTranslationTable($path, $locale); 30.. $this->setCurrentLocale($locale); 31.. } 32.. 33.. function getAvailableLocales() { 34.. $list = Array(); 35.. foreach ($this->_languageTable as $locale => $language) 36.. $list[] = $locale; 37.. return $list; 38.. } 39.. 40.. function getAvailableLanguages() { 41.. $list = Array(); 42.. foreach ($this->_languageTable as $locale => $language) 43.. $list[] = $language; 44.. return array_unique($list); 45.. } 46.. 47.. function getCurrentLanguage() { 48.. return $this->_currentLanguage; 49.. } 50.. 51.. function setCurrentLanguage($language) { 52.. $this->_currentLanguage = $language; 53.. } 54.. 55.. function setCurrentLocale($locale) { 56.. $language = $this->_languageTable[$locale]; 57.. if (strval($language) == "") { 58.. die ("LANGUAGE Error: Unsupported locale '$locale'"); 59.. } 60.. return $this->setCurrentLanguage($language); 61.. } 62.. 63.. function getDefaultLocale() { 64.. return $this->_defaultLocale; 65.. } 66.. 67.. function getHTTPAcceptLanguage() { 68.. $langs = explode(',', $_SERVER["HTTP_ACCEPT_LANGUAGE"]); 69.. foreach ($langs as $value) { 70.. // Loop through all the languages, to see if any match our supported ones 71.. if (in_array($value, array_keys($this->_languageTable))){ 72.. // If found, set the language 73.. $locale = $value; 74.. break; 75.. } 76.. } 77.. if (strval($locale) == ""){ 78.. // If we can't find their languages, well, they'll just have to use the 79.. // default 80.. $locale = $this->getDefaultLocale(); 81.. } 82.. return $locale; 83.. } 84.. 85.. function _loadTranslationTable($path, $locale=null) { 86.. if (file_exists($path)) { 87.. if (is_null($locale)) { 88.. $locale = $this->getDefaultLocale(); 89.. } 90.. $entries = file($path); 91.. $language = $this->_languageTable[$locale]; 92.. if (strval($language) == "") { 93.. die ("LANGUAGE Error: Unsupported locale '$locale'"); 94.. } 95.. if (!is_array($this->_translationTable[$language])) { 96.. die ("LANGUAGE Error: Language '$language' not available"); 97.. } 98.. if (is_array($this->_loadedTranslationTables[$language])) { 99.. if (in_array($path, $this->_loadedTranslationTables[$language])) { 100.. // Translation table was already loaded 101.. return true; 102.. } 103.. } 104.. $this->_translationTable[$language][$path] = Array(); 105.. $this->_loadedTranslationTables[$language][] = $path; 106.. foreach ($entries as $row) { 107.. if (substr(ltrim($row),0,2) == "//") // ignore comments 108.. continue; 109.. $keyValuePair = explode("=",$row); 110.. $key = trim($keyValuePair[0]); 111.. $value = $keyValuePair[1]; 112.. if (trim(strval($key)) != "") { 113.. $this->_translationTable[$language][$path][$key] = $value; 114.. } 115.. } 116.. return true; 117.. } 118.. return false; 119.. } 120.. 121.. function _unloadTranslationTable($path, $locale) { 122.. $language = $this->_languageTable[$locale]; 123.. if (strval($language) == "") { 124.. die ("LANGUAGE Error: Unsupported locale '$locale'"); 125.. } 126.. unset($this->_translationTable[$language][$path]); 127.. foreach($this->_loadedTranslationTables[$language] as $key => $value) { 128.. if ($value == $path) { 129.. unset($this->_loadedTranslationTables[$language][$key]); 130.. break; 131.. } 132.. } 133.. return true; 134.. } 135.. 136.. function loadTranslationTable($path, $locale=null) { 137.. // This method is only a placeholder and wants to be overwritten by YOU! ;-) 138.. $this->_loadTranslationTable($path, $locale); 139.. } 140.. 141.. function unloadTranslationTable($path, $locale) { 142.. // This method is only a placeholder and wants to be overwritten by YOU! ;-) 143.. $this->_unloadTranslationTable($path, $locale); 144.. } 145.. 146.. function getTranslation($key) { 147.. $language = $this->getCurrentLanguage(); 148.. $translation = $key; 149.. if (is_array($this->_translationTable[$language])) { 150.. foreach ($this->_loadedTranslationTables[$language] as $table) { 151.. if (isset($this->_translationTable[$language][$table][$key])) { 152.. $translation = $this->_translationTable[$language][$table][$key]; 153.. } 154.. } 155.. } 156.. return $translation; 157.. } 158.. 159.. } I have copied these two classes from a bigger project which uses some more methods and has alot more functionality. So I'm not sure if the above will work for you, I haven't tested it yet. Also it might seem some functions are a bit complicated or have unused parameters. Feel free to modify it ;-) Example Here are two simple language files 1.. // English language file 2.. // put in languages/eng/global.lng 3.. NG_OK=Ok 4.. NG_ABORT=Abort 5.. NG_CANCEL=Cancel 6.. NG_HELLO_WORLD=Hello World!<br>How do you do? 1.. // German language file 2.. // put in languages/deu/global.lng 3.. NG_OK=Ok 4.. NG_ABORT=Abbrechen 5.. NG_CANCEL=Abbrechen 6.. NG_HELLO_WORLD=Hallo Welt!<br>Wie geht es Dir? Put these files into the specified paths. And finally a template with multilanguage support: 1.. <html> 2.. <body> 3.. ##NG_HELLO_WORLD##<br> 4.. <input type="button" value="##NG_OK##" onclick="alert('##NG_OK##')"> 5.. <input type="button" value="##NG_CANCEL##" onclick="alert('##NG_CANCEL##')"> 6.. </body> 7.. </html> Finally how to use the smartyML class: 1.. <?php 2.. $smarty = new smartyML(); 3.. // [...] 4.. // $smarty->assign(...); 5.. $smarty->display("myTemplate.tpl"); 6.. ?> Easy, isn't it? The language will be determined by the browser settings. If you want to change it explicitly you can use something like this: 1.. <?php 2.. $smarty = new smartyML("de"); // now the language will be german regardless of the browser settings 3.. // [...] 4.. // $smarty->assign(...); 5.. $smarty->display("myTemplate.tpl"); 6.. ?>

« previous php.smarty.dev (#284) next »