public function testDefaultConfiguration() { $file = "{$this->_path}/source/a.html.php"; $data = <<<EOD <h2>Flowers</h2> <?=\$t('Apples are green.'); ?> EOD; file_put_contents($file, $data); $configs = Catalog::config(); $configKey1 = key($configs); next($configs); $configKey2 = key($configs); $this->_writeInput(array($configKey1, $configKey2, '', 'y')); $result = $this->command->run(); $expected = 0; $this->assertIdentical($expected, $result); $expected = '/.*Yielded 1 item.*/'; $result = $this->command->response->output; $this->assertPattern($expected, $result); $file = "{$this->_path}/destination/message_default.pot"; $result = file_exists($file); $this->assertTrue($result); $result = file_get_contents($file); $expected = '/msgid "Apples are green\\."/'; $this->assertPattern($expected, $result); $expected = '#/resources/tmp/tests/source(/|\\\\)a.html.php:2#'; $this->assertPattern($expected, $result); $result = $this->command->response->error; $this->assertFalse($result); }
public function testTransliteration() { $data = array( 'transliteration' => array( '\$' => 'dollar', '&' => 'and' ) ); Catalog::write('runtime', 'inflection', 'en', $data); Inflector::rules( 'transliteration', Catalog::read('runtime', 'inflection.transliteration', 'en') ); $result = Inflector::slug('this & that'); $expected = 'this-and-that'; $this->assertEqual($expected, $result); $data = array( 'transliteration' => array( 't' => 'd', '&' => 'und' ) ); Catalog::write('runtime', 'inflection', 'de', $data); Inflector::rules( 'transliteration', Catalog::read('runtime', 'inflection.transliteration', 'de') ); $result = Inflector::slug('this & that'); $expected = 'dhis-und-dhad'; $this->assertEqual($expected, $result); }
/** * 1. Extract all translated strings from the codebase * If you modify any text in the site, please follow Extract, Create and Compile */ public function extract() { $command = 'echo Y|del "F:\\Apache\\www\\TBG\\xgcwallet.org\\app\\resources\\tmp\\cache\\templates\\*.*"'; passthru($command); $data = Catalog::read('code', 'messageTemplate', 'root', array('lossy' => false)); $scope = 'default'; return Catalog::write('default', 'messageTemplate', 'root', $data, compact('scope')); }
public function testMultipleLocales() { $data = '/phone en_US/'; Catalog::write('runtime', 'validation.phone', 'en_US', $data); $data = '/phone en_GB/'; Catalog::write('runtime', 'validation.phone', 'en_GB', $data); Validator::add('phone', array('en_US' => Catalog::read('runtime', 'validation.phone', 'en_US'), 'en_GB' => Catalog::read('runtime', 'validation.phone', 'en_GB'))); $result = Validator::isPhone('phone en_US', 'en_US'); $this->assertTrue($result); $result = Validator::isPhone('phone en_GB', 'en_GB'); $this->assertTrue($result); }
/** * Tests the plural rule #1 which applies to the following languages * grouped by family and sorted alphabetically. * * Germanic family: * - English (en) * * @return void */ public function testPlurals1() { $locales = array('en'); foreach ($locales as $locale) { $result = Catalog::read('lithium', 'message.pluralForms', $locale); $this->assertEqual(2, $result, "Locale: `{$locale}`\n{:message}"); $rule = Catalog::read('lithium', 'message.pluralRule', $locale); $expected = '10111111111111111111111111111111111111111111111111'; $expected .= '11111111111111111111111111111111111111111111111111'; $expected .= '11111111111111111111111111111111111111111111111111'; $expected .= '11111111111111111111111111111111111111111111111111'; $result = ''; for ($n = 0; $n < 200; $n++) { $result .= $rule($n); } $this->assertIdentical($expected, $result, "Locale: `{$locale}`\n{:message}"); } }
public function testContextsNested() { $file = "{$this->_path}/source/a.html.php"; $data = <<<EOD <?=\$t('Robin, {:a}', array('a' => \$t('Michael, {:b}', array('b' => \$t('Bruce', array('context' => 'Lee')), 'context' => 'Jackson')), 'context' => 'Hood')); ?> EOD; file_put_contents($file, $data); $configs = Catalog::config(); $configKey1 = key($configs); next($configs); $configKey2 = key($configs); $this->_writeInput(array($configKey1, $configKey2, '', 'y')); $result = $this->command->run(); $expected = 0; $this->assertIdentical($expected, $result); $expected = '/.*Yielded 3 item.*/'; $result = $this->command->response->output; $this->assertPattern($expected, $result); $file = "{$this->_path}/destination/message_default.pot"; $this->assertFileExists($file); $result = file_get_contents($file); $expected = '#/tmp/tests/source(/|\\\\)a.html.php:1'; $expected .= "\n"; $expected .= 'msgctxt "Hood"'; $expected .= "\n"; $expected .= 'msgid "Robin, {:a}"#'; $this->assertPattern($expected, $result); $expected = '#/tmp/tests/source(/|\\\\)a.html.php:1'; $expected .= "\n"; $expected .= 'msgctxt "Jackson"'; $expected .= "\n"; $expected .= 'msgid "Michael, {:b}"#'; $this->assertPattern($expected, $result); $expected = '#/tmp/tests/source(/|\\\\)a.html.php:1'; $expected .= "\n"; $expected .= 'msgctxt "Lee"'; $expected .= "\n"; $expected .= 'msgid "Bruce"#'; $this->assertPattern($expected, $result); $result = $this->command->response->error; $this->assertEmpty($result); }
public function testNlNl() { Validator::add(Catalog::read('validation', 'nl_NL')); $this->assertTrue(Validator::isSsn('123456789')); $this->assertFalse(Validator::isSsn('12345678')); }
/** * Integration with `View`. Embeds message translation aliases into the `View` * class (or other content handler, if specified) when content is rendered. This * enables translation functions, i.e. `<?=$t("Translated content"); ?>`. */ Media::applyFilter('_handle', function ($self, $params, $chain) { $params['handler'] += array('outputFilters' => array()); $params['handler']['outputFilters'] += Message::aliases(); return $chain->next($self, $params, $chain); }); /** * Integration with `Validator`. You can load locale dependent rules into the `Validator` * by specifying them manually or retrieving them with the `Catalog` class. */ foreach (array('phone', 'postalCode', 'ssn') as $name) { Validator::add($name, Catalog::read(true, "validation.{$name}", 'en_US')); } /** * Intercepts dispatching processes in order to set the effective locale by using * the locale of the request or if that is not available retrieving a locale preferred * by the client. */ ActionDispatcher::applyFilter('_callable', function ($self, $params, $chain) { $request = $params['request']; $controller = $chain->next($self, $params, $chain); if (!$request->locale) { $request->params['locale'] = Locale::preferred($request); } Environment::set(Environment::get(), array('locale' => $request->locale)); return $controller; });
/** * Helps in selecting or - if required - adding a new `Catalog` collection * used for extracting or writing the template. A special configuration * with the name `temporary` may be created. Should a configuration with * that same name exist prior to entering this method it will be unset. * * @param array $options Options paired with defaults to prompt for. * @return string The name of the selected or newly created configuration. */ protected function _configuration(array $options = array()) { $configs = (array) Catalog::config(); if (isset($configs['temporary'])) { unset($configs['temporary']); } if ($configs) { $this->out('Available `Catalog` Configurations:'); $prompt = 'Please choose a configuration or hit enter to add a new one:'; foreach ($configs as $name => $config) { $this->out(" - {$name}"); } } else { $this->out(' - No configuration found. -'); $prompt = 'Please hit enter to add a temporary configuration:'; } $this->out(); $name = $this->in($prompt, array('choices' => array_keys($configs), 'default' => 'temporary')); if ($name == 'temporary') { foreach ($options as $option => $default) { $configs[$name][$option] = $this->in(ucfirst($option) . ':', compact('default')); } Catalog::config($configs); } return $name; }
public function testInvalidWrite() { Catalog::reset(); $this->assertException("Configuration `runtime` has not been defined.", function () { $data = array('house' => array('id' => 'house')); Catalog::write('runtime', 'message', 'de', $data); }); }
* and `li3_cldr` projects. * * Further enables support for multibyte strings through the `Multibyte` class by * overwriting rules (currently just `lengthBetween`). * * @link https://github.com/UnionOfRAD/li3_lldr * @link https://github.com/UnionOfRAD/li3_cldr * @see lithium\g11n\Catalog * @see lithium\g11n\Multibyte * @see lithium\util\Validator */ foreach (array('phone', 'postalCode', 'ssn') as $name) { $regex = Validator::rules($name); Validator::add($name, function ($value, $format, $options) use($name, $regex) { if ($format !== 'any') { $regex = Catalog::read(true, "validation.{$name}", $format); } if (!$regex) { $message = "Cannot find regular expression for validation rule `{$name}` "; $message .= "using format/locale `{$format}`."; throw new RuntimeException($message); } return preg_match($regex, $value); }); } Validator::add('lengthBetween', function ($value, $format, $options) { $length = Multibyte::strlen($value); $options += array('min' => 1, 'max' => 255); return $length >= $options['min'] && $length <= $options['max']; }); /**
/** * Retrieves translations through the `Catalog` class by using `$id` as the lookup * key and taking the current or - if specified - the provided locale as well as the * scope into account. Hereupon the correct plural form is determined by passing the * value of the `'count'` option to a closure. * * @param string $id The lookup key. * @param integer $count Used to determine the correct plural form. * @param string $locale The target locale. * @param array $options Passed through to `Catalog::read()`. Valid options are: * - `'scope'`: The scope of the message. * @return string|void The translation or `null` if none could be found or the plural * form could not be determined. * @see lithium\g11n\Catalog * @filter * @todo Message pages need caching. */ protected static function _translated($id, $count, $locale, $options = array()) { $params = compact('id', 'count', 'locale', 'options'); return static::_filter(__METHOD__, $params, function ($self, $params, $chain) { extract($params); $page = Catalog::read('message', $locale, $options); if (!isset($page[$id])) { return null; } $translated = (array) $page[$id]; if (!isset($page['plural']) || !is_callable($page['plural'])) { return null; } $key = $page['plural']($count); if (isset($translated[$key])) { return $translated[$key]; } }); }
public function testInvalidWrite() { Catalog::reset(); $data = array('house' => array('id' => 'house')); $this->expectException("Configuration 'runtime' has not been defined."); $this->assertFalse(Catalog::write('runtime', 'message', 'de', $data)); }
<?php use lithium\g11n\Catalog; /** * Register the g11n resources with `Catalog` while maintaining existing * configurations. This makes the resources contained in this plugin available * to the application this plugin is contained in. `Message::translate()` calls * will utilize these resources automatically as long as no or the `li3_lldr` * named configuration is selected. */ Catalog::config(array('li3_lldr' => array('adapter' => 'Php', 'path' => dirname(__DIR__) . '/resources/g11n/php')) + Catalog::config());
<?php /** * Register g11n resource. */ use lithium\g11n\Catalog; $catalog = array('li3_docs' => array('adapter' => 'Gettext', 'path' => dirname(__DIR__) . '/resources/g11n')); Catalog::config($catalog + Catalog::config()); if (file_exists(LITHIUM_APP_PATH . '/config/bootstrap/g11n.php')) { require_once LITHIUM_APP_PATH . '/config/bootstrap/g11n.php'; } /** * Initialize code index. */ use lithium\core\Libraries; use lithium\action\Dispatcher; use lithium\console\Dispatcher as ConsoleDispatcher; use li3_docs\extensions\docs\Code; $filter = function ($self, $params, $chain) { $indexPath = Libraries::get(true, 'path') . '/resources/docs.index.json'; if (file_exists($indexPath) && is_readable($indexPath)) { Code::index((array) json_decode(file_get_contents($indexPath), true)); } $result = $chain->next($self, $params, $chain); if (($index = Code::index()) && is_array($index) && is_writable(dirname($indexPath))) { file_put_contents($indexPath, json_encode($index)); } return $result; }; Dispatcher::applyFilter('run', $filter); ConsoleDispatcher::applyFilter('run', $filter);
public function testShortHandsSymmetry() { $data = array('house' => array('Haus', 'Häuser')); Catalog::write('message', 'de', $data, array('name' => 'runtime')); $filters = Message::shortHands(); $t = $filters['t']; $tn = $filters['tn']; $expected = Message::translate('house', array('locale' => 'de')); $result = $t('house', array('locale' => 'de')); $this->assertEqual($expected, $result); $expected = Message::translate('house', array('locale' => 'de', 'count' => 1)); $result = $tn('house', 'houses', 1, array('locale' => 'de')); $this->assertEqual($expected, $result); $expected = Message::translate('house', array('locale' => 'de', 'count' => 3)); $result = $tn('house', 'houses', 3, array('locale' => 'de')); $this->assertEqual($expected, $result); }
/** * Prompts for data source and writes template. * * @param array $data Data to save. * @return void */ protected function _writeTemplate($data) { $message[] = 'In order to proceed you need to choose a `Catalog` configuration'; $message[] = 'which is used for writing the template. The adapter for the configuration'; $message[] = 'should be capable of handling write requests for the `messageTemplate`'; $message[] = 'category.'; $this->out($message); $this->out(); $configs = (array) Catalog::config(); $this->out('Available `Catalog` Configurations:'); foreach ($configs as $name => $config) { $this->out(" - {$name}"); } $this->out(); $name = $this->in('Please choose a configuration or hit [enter] to add one:', array('choices' => array_keys($configs))); if (!$name) { $adapter = $this->in('Adapter:', array('default' => 'Gettext')); $path = $this->in('Path:', array('default' => $this->destination)); $scope = $this->in('Scope:', array('default' => $this->scope)); $name = 'runtime' . uniqid(); $configs[$name] = compact('adapter', 'path', 'scope'); Catalog::config($configs); } else { $scope = $this->in('Scope:', array('default' => $this->scope)); } $message = array(); $message[] = 'The template is now ready to be saved.'; $message[] = 'Please note that an existing template will be overwritten.'; $this->out($message); $this->out(); if ($this->in('Save?', array('choices' => array('y', 'n'), 'default' => 'y')) != 'y') { $this->out('Aborting upon user request.'); $this->stop(1); } try { return Catalog::write($name, 'messageTemplate', 'root', $data, compact('scope')); } catch (Exception $e) { return false; } }
public function testCaching() { $data = array('catalog' => 'Katalog'); Catalog::write('runtime', 'message', 'de', $data, array('scope' => 'foo')); $this->assertFalse(Message::cache()); $result = Message::translate('catalog', array('locale' => 'de', 'scope' => 'foo')); $this->assertEqual('Katalog', $result); $cache = Message::cache(); $this->assertEqual('Katalog', $cache['foo']['de']['catalog']); Message::cache(false); $this->assertFalse(Message::cache()); Message::cache(array('foo' => array('de' => array('catalog' => '<Katalog>')))); $result = Message::translate('catalog', array('locale' => 'de', 'scope' => 'foo')); $this->assertEqual('<Katalog>', $result); $options = array('locale' => 'de', 'scope' => 'foo', 'count' => 2); $this->assertEqual('<Katalog>', Message::translate('catalog', $options)); Message::cache(false); Message::cache(array('foo' => array('de' => array('catalog' => array('<Katalog>'))))); $this->assertNull(Message::translate('catalog', $options)); }
* Integration with `View`. Embeds message translation aliases into the `View` * class (or other content handler, if specified) when content is rendered. This * enables translation functions, i.e. `<?=$t("Translated content"); ?>`. */ Media::applyFilter('_handle', function ($self, $params, $chain) { $params['handler'] += array('outputFilters' => array()); $params['handler']['outputFilters'] += Message::aliases(); return $chain->next($self, $params, $chain); }); /** * Integration with `Validator`. You can load locale dependent rules into the `Validator` * by specifying them manually or retrieving them with the `Catalog` class. */ Validator::add('phone', Catalog::read('validation.phone', 'en_US')); Validator::add('postalCode', Catalog::read('validation.postalCode', 'en_US')); Validator::add('ssn', Catalog::read('validation.ssn', 'en_US')); /** * Intercepts dispatching processes in order to set the effective locale by using * the locale of the request or if that is not available retrieving a locale preferred * by the client. */ ActionDispatcher::applyFilter('_callable', function ($self, $params, $chain) { $request = $params['request']; $controller = $chain->next($self, $params, $chain); if (!$request->locale) { $request->params['locale'] = Locale::preferred($request); } Environment::set(Environment::get(), array('locale' => $request->locale)); return $controller; }); ConsoleDispatcher::applyFilter('_callable', function ($self, $params, $chain) {
public function testOutputLosslessFormat() { $data = array('house' => array('id' => 'house', 'ids' => array('singular' => 'house'), 'translated' => 'Haus', 'flags' => array(), 'comments' => array(), 'occurrences' => array())); Catalog::write('message', 'de', $data, array('name' => 'runtime')); $result = Catalog::read('message', 'de', array('lossy' => false)); $expected = array('house' => array('id' => 'house', 'ids' => array('singular' => 'house'), 'translated' => 'Haus', 'flags' => array(), 'comments' => array(), 'occurrences' => array())); $this->assertEqual($expected, $result); }
/** * Retrieves translations through the `Catalog` class by using `$id` as the lookup * key and taking the current or - if specified - the provided locale as well as the * scope into account. Hereupon the correct plural form is determined by passing the * value of the `'count'` option to a closure. * * @see lithium\g11n\Catalog * @param string $id The lookup key. * @param integer $count Used to determine the correct plural form. * @param string $locale The target locale. * @param array $options Passed through to `Catalog::read()`. Valid options are: * - `'scope'`: The scope of the message. * @return string|void The translation or `null` if none could be found or the plural * form could not be determined. * @filter */ protected static function _translated($id, $count, $locale, array $options = array()) { $params = compact('id', 'count', 'locale', 'options'); $cache =& static::$_cachedPages; return static::_filter(__METHOD__, $params, function ($self, $params, $chain) use(&$cache) { extract($params); if (!isset($cache[$options['scope']][$locale])) { $cache[$options['scope']][$locale] = Catalog::read(true, 'message', $locale, $options); } $page = $cache[$options['scope']][$locale]; if (!isset($page[$id])) { return null; } if (!is_array($page[$id])) { return $page[$id]; } if (!isset($page['pluralRule']) || !is_callable($page['pluralRule'])) { return null; } $key = $page['pluralRule']($count); if (isset($page[$id][$key])) { return $page[$id][$key]; } }); }
<?php /** * Lithium: the most rad php framework * * @copyright Copyright 2010, Union of RAD (http://union-of-rad.org) * @license http://opensource.org/licenses/bsd-license.php The BSD License */ namespace li3_cldr\config; use ConfigException; use lithium\g11n\Catalog; $insideLibrary = dirname(__DIR__) . '/resources/g11n'; $insideApp = LITHIUM_APP_PATH . '/resources/g11n/cldr'; if (is_dir($insideLibrary . '/main')) { $path = $insideLibrary; } elseif (is_dir($insideApp . '/main')) { $path = $insideApp; } else { $message = "CLDR resources could not be found at either `{$insideLibrary}` or `{$insideApp}`."; throw new ConfigException($message); } /** * Add the configuration for the cldr resource to the existing * `Catalog` configurations. */ Catalog::config(array('cldr' => array('adapter' => 'Cldr', 'path' => $path)) + Catalog::config());