{"id":20523085,"url":"https://github.com/itstructure/laravel-multilingual-tools","last_synced_at":"2026-02-16T00:02:01.470Z","repository":{"id":56994583,"uuid":"292365760","full_name":"itstructure/laravel-multilingual-tools","owner":"itstructure","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-02T00:47:28.000Z","size":84,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-08T12:57:56.750Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/itstructure.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-02T18:39:50.000Z","updated_at":"2025-03-02T00:47:25.000Z","dependencies_parsed_at":"2025-01-16T10:54:51.343Z","dependency_job_id":null,"html_url":"https://github.com/itstructure/laravel-multilingual-tools","commit_stats":{"total_commits":8,"total_committers":1,"mean_commits":8.0,"dds":0.0,"last_synced_commit":"7a5011d8868349717360f178ed1022796e21ade0"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/itstructure/laravel-multilingual-tools","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itstructure%2Flaravel-multilingual-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itstructure%2Flaravel-multilingual-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itstructure%2Flaravel-multilingual-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itstructure%2Flaravel-multilingual-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/itstructure","download_url":"https://codeload.github.com/itstructure/laravel-multilingual-tools/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itstructure%2Flaravel-multilingual-tools/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29494198,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-16T00:00:57.352Z","status":"ssl_error","status_checked_at":"2026-02-15T23:56:34.338Z","response_time":118,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-15T22:37:55.134Z","updated_at":"2026-02-16T00:02:01.453Z","avatar_url":"https://github.com/itstructure.png","language":"PHP","readme":"# MULT\n## Laravel multilingual tools\n\n[![Latest Stable Version](https://poser.pugx.org/itstructure/laravel-multilingual-tools/v/stable)](https://packagist.org/packages/itstructure/laravel-multilingual-tools)\n[![Latest Unstable Version](https://poser.pugx.org/itstructure/laravel-multilingual-tools/v/unstable)](https://packagist.org/packages/itstructure/laravel-multilingual-tools)\n[![License](https://poser.pugx.org/itstructure/laravel-multilingual-tools/license)](https://packagist.org/packages/itstructure/laravel-multilingual-tools)\n[![Total Downloads](https://poser.pugx.org/itstructure/laravel-multilingual-tools/downloads)](https://packagist.org/packages/itstructure/laravel-multilingual-tools)\n[![Build Status](https://scrutinizer-ci.com/g/itstructure/laravel-multilingual-tools/badges/build.png?b=master)](https://scrutinizer-ci.com/g/itstructure/laravel-multilingual-tools/build-status/master)\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/itstructure/laravel-multilingual-tools/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/itstructure/laravel-multilingual-tools/?branch=master)\n\n![MULT package label](https://github.com/itstructure/laravel-multilingual-tools/blob/master/mult.png)\n\n## 1 Introduction\n\n**MULT** - Package for the Laravel framework to content manage with different languages.\n\nFor example, you can store pages in English, Russian, French, German and some another languages...\n\nIt is you who add new languages to your application.\n\nAll multilingual fields will be with a language postfix, as in example:\n\n`title_en`, `description_en`, `content_en`\n\n`title_ru`, `description_ru`, `content_ru`, e t. c.\n\n## 2 Dependencies\n\n- laravel 8+ | 9+ | 10+ | 11+ | 12+\n- php \u003e= 7.3\n- composer\n\n## 3 Installation\n\n**Note!**\n\nVersion **2.x** is for laravel **8**, **9**, **10**, **11**, **12**.\n\nVersion **1.x** is for laravel **7**. You can use branch `laravel7-mult` with **1.x** versions.\n\n### 3.1 General installation from remote repository\n\nRun the composer command:\n\n`composer require itstructure/laravel-multilingual-tools \"~2.0.6\"`\n\n### 3.2 If you are testing this package from local server directory\n\nIn application `composer.json` file set the repository, as in example:\n\n```json\n\"repositories\": [\n    {\n        \"type\": \"path\",\n        \"url\": \"../laravel-multilingual-tools\"\n    }\n],\n```\n\nHere,\n\n**../laravel-multilingual-tools** - directory name, which has the same directory level as your project application and contains MULT package.\n\nThen run command:\n\n`composer require itstructure/laravel-multilingual-tools:dev-master --prefer-source`\n\n### 3.3 Next internal installation steps\n\n1. Publish files.\n        \n    - To publish migrations run command:\n            \n        `php artisan mult:publish --only=migrations`\n        \n        It stores migration file to `database/migrations` folder. There is a migration to create **languages** table.\n        \n    - To publish seeder run command:\n            \n        `php artisan mult:publish --only=seeders`\n        \n        It stores seeder files to `database/seeders` folder. There is a seeder to create a first **English** language DB entry as a default.\n        \n    - To publish all parts run command without `only` argument:\n    \n        `php artisan mult:publish`\n        \n    Else you can use `--force` argument to rewrite already published files.\n    \n2. Run command to run migration and seed:\n\n    `php artisan mult:database`\n    \n    The next will be acted:\n    \n    - A table **languages** will be created.\n    \n    - A first **English** language will be stored as a default.\n    \n    Or optional:\n    \n    To run just migration `php artisan mult:database --only=migrate`\n    \n    To run just seed `php artisan mult:database --only=seed`\n    \n    - Alternative variant for seeders.\n    \n        You can set published `MultSeeder` seeder class in to a special `DatabaseSeeder`:\n            \n        ```php\n        use Illuminate\\Database\\Seeder;\n        ```\n        \n        ```php\n        class DatabaseSeeder extends Seeder\n        {\n            public function run()\n            {\n                $this-\u003ecall(MultSeeder::class);\n            }\n        }\n        ```\n        \n        and run command: `php artisan db:seed`.\n\n## 4 Usage\n\n**Notes**:\n\n- There are no controllers, views, routes and another CRUD elements to manage languages. There is just a model `Language`. This CRUD you must to create by yourself in your application.\n\n- There are no controllers, models, views, routes and another CRUD elements to manage entity content. There are just base classes, which are written below. CRUDs you must to create by yourself in your application.\n\n### 4.1 Migration part\n\nFirst, before a develop multilingual application, make migrations with extending from `MultilingualMigration` base class.\n\nExample for **pages** table:\n\n```php\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Itstructure\\Mult\\Classes\\MultilingualMigration;\n```\n\n```php\nclass CreatePagesTable extends MultilingualMigration\n{\n    public function up()\n    {\n        $this-\u003ecreateMultilingualTable('pages', function (Blueprint $table) {\n            $table-\u003estring('title', 64);\n            $table-\u003etext('description')-\u003enullable();\n            \n        }, function (Blueprint $table) {\n            $table-\u003eunsignedTinyInteger('active')-\u003edefault(0)-\u003eindex();\n            $table-\u003estring('alias', 64)-\u003eindex();\n        });\n    }\n    \n    public function down()\n    {\n        $this-\u003edropMultilingualTable('pages');\n    }\n}\n```\n\nHere,\n\n**createMultilingualTable()** method provides:\n\n1. First argument: table name.\n\n2. Second argument: a callable with multilingual fields.\n\n3. Third argument: a callable with simple fields.\n\nAfter applying a migration, two tables will be created automatically:\n\n- **pages** - to store a simple data.\n\n- **pages_languages** - to store translates, some entries for concrete **pages** entry.\n\n**Note:** Timestamps created automatically for both tables.\n\nAnd the next special columns for **pages_languages** table with foreign keys will be created automatically:\n\n- column **pages_id**. Foreign key to **pages** table `pages_languages(pages_id) -\u003e pages(id)`\n\n- column **languages_id**. Foreign key to **languages** table `pages_languages(languages_id) -\u003e languages(id)`\n\nExample with already stored data:\n\n`Main table \"pages\"`\n\n    | id | active |    alias    |      created_at     |      updated_at     |\n    |----|--------|-------------|---------------------|---------------------|\n    | 1  |    1   | first-page  | 2020-01-14 18:06:33 | 2020-01-14 18:06:33 |\n    | 2  |    1   | second-page | 2020-01-14 18:10:00 | 2020-01-14 18:10:00 |\n    | 3  |    0   | third-page  | 2020-01-14 19:05:15 | 2020-01-14 19:05:15 |\n    \n`Translate table \"pages_languages\"`\n\n    | pages_id | languages_id |    title   |      description     |      created_at     |      updated_at     |\n    |----------|--------------|------------|----------------------|---------------------|---------------------|\n    |    1     |      1       | Page 1     |     Description 1    | 2020-01-14 18:06:33 | 2020-01-14 18:06:33 |\n    |    1     |      2       | Страница 1 |     Описание 1       | 2020-01-14 18:06:33 | 2020-01-14 18:06:33 |\n    |    2     |      1       | Page 2     |     Description 2    | 2020-01-14 18:10:00 | 2020-01-14 18:10:00 |\n    |    3     |      1       | Page 3     |     Description 3    | 2020-01-14 19:05:15 | 2020-01-14 19:05:15 |\n    |    3     |      2       | Страница 3 |     Описание 3       | 2020-01-14 19:05:15 | 2020-01-14 19:05:15 |\n    \n`Language table \"languages\"`\n\n    | id | locale | short_name |  name   | default |      created_at     |      updated_at     |\n    |----|--------|------------|---------|---------|---------------------|---------------------|\n    | 1  | en-US  |     en     | English |    1    | 2020-01-14 18:06:33 | 2020-01-14 18:06:33 |\n    | 2  | ru-RU  |     ru     | Русский |    0    | 2020-01-14 18:10:00 | 2020-01-14 18:10:00 |\n\n### 4.2 Model part\n\n**Notes:**\n\n- Access to multilingual value from a model entry is by using a language postfix. Example:\n\n    ```php\n    $model = Page::findOrFail($id);\n    echo $model-\u003etitle_en;\n    ```\n\n- Set a new multilingual value for a model is by using a language postfix. Example:\n\n    ```php\n    $model = Page::findOrFail($id);\n    $model-\u003etitle_en = 'New title value';\n    $model-\u003esave();\n    ```\n\n#### 4.2.1 Main simple model\n\nCreate a main model for base table and use `MultilingualModelTrait`.\n\nExample model for **pages** table:\n\n```php\nnamespace App\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Itstructure\\Mult\\Traits\\MultilingualModelTrait;\n```\n\n```php\nclass Page extends Model\n{\n    use MultilingualModelTrait;\n    \n    protected $table = 'pages';\n    \n    protected $fillable = ['active', 'alias'];\n}\n```\n\n#### 4.2.2 Translate model\n\nCreate a model for translates table.\n\nExample model for **pages_languages** table:\n\n```php\nnamespace App\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n```\n\n```php\nclass PageLanguage extends Model\n{\n    protected $table = 'pages_languages';\n    \n    protected $fillable = ['pages_id', 'languages_id', 'title', 'description'];\n    \n    public function page() // It is not necessary to create\n    {\n        return $this-\u003ehasOne(Page::class, 'id', 'pages_id');\n    }\n    \n    public function language() // It is not necessary to create\n    {\n        return $this-\u003ehasOne(Language::class, 'id', 'languages_id');\n    }\n}\n```\n\nIt is not necessary to create relation methods here, such as: `page()`, `language()`. It is additional.\n\n### 4.3 Validation requests part\n\nThis request classes can be useful in controller's methods.\n\n```php\nnamespace App\\Http\\Requests;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\nuse Itstructure\\Mult\\Models\\Language;\nuse Itstructure\\Mult\\Helpers\\MultilingualHelper;\n```\n\n```php\nclass StorePageRequest extends FormRequest\n{\n    protected $shortLanguageList = [];\n    \n    public function __construct()\n    {\n        parent::__construct();\n        \n        $this-\u003eshortLanguageList = Language::shortLanguageList();\n    }\n    \n    public function authorize()\n    {\n        return true;\n    }\n    \n    public function rules()\n    {\n        $multilingualRules = MultilingualHelper::fieldsTransformer([\n            'title' =\u003e 'required|string|min:3|max:64',\n            'description' =\u003e 'nullable|string'\n            \n        ], function ($fieldValue) {\n            return $fieldValue;\n            \n        }, $this-\u003eshortLanguageList);\n        \n        return array_merge([\n            'active' =\u003e 'required|numeric',\n            'alias' =\u003e 'required|string|min:3|max:64'\n            \n        ], $multilingualRules);\n    }\n    \n    public function attributes()\n    {\n        $multilingualAttributes = MultilingualHelper::fieldsTransformer([\n            'title' =\u003e __('messages.title'),\n            'description' =\u003e __('messages.description')\n            \n        ], function ($fieldValue) {\n            return $fieldValue;\n            \n        }, $this-\u003eshortLanguageList);\n        \n        return array_merge([\n            'active' =\u003e __('messages.activity'),\n            'alias' =\u003e __('messages.alias')\n            \n        ], $multilingualAttributes);\n    }\n}\n```\n\nHere `roles()` method makes the next result:\n\n```php\n[\n    \"active\" =\u003e \"required|numeric\",\n    \"alias\" =\u003e \"required|string|min:3|max:64\",\n    \"title_en\" =\u003e \"required|string|min:3|max:64\",\n    \"title_ru\" =\u003e \"required|string|min:3|max:64\",\n    \"description_en\" =\u003e \"nullable|string\",\n    \"description_ru\" =\u003e \"nullable|string\"\n]\n```\n\n### 4.4 Controller part\n\nShort page controller example just to create entry:\n\n```php\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\Foundation\\Auth\\Access\\AuthorizesRequests;\nuse Illuminate\\Foundation\\Bus\\DispatchesJobs;\nuse Illuminate\\Foundation\\Validation\\ValidatesRequests;\nuse Illuminate\\Routing\\Controller;\nuse Itstructure\\Mult\\Models\\Language;\nuse Itstructure\\Mult\\Helpers\\MultilingualHelper;\nuse App\\Models\\Page;\nuse App\\Http\\Requests\\StorePageRequest;\n```\n\n```php\nclass PageController extends Controller\n{\n    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;\n    \n    public function create()\n    {\n        $languageList = Language::languageList();\n        \n        return view('page.create', compact('languageList'));\n    }\n    \n    public function store(StorePageRequest $request)\n    {\n        MultilingualHelper::fill(new Page(), $request-\u003eall())-\u003esave();\n        \n        return redirect()-\u003eroute('page_list');\n    }\n}\n```\n\n### 4.5 View template part\n\nShort example for `page.create` blade view template:\n\n```blade\n\u003cform action=\"{{ route('page_store') }}\" method=\"post\"\u003e\n    \u003cul class=\"nav nav-tabs\"\u003e\n        @foreach($languageList as $langModel)\n            \u003cli class=\"nav-item\"\u003e\n                \u003ca class=\"nav-link @if($langModel-\u003edefault == 1)active @endif\" data-toggle=\"tab\" href=\"#lang_{{ $langModel-\u003eshort_name }}\"\u003e\n                    {{ $langModel-\u003ename }}\n                \u003c/a\u003e\n            \u003c/li\u003e\n        @endforeach\n    \u003c/ul\u003e\n    \u003cdiv class=\"tab-content my-2\"\u003e\n        @foreach($languageList as $langModel)\n            \u003cdiv class=\"tab-pane fade @if($langModel-\u003edefault == 1)show active @endif\" id=\"lang_{{ $langModel-\u003eshort_name }}\"\u003e\n                \u003cdiv class=\"row\"\u003e\n                    \u003cdiv class=\"col-12 col-sm-10 col-md-8 col-lg-6 col-xl-4\"\u003e\n                        \u003cdiv class=\"form-group\"\u003e\n                            \u003clabel for=\"page_title_{{ $langModel-\u003eshort_name }}\"\u003e{!! __('messages.title') !!}\u003c/label\u003e\n                            \u003cinput id=\"page_title_{{ $langModel-\u003eshort_name }}\"\n                                   type=\"text\"\n                                   class=\"form-control @if ($errors-\u003ehas('title_'.$langModel-\u003eshort_name)) is-invalid @endif\"\n                                   name=\"title_{{ $langModel-\u003eshort_name }}\"\n                                   value=\"{{ old('title_'.$langModel-\u003eshort_name, !empty($model) ? $model-\u003e{'title_'.$langModel-\u003eshort_name} : null) }}\"\u003e\n                            @if ($errors-\u003ehas('title_'.$langModel-\u003eshort_name))\n                                \u003cdiv class=\"invalid-feedback\"\u003e\n                                    \u003cstrong\u003e{{ $errors-\u003efirst('title_'.$langModel-\u003eshort_name) }}\u003c/strong\u003e\n                                \u003c/div\u003e\n                            @endif\n                        \u003c/div\u003e\n                    \u003c/div\u003e\n                \u003c/div\u003e\n                \u003cdiv class=\"row\"\u003e\n                    \u003cdiv class=\"col-12 col-sm-10 col-md-8 col-lg-6 col-xl-4\"\u003e\n                        \u003cdiv class=\"form-group\"\u003e\n                            \u003clabel for=\"page_description_{{ $langModel-\u003eshort_name }}\"\u003e{!! __('messages.description') !!}\u003c/label\u003e\n                            \u003cinput id=\"page_description_{{ $langModel-\u003eshort_name }}\"\n                                   type=\"text\"\n                                   class=\"form-control @if ($errors-\u003ehas('description_'.$langModel-\u003eshort_name)) is-invalid @endif\"\n                                   name=\"description_{{ $langModel-\u003eshort_name }}\"\n                                   value=\"{{ old('description_'.$langModel-\u003eshort_name, !empty($model) ? $model-\u003e{'description_'.$langModel-\u003eshort_name} : null) }}\"\u003e\n                            @if ($errors-\u003ehas('description_'.$langModel-\u003eshort_name))\n                                \u003cdiv class=\"invalid-feedback\"\u003e\n                                    \u003cstrong\u003e{{ $errors-\u003efirst('description_'.$langModel-\u003eshort_name) }}\u003c/strong\u003e\n                                \u003c/div\u003e\n                            @endif\n                        \u003c/div\u003e\n                    \u003c/div\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        @endforeach\n    \u003c/div\u003e\n    \n    \u003cdiv class=\"row mb-3\"\u003e\n        \u003cdiv class=\"col-12 col-sm-10 col-md-8 col-lg-6 col-xl-4\"\u003e\n            \u003cdiv class=\"custom-control custom-radio custom-control-inline\"\u003e\n                \u003cinput type=\"radio\" id=\"page_active_input\" name=\"active\" value=\"1\" class=\"custom-control-input\" \n                    @if(old('active', !empty($model) ? $model-\u003eactive : 1) == 1) checked @endif \u003e\n                \u003clabel class=\"custom-control-label\" for=\"page_active_input\"\u003e{!! __('messages.active') !!}\u003c/label\u003e\n            \u003c/div\u003e\n            \u003cdiv class=\"custom-control custom-radio custom-control-inline\"\u003e\n                \u003cinput type=\"radio\" id=\"page_inactive_input\" name=\"active\" value=\"0\" class=\"custom-control-input\" \n                    @if(old('active', !empty($model) ? $model-\u003eactive : 1) == 0) checked @endif \u003e\n                \u003clabel class=\"custom-control-label\" for=\"page_inactive_input\"\u003e{!! __('messages.inactive') !!}\u003c/label\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cbutton class=\"btn btn-primary\" type=\"submit\"\u003eCreate\u003c/button\u003e\n    \u003cinput type=\"hidden\" value=\"{!! csrf_token() !!}\" name=\"_token\"\u003e\n\u003c/form\u003e\n```\n\n## License\n\nCopyright © 2020-2025 Andrey Girnik girnikandrey@gmail.com.\n\nLicensed under the [MIT license](http://opensource.org/licenses/MIT). See LICENSE.txt for details.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitstructure%2Flaravel-multilingual-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fitstructure%2Flaravel-multilingual-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitstructure%2Flaravel-multilingual-tools/lists"}