Overview

Packages

  • CONTENIDO
  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentRssCreator
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
    • ScriptCookieDirective
  • mpAutoloaderClassMap
  • None
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SearchSolr
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob
  • Smarty
    • Cacher
    • Compiler
    • Config
    • Debug
    • PluginsBlock
    • PluginsFilter
    • PluginsFunction
    • PluginsInternal
    • PluginsModifier
    • PluginsModifierCompiler
    • PluginsShared
    • Security
    • Template
    • TemplateResources
  • Swift
    • ByteStream
    • CharacterStream
    • Encoder
    • Events
    • KeyCache
    • Mailer
    • Mime
    • Plugins
    • Transport

Classes

  • Swift_FailoverTransport
  • Swift_LoadBalancedTransport
  • Swift_MailTransport
  • Swift_Plugins_Loggers_ArrayLogger
  • Swift_Plugins_Loggers_EchoLogger
  • Swift_SendmailTransport
  • Swift_SmtpTransport
  • Swift_Transport_AbstractSmtpTransport
  • Swift_Transport_Esmtp_Auth_CramMd5Authenticator
  • Swift_Transport_Esmtp_Auth_LoginAuthenticator
  • Swift_Transport_Esmtp_Auth_PlainAuthenticator
  • Swift_Transport_Esmtp_AuthHandler
  • Swift_Transport_EsmtpTransport
  • Swift_Transport_FailoverTransport
  • Swift_Transport_LoadBalancedTransport
  • Swift_Transport_MailTransport
  • Swift_Transport_SendmailTransport
  • Swift_Transport_SimpleMailInvoker
  • Swift_Transport_StreamBuffer

Interfaces

  • Swift_Plugins_Logger
  • Swift_Plugins_Pop_Pop3Exception
  • Swift_Transport
  • Swift_Transport_Esmtp_Authenticator
  • Swift_Transport_EsmtpHandler
  • Swift_Transport_IoBuffer
  • Swift_Transport_MailInvoker
  • Swift_Transport_SmtpAgent
  • Swift_TransportException
  • Overview
  • Package
  • Function
  • Todo
  • Download
  1: <?php
  2: /**
  3:  * This file contains the the I18N class.
  4:  *
  5:  * @package Core
  6:  * @subpackage I18N
  7:  * @version SVN Revision $Rev:$
  8:  *
  9:  * @author Murat Purc <murat@purc.de>
 10:  * @copyright four for business AG <www.4fb.de>
 11:  * @license http://www.contenido.org/license/LIZENZ.txt
 12:  * @link http://www.4fb.de
 13:  * @link http://www.contenido.org
 14:  */
 15: 
 16: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
 17: 
 18: /**
 19:  * Internationalization (i18n) class.
 20:  *
 21:  * @package Core
 22:  * @subpackage I18N
 23:  */
 24: class cI18n {
 25: 
 26:     /**
 27:      * i18n related assoziative data cache.
 28:      *
 29:      * @var array
 30:      */
 31:     protected static $_i18nData = array(
 32:         'language' => NULL,
 33:         'domains' => array(),
 34:         'files' => array(),
 35:         'cache' => array()
 36:     );
 37: 
 38:     /**
 39:      * Initializes the i18n.
 40:      *
 41:      * @param string $localePath Path to the locales
 42:      * @param string $langCode Language code to set
 43:      * @param string $domain Language domain
 44:      */
 45:     public static function init($localePath, $langCode, $domain = 'contenido') {
 46:         if (function_exists('bindtextdomain')) {
 47:             // Bind the domain 'contenido' to our locale path
 48:             bindtextdomain($domain, $localePath);
 49: 
 50:             // Set the default text domain to 'contenido'
 51:             textdomain($domain);
 52: 
 53:             // Half brute-force to set the locale.
 54:             if (!ini_get('safe_mode')) {
 55:                 putenv("LANG=$langCode");
 56:             }
 57: 
 58:             if (defined('LC_MESSAGES')) {
 59:                 setlocale(LC_MESSAGES, $langCode);
 60:             }
 61: 
 62:             if (false === empty($langCode)) {
 63:                 setlocale(LC_CTYPE, $langCode);
 64:             }
 65:         }
 66: 
 67:         self::$_i18nData['domains'][$domain] = $localePath;
 68:         self::$_i18nData['language'] = $langCode;
 69:     }
 70: 
 71:     /**
 72:      * Returns translation of a specific text, wrapper for translate().
 73:      *
 74:      * @param string $string The string to translate
 75:      * @param string $domain The domain to look up
 76:      * @return string Returns the translation
 77:      */
 78:     public static function __($string, $domain = 'contenido') {
 79:         return self::translate($string, $domain);
 80:     }
 81: 
 82:     /**
 83:      * Returns translation of a specific text
 84:      *
 85:      * @param string $string The string to translate
 86:      * @param string $domain The domain to look up
 87:      * @throws cException if this is the backend mode and the $belang is not set
 88:      * @return string Returns the translation
 89:      */
 90:     public static function translate($string, $domain = 'contenido') {
 91:         global $cfg, $belang, $contenido;
 92: 
 93:         // Auto initialization
 94:         if (!self::$_i18nData['language']) {
 95:             if (!isset($belang)) {
 96:                 if ($contenido) {
 97:                     throw new cException('init $belang is not set');
 98:                 }
 99:                 // Needed - otherwise this won't work
100:                 $belang = false;
101:             }
102: 
103:             // CON-2165
104:             // initialise localisation of plugins correctly in frontend
105:             if ($domain === 'contenido') {
106:                 self::init($cfg['path']['contenido_locale'], $belang, $domain);
107:             } else {
108:                 if (empty($belang)) {
109:                     $oApiLang = cRegistry::getLanguage();
110:                     $language = $oApiLang->getProperty('language', 'code');
111:                     $country = $oApiLang->getProperty('country', 'code');
112:             
113:                     $locale = $language . '_' . strtoupper($country);
114:                     self::init($cfg['path']['contenido'] . $cfg['path']['plugins'] . $domain . '/locale/', $locale, $domain);
115:                 } else {
116:                     self::init($cfg['path']['contenido'] . $cfg['path']['plugins'] . $domain . '/locale/', $belang, $domain);
117:                 }
118:             }
119:         }
120: 
121:         // Is emulator to use?
122:         if (!$cfg['native_i18n']) {
123:             $ret = self::emulateGettext($string, $domain);
124:             // hopefully a proper replacement for
125:             // mb_convert_encoding($string, 'HTML-ENTITIES', 'utf-8');
126:             // see http://stackoverflow.com/q/11974008
127:             $ret = htmlspecialchars_decode(utf8_decode(conHtmlentities($ret, ENT_COMPAT, 'utf-8', false)));
128:             return $ret;
129:         }
130:         
131:         // Try to use native gettext implementation
132:         if (extension_loaded('gettext')) {
133:             if (function_exists('dgettext')) {
134:                 if ($domain != 'contenido') {
135:                     $translation = dgettext($domain, $string);
136:                     return $translation;
137:                 } else {
138:                     return gettext($string);
139:                 }
140:             }
141:         }
142:         
143:         // Emulator as fallback
144:         $ret = self::emulateGettext($string, $domain);
145:         if (isUtf8($ret)) {
146:             $ret = utf8_decode($ret);
147:         }
148:         return $ret;
149:     }
150: 
151:     /**
152:      * Returns the current language (if already defined)
153:      *
154:      * @return string|false
155:      */
156:     public static function getLanguage() {
157:         return (self::$_i18nData['language']) ? self::$_i18nData['language'] : false;
158:     }
159: 
160:     /**
161:      * Returns list of registered domains
162:      *
163:      * @return array
164:      */
165:     public static function getDomains() {
166:         return self::$_i18nData['domains'];
167:     }
168: 
169:     /**
170:      * Returns list of cached tranlation files
171:      *
172:      * @return array
173:      */
174:     public static function getFiles() {
175:         return self::$_i18nData['files'];
176:     }
177: 
178:     /**
179:      * Returns list of cached tranlations
180:      *
181:      * @return array
182:      */
183:     public static function getCache() {
184:         return self::$_i18nData['cache'];
185:     }
186: 
187:     /**
188:      * Resets cached translation data (language, domains, files, and cache)
189:      */
190:     public static function reset() {
191:         self::$_i18nData['language'] = NULL;
192:         self::$_i18nData['domains'] = array();
193:         self::$_i18nData['files'] = array();
194:         self::$_i18nData['cache'] = array();
195:     }
196: 
197:     /**
198:      * Emulates GNU gettext
199:      *
200:      * @param string $string The string to translate
201:      * @param string $domain The domain to look up
202:      * @return string Returns the translation
203:      */
204:     public static function emulateGettext($string, $domain = 'contenido') {
205:         if ($string == '') {
206:             return '';
207:         }
208: 
209:         if (!isset(self::$_i18nData['cache'][$domain])) {
210:             self::$_i18nData['cache'][$domain] = array();
211:         }
212:         if (isset(self::$_i18nData['cache'][$domain][$string])) {
213:             return self::$_i18nData['cache'][$domain][$string];
214:         }
215: 
216:         $translationFile = self::$_i18nData['domains'][$domain] . self::$_i18nData['language'] . '/LC_MESSAGES/' . $domain . '.po';
217:         if (!cFileHandler::exists($translationFile)) {
218:             return $string;
219:         }
220:         
221:         if (!isset(self::$_i18nData['files'][$domain])) {
222:             self::$_i18nData['files'][$domain] = self::_loadTranslationFile($translationFile);
223:         }
224: 
225:         $stringStart = strpos(self::$_i18nData['files'][$domain], '"' . str_replace(array(
226:             "\n",
227:             "\r",
228:             "\t"
229:         ), array(
230:             '\n',
231:             '\r',
232:             '\t'
233:         ), $string) . '"');
234:         if ($stringStart === false) {
235:             return $string;
236:         }
237: 
238:         $matches = array();
239:         $quotedString = preg_quote(str_replace(array(
240:             "\n",
241:             "\r",
242:             "\t"
243:         ), array(
244:             '\n',
245:             '\r',
246:             '\t'
247:         ), $string), '/');
248:         $result = preg_match("/msgid.*\"(" . $quotedString . ")\"(?:\s*)?\nmsgstr(?:\s*)\"(.*)\"/", self::$_i18nData['files'][$domain], $matches);
249:         // Old:
250:         // preg_match("/msgid.*\"".preg_quote($string,"/")."\".*\nmsgstr(\s*)\"(.*)\"/",
251:         // self::$_i18nData['files'][$domain], $matches);
252: 
253:         if ($result && !empty($matches[2])) {
254:             // Translation found, cache it
255:             self::$_i18nData['cache'][$domain][$string] = stripslashes(str_replace(array(
256:                 '\n',
257:                 '\r',
258:                 '\t'
259:             ), array(
260:                 "\n",
261:                 "\r",
262:                 "\t"
263:             ), $matches[2]));
264:         } else {
265:             // Translation not found, cache original string
266:             self::$_i18nData['cache'][$domain][$string] = $string;
267:         }
268: 
269:         return self::$_i18nData['cache'][$domain][$string];
270:     }
271: 
272:     /**
273:      * Registers a new i18n domain.
274:      *
275:      * @param string $localePath Path to the locales
276:      * @param string $domain Domain to bind to
277:      */
278:     public static function registerDomain($domain, $localePath) {
279:         if (function_exists('bindtextdomain')) {
280:             // Bind the domain 'contenido' to our locale path
281:             bindtextdomain($domain, $localePath);
282:         }
283:         self::$_i18nData['domains'][$domain] = $localePath;
284:     }
285: 
286:     /**
287:      * Loads gettext translation and file does some operations like stripping
288:      * comments on the content.
289:      *
290:      * @param string $translationFile
291:      * @return string The preparend translation file content
292:      */
293:     protected static function _loadTranslationFile($translationFile) {
294:         $content = cFileHandler::read($translationFile);
295: 
296:         // Normalize eol chars
297:         $content = str_replace("\n\r", "\n", $content);
298:         $content = str_replace("\r\n", "\n", $content);
299: 
300:         // Remove comment lines
301:         $content = preg_replace('/^#.+\n/m', '', $content);
302: 
303:         // Prepare for special po edit format
304:         /*
305:          * Something like: #, php-format msgid "" "Hello %s,\n" "\n" "you've got
306:          * a new reminder for the client '%s' at\n" "%s:\n" "\n" "%s" msgstr ""
307:          * "Hallo %s,\n" "\n" "du hast eine Wiedervorlage erhalten für den
308:          * Mandanten '%s' at\n" "%s:\n" "\n" "%s" has to be converted to: msgid
309:          * "Hello %s,\n\nyou've got a new reminder for the client '%s'
310:          * at\n%s:\n\n%s" msgstr "Hallo %s,\n\ndu hast eine Wiedervorlage
311:          * erhalten für den Mandanten '%s' at\n%s:\n\n%s"
312:          */
313:         // assemble broken long message lines (remove double quotes with a line
314:         // break in between, e. g. "\n")
315:         $content = preg_replace('/(""\\s+")/m', '"', $content);
316:         // replace line breaks followed by a whitespace character against a line
317:         // break
318:         $content = preg_replace('/\\n"\\s+"/m', '\\n', $content);
319:         // remove multiple line breaks
320:         $content = preg_replace('/("\n+")/m', '', $content);
321:         // remove the backslash from double quotes (\"foobar\" -> "foobar")
322:         $content = preg_replace('/(\\\")/m', '"', $content);
323: 
324:         return $content;
325:     }
326: }
CMS CONTENIDO 4.9.7 API documentation generated by ApiGen