crystoline/translation

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

v2.0.1 2018-12-02 13:02 UTC

README

Travis CI Scrutinizer Code Quality Latest Stable Version Total Downloads License

描述

Translation 是一个面向开发者的、数据库驱动的、自动翻译器,适用于 Laravel 5.*。难道不好吗?你只需在应用中常规地编写文本,它就会自动翻译、添加到数据库并在运行时进行缓存?以这个为例

控制器

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

视图

@extends('layout.default')

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

查看

Welcome to our home page

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

现在,如果我们设置区域为不同的内容,例如法语(fr),它将自动为你翻译。

控制器

public function index()
{
    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 stevebauman/translation

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

'Crystoline\Translation\TranslationServiceProvider',

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

'Translation' => 'Crystoline\Translation\Facades\Translation',

发布迁移

php artisan vendor:publish --provider="Crystoline\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 Crystoline\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()
    {
        $title = $this->translation->translate('My Blog');
        
        $entries = Blog::all();
        
        return view('pages.blog.index', compact('title', 'entries'));
    }
}

模型

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

区域模型

<?php    
    use Crystoline\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 Crystoline\Translation\Traits\TranslationTrait;
    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' => \Crystoline\Translation\Middleware\LocaleMiddleware::class
];

现在,在您的 app/Http/routes.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。使用自动翻译会将插入的文本发送到谷歌,并将返回的文本保存到数据库中。一旦翻译被保存到数据库中,它就不会再次发送到谷歌以获取重新翻译。这意味着您无需担心谷歌可能强加的限制。您实际上拥有该翻译。

问题 / 关注点

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

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

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

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

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

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

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

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

如果您修改翻译函数内的文本,它将创建一个新的记录,并且您需要重新翻译它。这是预期的,因为修改后的翻译可能完全不同。

例如使用

{{ _t('Welcome!') }}

并将其修改为

{{ _t('Welcome') }}

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

是否有自动翻译的最大文本量限制?

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

是的,根据 Google Translate PHP,每个请求有一个1300个单词的限制。只需确保将内容拆分,以免超过限制。

问题

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

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

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