itstructure / laravel-multilingual-tools
Laravel 多语言内容管理包
Requires
- php: >=7.3.0
- laravel/framework: ^8.0|^9.0|^10.0|^11.0
README
Laravel 多语言工具
1 简介
MULT - Laravel 框架的多语言内容管理包。
例如,您可以存储英语、俄语、法语、德语和其他一些语言中的页面...
您需要为您的应用程序添加新的语言。
所有多语言字段都将带有语言后缀,例如
title_en
、description_en
、content_en
title_ru
、description_ru
、content_ru
等。
2 依赖项
- laravel 8+ | 9+ | 10+ | 11+
- php >= 7.3
- composer
3 安装
注意!
版本 2.x 是针对 laravel 8、9、10、11。
版本 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 接下来的内部安装步骤
-
发布文件。
-
要发布迁移,运行命令
php artisan mult:publish --only=migrations
它将迁移文件存储到
database/migrations
文件夹。有一个迁移来创建 languages 表。 -
要发布种子,运行命令
php artisan mult:publish --only=seeders
它将种子文件存储到
database/seeders
文件夹。有一个种子来创建默认的 English 语言数据库条目。 -
要发布所有部分,运行不带
only
参数的命令php artisan mult:publish
否则,您可以使用
--force
参数重写已发布的文件。 -
-
运行命令以运行迁移和种子
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() 方法提供以下内容
-
第一个参数:表名。
-
第二个参数:一个包含多语言字段的调用。
-
第三个参数:一个包含简单字段的调用。
应用迁移后,将自动创建两个表
-
pages - 存储简单数据。
-
pages_languages - 用于存储翻译,为具体的 pages 条目存储一些条目。
注意: 自动为两个表创建时间戳。
接下来将为 pages_languages 表创建自动的特殊列
-
列 pages_id。外键指向 pages 表
pages_languages(pages_id) -> pages(id)
-
列 languages_id。外键指向 languages 表
pages_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。