31 const EXPIRE_CACHE = 60;
34 static protected $cache = array();
52 $this->locales = array();
65 self::LC_IDENTIFICATION,
67 foreach ($categories as $category) {
68 $this->locales[$category] =
"en_US";
70 $this->component = $component;
75 $categories = array_flip(
77 self::LC_CTYPE =>
'LC_CTYPE',
78 self::LC_NUMERIC =>
'LC_NUMERIC',
79 self::LC_TIME =>
'LC_TIME',
80 self::LC_COLLATE =>
'LC_COLLATE',
81 self::LC_MONETARY =>
'LC_MONETARY',
82 self::LC_MESSAGES =>
'LC_MESSAGES',
83 self::LC_PAPER =>
'LC_PAPER',
84 self::LC_NAME =>
'LC_NAME',
85 self::LC_ADDRESS =>
'LC_ADDRESS',
86 self::LC_TELEPHONE =>
'LC_TELEPHONE',
87 self::LC_MEASUREMENT =>
'LC_MEASUREMENT',
88 self::LC_IDENTIFICATION =>
'LC_IDENTIFICATION',
91 if (!isset($categories[$name])) {
92 throw new \InvalidArgumentException(
'Invalid category name');
94 return $categories[$name];
100 self::LC_CTYPE =>
'LC_CTYPE',
101 self::LC_NUMERIC =>
'LC_NUMERIC',
102 self::LC_TIME =>
'LC_TIME',
103 self::LC_COLLATE =>
'LC_COLLATE',
104 self::LC_MONETARY =>
'LC_MONETARY',
105 self::LC_MESSAGES =>
'LC_MESSAGES',
106 self::LC_PAPER =>
'LC_PAPER',
107 self::LC_NAME =>
'LC_NAME',
108 self::LC_ADDRESS =>
'LC_ADDRESS',
109 self::LC_TELEPHONE =>
'LC_TELEPHONE',
110 self::LC_MEASUREMENT =>
'LC_MEASUREMENT',
111 self::LC_IDENTIFICATION =>
'LC_IDENTIFICATION',
113 if (!isset($categories[$category])) {
114 throw new \InvalidArgumentException(
'Invalid category');
116 return $categories[$category];
121 if (!isset($this->locales[$category])) {
122 throw new \InvalidArgumentException(
'Invalid category');
124 return $this->locales[$category];
127 private function getBaseDir($component)
129 $reflector = new \ReflectionClass($component);
130 $parts = explode(DIRECTORY_SEPARATOR, $reflector->getFileName());
132 $last = array_pop($parts);
133 }
while ($last !==
'src' && count($parts));
136 $base = implode(DIRECTORY_SEPARATOR, $parts);
142 $categoryName = self::categoryToName($category);
143 if (!is_array($candidates)) {
144 $candidates = array($candidates);
146 if (!count($candidates)) {
147 throw new \InvalidArgumentException(
'Invalid locale');
150 $base = $this->getBaseDir($this->component);
152 foreach ($candidates as $candidate) {
153 if (!is_string($candidate)) {
154 throw new \InvalidArgumentException(
'Invalid locale');
157 $locale = \Locale::parseLocale($candidate);
158 if (!is_array($locale) || !isset($locale[
'language'])) {
159 throw new \InvalidArgumentException(
'Invalid locale');
164 if ($categoryName !=
'LC_MESSAGES') {
165 $newLocale = $candidate;
168 if ($newLocale !== null) {
172 $catalog = str_replace(
'\\',
'_', ltrim($this->component,
'\\'));
173 if (isset($locale[
'region'])) {
174 $normLocale = $locale[
'language'] .
'_' . $locale[
'region'];
176 DIRECTORY_SEPARATOR . $normLocale .
177 DIRECTORY_SEPARATOR . $categoryName .
178 DIRECTORY_SEPARATOR . $catalog;
180 if (file_exists($file .
'.mo')) {
181 $newLocale = $normLocale;
185 if (file_exists($file .
'.po')) {
186 $newLocale = $normLocale;
192 DIRECTORY_SEPARATOR . $locale[
'language'] .
193 DIRECTORY_SEPARATOR . $categoryName .
194 DIRECTORY_SEPARATOR . $catalog;
196 if (file_exists($file .
'.mo')) {
197 $newLocale = $locale[
'language'];
201 if (file_exists($file .
'.po')) {
202 $newLocale = $locale[
'language'];
207 if ($newLocale === null) {
208 $newLocale =
'en_US';
210 $this->locales[$category] = $newLocale;
244 $locale = $this->locales[self::LC_MESSAGES];
245 if (!isset(self::$cache[$component][$locale]) ||
246 $time > (self::$cache[$component][$locale][
'added'] + self::EXPIRE_CACHE)) {
247 if (isset(self::$cache[$component][$locale][
'file'])) {
248 $file = self::$cache[$component][$locale][
'file'];
251 $file = $this->getBaseDir($component);
256 $catalog = str_replace(
'\\',
'_', ltrim($component,
'\\'));
257 $file .= DIRECTORY_SEPARATOR . $locale .
258 DIRECTORY_SEPARATOR .
'LC_MESSAGES' .
259 DIRECTORY_SEPARATOR . $catalog .
'.mo';
261 if (!file_exists($file)) {
262 $file = substr($file, 0, -3) .
'.po';
265 if (!file_exists($file)) {
276 $oldErrorReporting = error_reporting(E_ERROR);
278 if (version_compare(PHP_VERSION,
'5.3.0',
'>=')) {
279 clearstatcache(
false, $file);
285 if ($file !==
false) {
286 $mtime = filemtime($file);
289 if ($mtime ===
false) {
292 self::$cache[$component][$locale] = array(
298 } elseif (!isset(self::$cache[$component][$locale]) ||
299 $mtime !== self::$cache[$component][$locale][
'mtime']) {
300 $parser = \File_Gettext::factory(substr($file, -2), $file);
302 self::$cache[$component][$locale] = array(
304 'strings' => $parser->strings,
309 error_reporting($oldErrorReporting);
312 if (isset(self::$cache[$component][$locale][
'strings'][$message])) {
313 return self::$cache[$component][$locale][
'strings'][$message];
337 $translation = $this->getTranslation(
341 return (!strlen($translation)) ? $message : $translation;
346 return $this->reallyGetText($message, $this->component);
349 public function _($message)
351 return $this->reallyGetText($message, $this->component);
362 self::$cache = array();
Interface to provide internationalization.
Base class for other (Erebot-related) exceptions.
$locales
The actual locales used for i18n.
A class which provides translations for messages used by the core and modules.
static categoryToName($category)
static nameToCategory($name)
reallyGetText($message, $component)
setLocale($category, $candidates)
$component
The component to get translations from (a module name or "Erebot").
getTranslation($component, $message)