Skip to content

Commit

Permalink
Merge pull request #5636 from cakephp/3.0-optional-i18n-cache
Browse files Browse the repository at this point in the history
3.0 optional i18n cache
  • Loading branch information
markstory committed Jan 13, 2015
2 parents 277cd75 + 06526cc commit 6a73a89
Show file tree
Hide file tree
Showing 8 changed files with 407 additions and 231 deletions.
6 changes: 4 additions & 2 deletions composer.json
Expand Up @@ -36,7 +36,8 @@
},
"files": [
"src/Core/functions.php",
"src/Collection/functions.php"
"src/Collection/functions.php",
"src/I18n/functions.php"
]
},
"autoload-dev": {
Expand All @@ -59,6 +60,7 @@
"cakephp/datasource": "self.version",
"cakephp/database": "self.version",
"cakephp/cache": "self.version",
"cakephp/log": "self.version"
"cakephp/log": "self.version",
"cakephp/i18n": "self.version"
}
}
8 changes: 7 additions & 1 deletion src/I18n/I18n.php
Expand Up @@ -17,6 +17,7 @@
use Aura\Intl\FormatterLocator;
use Aura\Intl\PackageLocator;
use Aura\Intl\TranslatorFactory;
use Cake\Cache\Cache;
use Cake\I18n\Formatter\IcuFormatter;
use Cake\I18n\Formatter\SprintfFormatter;
use Locale;
Expand Down Expand Up @@ -54,7 +55,7 @@ public static function translators()
return static::$_collection;
}

return static::$_collection = new TranslatorRegistry(
static::$_collection = new TranslatorRegistry(
new PackageLocator,
new FormatterLocator([
'sprintf' => function () {
Expand All @@ -67,6 +68,11 @@ public static function translators()
new TranslatorFactory,
static::locale()
);

if (class_exists('Cake\Cache\Cache')) {
static::$_collection->setCacher(Cache::engine('_cake_core_'));
}
return static::$_collection;
}

/**
Expand Down
89 changes: 89 additions & 0 deletions src/I18n/README.md
@@ -0,0 +1,89 @@
# CakePHP Internationalization Library

The I18n library provides a `I18n` service locator that can be used for setting
the current locale, building translation bundles and translating messages.

Additionally, it provides the `Time` and `Number` classes which can be used to
ouput dates, currencies and any numbers in the right format for the specified locale.

## Usage

Internally, the `I18n` class uses [Aura.Intl](https://github.com/auraphp/Aura.Intl).
Getting familiar with it, will help you understand how to build and manipulate translation bundles
should you wish to create them manually instead of using the conventions this library uses.

### Setting the Current Locale

```php
use Cake\I18n\I18n;

I18n::locale('en_US');
```

### Translating a message

```php
echo __(
'Hi {0,string}, your balance on the {1,date} is {2,number,currency}',
['Charles', '2014-01-13 11:12:00', 1354.37]
);

// Returns
Hi Charles, your balance on the Jan 13, 2014, 11:12 AM is $ 1,354.37
```

### Creating your Own Translators

```php
use Cake\I18n\I18n;
use Aura\Intl\Package;

I18n::translator('animals', 'fr_FR', function () {
$package = new Package(
'default', // The formatting strategy (ICU)
'default', // The fallback domain
);
$package->setMessages([
'Dog' => 'Chien',
'Cat' => 'Chat',
'Bird' => 'Oiseau'
...
]);

return $package;
});

I18n::locale('fr_FR');
__d('animals', 'Dog'); // Returns "Chien"
```

### Formatting Time

```php
$time = Time::now();
echo $time; // shows '4/20/14, 10:10 PM' for the en-US locale
```

### Formattng Numbers

```php
echo Number::format(100100100);
```

```php
echo Number::currency(123456.7890, 'EUR');
// outputs €123,456.79
```

## Documentation

Please make sure you check the [official I18n
documentation](http://book.cakephp.org/3.0/en/core-libraries/internationalization-and-localization.html)

The [documentation for the Time
class](http://book.cakephp.org/3.0/en/core-libraries/time.html) contains
instruction on how configure and output time strings for selected locales.

The [documentation for the Number
class](http://book.cakephp.org/3.0/en/core-libraries/number.html) shows how to
use the `Number` class for displaying numbers in specific locales.
68 changes: 53 additions & 15 deletions src/I18n/TranslatorRegistry.php
Expand Up @@ -15,7 +15,7 @@
namespace Cake\I18n;

use Aura\Intl\TranslatorLocator;
use Cake\Cache\Cache;
use Cake\Cache\CacheEngine;

/**
* Constructs and stores instances of translators that can be
Expand All @@ -42,6 +42,26 @@ class TranslatorRegistry extends TranslatorLocator
*/
protected $_defaultFormatter = 'default';

/**
* A CacheEngine object that is used to remember translator across
* requests.
*
* @var \Cake\Cache\CacheEngine
*/
protected $_cacher;

/**
* Sets the CacheEngine instance used to remember translators across
* requests.
*
* @param \Cake\Cache\CacheEngine $cacher The cacher instance.
* @return void
*/
public function setCacher(CacheEngine $cacher)
{
$this->_cacher = $cacher;
}

/**
* Gets a translator from the registry by package for a locale.
*
Expand All @@ -62,25 +82,43 @@ public function get($name, $locale = null)
$locale = $this->getLocale();
}

if (!isset($this->registry[$name][$locale])) {
$key = "translations.$name.$locale";
$translator = Cache::remember($key, function () use ($name, $locale) {
try {
return parent::get($name, $locale);
} catch (\Aura\Intl\Exception $e) {
}
if (isset($this->registry[$name][$locale])) {
return $this->registry[$name][$locale];
}

if (!isset($this->_loaders[$name])) {
$this->registerLoader($name, $this->_partialLoader());
}
if (!$this->_cacher) {
return $this->registry[$name][$locale] = $this->_getTranslator($name, $locale);
}

return $this->_getFromLoader($name, $locale);
}, '_cake_core_');
$key = "translations.$name.$locale";
$translator = $this->_cacher->read($key);
if (!$translator) {
$translator = $this->_getTranslator($name, $locale);
$this->_cacher->write($key, $translator);
}

return $this->registry[$name][$locale] = $translator;
}

return $this->registry[$name][$locale] = $translator;
/**
* Gets a translator from the registry by package for a locale.
*
* @param string $name The translator package to retrieve.
* @param string|null $locale The locale to use; if empty, uses the default
* locale.
* @return \Aura\Intl\TranslatorInterface A translator object.
*/
protected function _getTranslator($name, $locale)
{
try {
return parent::get($name, $locale);
} catch (\Aura\Intl\Exception $e) {
}

return $this->registry[$name][$locale];
if (!isset($this->_loaders[$name])) {
$this->registerLoader($name, $this->_partialLoader());
}
return $this->_getFromLoader($name, $locale);
}

/**
Expand Down
27 changes: 27 additions & 0 deletions src/I18n/composer.json
@@ -0,0 +1,27 @@
{
"name": "cakephp/i18n",
"description": "CakePHP Internationalization library with support for messages translation and dates and numbers localization",
"license": "MIT",
"authors": [
{
"name": "CakePHP Community",
"homepage": "http://cakephp.org"
}
],
"autoload": {
"psr-4": {
"Cake\\I18n\\": "."
},
"files": ["functions.php"]
},
"require": {
"cakephp/core": "dev-master",
"ext-intl": "*",
"nesbot/Carbon": "~1.13",
"aura/intl": "1.1.*"
},
"suggest": {
"cakephp/cache": "Require this if you want automatic caching of translators"
},
"minimum-stability": "dev"
}

0 comments on commit 6a73a89

Please sign in to comment.