1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15:
16: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
17:
18: 19: 20: 21: 22: 23:
24: class cI18n {
25:
26: 27: 28: 29: 30:
31: protected static $_i18nData = array(
32: 'language' => NULL,
33: 'domains' => array(),
34: 'files' => array(),
35: 'cache' => array()
36: );
37:
38: 39: 40: 41: 42: 43: 44: 45: 46: 47:
48: public static function init($localePath, $langCode, $domain = 'contenido') {
49: if (function_exists('bindtextdomain')) {
50:
51: bindtextdomain($domain, $localePath);
52:
53:
54: textdomain($domain);
55:
56:
57: if (!ini_get('safe_mode')) {
58: putenv("LANG=$langCode");
59: }
60:
61: if (defined('LC_MESSAGES')) {
62: setlocale(LC_MESSAGES, $langCode);
63: }
64:
65: if (false === empty($langCode)) {
66: setlocale(LC_CTYPE, $langCode);
67: }
68: }
69:
70: self::$_i18nData['domains'][$domain] = $localePath;
71: self::$_i18nData['language'] = $langCode;
72: }
73:
74: 75: 76: 77: 78: 79: 80: 81: 82: 83:
84: public static function __($string, $domain = 'contenido') {
85: return self::translate($string, $domain);
86: }
87:
88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99:
100: public static function translate($string, $domain = 'contenido') {
101: global $cfg, $belang, $contenido;
102:
103:
104: if (!self::$_i18nData['language']) {
105: if (!isset($belang)) {
106: if ($contenido) {
107: throw new cException('init $belang is not set');
108: }
109:
110: $belang = false;
111: }
112:
113:
114:
115: if ($domain === 'contenido') {
116: self::init($cfg['path']['contenido_locale'], $belang, $domain);
117: } else {
118: if (empty($belang)) {
119: $oApiLang = cRegistry::getLanguage();
120: $language = $oApiLang->getProperty('language', 'code');
121: $country = $oApiLang->getProperty('country', 'code');
122:
123: $locale = $language . '_' . strtoupper($country);
124: self::init($cfg['path']['contenido'] . $cfg['path']['plugins'] . $domain . '/locale/', $locale, $domain);
125: } else {
126: self::init($cfg['path']['contenido'] . $cfg['path']['plugins'] . $domain . '/locale/', $belang, $domain);
127: }
128: }
129: }
130:
131:
132: if (!$cfg['native_i18n']) {
133: $ret = self::emulateGettext($string, $domain);
134:
135:
136:
137: $ret = htmlspecialchars_decode(utf8_decode(conHtmlentities($ret, ENT_COMPAT, 'utf-8', false)));
138: return $ret;
139: }
140:
141:
142: if (extension_loaded('gettext')) {
143: if (function_exists('dgettext')) {
144: if ($domain != 'contenido') {
145: $translation = dgettext($domain, $string);
146: return $translation;
147: } else {
148: return gettext($string);
149: }
150: }
151: }
152:
153:
154: $ret = self::emulateGettext($string, $domain);
155: if (cString::isUtf8($ret)) {
156: $ret = utf8_decode($ret);
157: }
158: return $ret;
159: }
160:
161: 162: 163: 164: 165:
166: public static function getLanguage() {
167: return (self::$_i18nData['language']) ? self::$_i18nData['language'] : false;
168: }
169:
170: 171: 172: 173: 174:
175: public static function getDomains() {
176: return self::$_i18nData['domains'];
177: }
178:
179: 180: 181: 182: 183:
184: public static function getFiles() {
185: return self::$_i18nData['files'];
186: }
187:
188: 189: 190: 191: 192:
193: public static function getCache() {
194: return self::$_i18nData['cache'];
195: }
196:
197: 198: 199:
200: public static function reset() {
201: self::$_i18nData['language'] = NULL;
202: self::$_i18nData['domains'] = array();
203: self::$_i18nData['files'] = array();
204: self::$_i18nData['cache'] = array();
205: }
206:
207: 208: 209: 210: 211: 212: 213: 214: 215: 216:
217: public static function emulateGettext($string, $domain = 'contenido') {
218: if ($string == '') {
219: return '';
220: }
221:
222: if (!isset(self::$_i18nData['cache'][$domain])) {
223: self::$_i18nData['cache'][$domain] = array();
224: }
225: if (isset(self::$_i18nData['cache'][$domain][$string])) {
226: return self::$_i18nData['cache'][$domain][$string];
227: }
228:
229: $translationFile = self::$_i18nData['domains'][$domain] . self::$_i18nData['language'] . '/LC_MESSAGES/' . $domain . '.po';
230: if (!cFileHandler::exists($translationFile)) {
231: return $string;
232: }
233:
234: if (!isset(self::$_i18nData['files'][$domain])) {
235: self::$_i18nData['files'][$domain] = self::_loadTranslationFile($translationFile);
236: }
237:
238: $stringStart = strpos(self::$_i18nData['files'][$domain], '"' . str_replace(array(
239: "\n",
240: "\r",
241: "\t"
242: ), array(
243: '\n',
244: '\r',
245: '\t'
246: ), $string) . '"');
247: if ($stringStart === false) {
248: return $string;
249: }
250:
251: $matches = array();
252: $quotedString = preg_quote(str_replace(array(
253: "\n",
254: "\r",
255: "\t"
256: ), array(
257: '\n',
258: '\r',
259: '\t'
260: ), $string), '/');
261: $result = preg_match("/msgid.*\"(" . $quotedString . ")\"(?:\s*)?\nmsgstr(?:\s*)\"(.*)\"/", self::$_i18nData['files'][$domain], $matches);
262:
263:
264:
265:
266: if ($result && !empty($matches[2])) {
267:
268: self::$_i18nData['cache'][$domain][$string] = stripslashes(str_replace(array(
269: '\n',
270: '\r',
271: '\t'
272: ), array(
273: "\n",
274: "\r",
275: "\t"
276: ), $matches[2]));
277: } else {
278:
279: self::$_i18nData['cache'][$domain][$string] = $string;
280: }
281:
282: return self::$_i18nData['cache'][$domain][$string];
283: }
284:
285: 286: 287: 288: 289: 290: 291: 292:
293: public static function registerDomain($domain, $localePath) {
294: if (function_exists('bindtextdomain')) {
295:
296: bindtextdomain($domain, $localePath);
297: }
298: self::$_i18nData['domains'][$domain] = $localePath;
299: }
300:
301: 302: 303: 304: 305: 306: 307: 308:
309: protected static function _loadTranslationFile($translationFile) {
310: $content = cFileHandler::read($translationFile);
311:
312:
313: $content = str_replace("\n\r", "\n", $content);
314: $content = str_replace("\r\n", "\n", $content);
315:
316:
317: $content = preg_replace('/^#.+\n/m', '', $content);
318:
319:
320: 321: 322: 323: 324: 325: 326: 327: 328:
329:
330:
331: $content = preg_replace('/(""\\s+")/m', '"', $content);
332:
333:
334: $content = preg_replace('/\\n"\\s+"/m', '\\n', $content);
335:
336: $content = preg_replace('/("\n+")/m', '', $content);
337:
338: $content = preg_replace('/(\\\")/m', '"', $content);
339:
340: return $content;
341: }
342: }