]>
Commit | Line | Data |
---|---|---|
659468eb AD |
1 | <?php |
2 | /* | |
3 | Copyright (c) 2005 Steven Armstrong <sa at c-area dot ch> | |
4 | ||
5 | Drop in replacement for native gettext. | |
6 | ||
7 | This file is part of PHP-gettext. | |
8 | ||
9 | PHP-gettext is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License as published by | |
11 | the Free Software Foundation; either version 2 of the License, or | |
12 | (at your option) any later version. | |
13 | ||
14 | PHP-gettext is distributed in the hope that it will be useful, | |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | GNU General Public License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
20 | along with PHP-gettext; if not, write to the Free Software | |
21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
22 | ||
23 | */ | |
24 | /* | |
25 | LC_CTYPE 0 | |
26 | LC_NUMERIC 1 | |
27 | LC_TIME 2 | |
28 | LC_COLLATE 3 | |
29 | LC_MONETARY 4 | |
30 | LC_MESSAGES 5 | |
31 | LC_ALL 6 | |
32 | */ | |
33 | ||
34 | require('streams.php'); | |
35 | require('gettext.php'); | |
36 | ||
37 | ||
38 | // Variables | |
39 | ||
40 | global $text_domains, $default_domain, $LC_CATEGORIES, $EMULATEGETTEXT, $CURRENTLOCALE; | |
41 | $text_domains = array(); | |
42 | $default_domain = 'messages'; | |
43 | $LC_CATEGORIES = array('LC_CTYPE', 'LC_NUMERIC', 'LC_TIME', 'LC_COLLATE', 'LC_MONETARY', 'LC_MESSAGES', 'LC_ALL'); | |
44 | $EMULATEGETTEXT = 0; | |
45 | $CURRENTLOCALE = ''; | |
46 | ||
47 | ||
48 | // Utility functions | |
49 | ||
50 | /** | |
51 | * Utility function to get a StreamReader for the given text domain. | |
52 | */ | |
53 | function _get_reader($domain=null, $category=5, $enable_cache=true) { | |
54 | global $text_domains, $default_domain, $LC_CATEGORIES; | |
55 | if (!isset($domain)) $domain = $default_domain; | |
56 | if (!isset($text_domains[$domain]->l10n)) { | |
57 | // get the current locale | |
58 | $locale = _setlocale(LC_MESSAGES, 0); | |
59 | $p = isset($text_domains[$domain]->path) ? $text_domains[$domain]->path : './'; | |
60 | $path = $p . "$locale/". $LC_CATEGORIES[$category] ."/$domain.mo"; | |
61 | if (file_exists($path)) { | |
62 | $input = new FileReader($path); | |
63 | } | |
64 | else { | |
65 | $input = null; | |
66 | } | |
67 | $text_domains[$domain]->l10n = new gettext_reader($input, $enable_cache); | |
68 | } | |
69 | return $text_domains[$domain]->l10n; | |
70 | } | |
71 | ||
72 | /** | |
73 | * Returns whether we are using our emulated gettext API or PHP built-in one. | |
74 | */ | |
75 | function locale_emulation() { | |
76 | global $EMULATEGETTEXT; | |
77 | return $EMULATEGETTEXT; | |
78 | } | |
79 | ||
80 | /** | |
81 | * Checks if the current locale is supported on this system. | |
82 | */ | |
83 | function _check_locale() { | |
84 | global $EMULATEGETTEXT; | |
85 | return !$EMULATEGETTEXT; | |
86 | } | |
87 | ||
88 | /** | |
89 | * Get the codeset for the given domain. | |
90 | */ | |
91 | function _get_codeset($domain=null) { | |
92 | global $text_domains, $default_domain, $LC_CATEGORIES; | |
93 | if (!isset($domain)) $domain = $default_domain; | |
94 | return (isset($text_domains[$domain]->codeset))? $text_domains[$domain]->codeset : ini_get('mbstring.internal_encoding'); | |
95 | } | |
96 | ||
97 | /** | |
98 | * Convert the given string to the encoding set by bind_textdomain_codeset. | |
99 | */ | |
100 | function _encode($text) { | |
101 | $source_encoding = mb_detect_encoding($text); | |
102 | $target_encoding = _get_codeset(); | |
103 | if ($source_encoding != $target_encoding) { | |
104 | return mb_convert_encoding($text, $target_encoding, $source_encoding); | |
105 | } | |
106 | else { | |
107 | return $text; | |
108 | } | |
109 | } | |
110 | ||
111 | ||
112 | ||
113 | ||
114 | // Custom implementation of the standard gettext related functions | |
115 | ||
116 | /** | |
117 | * Sets a requested locale, if needed emulates it. | |
118 | */ | |
119 | function _setlocale($category, $locale) { | |
120 | global $CURRENTLOCALE, $EMULATEGETTEXT; | |
121 | if ($locale === 0) { // use === to differentiate between string "0" | |
122 | if ($CURRENTLOCALE != '') | |
123 | return $CURRENTLOCALE; | |
124 | else | |
125 | // obey LANG variable, maybe extend to support all of LC_* vars | |
126 | // even if we tried to read locale without setting it first | |
127 | return _setlocale($category, $CURRENTLOCALE); | |
128 | } else { | |
129 | $ret = 0; | |
130 | if (function_exists('setlocale')) // I don't know if this ever happens ;) | |
131 | $ret = setlocale($category, $locale); | |
132 | if (($ret and $locale == '') or ($ret == $locale)) { | |
133 | $EMULATEGETTEXT = 0; | |
134 | $CURRENTLOCALE = $ret; | |
135 | } else { | |
136 | if ($locale == '') // emulate variable support | |
137 | $CURRENTLOCALE = getenv('LANG'); | |
138 | else | |
139 | $CURRENTLOCALE = $locale; | |
140 | $EMULATEGETTEXT = 1; | |
141 | } | |
142 | return $CURRENTLOCALE; | |
143 | } | |
144 | } | |
145 | ||
146 | /** | |
147 | * Sets the path for a domain. | |
148 | */ | |
149 | function _bindtextdomain($domain, $path) { | |
150 | global $text_domains; | |
151 | // ensure $path ends with a slash | |
152 | if ($path[strlen($path) - 1] != '/') $path .= '/'; | |
153 | elseif ($path[strlen($path) - 1] != '\\') $path .= '\\'; | |
154 | $text_domains[$domain]->path = $path; | |
155 | } | |
156 | ||
157 | /** | |
158 | * Specify the character encoding in which the messages from the DOMAIN message catalog will be returned. | |
159 | */ | |
160 | function _bind_textdomain_codeset($domain, $codeset) { | |
161 | global $text_domains; | |
162 | $text_domains[$domain]->codeset = $codeset; | |
163 | } | |
164 | ||
165 | /** | |
166 | * Sets the default domain. | |
167 | */ | |
168 | function _textdomain($domain) { | |
169 | global $default_domain; | |
170 | $default_domain = $domain; | |
171 | } | |
172 | ||
173 | /** | |
174 | * Lookup a message in the current domain. | |
175 | */ | |
176 | function _gettext($msgid) { | |
177 | $l10n = _get_reader(); | |
178 | //return $l10n->translate($msgid); | |
179 | return _encode($l10n->translate($msgid)); | |
180 | } | |
181 | /** | |
182 | * Alias for gettext. | |
183 | */ | |
184 | function __($msgid) { | |
185 | return _gettext($msgid); | |
186 | } | |
187 | /** | |
188 | * Plural version of gettext. | |
189 | */ | |
190 | function _ngettext($single, $plural, $number) { | |
191 | $l10n = _get_reader(); | |
192 | //return $l10n->ngettext($single, $plural, $number); | |
193 | return _encode($l10n->ngettext($single, $plural, $number)); | |
194 | } | |
195 | ||
196 | /** | |
197 | * Override the current domain. | |
198 | */ | |
199 | function _dgettext($domain, $msgid) { | |
200 | $l10n = _get_reader($domain); | |
201 | //return $l10n->translate($msgid); | |
202 | return _encode($l10n->translate($msgid)); | |
203 | } | |
204 | /** | |
205 | * Plural version of dgettext. | |
206 | */ | |
207 | function _dngettext($domain, $single, $plural, $number) { | |
208 | $l10n = _get_reader($domain); | |
209 | //return $l10n->ngettext($single, $plural, $number); | |
210 | return _encode($l10n->ngettext($single, $plural, $number)); | |
211 | } | |
212 | ||
213 | /** | |
214 | * Overrides the domain and category for a single lookup. | |
215 | */ | |
216 | function _dcgettext($domain, $msgid, $category) { | |
217 | $l10n = _get_reader($domain, $category); | |
218 | //return $l10n->translate($msgid); | |
219 | return _encode($l10n->translate($msgid)); | |
220 | } | |
221 | /** | |
222 | * Plural version of dcgettext. | |
223 | */ | |
224 | function _dcngettext($domain, $single, $plural, $number, $category) { | |
225 | $l10n = _get_reader($domain, $category); | |
226 | //return $l10n->ngettext($single, $plural, $number); | |
227 | return _encode($l10n->ngettext($single, $plural, $number)); | |
228 | } | |
229 | ||
230 | ||
231 | ||
232 | // Wrappers to use if the standard gettext functions are available, but the current locale is not supported by the system. | |
233 | // Use the standard impl if the current locale is supported, use the custom impl otherwise. | |
234 | ||
235 | function T_setlocale($category, $locale) { | |
236 | return _setlocale($category, $locale); | |
237 | } | |
238 | ||
239 | function T_bindtextdomain($domain, $path) { | |
240 | if (_check_locale()) return bindtextdomain($domain, $path); | |
241 | else return _bindtextdomain($domain, $path); | |
242 | } | |
243 | function T_bind_textdomain_codeset($domain, $codeset) { | |
244 | // bind_textdomain_codeset is available only in PHP 4.2.0+ | |
245 | if (_check_locale() and function_exists('bind_textdomain_codeset')) return bind_textdomain_codeset($domain, $codeset); | |
246 | else return _bind_textdomain_codeset($domain, $codeset); | |
247 | } | |
248 | function T_textdomain($domain) { | |
249 | if (_check_locale()) return textdomain($domain); | |
250 | else return _textdomain($domain); | |
251 | } | |
252 | function T_gettext($msgid) { | |
253 | if (_check_locale()) return gettext($msgid); | |
254 | else return _gettext($msgid); | |
255 | } | |
256 | function T_($msgid) { | |
257 | if (_check_locale()) return _($msgid); | |
258 | return __($msgid); | |
259 | } | |
260 | function T_ngettext($single, $plural, $number) { | |
261 | if (_check_locale()) return ngettext($single, $plural, $number); | |
262 | else return _ngettext($single, $plural, $number); | |
263 | } | |
264 | function T_dgettext($domain, $msgid) { | |
265 | if (_check_locale()) return dgettext($domain, $msgid); | |
266 | else return _dgettext($domain, $msgid); | |
267 | } | |
268 | function T_dngettext($domain, $single, $plural, $number) { | |
269 | if (_check_locale()) return dngettext($domain, $single, $plural, $number); | |
270 | else return _dngettext($domain, $single, $plural, $number); | |
271 | } | |
272 | function T_dcgettext($domain, $msgid, $category) { | |
273 | if (_check_locale()) return dcgettext($domain, $msgid, $category); | |
274 | else return _dcgettext($domain, $msgid, $category); | |
275 | } | |
276 | function T_dcngettext($domain, $single, $plural, $number, $category) { | |
277 | if (_check_locale()) return dcngettext($domain, $single, $plural, $number, $category); | |
278 | else return _dcngettext($domain, $single, $plural, $number, $category); | |
279 | } | |
280 | ||
281 | ||
282 | ||
283 | // Wrappers used as a drop in replacement for the standard gettext functions | |
284 | ||
285 | if (!function_exists('gettext')) { | |
286 | function bindtextdomain($domain, $path) { | |
287 | return _bindtextdomain($domain, $path); | |
288 | } | |
289 | function bind_textdomain_codeset($domain, $codeset) { | |
290 | return _bind_textdomain_codeset($domain, $codeset); | |
291 | } | |
292 | function textdomain($domain) { | |
293 | return _textdomain($domain); | |
294 | } | |
295 | function gettext($msgid) { | |
296 | return _gettext($msgid); | |
297 | } | |
298 | function _($msgid) { | |
299 | return __($msgid); | |
300 | } | |
301 | function ngettext($single, $plural, $number) { | |
302 | return _ngettext($single, $plural, $number); | |
303 | } | |
304 | function dgettext($domain, $msgid) { | |
305 | return _dgettext($domain, $msgid); | |
306 | } | |
307 | function dngettext($domain, $single, $plural, $number) { | |
308 | return _dngettext($domain, $single, $plural, $number); | |
309 | } | |
310 | function dcgettext($domain, $msgid, $category) { | |
311 | return _dcgettext($domain, $msgid, $category); | |
312 | } | |
313 | function dcngettext($domain, $single, $plural, $number, $category) { | |
314 | return _dcngettext($domain, $single, $plural, $number, $category); | |
315 | } | |
316 | } | |
317 | ||
318 | ?> |