ali-translator / translator
Translator
Requires
- php: >=7.4
Requires (Dev)
- ext-pdo: *
- phpunit/phpunit: ^9.0
- symfony/var-dumper: ^5.0
Suggests
- ali-translator/auto-html-translation: Parses html document, and translate included texts
- ali-translator/buffered-translation: Manually pasted text on document for translation, by means of buffering is translated by one approach (helpful for DB sources)
- ali-translator/translator-js-integrate: Integrate this packet to frontend js
- ali-translator/url-template: Helps on url parameters resolving (as language, country, etc.)
README
The Translation component provides tools to internationalize your application.
Installation
$ composer require ali-translator/translator
Simplified translator
Example of init one direction translator (one original and one translation languages):
use \ALI\Translator\Source\Sources\MySqlSource\MySqlSource; use \ALI\Translator\PlainTranslator\PlainTranslatorFactory; $originalLanguageAlias = 'en'; $translationLanguageAlias = 'ru'; $connection = new PDO(SOURCE_MYSQL_DNS, SOURCE_MYSQL_USER, SOURCE_MYSQL_PASSWORD); $source = new MySqlSource($connection, $originalLanguageAlias); // Install source $installer = $source->generateInstaller(); if($installer->isInstalled()){ $installer->install(); // $installer->destroy(); } $plainTranslator = (new PlainTranslatorFactory())->createPlainTranslator($source, $translationLanguageAlias); $plainTranslator->saveTranslate('Hello','Привет'); $plainTranslator->translate('Hello', true); // -> 'Привет' $plainTranslator->translateAll(['Hello']); // -> ['Привет'] // Try translate not exist phrase $plainTranslator->translate('Goodbye', false); // -> null $plainTranslator->translate('Goodbye', true); // With fallback -> 'Goodbye' $plainTranslator->delete('Hello');
Complex translator
If you need few original and translation languages, this way for you:
use \ALI\Translator\Translator; use \ALI\Translator\Source\SourceInterface; use \ALI\Translator\Source\SourcesCollection; use \ALI\Translator\PlainTranslator\PlainTranslator; /** @var SourceInterface $firsSource */ /** @var SourceInterface $secondSource */ $sourceCollection = new SourcesCollection(); $sourceCollection->addSource($firsSource,['ua', 'ru']); $sourceCollection->addSource($secondSource); // Second source for all another translation languages $translator = new Translator($sourceCollection); $translator->saveTranslate('en', 'ru', 'Hello', 'Привет'); $translator->translate('en', 'ru', 'Hello'); // Also, if you need, you always can transform translator to plainTranslator to work simplification $plainTranslator = new PlainTranslator('en', 'ru', $translator);
Parameters resolving
/** @var \ALI\Translator\PlainTranslator\PlainTranslatorInterface $plainTranslator */ // Simple parameter $translatedPhrase = $plainTranslator->translate('Осталось {number}', true); echo MessageFormatter::formatMessage('ru_RU', $translatedPhrase, ['number' => 25]); // -> 'Осталось 25' // Plural forms $translatedPhrase = $plainTranslator->translate('Осталось {placeLeft, plural, =0{# мест} one{# место} few{# места} other{# мест}}', true); echo MessageFormatter::formatMessage('ru_RU', $translatedPhrase, [ 'placeLeft' => 1, ]); // -> 'Осталось 1 место'
Catchers of missing translations
Packet allow set catchers of phrases without translation, which will run after tranlsate
method failing
use ALI\Translator\TranslatorInterface; use ALI\Translator\MissingTranslateCatchers\CollectorMissingTranslatesCatcher; /** @var TranslatorInterface $translator */ $translator->addMissingTranslationCatchers(function (string $searchPhrase, TranslatorInterface $translator){ ... }); // Or use existed CollectorMissingTranslatesCatcher $collectorMissingTranslatesCatcher = new CollectorMissingTranslatesCatcher(); $translator->addMissingTranslationCatchers($collectorMissingTranslatesCatcher); $translator->translate('Hello 123'); $collectorMissingTranslatesCatcher->getOriginalPhraseCollectionsByLanguageAlias('ru')->getAll(); // -> ['Hello 123']
Phrase decorators
If you need decorate original-phrase or translated-phrase before output - this section for you.
Example, of existed decorator, which replaces numbers to "0" before saving originals,
and restoring correct number after translate.
use ALI\Translator\Decorators\PhraseDecorators\OriginalDecorators\ReplaceNumbersOriginalDecorator; use ALI\Translator\Decorators\PhraseDecorators\OriginalPhraseDecoratorManager; use ALI\Translator\Decorators\PhraseDecorators\TranslateDecorators\RestoreNumbersTranslateDecorator; use ALI\Translator\Decorators\PhraseDecorators\TranslatePhraseDecoratorManager; use ALI\Translator\Decorators\PhraseTranslatorDecorator; use ALI\Translator\TranslatorInterface; use ALI\Translator\PlainTranslator\PlainTranslator; /** @var TranslatorInterface $translator */ $originalDecoratorManger = new OriginalPhraseDecoratorManager([ new ReplaceNumbersOriginalDecorator(), ]); $translateDecoratorManager = new TranslatePhraseDecoratorManager([ new RestoreNumbersTranslateDecorator(), ]); $phraseTranslatorDecorator = new PhraseTranslatorDecorator($translator, $originalDecoratorManger, $translateDecoratorManager); // For simplifying $plainPhraseTranslatorDecorator = new PlainTranslator('en', 'ua', $phraseTranslatorDecorator); $plainPhraseTranslatorDecorator->saveTranslate('Hello 123 Hi 000', 'Привіт 123 Хай 000'); // and when translate text with another numbers, you get previous saved translation $plainPhraseTranslatorDecorator->translate('Hello 555 Hi 8676', true); // -> 'Привіт 555 Хай 8676'
Originals grouping
Optionality, you can add group to the originals. This can be useful for cases, when many different processes adding originals, and then when one of these processes removes its dependencies form them, to deciding whether to remove the original from the translator - use the groups. If original now does not have any group - remove them.
use ALI\Translator\OriginalGroups\Repository\Mysql\MysqlOriginalGroupRepository; use ALI\Translator\OriginalGroups\Repository\Mysql\MySqlRepositoryConfig; use ALI\Translator\Source\SourceInterface; use \PDO; /** @var SourceInterface $translatorSource */ /** @var PDO $pdo */ $mysqlConfig = new MySqlRepositoryConfig($pdo); $groupRepositories = new MysqlOriginalGroupRepository($mysqlConfig, $translatorSource); // Installing $installer = $groupRepositories->generateInstaller(); if(!$installer->isInstalled()){ $installer->install(); // $installer->destroy(); } // Use cases $groupRepositories->addGroups(['Hello world','test'],['default','models']); $groupRepositories->getGroups(['Hello world','test']); $groupRepositories->getOriginalsByGroup('default', 0 , 20); $groupRepositories->removeGroups(['Hello world','test'],['default']); $groupRepositories->removeAllGroups(['Hello world','test']);
Available sources
- MySqlSource - recommended for using with ali-translator/buffered-translation to reduce the number of requests to Source
- CsvFileSource - csv source. Files will be look like as
en-ua.csv
Languages
For convenience, a couple of classes are integrated into this package to help with languages.
LanguageInterface
- Has getTitle()
, getIsoCode()
and getAlias()
methods
LanguageRepositoryInterface
- Has save(LanguageInterface $language, $isActive)
, find($alias)
, findByIsoCode($isoCode)
, getAll($onlyActive)
methods.
And realizations for repository interface: ArrayLanguageRepository
(ArrayLanguageRepositoryFactory
) and MySqlLanguageRepository
Suggest packets
- ali-translator/buffered-translation - Manually pasted text on document for translation, by means of buffering is translated by one approach (helpful for DB sources)
- ali-translator/translator-js-integrate - Integrate this packet to frontend js
- ali-translator/auto-html-translation - Parses html document, and translate included texts
- ali-translator/url-template - Helps on url language resolving
Tests
In packet exist docker-compose file, with environment for testing.
docker-compose up -d
docker-compose exec php bash
docker-compose run php composer install
docker-compose run php vendor/bin/phpunit