public function setLocale($locale)
 {
     if ($locale == 'en_US' && !Config::get('concrete.misc.enable_translate_locale_en_us')) {
         $this->translate = null;
     } else {
         $this->translate = new Translator();
         $this->translate->setLocale($locale);
         $this->translate->setCache(self::getCache());
         // Core language files
         $languageFile = DIR_LANGUAGES . "/{$locale}/LC_MESSAGES/messages.mo";
         if (!is_file($languageFile)) {
             $languageFile = DIR_LANGUAGES_CORE . "/{$locale}/LC_MESSAGES/messages.mo";
             if (!is_file($languageFile)) {
                 $languageFile = '';
             }
         }
         if ($languageFile !== '') {
             $this->translate->addTranslationFile('gettext', $languageFile);
         }
         // Package language files
         if (Config::get('app.bootstrap.packages_loaded') === true) {
             $pkgList = \Concrete\Core\Package\PackageList::get();
             foreach ($pkgList->getPackages() as $pkg) {
                 $pkg->setupPackageLocalization($locale, $this->translate);
             }
             // Site language files
             static::setupSiteLocalization($this->translate);
         }
     }
     PunicData::setDefaultLocale($locale);
     $event = new \Symfony\Component\EventDispatcher\GenericEvent();
     $event->setArgument('locale', $locale);
     Events::dispatch('on_locale_load', $event);
 }
 public function setLocale($locale)
 {
     $localeNeededLoading = false;
     if ($locale == 'en_US' && !Config::get('concrete.misc.enable_translate_locale_en_us')) {
         if (isset($this->translate)) {
             unset($this->translate);
         }
         PunicData::setDefaultLocale($locale);
         return;
     }
     if (is_dir(DIR_LANGUAGES . '/' . $locale)) {
         $languageDir = DIR_LANGUAGES . '/' . $locale;
     } elseif (is_dir(DIR_LANGUAGES_CORE . '/' . $locale)) {
         $languageDir = DIR_LANGUAGES_CORE . '/' . $locale;
     } else {
         return;
     }
     $this->translate = new Translator();
     $this->translate->addTranslationFilePattern('gettext', $languageDir, 'LC_MESSAGES/messages.mo');
     $this->translate->setLocale($locale);
     $this->translate->setCache(new ZendCacheDriver('cache/expensive'));
     PunicData::setDefaultLocale($locale);
     $event = new \Symfony\Component\EventDispatcher\GenericEvent();
     $event->setArgument('locale', $locale);
     Events::dispatch('on_locale_load', $event);
 }
Example #3
0
 /**
  * Initializes the instance.
  *
  * @param string $locale
  * @param bool $caseSensitive
  */
 public function __construct($locale = null, $caseSensitive = false)
 {
     $this->cache = array();
     $this->locale = isset($locale) ? $locale : \Punic\Data::getDefaultLocale();
     $this->caseSensitive = (bool) $caseSensitive;
     $this->collator = class_exists('\\Collator') ? new \Collator($this->locale) : null;
     $this->iconv = function_exists('iconv');
 }
Example #4
0
 /**
  * gets list of locales
  *
  * @param boolean $showInCodeLanguage true to show a code's name in the language the code represents
  *
  * @return array
  */
 public static function getList($showInCodeLanguage = false)
 {
     $locales = Data::getAvailableLocales();
     $languages = array();
     foreach ($locales as $locale) {
         $key = \Xoops\Locale::normalizeLocale($locale);
         $languages[$key] = Language::getName($locale, $showInCodeLanguage ? $locale : null);
     }
     \XoopsLocale::asort($languages);
     return $languages;
 }
Example #5
0
 /**
  * Initializes the instance.
  *
  * @param string $locale
  * @param bool $caseSensitive
  */
 public function __construct($locale = null, $caseSensitive = false)
 {
     $this->cache = array();
     $this->locale = isset($locale) ? $locale : \Punic\Data::getDefaultLocale();
     $this->caseSensitive = (bool) $caseSensitive;
     $this->collator = null;
     if (class_exists('\\Collator')) {
         try {
             $this->collator = new Collator($this->locale);
         } catch (PHPException $x) {
         }
     }
     $this->iconv = function_exists('iconv');
 }
Example #6
0
 protected static function joinInternal($list, $keys, $locale)
 {
     $result = '';
     if (is_array($list)) {
         $list = array_values($list);
         $n = count($list);
         switch ($n) {
             case 0:
                 break;
             case 1:
                 $result = strval($list[0]);
                 break;
             default:
                 $allData = \Punic\Data::get('listPatterns', $locale);
                 $data = null;
                 if (!empty($keys)) {
                     foreach ($keys as $key) {
                         if (array_key_exists($key, $allData)) {
                             $data = $allData[$key];
                             break;
                         }
                     }
                 }
                 if (is_null($data)) {
                     $data = $allData['standard'];
                 }
                 if (array_key_exists($n, $data)) {
                     $result = vsprintf($data[$n], $list);
                 } else {
                     $result = sprintf($data['end'], $list[$n - 2], $list[$n - 1]);
                     if ($n > 2) {
                         for ($index = $n - 3; $index > 0; $index--) {
                             $result = sprintf($data['middle'], $list[$index], $result);
                         }
                         $result = sprintf($data['start'], $list[0], $result);
                     }
                 }
                 break;
         }
     }
     return $result;
 }
Example #7
0
 /**
  * Return the plural rule ('zero', 'one', 'two', 'few', 'many' or 'other') for a number and a locale
  * @param string|int|float $number The number to check the plural rule for for
  * @param string $locale = '' The locale to use. If empty we'll use the default locale set in \Punic\Data
  * @return string Returns one of the following values: 'zero', 'one', 'two', 'few', 'many', 'other'
  * @throws \Punic\Exception\BadArgumentType Throws a \Punic\Exception\BadArgumentType if $number is not a valid number
  * @throws \Exception Throws a \Exception if there were problems calculating the plural rule
  */
 public static function getRule($number, $locale = '')
 {
     if (is_int($number)) {
         $intPartAbs = strval(abs($number));
         $floatPart = '';
     } elseif (is_float($number)) {
         $s = strval($number);
         if (strpos($s, '.') === false) {
             $intPart = $s;
             $floatPart = '';
         } else {
             list($intPart, $floatPart) = explode('.', $s);
         }
         $intPartAbs = strval(abs(intval($intPart)));
     } elseif (is_string($number) && strlen($number)) {
         if (preg_match('/^[+|\\-]?\\d+\\.?$/', $number)) {
             $v = intval($number);
             $intPartAbs = strval(abs($v));
             $floatPart = '';
         } elseif (preg_match('/^(\\d*)\\.(\\d+)$/', $number, $m)) {
             list($intPart, $floatPart) = explode('.', $number);
             $v = @intval($intPart);
             $intPartAbs = strval(abs($v));
         } else {
             throw new Exception\BadArgumentType($number, 'number');
         }
     } else {
         throw new Exception\BadArgumentType($number, 'number');
     }
     // 'n' => '%1$s', // absolute value of the source number (integer and decimals).
     $v1 = $intPartAbs . (strlen($floatPart) ? ".{$floatPart}" : '');
     // 'i' => '%2$s', // integer digits of n
     $v2 = $intPartAbs;
     // 'v' => '%3$s', // number of visible fraction digits in n, with trailing zeros.
     $v3 = strlen($floatPart);
     // 'w' => '%4$s', // number of visible fraction digits in n, without trailing zeros.
     $v4 = strlen(rtrim($floatPart, '0'));
     // 'f' => '%5$s', // visible fractional digits in n, with trailing zeros.
     $v5 = strlen($floatPart) ? strval(intval($floatPart)) : '0';
     // 't' => '%6$s', // visible fractional digits in n, without trailing zeros.
     $v6 = trim($floatPart, '0');
     if (!strlen($v6)) {
         $v6 = '0';
     }
     $result = 'other';
     $node = \Punic\Data::getLanguageNode(\Punic\Data::getGeneric('plurals'), $locale);
     foreach ($node as $rule => $formulaPattern) {
         $formula = sprintf($formulaPattern, $v1, $v2, $v3, $v4, $v5, $v6);
         $check = str_replace(array('static::inRange(', ' and ', ' or ', ', false, ', ', true, ', ', array('), ' , ', $formula);
         if (preg_match('/[a-z]/', $check)) {
             throw new \Exception('Bad formula!');
         }
         // fix for difference in modulo (%) in the definition and the one implemented in PHP for decimal numbers
         while (preg_match('/(\\d+\\.\\d+) % (\\d+(\\.\\d+)?)/', $formula, $m)) {
             list(, $decimalPart) = explode('.', $m[1], 2);
             $decimals = strlen(rtrim($decimalPart, '0'));
             if ($decimals > 0) {
                 $pow = intval(pow(10, $decimals));
                 $repl = '(' . strval(intval(floatval($m[1]) * $pow)) . ' % ' . strval(intval(floatval($m[2] * $pow))) . ') / ' . $pow;
             } else {
                 $repl = strval(intval($m[1])) . ' % ' . $m[2];
             }
             $formula = str_replace($m[0], $repl, $formula);
         }
         $formulaResult = @eval("return ({$formula}) ? 'yes' : 'no';");
         if ($formulaResult === 'yes') {
             $result = $rule;
             break;
         } elseif ($formulaResult !== 'no') {
             throw new \Exception('There was a problem in the formula ' . $formulaPattern);
         }
     }
     return $result;
 }
Example #8
0
 /**
  * Format a unit string
  * @param int|float|string $number The unit amount
  * @param string $unit The unit identifier (eg 'duration/millisecond' or 'millisecond')
  * @param string $width = 'short' The format name; it can be 'long' (eg '3 milliseconds'), 'short' (eg '3 ms') or 'narrow' (eg '3ms'). You can also add a precision specifier ('long,2' or just '2')
  * @param string $locale = '' The locale to use. If empty we'll use the default locale set in \Punic\Data
  */
 public static function format($number, $unit, $width = 'short', $locale = '')
 {
     $data = \Punic\Data::get('units', $locale);
     $precision = null;
     if (is_int($width)) {
         $precision = $width;
         $width = 'short';
     } elseif (is_string($width) && preg_match('/^(?:(.*),)?([+\\-]?\\d+)$/', $width, $m)) {
         $precision = intval($m[2]);
         $width = $m[1];
         if (!strlen($width)) {
             $width = 'short';
         }
     }
     if (strpos($width, '_') === 0 || !array_key_exists($width, $data)) {
         $widths = array();
         foreach (array_keys($data) as $w) {
             if (strpos($w, '_') !== 0) {
                 $widths[] = $w;
             }
         }
         throw new Exception\ValueNotInList($width, $widths);
     }
     $data = $data[$width];
     if (strpos($unit, '/') === false) {
         $unitCategory = null;
         $unitID = null;
         foreach (array_keys($data) as $c) {
             if (strpos($c, '_') === false) {
                 if (array_key_exists($unit, $data[$c])) {
                     if (is_null($unitCategory)) {
                         $unitCategory = $c;
                         $unitID = $unit;
                     } else {
                         $unitCategory = null;
                         break;
                     }
                 }
             }
         }
     } else {
         list($unitCategory, $unitID) = explode('/', $unit, 2);
     }
     $rules = null;
     if (strpos($unit, '_') === false && !is_null($unitCategory) && !is_null($unitID) && array_key_exists($unitCategory, $data) && array_key_exists($unitID, $data[$unitCategory])) {
         $rules = $data[$unitCategory][$unitID];
     }
     if (is_null($rules)) {
         $units = array();
         foreach ($data as $c => $us) {
             if (strpos($c, '_') === false) {
                 foreach (array_keys($us) as $u) {
                     if (strpos($c, '_') === false) {
                         $units[] = "{$c}/{$u}";
                     }
                 }
             }
         }
         throw new \Punic\Exception\ValueNotInList($unit, $units);
     }
     $pluralRule = \Punic\Plural::getRule($number, $locale);
     //@codeCoverageIgnoreStart
     // These checks aren't necessary since $pluralRule should always be in $rules, but they don't hurt ;)
     if (!array_key_exists($pluralRule, $rules)) {
         if (array_key_exists('other', $rules)) {
             $pluralRule = 'other';
         } else {
             $availableRules = array_keys($rules);
             $pluralRule = $availableRules[0];
         }
     }
     //@codeCoverageIgnoreEnd
     return sprintf($rules[$pluralRule], \Punic\Number::format($number, $precision, $locale));
 }
Example #9
0
 /**
  * Convert a localized representation of a number to a number (for instance, converts the string '1,234' to 1234 in case of English and to 1.234 in case of Italian)
  * @param string $value The string value to convert
  * @param string $locale = '' The locale to use. If empty we'll use the default locale set in \Punic\Data
  * @return int|float|null Returns null if $value is not valid, the numeric value otherwise
  */
 public static function unformat($value, $locale = '')
 {
     $result = null;
     if (is_int($value) || is_float($value)) {
         $result = $value;
     } elseif (is_string($value) && strlen($value)) {
         $data = \Punic\Data::get('numbers', $locale);
         $plus = $data['symbols']['plusSign'];
         $plusQ = preg_quote($plus);
         $minus = $data['symbols']['minusSign'];
         $minusQ = preg_quote($minus);
         $decimal = $data['symbols']['decimal'];
         $decimalQ = preg_quote($decimal);
         $group = $data['symbols']['group'];
         $groupQ = preg_quote($group);
         $ok = true;
         if (preg_match('/^' . "({$plusQ}|{$minusQ})?(\\d+(?:{$groupQ}\\d+)*)" . '$/', $value, $m)) {
             $sign = $m[1];
             $int = $m[2];
             $float = null;
         } elseif (preg_match('/^' . "({$plusQ}|{$minusQ})?(\\d+(?:{$groupQ}\\d+)*){$decimalQ}" . '$/', $value, $m)) {
             $sign = $m[1];
             $int = $m[2];
             $float = '';
         } elseif (preg_match('/^' . "({$plusQ}|{$minusQ})?(\\d+(?:{$groupQ}\\d+)*){$decimalQ}(\\d+)" . '$/', $value, $m)) {
             $sign = $m[1];
             $int = $m[2];
             $float = $m[3];
         } elseif (preg_match('/^' . "({$plusQ}|{$minusQ})?{$decimalQ}(\\d+)" . '$/', $value, $m)) {
             $sign = $m[1];
             $int = '0';
             $float = $m[2];
         } else {
             $ok = false;
         }
         if ($ok) {
             if ($sign === $minus) {
                 $sign = '-';
             } else {
                 $sign = '';
             }
             $int = str_replace($group, '', $int);
             if (is_null($float)) {
                 $result = intval("{$sign}{$int}");
             } else {
                 $result = floatval("{$sign}{$int}.{$float}");
             }
         }
     }
     return $result;
 }
Example #10
0
 /**
  * To be called every time the current locale changes.
  *
  * @param string $locale
  */
 protected function currentLocaleChanged($locale)
 {
     PunicData::setDefaultLocale($locale);
     $app = Facade::getFacadeApplication();
     if ($app->bound('director')) {
         $event = new \Symfony\Component\EventDispatcher\GenericEvent();
         $event->setArgument('locale', $locale);
         $app->make('director')->dispatch('on_locale_load', $event);
     }
 }
Example #11
0
 /**
  * Describe an relative interval from $dateStart to $dateEnd (eg '2 days ago').
  * Only the largest differing unit is described, and the next smaller unit will be used
  * for rounding.
  *
  * @param \DateTime      $dateEnd   The terminal date
  * @param \DateTime|null $dateStart The anchor date, defaults to now. (if it has a timezone different than
  *                        $dateEnd, we'll use the one of $dateEnd)
  * @param string         $width     The format name; it can be '', 'short' or 'narrow'
  * @param string         $locale    The locale to use. If empty we'll use the default locale set in \Punic\Data
  *
  * @return string
  *
  * @throws \InvalidArgumentException
  */
 public static function describeRelativeInterval($dateEnd, $dateStart = null, $width = '', $locale = '')
 {
     if (!is_a($dateEnd, '\\DateTime')) {
         throw new \InvalidArgumentException('Not a DateTime object');
     }
     if (empty($dateStart) && $dateStart !== 0 && $dateStart !== '0') {
         $dateStart = new \DateTime('now');
     } elseif (!is_a($dateStart, '\\DateTime')) {
         throw new \InvalidArgumentException('Not a DateTime object');
     } else {
         $dateStart = clone $dateStart;
     }
     $dateStart->setTimezone($dateEnd->getTimezone());
     //$utc = new \DateTimeZone('UTC');
     //$dateEndUTC = new \DateTime($dateEnd->format('Y-m-d H:i:s'), $utc);
     //$dateStartUTC = new \DateTime($dateStart->format('Y-m-d H:i:s'), $utc);
     $parts = array();
     $data = Data::get('dateFields', $locale);
     $diff = $dateStart->diff($dateEnd, false);
     $past = (bool) $diff->invert;
     $value = 0;
     $key = '';
     if ($diff->y != 0) {
         $key = 'year';
         $value = $diff->y + ($diff->m > 6 ? 1 : 0);
     } elseif ($diff->m != 0) {
         $key = 'month';
         $value = $diff->m + ($diff->d > 15 ? 1 : 0);
     } elseif ($diff->d != 0) {
         $key = 'day';
         $value = $diff->d + ($diff->h > 12 ? 1 : 0);
     } elseif ($diff->h != 0) {
         $key = 'hour';
         $value = $diff->h + ($diff->i > 30 ? 1 : 0);
     } elseif ($diff->i != 0) {
         $key = 'minute';
         $value = $diff->i + ($diff->s > 30 ? 1 : 0);
     } elseif ($diff->s != 0) {
         $key = 'second';
         $value = $diff->s;
     }
     if ($value == 0) {
         $key = 'second';
         $relKey = 'relative-type-0';
         $relPattern = null;
     } elseif ($key === 'day' && $value > 1 && $value < 7) {
         $dow = $dateEnd->format('N') - 1;
         $days = array('mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun');
         $key = $days[$dow];
         $relKey = $past ? "relative-type--1" : "relative-type-1";
         $relPattern = null;
     } else {
         if ($value == 1 && isset($data[$key]['relative-type--1'])) {
             $relKey = $past ? 'relative-type--1' : 'relative-type-1';
             $relPattern = null;
         } else {
             $relKey = $past ? 'relativeTime-type-past' : 'relativeTime-type-future';
             $rule = Plural::getRule($value, $locale);
             $relPattern = 'relativeTimePattern-count-' . $rule;
         }
     }
     if (!empty($width) && array_key_exists($key . '-' . $width, $data)) {
         $key .= '-' . $width;
     }
     if (empty($relPattern)) {
         $relativeString = $data[$key][$relKey];
     } else {
         $tempString = $data[$key][$relKey][$relPattern];
         $tempString = str_replace('{0}', '%d', $tempString);
         $relativeString = sprintf($tempString, $value);
     }
     return $relativeString;
 }
Example #12
0
 /**
  * Convert a locale designation to a normal form ll_Ssss_CC, where
  *   ll   is language code
  *   Ssss is the script code, if specified
  *   CC   is the country code, if specified
  *
  * @param string $locale     locale code
  * @param string $separator  string to use to join locale parts
  * @param bool   $withScript include script if specified, always remove if false
  *
  * @return string normalized locale, or empty string on error
  */
 public static function normalizeLocale($locale, $separator = '_', $withScript = true)
 {
     try {
         $keys = Data::explodeLocale($locale);
         $key = strtolower($keys['language']);
         $key .= empty($keys['script']) || false === $withScript ? '' : $separator . ucfirst(strtolower($keys['script']));
         $key .= empty($keys['territory']) ? '' : $separator . strtoupper($keys['territory']);
     } catch (InvalidLocale $e) {
         $key = '';
     }
     return $key;
 }
Example #13
0
 /**
  * detect locale & set cookie if neccesary
  */
 private function initLocale()
 {
     $this->locale = $this->detectLocale();
     // datetime format
     if (!setlocale(LC_TIME, $this->locales[$this->locale])) {
         throw new \Exception(sprintf("Unable to set locale to '%s'", $this->locales[$this->locale]));
     }
     // punic default value
     Data::setDefaultLocale($this->getIETF());
     if ('cli' !== PHP_SAPI) {
         if (!self::request()->getCookie(self::COOKIE_LANGUAGE)) {
             self::response()->addCookie(new Cookie(self::COOKIE_LANGUAGE, $this->locale, 60 * 60 * 24 * 365));
         }
     }
 }
Example #14
0
 protected static function decodeTimezoneDelta(\DateTime $value, $count, $locale)
 {
     $offset = $value->getOffset();
     $sign = $offset < 0 ? '-' : '+';
     $seconds = abs($offset);
     $hours = intval(floor($seconds / 3600));
     $seconds -= $hours * 3600;
     $minutes = intval(floor($seconds / 60));
     $seconds -= $minutes * 60;
     $partsWithoutSeconds = array();
     $partsWithoutSeconds[] = $sign . substr('0' . strval($hours), -2);
     $partsWithoutSeconds[] = substr('0' . strval($minutes), -2);
     $partsMaybeWithSeconds = $partsWithoutSeconds;
     /* @TZWS
        if ($seconds > 0) {
            $partsMaybeWithSeconds[] = substr('0' . strval($seconds), -2);
        }
        */
     switch ($count) {
         case 1:
         case 2:
         case 3:
             return implode('', $partsMaybeWithSeconds);
         case 4:
             $data = \Punic\Data::get('timeZoneNames', $locale);
             $format = array_key_exists('gmtFormat', $data) ? $data['gmtFormat'] : 'GMT%1$s';
             return sprintf($format, implode(':', $partsWithoutSeconds));
         case 5:
             return implode(':', $partsMaybeWithSeconds);
         default:
             throw new Exception\ValueNotInList($count, array(1, 2, 3, 4, 5));
     }
 }