35 protected static function transCallable($callback, $id, array $parameters = array (), $domain =
null,
$locale =
null) {
36 if (
null === $domain) {
40 $catalogue = self::getCatalogue (
$locale );
41 if ($catalogue ===
false) {
42 if (isset ( self::$fallbackLocale ) &&
$locale !== self::$fallbackLocale) {
43 self::setLocale ( self::$fallbackLocale );
44 Logger::warn (
'Translation',
'Locale ' .
$locale .
' not found, set active locale to ' . self::$locale );
45 return self::trans ( $id, $parameters, $domain, self::$locale );
47 Logger::error (
'Translation',
'Locale not found, no valid fallbackLocale specified' );
51 $transId = self::getTransId ( $id, $domain );
52 if (isset ( $catalogue [$transId] )) {
53 return $callback ( $catalogue [$transId], $parameters );
54 } elseif (self::$fallbackLocale !==
null &&
$locale !== self::$fallbackLocale) {
55 Logger::warn (
'Translation',
'Translation not found for ' . $id .
'. Switch to fallbackLocale ' . self::$fallbackLocale );
56 return self::trans ( $id, $parameters, $domain, self::$fallbackLocale );
58 Logger::warn (
'Translation',
'Translation not found for ' . $id .
'. in locales.' );
71 protected static function doChoice($message, array $choice, array $parameters = [ ]) {
72 $message = ( string ) $message;
74 $number = ( float ) current ( $choice );
75 $parameters = $parameters + $choice;
77 if (preg_match (
'/^\|++$/', $message )) {
78 $parts = explode (
'|', $message );
79 } elseif (preg_match_all (
'/(?:\|\||[^\|])++/', $message, $matches )) {
80 $parts = $matches [0];
82 $intervalRegexp = <<<
'EOF'
85 (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
88 (?P<left_delimiter>[\[\]])
90 (?P<left>-Inf|\-?\d+(\.\d+)?)
92 (?P<right>\+?Inf|\-?\d+(\.\d+)?)
94 (?P<right_delimiter>[\[\]])
95 )\s*(?P<message>.*?)$/xs
97 foreach ( $parts as $part ) {
98 $part = trim ( str_replace (
'||',
'|', $part ) );
99 if (preg_match ( $intervalRegexp, $part, $matches )) {
101 foreach ( explode (
',', $matches [3] ) as $n ) {
103 return self::replaceParams ( $matches [
'message'], $parameters );
107 $leftNumber =
'-Inf' === $matches [
'left'] ? - INF : ( float ) $matches [
'left'];
108 $rightNumber = \is_numeric ( $matches [
'right'] ) ? ( float ) $matches [
'right'] : INF;
109 if ((
'[' === $matches [
'left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber) && (
']' === $matches [
'right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber)) {
110 return self::replaceParams ( $matches [
'message'], $parameters );
114 return self::replaceParams ( $message, $parameters );
119 protected static function replaceParams($trans, array $parameters = array ()) {
120 foreach ( $parameters as $k => $v ) {
121 $trans = str_replace (
'%' . $k .
'%', $v, $trans );
126 protected static function getTransId($id, $domain) {
127 return $domain .
'.' . $id;
130 protected static function assertValidLocale(
$locale) {
131 if (1 !== preg_match (
'/^[a-z0-9@_\\.\\-]*$/i',
$locale )) {
132 throw new \InvalidArgumentException ( sprintf (
'Invalid "%s" locale.',
$locale ) );
136 public static function isValidLocale(
$locale) {
137 return (1 === preg_match (
'/^[a-z0-9@_\\.\\-]*$/i',
$locale ));
151 self::setRootDir ( $rootDir );
159 public static function setLocale(
$locale) {
160 self::assertValidLocale (
$locale );
170 public static function setRootDir($rootDir =
null) {
171 if (! isset ( $rootDir )) {
172 $rootDir = \ROOT . \DS .
'translations';
174 self::$loader =
new ArrayLoader ( $rootDir );
182 public static function getLocale() {
195 public static function trans($id, array $parameters = array (), $domain =
null,
$locale =
null) {
197 return self::replaceParams ( $trans, $parameters );
198 }, $id, $parameters, $domain,
$locale );
211 public static function transChoice($id, array $choice, array $parameters = array (), $domain =
null,
$locale =
null) {
214 }, $id, $parameters, $domain,
$locale );
223 public static function getCatalogue(&
$locale =
null) {
227 self::assertValidLocale (
$locale );
229 if (! isset ( self::$catalogues [
$locale] )) {
230 self::loadCatalogue (
$locale );
232 return self::$catalogues [
$locale] ??
false;
240 public static function loadCatalogue(
$locale =
null) {
249 public static function getFallbackLocale() {
265 public static function clearCache() {
266 self::$loader->clearCache (
'*' );
272 public static function clearLocaleCache(
$locale) {
273 self::$loader->clearCache (
$locale );
281 public static function getLocales() {
283 $dirs = \glob ( self::getRootDir () . \DS .
'*', GLOB_ONLYDIR );
284 foreach ( $dirs as $dir ) {
285 $locales [] = \basename ( $dir );
296 public static function getDomains(
$locale) {
297 $catalog =
new MessagesCatalog (
$locale, self::$loader );
298 return $catalog->getDomains ();
306 public static function getRootDir() {
307 return self::$loader->getRootDir ();
315 public static function getLoader() {
324 public static function getCatalogues() {
334 public static function initialize($rootDir =
null) {
335 $locale = URequest::getDefaultLanguage ();
336 self::createLocale ( self::fixLocale (
$locale ), $rootDir );
337 return self::getLocales ();
340 public static function fixLocale($language) {
341 return \str_replace ( [
'-',
'.' ],
'_', $language );
350 public static function createLocale(
$locale, $rootDir =
null) {
351 self::setRootDir ( $rootDir );
352 UFileSystem::safeMkdir ( self::getRootDir () . \DS .
$locale );
365 public static function createDomain(
$locale, $domain, $defaultValues =
null) {
366 if (isset ( self::$loader )) {
367 $domains = self::getDomains (
$locale );
368 if (\array_search ( $domain, $domains ) ===
false) {
369 $dom =
new MessagesDomain (
$locale, self::$loader, $domain );
370 if (\is_array ( $defaultValues )) {
371 $dom->setMessages ( $defaultValues );
378 throw new CacheException (
'TranslatorManager is not started!' );
388 public static function cacheExist(
$locale, $domain =
'*') {
389 return self::$loader->cacheExists (
$locale, $domain );