itstructure/laravel-multilingual-tools

Laravel 多语言内容管理包

2.0.5 2024-03-31 13:19 UTC

This package is auto-updated.

Last update: 2024-08-31 00:26:42 UTC


README

Laravel 多语言工具

Latest Stable Version Latest Unstable Version License Total Downloads Build Status Scrutinizer Code Quality

MULT package label

1 简介

MULT - Laravel 框架的多语言内容管理包。

例如,您可以存储英语、俄语、法语、德语和其他一些语言中的页面...

您需要为您的应用程序添加新的语言。

所有多语言字段都将带有语言后缀,例如

title_endescription_encontent_en

title_rudescription_rucontent_ru 等。

2 依赖项

  • laravel 8+ | 9+ | 10+ | 11+
  • php >= 7.3
  • composer

3 安装

注意!

版本 2.x 是针对 laravel 891011

版本 1.x 是针对 laravel 7。您可以使用 1.x 版本的分支 laravel7-mult

3.1 从远程仓库进行常规安装

运行 composer 命令

composer require itstructure/laravel-multilingual-tools "~2.0.5"

3.2 如果您正在从本地服务器目录测试此包

在应用程序 composer.json 文件中设置仓库,如下所示

"repositories": [
    {
        "type": "path",
        "url": "../laravel-multilingual-tools"
    }
],

这里,

../laravel-multilingual-tools - 目录名称,与项目应用程序处于相同目录级别,并包含 MULT 包。

然后运行命令

composer require itstructure/laravel-multilingual-tools:dev-master --prefer-source

3.3 接下来的内部安装步骤

  1. 发布文件。

    • 要发布迁移,运行命令

      php artisan mult:publish --only=migrations

      它将迁移文件存储到 database/migrations 文件夹。有一个迁移来创建 languages 表。

    • 要发布种子,运行命令

      php artisan mult:publish --only=seeders

      它将种子文件存储到 database/seeders 文件夹。有一个种子来创建默认的 English 语言数据库条目。

    • 要发布所有部分,运行不带 only 参数的命令

      php artisan mult:publish

    否则,您可以使用 --force 参数重写已发布的文件。

  2. 运行命令以运行迁移和种子

    php artisan mult:database

    以下操作将执行

    • 将创建一个名为 languages 的表。

    • 将存储默认的 English 语言。

    或可选

    仅运行迁移:`php artisan mult:database --only=migrate`

    仅运行种子:`php artisan mult:database --only=seed`

    • 种子器的替代方案。

      您可以将发布的 MultSeeder 种子类设置到特殊的 DatabaseSeeder

      use Illuminate\Database\Seeder;
      class DatabaseSeeder extends Seeder
      {
          public function run()
          {
              $this->call(MultSeeder::class);
          }
      }

      并运行命令:`php artisan db:seed`。

4 使用方法

注意:

  • 没有控制器、视图、路由和其他 CRUD 元素来管理语言。只有一个 Language 模型。您必须自己创建应用程序中的 CRUD。

  • 没有控制器、模型、视图、路由和其他 CRUD 元素来管理实体内容。只有以下基础类。您必须自己创建应用程序中的 CRUD。

4.1 迁移部分

首先,在开发多语言应用程序之前,使用扩展自 MultilingualMigration 基础类的迁移。

对于 pages 表的示例

use Illuminate\Database\Schema\Blueprint;
use Itstructure\Mult\Classes\MultilingualMigration;
class CreatePagesTable extends MultilingualMigration
{
    public function up()
    {
        $this->createMultilingualTable('pages', function (Blueprint $table) {
            $table->string('title', 64);
            $table->text('description')->nullable();
            
        }, function (Blueprint $table) {
            $table->unsignedTinyInteger('active')->default(0)->index();
            $table->string('alias', 64)->index();
        });
    }
    
    public function down()
    {
        $this->dropMultilingualTable('pages');
    }
}

这里,

createMultilingualTable() 方法提供以下内容

  1. 第一个参数:表名。

  2. 第二个参数:一个包含多语言字段的调用。

  3. 第三个参数:一个包含简单字段的调用。

应用迁移后,将自动创建两个表

  • pages - 存储简单数据。

  • pages_languages - 用于存储翻译,为具体的 pages 条目存储一些条目。

注意: 自动为两个表创建时间戳。

接下来将为 pages_languages 表创建自动的特殊列

  • pages_id。外键指向 pagespages_languages(pages_id) -> pages(id)

  • languages_id。外键指向 languagespages_languages(languages_id) -> languages(id)

已有存储数据的示例

主表 "pages"

| id | active |    alias    |      created_at     |      updated_at     |
|----|--------|-------------|---------------------|---------------------|
| 1  |    1   | first-page  | 2020-01-14 18:06:33 | 2020-01-14 18:06:33 |
| 2  |    1   | second-page | 2020-01-14 18:10:00 | 2020-01-14 18:10:00 |
| 3  |    0   | third-page  | 2020-01-14 19:05:15 | 2020-01-14 19:05:15 |

翻译表 "pages_languages"

| pages_id | languages_id |    title   |      description     |      created_at     |      updated_at     |
|----------|--------------|------------|----------------------|---------------------|---------------------|
|    1     |      1       | Page 1     |     Description 1    | 2020-01-14 18:06:33 | 2020-01-14 18:06:33 |
|    1     |      2       | Страница 1 |     Описание 1       | 2020-01-14 18:06:33 | 2020-01-14 18:06:33 |
|    2     |      1       | Page 2     |     Description 2    | 2020-01-14 18:10:00 | 2020-01-14 18:10:00 |
|    3     |      1       | Page 3     |     Description 3    | 2020-01-14 19:05:15 | 2020-01-14 19:05:15 |
|    3     |      2       | Страница 3 |     Описание 3       | 2020-01-14 19:05:15 | 2020-01-14 19:05:15 |

语言表 "languages"

| id | locale | short_name |  name   | default |      created_at     |      updated_at     |
|----|--------|------------|---------|---------|---------------------|---------------------|
| 1  | en-US  |     en     | English |    1    | 2020-01-14 18:06:33 | 2020-01-14 18:06:33 |
| 2  | ru-RU  |     ru     | Русский |    0    | 2020-01-14 18:10:00 | 2020-01-14 18:10:00 |

4.2 模型部分

注意

  • 通过使用语言后缀从模型条目访问多语言值。示例

    $model = Page::findOrFail($id);
    echo $model->title_en;
  • 通过使用语言后缀设置模型的新多语言值。示例

    $model = Page::findOrFail($id);
    $model->title_en = 'New title value';
    $model->save();

4.2.1 主要简单模型

为基表创建主模型并使用 MultilingualModelTrait

针对 pages 表的示例模型

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Itstructure\Mult\Traits\MultilingualModelTrait;
class Page extends Model
{
    use MultilingualModelTrait;
    
    protected $table = 'pages';
    
    protected $fillable = ['active', 'alias'];
}

4.2.2 翻译模型

为翻译表创建模型。

针对 pages_languages 表的示例模型

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
class PageLanguage extends Model
{
    protected $table = 'pages_languages';
    
    protected $fillable = ['pages_id', 'languages_id', 'title', 'description'];
    
    public function page() // It is not necessary to create
    {
        return $this->hasOne(Page::class, 'id', 'pages_id');
    }
    
    public function language() // It is not necessary to create
    {
        return $this->hasOne(Language::class, 'id', 'languages_id');
    }
}

在此处创建关系方法不是必需的,例如: page()language()。这是额外的。

4.3 验证请求部分

这些请求类在控制器的方法中可能很有用。

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Itstructure\Mult\Models\Language;
use Itstructure\Mult\Helpers\MultilingualHelper;
class StorePageRequest extends FormRequest
{
    protected $shortLanguageList = [];
    
    public function __construct()
    {
        parent::__construct();
        
        $this->shortLanguageList = Language::shortLanguageList();
    }
    
    public function authorize()
    {
        return true;
    }
    
    public function rules()
    {
        $multilingualRules = MultilingualHelper::fieldsTransformer([
            'title' => 'required|string|min:3|max:64',
            'description' => 'nullable|string'
            
        ], function ($fieldValue) {
            return $fieldValue;
            
        }, $this->shortLanguageList);
        
        return array_merge([
            'active' => 'required|numeric',
            'alias' => 'required|string|min:3|max:64'
            
        ], $multilingualRules);
    }
    
    public function attributes()
    {
        $multilingualAttributes = MultilingualHelper::fieldsTransformer([
            'title' => __('messages.title'),
            'description' => __('messages.description')
            
        ], function ($fieldValue) {
            return $fieldValue;
            
        }, $this->shortLanguageList);
        
        return array_merge([
            'active' => __('messages.activity'),
            'alias' => __('messages.alias')
            
        ], $multilingualAttributes);
    }
}

在这里 roles() 方法生成以下结果

[
    "active" => "required|numeric",
    "alias" => "required|string|min:3|max:64",
    "title_en" => "required|string|min:3|max:64",
    "title_ru" => "required|string|min:3|max:64",
    "description_en" => "nullable|string",
    "description_ru" => "nullable|string"
]

4.4 控制器部分

简短的页面控制器示例,仅用于创建条目

namespace App\Http\Controllers;

use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller;
use Itstructure\Mult\Models\Language;
use Itstructure\Mult\Helpers\MultilingualHelper;
use App\Models\Page;
use App\Http\Requests\StorePageRequest;
class PageController extends Controller
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
    
    public function create()
    {
        $languageList = Language::languageList();
        
        return view('page.create', compact('languageList'));
    }
    
    public function store(StorePageRequest $request)
    {
        MultilingualHelper::fill(new Page(), $request->all())->save();
        
        return redirect()->route('page_list');
    }
}

4.5 视图模板部分

针对 page.create blade 视图模板的简短示例

<form action="{{ route('page_store') }}" method="post">
    <ul class="nav nav-tabs">
        @foreach($languageList as $langModel)
            <li class="nav-item">
                <a class="nav-link @if($langModel->default == 1)active @endif" data-toggle="tab" href="#lang_{{ $langModel->short_name }}">
                    {{ $langModel->name }}
                </a>
            </li>
        @endforeach
    </ul>
    <div class="tab-content my-2">
        @foreach($languageList as $langModel)
            <div class="tab-pane fade @if($langModel->default == 1)show active @endif" id="lang_{{ $langModel->short_name }}">
                <div class="row">
                    <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-4">
                        <div class="form-group">
                            <label for="page_title_{{ $langModel->short_name }}">{!! __('messages.title') !!}</label>
                            <input id="page_title_{{ $langModel->short_name }}"
                                   type="text"
                                   class="form-control @if ($errors->has('title_'.$langModel->short_name)) is-invalid @endif"
                                   name="title_{{ $langModel->short_name }}"
                                   value="{{ old('title_'.$langModel->short_name, !empty($model) ? $model->{'title_'.$langModel->short_name} : null) }}">
                            @if ($errors->has('title_'.$langModel->short_name))
                                <div class="invalid-feedback">
                                    <strong>{{ $errors->first('title_'.$langModel->short_name) }}</strong>
                                </div>
                            @endif
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-4">
                        <div class="form-group">
                            <label for="page_description_{{ $langModel->short_name }}">{!! __('messages.description') !!}</label>
                            <input id="page_description_{{ $langModel->short_name }}"
                                   type="text"
                                   class="form-control @if ($errors->has('description_'.$langModel->short_name)) is-invalid @endif"
                                   name="description_{{ $langModel->short_name }}"
                                   value="{{ old('description_'.$langModel->short_name, !empty($model) ? $model->{'description_'.$langModel->short_name} : null) }}">
                            @if ($errors->has('description_'.$langModel->short_name))
                                <div class="invalid-feedback">
                                    <strong>{{ $errors->first('description_'.$langModel->short_name) }}</strong>
                                </div>
                            @endif
                        </div>
                    </div>
                </div>
            </div>
        @endforeach
    </div>
    
    <div class="row mb-3">
        <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-4">
            <div class="custom-control custom-radio custom-control-inline">
                <input type="radio" id="page_active_input" name="active" value="1" class="custom-control-input" 
                    @if(old('active', !empty($model) ? $model->active : 1) == 1) checked @endif >
                <label class="custom-control-label" for="page_active_input">{!! __('messages.active') !!}</label>
            </div>
            <div class="custom-control custom-radio custom-control-inline">
                <input type="radio" id="page_inactive_input" name="active" value="0" class="custom-control-input" 
                    @if(old('active', !empty($model) ? $model->active : 1) == 0) checked @endif >
                <label class="custom-control-label" for="page_inactive_input">{!! __('messages.inactive') !!}</label>
            </div>
        </div>
    </div>
    <button class="btn btn-primary" type="submit">Create</button>
    <input type="hidden" value="{!! csrf_token() !!}" name="_token">
</form>

许可

版权所有 © 2020-2024 Andrey Girnik girnikandrey@gmail.com

根据 MIT 许可协议 许可。有关详细信息,请参阅 LICENSE.txt。