ricardosierra/translation

Laravel 5.* 的简单自动数据库驱动翻译器

v3.2.0 2020-07-23 03:25 UTC

README

Travis CI Scrutinizer Code Quality Latest Stable Version Total Downloads License

描述

Translation 是一个针对 Laravel 5.* 的开发者友好、数据库驱动、自动翻译器。您是否希望在应用程序中常规地编写文本,然后自动将其翻译、添加到数据库并在运行时进行缓存呢?以下是一个示例:

控制器

public function index(Request $request)
{
    return view('home.index');
}

视图

@extends('layout.default')

{{ _t('Welcome to our home page') }}

已查看

Welcome to our home page

当您访问页面时,您可能不会注意到任何不同之处,但如果您查看您的数据库,您的默认应用程序区域设置已经创建,并且与该区域设置关联的翻译。

现在,如果我们设置区域设置为其他语言,比如法语(fr),它将自动为您翻译。

控制器

public function index(Request $request)
{
    Translation::setLocale('fr');
    
    return view('home.index');
}

视图

@extends('layout.default')

{{ _t('Welcome to our home page') }}

已查看

Bienvenue sur notre page d'accueil

我们甚至可以使用占位符来表示动态内容

视图

{{ _t('Welcome :name, to our home page', ['name' => 'John']) }}

已查看

Bienvenue John , à notre page d'accueil

请注意,我们没有真正更改视图中的文本,这意味着对于您(开发者)来说,所有内容在您所在的区域设置中都是完全可读的,这意味着不再需要管理大量的翻译文件并尝试解析那个点注释的翻译路径中的文本

{{ trans('page.home.index.welcome') }}

安装

需要翻译包

composer require ricardosierra/translation

将服务提供者添加到您的 config/app.php 配置文件中(Laravel 5.8 及以下版本)

Translation\TranslationServiceProvider::class,

将外观添加到您的 config/app.php 配置文件中的别名中(Laravel 5.8 及以下版本)

'Translation' => Translation\Facades\Translation::class,

发布迁移

php artisan vendor:publish --provider="Translation\TranslationServiceProvider"

运行迁移

php artisan migrate

您已经准备就绪!

用法

在应用程序的任何位置,您可以使用简写函数(可以在配置文件中禁用)

_t('Translate me!')

Translation::translate('Translate me!')

这在 blade 视图中通常非常有用

{{ _t('Translate me!') }}

您甚至可以通过插入您的文本轻松地翻译模型

{{ _t($post->title) }}

或使用占位符

{{ _t('Post :title', ['title' => $post->title]) }}

在您的 locales 数据库表中您将会有

| id | code |  name  | display_name | lang_code |
   1    en    English      NULL          NULL

在您的 translations 数据库表中您将会有

| id | locale_id | translation_id | translation |
  1        NULL         NULL        'Translate me!'

要切换用户会话的语言,只需调用

Translation::setLocale('fr') // Setting to French locale

当您调用 Translation::setLocale($code) 方法时,会自动创建区域设置,并且在调用翻译函数时,它将为新的区域设置自动创建一个新的翻译记录,并带有默认区域设置的翻译。默认区域设置来自 laravel 的 app.php 配置文件。

现在,一旦您访问页面,您将在 locales 表中看到以下内容

| id | code | name | display_name | lang_code |
   1    en    English     NULL         NULL
   2    fr    French      NULL         NULL

以及以下内容在您的 translations 表中

| id | locale_id | translation_id | translation |
   1        1         NULL        'Translate me!'
   2        2          1          'Traduisez-moi !'

现在您可以在新的记录上更新翻译,并且它将在需要的地方显示

_t('Translate me!')`
需要翻译单个文本而不设置用户默认区域设置怎么办?

只需将区域设置传递给上面翻译函数的第三个参数即可,如下所示

视图

{{ _t('Our website also supports russian!', [], 'ru') }}

<br>

{{ _t('And french!', [], 'fr') }}

已查看

Наш сайт также поддерживает России !

Et françaises !

这对于在不更改整个站点语言的情况下向用户展示您的网站支持不同语言非常有用。您还可以像通常那样执行替换

视图

{{ _t('Hello :name, we also support french!', ['name' => 'John Doe'], 'fr') }}

已查看

Bonjour John Doe , nous soutenons aussi le français !

执行此操作将在您的数据库中创建区域设置,保存翻译,并在需要时将其缓存。

您必须提供自己的更新翻译的方式(控制器/视图等)使用提供的 eloquent 模型。

注入翻译

v1.3.4 版本开始,您现在可以将 Translation 合同注入到您的控制器中,而不需要使用外观

<?php
    
use Translation\Contracts\Translation;
use App\Http\Controllers\Controller;
use App\Http\Blog;

class BlogController extends Controller
{
    /**
     * @var Translation
     */
    protected $translation;
    
    /**
     * Constructor.
     *
     * @param Translation $translation
     */
    public function __construct(Translation $translation)
    {
        $this->translation = $translation;
    }
    
    /**
     * Returns all blog entries.
     *
     * @return Illuminate\View\View
     */
    public function index(Request $request)
    {
        $title = $this->translation->translate('My Blog');
        
        $entries = Blog::all();
        
        return view('pages.blog.index', compact('title', 'entries'));
    }
}

模型

默认情况下,包括并选择两个模型在配置文件中。如果您想使用自己的模型,您必须创建它们并实现它们的特质。以下是一个示例

区域模型

<?php    
    use Translation\Traits\LocaleTrait;
    use Illuminate\Database\Eloquent\Model;
    
    class Locale extends Model
    {
        use LocaleTrait;
    
        /**
         * The locales table.
         *
         * @var string
         */
        protected $table = 'locales';
    
        /**
         * The fillable locale attributes.
         *
         * @var array
         */
        protected $fillable = [
            'code',
            'lang_code',
            'name',
            'display_name',
        ];
    
        /**
         * {@inheritdoc]
         */
        public function translations()
        {
            return $this->hasMany(Translation::class);
        }
    }

翻译模型

<?php
    use Translation\Observers\HasTranslations;
    use Illuminate\Database\Eloquent\Model;
    
    class Translation extends Model
    {
        use TranslationTrait;
    
        /**
         * The locale translations table.
         *
         * @var string
         */
        protected $table = 'translations';
    
        /**
         * The fillable locale translation attributes.
         *
         * @var array
         */
        protected $fillable = [
            'locale_id',
            'translation_id',
            'translation',
        ];
    
        /**
         * {@inheritdoc}
         */
        public function locale()
        {
            return $this->belongsTo(Locale::class);
        }
    
        /**
         * {@inheritdoc}
         */
        public function parent()
        {
            return $this->belongsTo(self::class);
        }
    }

创建这些模型后,将它们插入到 translation.php 配置文件中。

   <?php 
   [
   /*
   |--------------------------------------------------------------------------
   | Locale Model
   |--------------------------------------------------------------------------
   |
   |  The locale model is used for storing locales such as `en` or `fr`.
   |
   */

   'locale' => App\Models\Locale::class,


   /*
   |--------------------------------------------------------------------------
   | Translation Model
   |--------------------------------------------------------------------------
   |
   |  The translation model is used for storing translations.
   |
   */

   'translation' => App\Models\Translation::class,
   ];

路由

使用区域前缀翻译您的网站非常简单。首先在您的 app/Http/Kernel.php 文件中,插入区域中间件

<?php
 /**
 * The application's route middleware.
 *
 * @var array
 */
protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    
    // Insert Locale Middleware
    'locale' => \Translation\Middleware\LocaleMiddleware::class
];

现在,在您的 routes/web.php 文件中,按照如下方式在路由组前缀中插入中间件和以下翻译方法

     <?php
    Route::group(['prefix' => Translation::getRoutePrefix(), 'middleware' => ['locale']], function()
    {
        Route::get('home', function ()
        {
            return view('home');
        });
    });

现在您应该可以访问以下路由

https:///home
https:///en/home
https:///fr/home

新增功能

您还可以在HTTP请求中使用区域。特别是在API调用期间###示例

Header -> locale=fr
Cookies -> locale=it
QueryString -> locale=es

您还可以在Laravel中将区域信息设置为会话

    <?php 
    session("locale", 'fr');
## Automatic Translation

默认情况下,配置文件中已启用自动翻译。它使用由Stichoza提供的出色的Google Translate PHP软件包。使用自动翻译将插入的文本发送到Google,并将返回的文本保存到数据库中。一旦翻译保存在数据库中,就永远不会再次发送到Google进行重新翻译。这意味着您不必担心Google可能强加的限制。您实际上拥有那个翻译。

问题/关注点

为什么我的数据库翻译中占位符的地方有下划线?

当您在翻译中添加占位符并将数据添加以替换它时,例如

_t('Hi :name', ['name' => 'John'])

翻译将解析数据数组中的每个条目,以查看占位符是否实际存在于插入的数据中。例如,在数据库中的翻译字段中,保存的内容如下

_t('Hi :name', ['name' => 'John']) // Hi __name__

_t('Hi :name', ['test' => 'John']) // Hi :name

由于插入的占位符数据与字符串中的占位符不匹配,因此文本将保持不变。下划线的原因是,Google翻译将尝试翻译包含:name的文本,但是通过在占位符两侧提供双下划线,可以防止Google翻译那个特定的单词,允许我们翻译其他所有内容,同时保持占位符完整。然后,翻译在运行时替换占位符的双下划线变体(在这种情况下为__name__)。

如果我在翻译函数中更新/修改文本,会发生什么?

如果您修改翻译函数中的文本,它将创建一个新的记录,您需要再次进行翻译。这是故意的,因为修改后可能是一个完全不同的翻译。

例如使用

{{ _t('Welcome!') }}

并将其修改为

{{ _t('Welcome') }}

将自动生成一个新的翻译记录。

是否有可以自动翻译的文本的最大数量?

更新:此软件包现在使用Stichoza的新3.0更新。这允许您每次请求翻译最多4200个单词(已测试,可能允许更多)。

是的,根据Google Translate PHP,每个请求的单词限制为1300个。只需确保将您的内容分割开,以免超出限制。

问题

我试图在路由文件中设置区域,但它从不改变?

您是否偶然使用的是file会话驱动程序?这是Laravel 5文件会话驱动程序的一个已知问题laravel/framework#8244

暂时使用其他会话驱动程序,例如数组或数据库。