1 |
<?php |
1 |
<?php |
2 |
|
2 |
|
3 |
/** |
3 |
/** |
4 |
* Translation class. |
4 |
* Translation class. |
5 |
* @license http://opensource.org/licenses/gpl-license.php GNU General Public License |
5 |
* @license http://opensource.org/licenses/gpl-license.php GNU General Public License |
6 |
* @copyright (c)2003-2005 Tamlyn Rhodes |
6 |
* @copyright (c)2003-2005 Tamlyn Rhodes |
7 |
* @version $Id: translator.class.php,v 1.5 2006/02/06 18:47:57 tamlyn Exp $ |
7 |
* @version $Id: translator.class.php,v 1.5 2006/02/06 18:47:57 tamlyn Exp $ |
8 |
*/ |
8 |
*/ |
9 |
|
9 |
|
10 |
/** |
10 |
/** |
11 |
* Provides functions for translating strings using GNU Gettext PO files |
11 |
* Provides functions for translating strings using GNU Gettext PO files |
12 |
* @package singapore |
12 |
* @package singapore |
13 |
* @author Joel Sjögren <joel dot sjogren at nonea dot se> |
13 |
* @author Joel Sjögren <joel dot sjogren at nonea dot se> |
14 |
* @author Tamlyn Rhodes <tam at zenology dot co dot uk> |
14 |
* @author Tamlyn Rhodes <tam at zenology dot co dot uk> |
15 |
* @copyright (c)2003, 2004 Tamlyn Rhodes |
15 |
* @copyright (c)2003, 2004 Tamlyn Rhodes |
16 |
*/ |
16 |
*/ |
17 |
class Translator |
17 |
class Translator |
18 |
{ |
18 |
{ |
19 |
/** |
19 |
/** |
20 |
* Array of language strings in the form |
20 |
* Array of language strings in the form |
21 |
* "english string" => "foreign string" |
21 |
* "english string" => "foreign string" |
22 |
* @private |
22 |
* @private |
23 |
* @var array |
23 |
* @var array |
24 |
*/ |
24 |
*/ |
25 |
var $languageStrings = array(); |
25 |
var $languageStrings = array(); |
26 |
|
26 |
|
27 |
var $language = "en"; |
27 |
var $language = "en"; |
28 |
|
28 |
|
29 |
/** |
29 |
/** |
30 |
* Constructor |
30 |
* Constructor |
31 |
* @param string language code |
31 |
* @param string language code |
32 |
* @private |
32 |
* @private |
33 |
*/ |
33 |
*/ |
34 |
function Translator($language) |
34 |
function Translator($language) |
35 |
{ |
35 |
{ |
36 |
$this->language = $language; |
36 |
$this->language = $language; |
37 |
} |
37 |
} |
38 |
|
38 |
|
39 |
/** |
39 |
/** |
40 |
* Implements a version of the Singleton design pattern by always returning |
40 |
* Implements a version of the Singleton design pattern by always returning |
41 |
* a reference to the same Translator object for each language. If no |
41 |
* a reference to the same Translator object for each language. If no |
42 |
* language is specified then the first loaded Translator is returned. |
42 |
* language is specified then the first loaded Translator is returned. |
43 |
* @param string language code (optional) |
43 |
* @param string language code (optional) |
44 |
* @static |
44 |
* @static |
45 |
*/ |
45 |
*/ |
46 |
function &getInstance($language = 0) |
46 |
function &getInstance($language = 0) |
47 |
{ |
47 |
{ |
48 |
static $instances = array(); |
48 |
static $instances = array(); |
49 |
|
49 |
|
50 |
$key = empty($instances) ? 0 : $language; |
50 |
$key = empty($instances) ? 0 : $language; |
51 |
|
51 |
|
52 |
if(!isset($instances[$key])) |
52 |
if(!isset($instances[$key])) |
53 |
//note that the new object is NOT assigned by reference as |
53 |
//note that the new object is NOT assigned by reference as |
54 |
//references are not stored in static variables (don't ask me...) |
54 |
//references are not stored in static variables (don't ask me...) |
55 |
$instances[$key] = new Translator($language); |
55 |
$instances[$key] = new Translator($language); |
56 |
return $instances[$key]; |
56 |
return $instances[$key]; |
57 |
} |
57 |
} |
58 |
|
58 |
|
59 |
/** |
59 |
/** |
60 |
* Reads a language file and saves the strings in an array. |
60 |
* Reads a language file and saves the strings in an array. |
61 |
* Note that the language code is used in the filename for the |
61 |
* Note that the language code is used in the filename for the |
62 |
* datafile, and is case sensitive. |
62 |
* datafile, and is case sensitive. |
63 |
* |
63 |
* |
64 |
* @author Joel Sjögren <joel dot sjogren at nonea dot se> |
64 |
* @author Joel Sjögren <joel dot sjogren at nonea dot se> |
65 |
* @param string file to load |
65 |
* @param string file to load |
66 |
* @return bool success |
66 |
* @return bool success |
67 |
*/ |
67 |
*/ |
68 |
function readLanguageFile($languageFile) |
68 |
function readLanguageFile($languageFile) |
69 |
{ |
69 |
{ |
70 |
// Look for the language file |
70 |
// Look for the language file |
71 |
if(!file_exists($languageFile)) |
71 |
if(!file_exists($languageFile)) |
72 |
return false; |
72 |
return false; |
73 |
|
73 |
|
74 |
// Open the file |
74 |
// Open the file |
75 |
$fp = @fopen($languageFile, "r"); |
75 |
$fp = @fopen($languageFile, "r"); |
76 |
if (!$fp) return false; |
76 |
if (!$fp) return false; |
77 |
|
77 |
|
78 |
// Read contents |
78 |
// Read contents |
79 |
$str = ''; |
79 |
$str = ''; |
80 |
while (!feof($fp)) $str .= fread($fp, 1024); |
80 |
while (!feof($fp)) $str .= fread($fp, 1024); |
81 |
// Unserialize |
81 |
// Unserialize |
82 |
$newStrings = @unserialize($str); |
82 |
$newStrings = @unserialize($str); |
83 |
|
83 |
|
84 |
//Append new strings to current languageStrings array |
84 |
//Append new strings to current languageStrings array |
85 |
$this->languageStrings = array_merge($this->languageStrings, $newStrings); |
85 |
$this->languageStrings = array_merge($this->languageStrings, $newStrings); |
86 |
|
86 |
|
87 |
// Return successful |
87 |
// Return successful |
88 |
return (bool) $newStrings; |
88 |
return (bool) $newStrings; |
89 |
} |
89 |
} |
90 |
|
90 |
|
91 |
/** |
91 |
/** |
92 |
* Returns a translated string, or the same if no language is chosen. |
92 |
* Returns a translated string, or the same if no language is chosen. |
93 |
* You can pass more arguments to use for replacement within the |
93 |
* You can pass more arguments to use for replacement within the |
94 |
* string - just like sprintf(). It also removes anything before |
94 |
* string - just like sprintf(). It also removes anything before |
95 |
* the first | in the text to translate. This is used to distinguish |
95 |
* the first | in the text to translate. This is used to distinguish |
96 |
* strings with different meanings, but with the same spelling. |
96 |
* strings with different meanings, but with the same spelling. |
97 |
* Examples: |
97 |
* Examples: |
98 |
* _g("Text"); |
98 |
* _g("Text"); |
99 |
* _g("Use a %s to drink %s", _g("glass"), "water"); |
99 |
* _g("Use a %s to drink %s", _g("glass"), "water"); |
100 |
* |
100 |
* |
101 |
* @author Joel Sjögren <joel dot sjogren at nonea dot se> |
101 |
* @author Joel Sjögren <joel dot sjogren at nonea dot se> |
102 |
* @param string text to translate |
102 |
* @param string text to translate |
103 |
* @return string translated string |
103 |
* @return string translated string |
104 |
*/ |
104 |
*/ |
105 |
function _g ($text) |
105 |
function _g ($text) |
106 |
{ |
106 |
{ |
107 |
// String exists and is not empty? |
107 |
// String exists and is not empty? |
108 |
if(!empty($this->languageStrings[$text])) { |
108 |
if(!empty($this->languageStrings[$text])) { |
109 |
$text = $this->languageStrings[$text]; |
109 |
$text = $this->languageStrings[$text]; |
110 |
} else { |
110 |
} else { |
111 |
$text = preg_replace("/^[^\|]*\|/", "", $text); |
111 |
$text = preg_replace("/^[^\|]*\|/", "", $text); |
112 |
} |
112 |
} |
113 |
|
113 |
|
114 |
// More arguments were passed? sprintf() them... |
114 |
// More arguments were passed? sprintf() them... |
115 |
if (func_num_args() > 1) { |
115 |
if (func_num_args() > 1) { |
116 |
$args = func_get_args(); |
116 |
$args = func_get_args(); |
117 |
array_shift($args); |
117 |
array_shift($args); |
118 |
//preg_match_all("/%((\d+\\\$)|.)/", str_replace("%%", "", $text), $m); |
118 |
//preg_match_all("/%((\d+\\\$)|.)/", str_replace("%%", "", $text), $m); |
119 |
//while (count($args) < count($m[0])) $args[] = ''; |
119 |
//while (count($args) < count($m[0])) $args[] = ''; |
120 |
$text = vsprintf($text, $args); |
120 |
$text = vsprintf($text, $args); |
121 |
} |
121 |
} |
122 |
return $text; |
122 |
return $text; |
123 |
} |
123 |
} |
124 |
|
124 |
|
125 |
/** |
125 |
/** |
126 |
* Plural form of _g(). |
126 |
* Plural form of _g(). |
127 |
* |
127 |
* |
128 |
* @param string singular form of text to translate |
128 |
* @param string singular form of text to translate |
129 |
* @param string plural form of text to translate |
129 |
* @param string plural form of text to translate |
130 |
* @param string number |
130 |
* @param string number |
131 |
* @return string translated string |
131 |
* @return string translated string |
132 |
*/ |
132 |
*/ |
133 |
function _ng ($msgid1, $msgid2, $n) |
133 |
function _ng ($msgid1, $msgid2, $n) |
134 |
{ |
134 |
{ |
135 |
//calculate which plural to use |
135 |
//calculate which plural to use |
136 |
if(!empty($this->languageStrings[0]["plural"])) |
136 |
if(!empty($this->languageStrings[0]["plural"])) |
137 |
eval($this->languageStrings[0]["plural"]); |
137 |
eval($this->languageStrings[0]["plural"]); |
138 |
else |
138 |
else |
139 |
$plural = $n==1?0:1; |
139 |
$plural = $n==1?0:1; |
140 |
|
140 |
|
141 |
// String exists and is not empty? |
141 |
// String exists and is not empty? |
142 |
if (!empty($this->languageStrings[$msgid1][$plural])) { |
142 |
if (!empty($this->languageStrings[$msgid1][$plural])) { |
143 |
$text = $this->languageStrings[$msgid1][$plural]; |
143 |
$text = $this->languageStrings[$msgid1][$plural]; |
144 |
} else { |
144 |
} else { |
145 |
$text = preg_replace("/^[^\|]*\|/", "", ($n == 1 ? $msgid1 : $msgid2)); |
145 |
$text = preg_replace("/^[^\|]*\|/", "", ($n == 1 ? $msgid1 : $msgid2)); |
146 |
} |
146 |
} |
147 |
|
147 |
|
148 |
if (func_num_args() > 3) { |
148 |
if (func_num_args() > 3) { |
149 |
$args = func_get_args(); |
149 |
$args = func_get_args(); |
150 |
array_shift($args); |
150 |
array_shift($args); |
151 |
array_shift($args); |
151 |
array_shift($args); |
152 |
return vsprintf($text, $args); |
152 |
return vsprintf($text, $args); |
153 |
} |
153 |
} |
154 |
|
154 |
|
155 |
return sprintf($text, $n); |
155 |
return sprintf($text, $n); |
156 |
} |
156 |
} |
157 |
|
157 |
|
158 |
} |
158 |
} |
159 |
|
159 |
|
160 |
?> |
160 |
?> |