Contributte Translation
# Content
# Setup
Require package:
composer require contributte/translation
Register extension:
extensions:
translation: Contributte\Translation\DI\TranslationExtension
2
# Configuration
Basic configuration:
translation:
locales:
whitelist: [en, cs, sk]
default: en
fallback: [en]
dirs:
- %appDir%/lang
returnOriginalMessage: true # to not translate undefined messages, default is true
2
3
4
5
6
7
8
Note: The fallback
configuration values should always reflect the locale code used in the file you wish to fallback to (e.g. en_US
for messages.en_US.neon
, or en
for messages.en.neon
).
# Locale resolvers
This configuration instructs the extension how to resolve the locale and the order in which it will do so:
translation:
localeResolvers:
- Contributte\Translation\LocalesResolvers\Router
2
3
Available resolvers:
- Contributte\Translation\LocalesResolvers\Router
- Contributte\Translation\LocalesResolvers\Header (HTTP header)
- Contributte\Translation\LocalesResolvers\Parameter (Get parameter)
- Contributte\Translation\LocalesResolvers\Session
By default the Router
, Parameter
and Session
resolvers expect the name of the parameter/key to be locale
.
# Examples
# Presenter
<?php declare(strict_types = 1);
namespace App;
use Nette;
use Contributte;
class BasePresenter extends Nette\Application\UI\Presenter
{
/** @var Nette\Localization\ITranslator @inject */
public $translator;
/** @var Contributte\Translation\LocalesResolvers\Session @inject */
public $translatorSessionResolver;
public function handleChangeLocale(string $locale): void
{
$this->translatorSessionResolver->setLocale($locale);
$this->redirect('this');
}
public function renderDefault(): void
{
$this->translator->translate('domain.message');
$prefixedTranslator = $this->translator->createPrefixedTranslator('domain');
$prefixedTranslator->translate('message');
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Model
<?php declare(strict_types = 1);
namespace App\Model;
use Nette;
class Model
{
/** @var Nette\Localization\ITranslator */
private $translator;
public function __construct(Nette\Localization\ITranslator $translator)
{
$this->translator = $translator;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Latte
How to use on frontend.
{_domain.message}
{_domain.message, $count}
{_domain.message, [name => "Ales"]}
{translator domain}
{_message}
{_message, $count}
{_message, [name => "Ales"]}
{/translator}
{var $myMessage = 'domain.message'}
{$myMessage|translate}
2
3
4
5
6
7
8
9
10
11
12
# Neon
File name format:
locale
|
/--\
messages.en_US.neon
\______/ \__/
| |
domain extension
2
3
4
5
6
7
File content format:
prefix:
for: "message" # messages.prefix.for
2
# Parameters in messages
Sometimes it is convenient to include a dynamic parameter in the translation - as seen in the Latte examples above.
Neon:
user.name.taken: "Sorry, the username %name% is already taken, please try a different one."
Latte:
{_user.name.taken, [name => "Ales"]}
Presenter/Model:
$this->translator->translate('user.name.taken', [name => 'Ales']);
Note: When passing parameters to the translator, the parameter names must not be enclosed in %
characters. This is done by Contributte/Translation
automatically.
# Loaders
By default the extension will look for .neon
files.
# File loaders
array: Symfony\Component\Translation\Loader\ArrayLoader
csv: Symfony\Component\Translation\Loader\CsvFileLoader
dat: Symfony\Component\Translation\Loader\IcuDatFileLoader
res: Symfony\Component\Translation\Loader\IcuResFileLoader
ini: Symfony\Component\Translation\Loader\IniFileLoader
json: Symfony\Component\Translation\Loader\JsonFileLoader
mo: Symfony\Component\Translation\Loader\MoFileLoader
php: Symfony\Component\Translation\Loader\PhpFileLoader
po: Symfony\Component\Translation\Loader\PoFileLoader
ts: Symfony\Component\Translation\Loader\QtFileLoader
xlf: Symfony\Component\Translation\Loader\XliffFileLoader
yml: Symfony\Component\Translation\Loader\YamlFileLoader
2
3
4
5
6
7
8
9
10
11
12
# Database loaders
Package includes database loaders for Doctrine 2 (opens new window) and Nette Database 3 (opens new window).
# Doctrine
You must create a file with specific format in scanned dirs such as messages.en_US.doctrine. All parameters are optional, but the file has to exist.
table: "My\Entity" # if you specify the entity key, "messages" from file name will be ignored
id: "id" # id column name, default is "id"
locale: "locale" # locale column name, default is "locale"
message: "message" # message column name, default is "message"
2
3
4
Add loader to translation configuration:
translation:
loaders:
doctrine: Contributte\Translation\Loaders\Doctrine
2
3
Entity example:
<?php declare(strict_types = 1);
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="messages")
*/
class Messages
{
/**
* @ORM\Id
* @ORM\Column(type="integer", nullable=false)
* @ORM\GeneratedValue
*/
public $messageId;
/**
* @ORM\Column(type="string", nullable=false)
*/
public $id;
/**
* @ORM\Column(type="string", nullable=false)
*/
public $locale;
/**
* @ORM\Column(type="string", nullable=false)
*/
public $message;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# Nette Database
You must create a file with specific format in scanned dirs such as messages.en_US.nettedatabase. All parameters are optional, but the file has to exist.
table: "my_table" # if you specify table key, "messages" from file name will be ignored
id: "id" # id column name, default is "id"
locale: "locale" # locale column name, default is "locale"
message: "message" # message column name, default is "message"
2
3
4
Add loader to translation configuration:
translation:
loaders:
nettedatabase: Contributte\Translation\Loaders\NetteDatabase
2
3
DB table example:
CREATE TABLE `messages` (
`id` varchar(191) NOT NULL,
`locale` char(5) NOT NULL,
`message` varchar(191) NOT NULL,
UNIQUE KEY `id` (`id`),
KEY `locale` (`locale`),
KEY `message` (`message`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2
3
4
5
6
7
8
# Features
# Wrappers
It is possible to pass pluralization to components without pre-translation and avoiding double translation.
$form = new Nette\Application\UI\Form;
$form->addText('mail', 'form.mail.label')
->setOption('description', new Contributte\Translation\Wrappers\Message('form.mail.description', [...]);
2
3
4
Or pass the not translatable texts:
$form->addSelect('country', 'form.country.label')
->setItems([
new Contributte\Translation\Wrappers\NotTranslate('Czech republic'),
new Contributte\Translation\Wrappers\NotTranslate('Slovak republic'),
]);
2
3
4
5
# TranslationProviderInterface
It is possible to pass additional translation resources from your compiler extensions by implementing the TranslationProviderInterface
.
use Nette\DI\CompilerExtension;
use Contributte\Translation\DI\TranslationProviderInterface;
class MyExtension extends CompilerExtension implements TranslationProviderInterface
{
public function getTranslationResources(): array
{
return [
__DIR__ . '/../lang/',
];
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14