Multilanguage Support Solution
| From: | Andr� Rabold | 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.. ?>