/** * Given an array of strings, a number and, if wanted, an optional locale (the default one is used * otherwise), this picks the right string according to plural rules of the locale * * @param array|string $strings * @param int $number * @throws Exception\InvalidArgumentException * @return string */ public function __invoke($strings, $number) { if ($this->rule === null) { throw new Exception\InvalidArgumentException(sprintf('No plural rule was set')); } if (!is_array($strings)) { $strings = (array) $strings; } $pluralIndex = $this->rule->evaluate($number); return $strings[$pluralIndex]; }
/** * load(): defined by FileLoaderInterface. * * @see FileLoaderInterface::load() * @param string $locale * @param string $filename * @return TextDomain|null * @throws Exception\InvalidArgumentException */ public function load($locale, $filename) { $resolvedIncludePath = stream_resolve_include_path($filename); $fromIncludePath = $resolvedIncludePath !== false ? $resolvedIncludePath : $filename; if (!$fromIncludePath || !is_file($fromIncludePath) || !is_readable($fromIncludePath)) { throw new Exception\InvalidArgumentException(sprintf('Could not find or open file %s for reading', $filename)); } $messages = []; $iniReader = new IniReader(); $messagesNamespaced = $iniReader->fromFile($fromIncludePath); $list = $messagesNamespaced; if (isset($messagesNamespaced['translation'])) { $list = $messagesNamespaced['translation']; } foreach ($list as $message) { if (!is_array($message) || count($message) < 2) { throw new Exception\InvalidArgumentException('Each INI row must be an array with message and translation'); } if (isset($message['message']) && isset($message['translation'])) { $messages[$message['message']] = $message['translation']; continue; } $messages[array_shift($message)] = array_shift($message); } if (!is_array($messages)) { throw new Exception\InvalidArgumentException(sprintf('Expected an array, but received %s', gettype($messages))); } $textDomain = new TextDomain($messages); if (array_key_exists('plural', $messagesNamespaced) && isset($messagesNamespaced['plural']['plural_forms'])) { $textDomain->setPluralRule(PluralRule::fromString($messagesNamespaced['plural']['plural_forms'])); } return $textDomain; }
/** * Get the plural rule. * * Lazy loads a default rule if none already registered * * @return PluralRule */ public function getPluralRule() { if ($this->pluralRule === null) { $this->setPluralRule(PluralRule::fromString('nplurals=2; plural=n != 1;')); } return $this->pluralRule; }
/** * @dataProvider completeRuleProvider */ public function testCompleteRules($rule, $expectedValues) { $rule = Rule::fromString('nplurals=9; plural=' . $rule); for ($i = 0; $i < 200; $i++) { $this->assertEquals((int) $expectedValues[$i], $rule->evaluate($i)); } }
/** * Returns a shared default plural rule. * * @return PluralRule */ public static function getDefaultPluralRule() { if (static::$defaultPluralRule === null) { static::$defaultPluralRule = PluralRule::fromString('nplurals=2; plural=n != 1;'); } return static::$defaultPluralRule; }
/** * Set the plural rule to use * * @param PluralRule|string $pluralRule * @return Plural */ public function setPluralRule($pluralRule) { if (!$pluralRule instanceof PluralRule) { $pluralRule = PluralRule::fromString($pluralRule); } $this->rule = $pluralRule; return $this; }
public function testMergingIncompatibleTextDomains() { $this->setExpectedException('Zend\\I18n\\Exception\\RuntimeException', 'is not compatible'); $domainA = new TextDomain(); $domainB = new TextDomain(); $domainB->setPluralRule(PluralRule::fromString('nplurals=3; plural=n')); $domainA->merge($domainB); }
public function testMergingTextDomainWithoutPluralRuleIntoTextDomainWithPluralRule() { $domainA = new TextDomain(); $domainB = new TextDomain(); $domainA->setPluralRule(PluralRule::fromString('nplurals=3; plural=n')); $domainA->merge($domainB); $this->assertEquals(3, $domainA->getPluralRule()->getNumPlurals()); $this->assertFalse($domainB->hasPluralRule()); }
/** * Translate a plural message. * * @param string $singular * @param string $plural * @param int $number * @param string $textDomain * @param string|null $locale * @return string * @throws Exception\OutOfBoundsException */ public function translatePlural($singular, $plural, $number, $textDomain = 'default', $locale = null) { $locale = $locale ?: $this->getLocale(); $translation = $this->getTranslatedMessage($singular, $locale, $textDomain); if ($translation === null || $translation === '') { if (null !== ($fallbackLocale = $this->getFallbackLocale()) && $locale !== $fallbackLocale) { return $this->translatePlural($singular, $plural, $number, $textDomain, $fallbackLocale); } return $number == 1 ? $singular : $plural; } $index = Rule::fromString('nplurals=3; nplural=(n%100>10&&n%100<20 ? 2 : (n%100%10>1&&n%100%10<5 ? 1 : (n%100%10==1 ? 0 : 2)))')->evaluate($number); if (!isset($translation[$index])) { throw new Exception\OutOfBoundsException(sprintf('Provided index %d does not exist in plural array', $index)); } return $translation[$index]; }
/** * {@inheritdoc} */ public function load($locale, $filename) { if (!is_file($filename) || !is_readable($filename)) { throw new Exception\InvalidArgumentException(sprintf('Could not open file %s for reading', $filename)); } $messages = (include $filename); if (!is_array($messages)) { throw new Exception\InvalidArgumentException(sprintf('Expected an array, but received %s', gettype($messages))); } $textDomain = new TextDomain($messages); if (array_key_exists('', $textDomain)) { if (isset($textDomain['']['plural_forms'])) { $textDomain->setPluralRule(PluralRule::fromString($textDomain['']['plural_forms'])); } unset($textDomain['']); } return $textDomain; }
/** * Load translations from a remote source. * * @param string $locale * @param string $textDomain * * @throws \Zend\I18n\Exception\InvalidArgumentException * @return \Zend\I18n\Translator\TextDomain|null */ public function load($locale, $textDomain) { if (!is_array($this->messages)) { throw new Exception\InvalidArgumentException(sprintf('Expected an array, but received %s', gettype($this->messages))); } if (!isset($this->messages[$textDomain])) { throw new Exception\InvalidArgumentException(sprintf('Expected textdomain "%s" to be an array, but it is not set', $textDomain)); } if (!isset($this->messages[$textDomain][$locale])) { throw new Exception\InvalidArgumentException(sprintf('Expected locale "%s" to be an array, but it is not set', $locale)); } $textDomain = new TextDomain($this->messages[$textDomain][$locale]); if (array_key_exists('', $textDomain)) { if (isset($textDomain['']['plural_forms'])) { $textDomain->setPluralRule(PluralRule::fromString($textDomain['']['plural_forms'])); } unset($textDomain['']); } return $textDomain; }
/** * load(): defined by FileLoaderInterface. * * @see FileLoaderInterface::load() * @param string $locale * @param string $filename * @return TextDomain|null * @throws Exception\InvalidArgumentException */ public function load($locale, $filename) { if (!is_file($filename) || !is_readable($filename)) { throw new Exception\InvalidArgumentException(sprintf('Could not open file %s for reading', $filename)); } $messages = json_decode(file_get_contents($filename), true); if (!is_array($messages)) { if (ipConfig()->isDevelopmentEnvironment()) { throw new Exception\InvalidArgumentException(sprintf('Expected an array, but received %s', gettype($messages))); } else { return null; } } $textDomain = new TextDomain($messages); if (array_key_exists('', $textDomain)) { if (isset($textDomain['']['plural_forms'])) { $textDomain->setPluralRule(PluralRule::fromString($textDomain['']['plural_forms'])); } unset($textDomain['']); } return $textDomain; }
/** * load(): defined by LoaderInterface. * * @see LoaderInterface::load() * @param string $filename * @param string $locale * @return TextDomain|null * @throws Exception\InvalidArgumentException */ public function load($locale, $filename) { if (!is_file($filename) || !is_readable($filename)) { throw new Exception\InvalidArgumentException(sprintf('Could not open file %s for reading', $filename)); } $messages = array(); if (($handle = fopen($filename, "r")) !== false) { while (($cell = $this->fgetcsv($handle)) !== false) { if (!isset($cell[0])) { continue; } $messages[strtolower($cell[0])] = isset($cell[1]) ? $cell[1] : ''; } fclose($handle); } $textDomain = new TextDomain($messages); if (array_key_exists('', $textDomain)) { if (isset($textDomain['']['plural_forms'])) { $textDomain->setPluralRule(PluralRule::fromString($textDomain['']['plural_forms'])); } unset($textDomain['']); } return $textDomain; }
public function testPluralRuleSetter() { $domain = new TextDomain(); $domain->setPluralRule(PluralRule::fromString('nplurals=3; plural=n')); $this->assertEquals(2, $domain->getPluralRule()->evaluate(2)); }
/** * load(): defined by FileLoaderInterface. * * @see FileLoaderInterface::load() * @param string $locale * @param string $filename * @return TextDomain * @throws Exception\InvalidArgumentException */ public function load($locale, $filename) { $resolvedFile = $this->resolveFile($filename); if (!$resolvedFile) { throw new Exception\InvalidArgumentException(sprintf('Could not find or open file %s for reading', $filename)); } $textDomain = new TextDomain(); ErrorHandler::start(); $this->file = fopen($resolvedFile, 'rb'); $error = ErrorHandler::stop(); if (false === $this->file) { throw new Exception\InvalidArgumentException(sprintf('Could not open file %s for reading', $filename), 0, $error); } // Verify magic number $magic = fread($this->file, 4); if ($magic == "•Þ") { $this->littleEndian = false; } elseif ($magic == "Þ•") { $this->littleEndian = true; } else { fclose($this->file); throw new Exception\InvalidArgumentException(sprintf('%s is not a valid gettext file', $filename)); } // Verify major revision (only 0 and 1 supported) $majorRevision = $this->readInteger() >> 16; if ($majorRevision !== 0 && $majorRevision !== 1) { fclose($this->file); throw new Exception\InvalidArgumentException(sprintf('%s has an unknown major revision', $filename)); } // Gather main information $numStrings = $this->readInteger(); $originalStringTableOffset = $this->readInteger(); $translationStringTableOffset = $this->readInteger(); // Usually there follow size and offset of the hash table, but we have // no need for it, so we skip them. fseek($this->file, $originalStringTableOffset); $originalStringTable = $this->readIntegerList(2 * $numStrings); fseek($this->file, $translationStringTableOffset); $translationStringTable = $this->readIntegerList(2 * $numStrings); // Read in all translations for ($current = 0; $current < $numStrings; $current++) { $sizeKey = $current * 2 + 1; $offsetKey = $current * 2 + 2; $originalStringSize = $originalStringTable[$sizeKey]; $originalStringOffset = $originalStringTable[$offsetKey]; $translationStringSize = $translationStringTable[$sizeKey]; $translationStringOffset = $translationStringTable[$offsetKey]; $originalString = array(''); if ($originalStringSize > 0) { fseek($this->file, $originalStringOffset); $originalString = explode("", fread($this->file, $originalStringSize)); } if ($translationStringSize > 0) { fseek($this->file, $translationStringOffset); $translationString = explode("", fread($this->file, $translationStringSize)); if (count($originalString) > 1 && count($translationString) > 1) { $textDomain[$originalString[0]] = $translationString; array_shift($originalString); foreach ($originalString as $string) { $textDomain[$string] = ''; } } else { $textDomain[$originalString[0]] = $translationString[0]; } } } // Read header entries if (array_key_exists('', $textDomain)) { $rawHeaders = explode("\n", trim($textDomain[''])); foreach ($rawHeaders as $rawHeader) { list($header, $content) = explode(':', $rawHeader, 2); if (trim(strtolower($header)) === 'plural-forms') { $textDomain->setPluralRule(PluralRule::fromString($content)); } } unset($textDomain['']); } fclose($this->file); return $textDomain; }
public function testGetNumPlurals() { $rule = Rule::fromString('nplurals=9; plural=n'); $this->assertEquals(9, $rule->getNumPlurals()); }