# Content

# Setup

Require package:

composer require contributte/translation
1

Register extension:

extensions:
    translation: Contributte\Translation\DI\TranslationExtension
1
2

# Configuration

Basic configuration:

translation:
    locales:
        whitelist: [en, cs, sk]
        default: en
        fallback: [en]
    dirs:
        - %appDir%/lang
1
2
3
4
5
6
7

# 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
1
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');
    }
    
}
1
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;
    }
    
}
1
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}
1
2
3
4
5
6
7
8
9
10
11
12

# Neon

File name format:

        locale
          |
         /--\
messages.en_US.neon
\______/       \__/
   |            |
 domain     extension
1
2
3
4
5
6
7

File content format:

prefix:
    for: "message" # messages.prefix.for
1
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."
1

Latte:

{_user.name.taken, [name => "Ales"]}
1

Presenter/Model:

$this->translator->translate('user.name.taken', [name => 'Ales']);
1

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
1
2
3
4
5
6
7
8
9
10
11
12

# Database loaders

Package includes database loaders for Doctrine 2 and Nette Database 3.

# 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"
1
2
3
4

Add loader to translation configuration:

translation:
    loaders:
        doctrine: Contributte\Translation\Loaders\Doctrine
1
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;
    
}
1
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"
1
2
3
4

Add loader to translation configuration:

translation:
    loaders:
        nettedatabase: Contributte\Translation\Loaders\NetteDatabase
1
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;
1
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', [...]);
1
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'),
    ]);
1
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/',
      ];
   }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14