tobento/service-translation
Composer 安装命令:
composer require tobento/service-translation
包简介
Allowing you to support multiple languages within your application.
README 文档
README
With the Translation Service you can translate messages easily.
Table of Contents
- Getting started
- Documentation
- Credits
Getting started
Add the latest version of the translation service running this command.
composer require tobento/service-translation
Requirements
- PHP 8.4 or greater
Highlights
- Framework-agnostic, will work with any project
- Decoupled design
Simple Example
Here is a simple example of how to use the translation service:
use Tobento\Service\Translation\Translator; use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; use Tobento\Service\Translation\Modifiers; use Tobento\Service\Translation\Modifier\ParameterReplacer; use Tobento\Service\Translation\Modifier\Pluralization; use Tobento\Service\Translation\MissingTranslationHandler; $translator = new Translator( new Resources( new Resource('*', 'de', [ 'Hello World' => 'Hallo Welt', ]), ), new Modifiers( new Pluralization(), new ParameterReplacer(), ), new MissingTranslationHandler(), 'en', ); var_dump($translator->trans('Hello World')); // string(11) "Hello World" var_dump($translator->trans('Hello World', [], 'de')); // string(10) "Hallo Welt"
Documentation
Translator
Create Translator
use Tobento\Service\Translation\Translator; use Tobento\Service\Translation\TranslatorInterface; use Tobento\Service\Translation\LocaleAware; use Tobento\Service\Translation\ResourcesAware; use Tobento\Service\Translation\ModifiersAware; use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; use Tobento\Service\Translation\Modifiers; use Tobento\Service\Translation\Modifier\ParameterReplacer; use Tobento\Service\Translation\MissingTranslationHandler; $translator = new Translator( resources: new Resources( new Resource('*', 'de', [ 'Hello World' => 'Hallo Welt', ]), ), modifiers: new Modifiers( new ParameterReplacer(), ), missingTranslationHandler: new MissingTranslationHandler(), locale: 'en', localeFallbacks: ['de' => 'en'], localeMapping: ['de' => 'de-CH'], ); var_dump($translator instanceof TranslatorInterface); // bool(true) var_dump($translator instanceof LocaleAware); // bool(true) var_dump($translator instanceof ResourcesAware); // bool(true) var_dump($translator instanceof ModifiersAware); // bool(true)
Translator Interface
use Tobento\Service\Translation\TranslatorInterface; $translated = $translator->trans( message: 'Hi :name', parameters: [':name' => 'John'], locale: 'de' );
Locale Aware
use Tobento\Service\Translation\LocaleAware; // set the default locale: $translator->setLocale('de'); // get the default locale: var_dump($translator->getLocale()); // string(2) "de" // set the locale fallbacks: $translator->setLocaleFallbacks(['de' => 'en']); // get the locale fallbacks: var_dump($translator->getLocaleFallbacks()); // array(1) { ["de"]=> string(2) "en" } // set the locale mapping: $translator->setLocaleMapping(['de' => 'de-CH']); // get the locale mapping: var_dump($translator->getLocaleMapping()); // array(1) { ["de"]=> string(5) "de-CH" }
Resources Aware
See also Resources or Files Resources for more details.
use Tobento\Service\Translation\ResourcesAware; use Tobento\Service\Translation\ResourcesInterface; // get the resources: var_dump($translator->resources() instanceof ResourcesInterface); // bool(true) // returns the translations of the specified resource: $translations = $translator->getResource( name: '*', locale: 'de' // or null to use default ); var_dump($translations); // array(1) { ["Hello World"]=> string(10) "Hallo Welt" } // returns a new instance with the specified resources: $translator = $translator->withResources( resources: $resources // ResourcesInterface );
Modifiers Aware
See also Modifiers for more details.
use Tobento\Service\Translation\ModifiersAware; use Tobento\Service\Translation\ModifiersInterface; // get the modifiers: var_dump($translator->modifiers() instanceof ModifiersInterface); // bool(true) // returns a new instance with the specified modifiers: $translator = $translator->withModifiers( modifiers: $modifiers // ModifiersInterface );
Translate Message
use Tobento\Service\Translation\Translator; use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; use Tobento\Service\Translation\Modifiers; use Tobento\Service\Translation\Modifier\Pluralization; use Tobento\Service\Translation\Modifier\ParameterReplacer; use Tobento\Service\Translation\MissingTranslationHandler; $translator = new Translator( resources: new Resources( new Resource('*', 'de', [ 'Hi :name' => 'Hi :name', 'It takes :minutes minute|It takes :minutes minutes' => 'Es dauert :minutes Minute|Es dauert :minutes Minuten' ]), ), modifiers: new Modifiers( new Pluralization(), new ParameterReplacer(), ), missingTranslationHandler: new MissingTranslationHandler(), locale: 'en', localeFallbacks: ['de' => 'en'], ); $translated = $translator->trans( message: 'Hi :name', parameters: [':name' => 'John'], locale: 'de' ); var_dump($translated); // string(7) "Hi John" $translated = $translator->trans( message: 'It takes :minutes minute|It takes :minutes minutes', parameters: [':minutes' => 5, 'count' => 5], locale: 'de' ); var_dump($translated); // string(19) "Es dauert 5 Minuten"
By default, resources will be sorted by its priority!
Using specific resource
Keep in mind that named resources are only loaded on the first resource request.
Resources with "*" named are always loaded.
use Tobento\Service\Translation\Translator; use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; use Tobento\Service\Translation\Modifiers; use Tobento\Service\Translation\MissingTranslationHandler; $translator = new Translator( resources: new Resources( new Resource('shop', 'de', [ 'noProducts' => 'Keine Produkte', 'No items in your shopping bag.' => 'Keine Artikel sind in deinem Warenkorb.', ]), ), modifiers: new Modifiers(), missingTranslationHandler: new MissingTranslationHandler(), locale: 'en', localeFallbacks: ['de' => 'en'], ); // with dot notation $translated = $translator->trans( message: 'shop.noProducts', locale: 'de' ); var_dump($translated); // string(14) "Keine Produkte" // with src parameter $translated = $translator->trans( message: 'No items in your shopping bag.', parameters: ['src' => 'shop'], locale: 'de' ); var_dump($translated); // string(39) "Keine Artikel sind in deinem Warenkorb."
Resources
Create Resources
use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\ResourcesInterface; use Tobento\Service\Translation\Resource; $resources = new Resources( new Resource( name: '*', locale: 'en', translations: ['Hello World' => 'Hallo Welt'], group: 'front', priority: 10, ), ); var_dump($resources instanceof ResourcesInterface); // bool(true)
Add Resources
You may add resources by using the add method:
add resource
use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; $resources = new Resources(); $resources->add(new Resource('*', 'de', [ 'Hello World' => 'Hallo Welt', ]));
add resources
use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; $resources = new Resources(); $resources->add(new Resources( new Resource('*', 'de', [ 'Hello World' => 'Hallo Welt', ]), ));
Filter Resources
You may use the filter methods returning a new instance.
filter
use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; use Tobento\Service\Translation\ResourceInterface; $resources = new Resources( new Resource( name: '*', locale: 'en', translations: ['Hello World' => 'Hallo Welt'], group: 'front', ), new Resource( name: '*', locale: 'en', translations: ['Hello World' => 'Hallo Welt'], group: 'back', ), ); // filter by group: $resources = $resources->filter( fn(ResourceInterface $r): bool => $r->group() === 'front' );
locale
use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; $resources = new Resources( new Resource( name: '*', locale: 'en', translations: ['Hello World' => 'Hallo Welt'], ), new Resource( name: '*', locale: 'de', translations: ['Hello World' => 'Hallo Welt'], ), ); // filter by locale: $resources = $resources->locale('en');
locales
use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; $resources = new Resources( new Resource( name: '*', locale: 'en', translations: ['Hello World' => 'Hallo Welt'], ), new Resource( name: '*', locale: 'de', translations: ['Hello World' => 'Hallo Welt'], ), ); // filter by locales: $resources = $resources->locales(['en', 'de']);
name
use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; $resources = new Resources( new Resource( name: 'shop', locale: 'en', translations: ['Hello World' => 'Hallo Welt'], ), new Resource( name: 'shop', locale: 'de', translations: ['Hello World' => 'Hallo Welt'], ), ); // filter by name: $resources = $resources->name('shop');
Sort Resources
sort by priority
use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; $resources = new Resources( new Resource( name: '*', locale: 'en', translations: ['Hello World' => 'Hallo Welt'], priority: 10, ), new Resource( name: '*', locale: 'en', translations: ['Hello World' => 'Hallo Welt'], priority: 15, ), ); // sort by priority: $resources = $resources->sort();
sort by callback
use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; use Tobento\Service\Translation\ResourceInterface; $resources = new Resources( new Resource( name: 'users', locale: 'en', translations: ['Hello World' => 'Hallo Welt'], priority: 10, ), new Resource( name: 'shop', locale: 'en', translations: ['Hello World' => 'Hallo Welt'], priority: 15, ), ); // sort by name: $resources = $resources->sort( fn(ResourceInterface $a, ResourceInterface $b): int => $a->name() <=> $b->name() );
Get Resources / Translations
all
use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; use Tobento\Service\Translation\ResourceInterface; $resources = new Resources( new Resource( name: '*', locale: 'en', translations: ['Hello World' => 'Hallo Welt'], ), ); foreach($resources->all() as $resource) { var_dump($resource instanceof ResourceInterface); // bool(true) var_dump($resource->name()); // string(1) "*" var_dump($resource->locale()); // string(2) "en" var_dump($resource->group()); // string(7) "default" var_dump($resource->priority()); // int(0) var_dump($resource->translations()); // array(1) { ["Hello World"]=> string(10) "Hallo Welt" } }
translations
use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; $resources = new Resources( new Resource( name: '*', locale: 'en', translations: ['Hello World' => 'Hallo Welt'], priority: 10, ), ); $translations = $resources->locale('en')->translations(); /*Array ( [Hello World] => Hallo Welt )*/
⚠️ You must call locale() or locales() before all() or translations() method if you have added (sub or lazy) resources, otherwise they will not get created.
foreach($resources->locale('en')->all() as $resource) { var_dump($resource instanceof ResourceInterface); // bool(true) }
Files Resources
Create Files Resources
use Tobento\Service\Translation\FilesResources; use Tobento\Service\Dir\Dirs; use Tobento\Service\Translation\ResourcesInterface; $resources = new FilesResources( new Dirs()->dir(dir: 'private/trans/', group: 'front', priority: 10) ); var_dump($resources instanceof ResourcesInterface); // bool(true)
Directory Structure
Files starting with the locale are stored as * resource name. They are all fetched and merged together on the first translations request.
Files not starting with the locale are only loaded on the first resource request. Furthermore, files named like routes.shop.json and routes.blog.json are merged together as resource name routes.
private/
trans/
en/
en.php
en.json
en-shop.json
shop.json
routes.shop.json
routes.blog.json
de-CH/
de-CH.json
de-CH-shop.json
shop.json
routes.shop.json
Supported Files
Currently supported files are json and php.
json
{
"Using Real Message": "Using Real Message",
"usingKeywordMessage": "Using Keyword Message"
}
php
return [ 'Using Real Message' => 'Using Real Message', 'usingKeywordMessage' => 'Using Keyword Message', ];
Supporting Other Files
You may support others files by providing your own resource factory:
use Tobento\Service\Translation\FilesResources; use Tobento\Service\Dir\Dirs; use Tobento\Service\Translation\ResourceFactory; use Tobento\Service\Translation\ResourceInterface; use Tobento\Service\Filesystem\File; class CustomResourceFactory extends ResourceFactory { /** * Create a new Resource from file. * * @param string|File $file * @param string $locale * @param string $group * @param int $priority * @return ResourceInterface */ public function createResourceFromFile( string|File $file, string $locale, string $group = 'default', int $priority = 0, ): ResourceInterface { // Create your custom resource for the specific file extension // Otherwise use parent return parent::createResourceFromFile($file, $locale, $group, $priority); } } $resources = new FilesResources( new Dirs()->dir(dir: 'private/trans/', group: 'front', priority: 10), new CustomResourceFactory() );
Modifiers
Create Modifiers
use Tobento\Service\Translation\Modifiers; use Tobento\Service\Translation\ModifiersInterface; use Tobento\Service\Translation\Modifier\ParameterReplacer; $modifiers = new Modifiers( new ParameterReplacer(), ); var_dump($modifiers instanceof ModifiersInterface); // bool(true)
Add Modifier
use Tobento\Service\Translation\Modifiers; use Tobento\Service\Translation\Modifier\ParameterReplacer; $modifiers = new Modifiers(); $modifiers->add(new ParameterReplacer());
Get all modifiers
use Tobento\Service\Translation\Modifiers; use Tobento\Service\Translation\Modifier\ParameterReplacer; use Tobento\Service\Translation\ModifierInterface; $modifiers = new Modifiers(new ParameterReplacer()); $allModifiers = $modifiers->all(); // array<int, ModifierInterface>
Modify message
use Tobento\Service\Translation\Modifiers; use Tobento\Service\Translation\Modifier\ParameterReplacer; $modifiers = new Modifiers( new ParameterReplacer(), ); [$message, $parameters] = $modifiers->modify( message: 'Hi :name', parameters: [':name' => 'John'], ); var_dump($message); // string(7) "Hi John"
Pluralization
use Tobento\Service\Translation\Modifier\Pluralization; $modifier = new Pluralization(key: 'count'); [$message, $parameters] = $modifier->modify( message: 'There is one apple|There are many apples', parameters: ['count' => 5], ); var_dump($message); // string(21) "There are many apples" [$message, $parameters] = $modifier->modify( message: 'There is one apple|There are many apples', parameters: ['count' => 1], ); var_dump($message); // string(18) "There is one apple"
Parameter Replacer
use Tobento\Service\Translation\Modifier\ParameterReplacer; $modifier = new ParameterReplacer(); [$message, $parameters] = $modifier->modify( message: 'Hi :name', parameters: [':name' => 'John'], ); var_dump($message); // string(7) "Hi John"
Missing Translation Handler
You may add a logger to log missing messages:
use Tobento\Service\Translation\Translator; use Tobento\Service\Translation\Resources; use Tobento\Service\Translation\Resource; use Tobento\Service\Translation\Modifiers; use Tobento\Service\Translation\MissingTranslationHandler; use Psr\Log\LoggerInterface; use Monolog\Logger; use Monolog\Handler\StreamHandler; $logger = new Logger('name'); $logger->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING)); $translator = new Translator( new Resources( new Resource('*', 'de', [ 'Hello World' => 'Hallo Welt', ]), ), new Modifiers(), new MissingTranslationHandler($logger), // any PSR-3 logger ); var_dump($translator->trans('Hello World'));
Credits
tobento/service-translation 适用场景与选型建议
tobento/service-translation 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 215 次下载、GitHub Stars 达 0, 最近一次更新时间为 2021 年 11 月 14 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「package」 「translations」 「tobento」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 tobento/service-translation 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 tobento/service-translation 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 tobento/service-translation 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Deepl Automated translations for Laravel lang files
Simple ASCII output of array data
Adds support for dynamic translations from Google Spreadsheets.
A Laravel package for multilingual models
TranslationBundle bundle
统计信息
- 总下载量: 215
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 20
- 依赖项目数: 7
- 推荐数: 2
其他信息
- 授权协议: MIT
- 更新时间: 2021-11-14