public function testReadMo() { $l = Locale::readMo('tests/_data/I18n/da.mo'); $this->assertEquals('juni', $l->get('June')); $this->assertEquals('d/m/Y', $l->shortDate); $this->assertTrue(isset($l->shortTime)); $this->assertEquals('Der er 0 brugere', $l->nget('There are %1 users', 'There is %1 user', 0)); $this->assertEquals('Der er 1 bruger', $l->nget('There are %1 users', 'There is %1 user', 1)); $this->assertEquals('Der er 2 brugere', $l->nget('There are %1 users', 'There is %1 user', 2)); // big endian file: $l = Locale::readMo('tests/_data/I18n/da.be.mo'); $this->assertEquals('juni', $l->get('June')); $this->assertEquals('d/m/Y', $l->shortDate); $this->assertTrue(isset($l->shortTime)); $this->assertEquals('Der er 0 brugere', $l->nget('There are %1 users', 'There is %1 user', 0)); $this->assertEquals('Der er 1 bruger', $l->nget('There are %1 users', 'There is %1 user', 1)); $this->assertEquals('Der er 2 brugere', $l->nget('There are %1 users', 'There is %1 user', 2)); // not a MO file: $this->assertThrows('Jivoo\\I18n\\LocaleException', function () { $l = Locale::readMo('tests/_data/I18n/da.po'); }); // not a MO file: // TODO: why does this not work? // $this->assertThrows('Jivoo\I18n\LocaleException', function() { // $l = Locale::readMo('tests/_data/I18n/notafile'); // }); }
/** * Load a localization for the current language from a directory. * * @param string $dir * Directory path. * @param bool $extend * Whether to extend the existing localization object * (true) or replace it (false). * @return bool True if language file found, false otherwise. */ public static function loadFrom($dir, $extend = true) { $file = $dir . '/' . self::$language . '.'; if (isset(self::$cache)) { $cached = self::$cache->getItem($file); if ($cached->isHit()) { $value = $cached->get(); if (is_array($value)) { $localization = new Locale($value); self::load($localization, $extend); return true; } else { self::$cache->deleteItems(array($file)); } } } if (file_exists($file . 'pot')) { return true; } elseif (file_exists($file . 'mo')) { $localization = Locale::readMo($file . 'mo'); } elseif (file_exists($file . 'po')) { $localization = Locale::readPo($file . 'po'); } else { return false; } if (isset(self::$cache)) { // self::$cache->set($file, $localization->getMessages(), 3600); $item = self::$cache->getItem($file); $item->set($localization->getMessages()); $item->expiresAfter(3600); self::$cache->save($item); } self::load($localization, $extend); return true; }
/** * Read a gettext MO-file. * * @param string $file * MO-file. * @return Locale Localization object. */ public static function readMo($file) { $f = file_get_contents($file); if (!is_string($f)) { throw new LocaleException('Could not open file: ' . $file); } $magic = bin2hex(substr($f, 0, 4)); if ($magic === '950412de') { // Big endian $header = 'Nrev/NN/NO/NT/NS/NH'; $format = 'N'; } elseif ($magic === 'de120495') { // Little endian $header = 'Vrev/VN/VO/VT/VS/VH'; $format = 'V'; } else { throw new LocaleException('Not a valid MO file: incorrect magic number: ' . $magic); } $o = 4; $data = unpack($header, substr($f, $o, 24)); $num = $data['N']; $oOffset = $data['O']; $tOffset = $data['T']; if ($num == 0) { return new Locale(); } $format = $format . $num * 2; $o = $oOffset; $oTable = unpack($format, substr($f, $o, 8 * $num)); $o = $tOffset; $tTable = unpack($format, substr($f, $o, 8 * $num)); $offsets = array(); $n = $num * 2; $o = $oTable[2]; $messages = array(); for ($i = 1; $i <= $n; $i += 2) { $length = $oTable[$i]; if ($length == 0) { $message = ''; $o += 1; } else { $message = substr($f, $o, $length); $o += $length + 1; $hasNul = strpos($message, ""); if ($hasNul !== false) { $message = substr($message, $hasNul + 1); // gets plural } } $messages[$i] = $message; } $o = $tTable[2]; $l = new Locale(); for ($i = 1; $i <= $n; $i += 2) { $length = $tTable[$i]; if ($length > 0) { $translation = substr($f, $o, $length); $o += $length + 1; if ($messages[$i] == '') { $properties = explode("\n", $translation); foreach ($properties as $property) { list($property, $value) = explode(':', $property, 2); if (trim(strtolower($property)) == 'plural-forms') { $l->pluralForms = $value; break; } elseif (trim(strtolower($property)) == 'language') { $value = LanguageTag::parseTag($value); $l->name = $value[0]; $l->region = $value[1]; } } } if (strpos($translation, "") !== false) { $translation = explode("", $translation); } $l->set($messages[$i], $translation); } else { $o += 1; } } return $l; }