{"id":25600593,"url":"https://github.com/codezero-be/laravel-unique-translation","last_synced_at":"2025-10-07T16:39:18.020Z","repository":{"id":50576572,"uuid":"107321517","full_name":"codezero-be/laravel-unique-translation","owner":"codezero-be","description":"⭐️ Check if a translated value in a JSON column is unique in the database.","archived":false,"fork":false,"pushed_at":"2024-04-17T08:30:59.000Z","size":79,"stargazers_count":188,"open_issues_count":2,"forks_count":25,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-03T23:11:46.435Z","etag":null,"topics":["database","json","language","laravel","mysql","php","rule","translation","unique","validation","validator"],"latest_commit_sha":null,"homepage":"","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/codezero-be.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"ko_fi":"ivanvermeyen","custom":"https://paypal.me/ivanvermeyen"}},"created_at":"2017-10-17T20:42:08.000Z","updated_at":"2025-04-01T05:16:01.000Z","dependencies_parsed_at":"2024-04-17T09:39:06.017Z","dependency_job_id":"01aadbcd-42a8-4c5a-a48f-68dfdccfd9f1","html_url":"https://github.com/codezero-be/laravel-unique-translation","commit_stats":{"total_commits":97,"total_committers":6,"mean_commits":"16.166666666666668","dds":"0.061855670103092786","last_synced_commit":"eadaa83dbbcacb85522d36024b9f2aee5d617f1c"},"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codezero-be%2Flaravel-unique-translation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codezero-be%2Flaravel-unique-translation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codezero-be%2Flaravel-unique-translation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codezero-be%2Flaravel-unique-translation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codezero-be","download_url":"https://codeload.github.com/codezero-be/laravel-unique-translation/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248631669,"owners_count":21136554,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["database","json","language","laravel","mysql","php","rule","translation","unique","validation","validator"],"created_at":"2025-02-21T15:27:05.699Z","updated_at":"2025-10-07T16:39:17.947Z","avatar_url":"https://github.com/codezero-be.png","language":"PHP","funding_links":["https://ko-fi.com/ivanvermeyen","https://paypal.me/ivanvermeyen","https://ko-fi.com/R6R3UQ8V"],"categories":[],"sub_categories":[],"readme":"# Laravel Unique Translation\n\n## IMPORTANT: March 2022\n\n[![Support Ukraine](https://raw.githubusercontent.com/hampusborgos/country-flags/main/png100px/ua.png)](https://github.com/hampusborgos/country-flags/blob/main/png100px/ua.png)\n\nIt's horrible to see what is happening now in Ukraine, as Russian army is\n[bombarding houses, hospitals and kindergartens](https://twitter.com/DavidCornDC/status/1501620037785997316).\n\nPlease [check out supportukrainenow.org](https://supportukrainenow.org/) for the ways how you can help people there.\nSpread the word.\n\nAnd if you are from Russia and you are against this war, please express your protest in some way.\nI know you can get punished for this, but you are one of the hopes of those innocent people.\n\n---\n\n[![GitHub release](https://img.shields.io/github/release/codezero-be/laravel-unique-translation.svg?style=flat-square)](https://github.com/codezero-be/laravel-unique-translation/releases)\n[![Laravel](https://img.shields.io/badge/laravel-11-red?style=flat-square\u0026logo=laravel\u0026logoColor=white)](https://laravel.com)\n[![License](https://img.shields.io/packagist/l/codezero/laravel-unique-translation.svg?style=flat-square)](LICENSE.md)\n[![Build Status](https://img.shields.io/github/actions/workflow/status/codezero-be/laravel-unique-translation/run-tests.yml?style=flat-square\u0026logo=github\u0026logoColor=white\u0026label=tests)](https://github.com/codezero-be/laravel-unique-translation/actions)\n[![Code Coverage](https://img.shields.io/codacy/coverage/bb5f876fb1a94aa0a426fd31a2656e5b/master?style=flat-square)](https://app.codacy.com/gh/codezero-be/laravel-unique-translation)\n[![Code Quality](https://img.shields.io/codacy/grade/bb5f876fb1a94aa0a426fd31a2656e5b/master?style=flat-square)](https://app.codacy.com/gh/codezero-be/laravel-unique-translation)\n[![Total Downloads](https://img.shields.io/packagist/dt/codezero/laravel-unique-translation.svg?style=flat-square)](https://packagist.org/packages/codezero/laravel-unique-translation)\n\n[![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/R6R3UQ8V)\n\n#### Check if a translated value in a JSON column is unique in the database.\n\nImagine you want store a `slug` for a `Post` model in different languages.\n\nThe amazing [`spatie/laravel-translatable`](https://github.com/spatie/laravel-translatable) package makes this a cinch!\n\nBut then you want to make sure each translation is unique for its language.\n\nThat's where this package comes in to play.\n\nThis package also supports [`spatie/nova-translatable`](https://github.com/spatie/nova-translatable/) in case you are using [Laravel Nova](https://nova.laravel.com/) and [`filamentphp/spatie-laravel-translatable-plugin`](https://github.com/filamentphp/spatie-laravel-translatable-plugin) in case you are using [Filament](https://filamentphp.com/).\n\n## ✅ Requirements\n\n-   PHP ^7.2 or PHP ^8.0\n-   MySQL \u003e= 5.7\n-   [Laravel](https://laravel.com/) \u003e= 6\n-   [spatie/laravel-translatable](https://github.com/spatie/laravel-translatable) ^4.4|^5.0|^6.0\n-   [spatie/nova-translatable](https://github.com/spatie/nova-translatable/) ^3.0\n-   [filamentphp/spatie-laravel-translatable-plugin](https://github.com/filamentphp/spatie-laravel-translatable-plugin) ^3.0\n\n## 📦 Installation\n\nRequire the package via Composer:\n\n```\ncomposer require codezero/laravel-unique-translation\n```\nLaravel will automatically register the [ServiceProvider](https://github.com/codezero-be/laravel-unique-translation/blob/master/src/UniqueTranslationServiceProvider.php).\n\n## 🛠 Usage\n\nFor the following examples, I will use a `slug` in a `posts` table as the subject of our validation.\n\n### ☑️ Validate a Single Translation\n\nYour form can submit a single slug:\n\n```html\n\u003cinput name=\"slug\"\u003e\n```\n\nWe can then check if it is unique **in the current locale**:\n\n```php\n$attributes = request()-\u003evalidate([\n    'slug' =\u003e 'required|unique_translation:posts',\n]);\n```\n\nYou could also use the Rule instance:\n\n```php\nuse CodeZero\\UniqueTranslation\\UniqueTranslationRule;\n\n$attributes = request()-\u003evalidate([\n    'slug' =\u003e ['required', UniqueTranslationRule::for('posts')],\n]);\n```\n\n### ☑️ Validate an Array of Translations\n\nYour form can also submit an array of slugs.\n\n```html\n\u003cinput name=\"slug[en]\"\u003e\n\u003cinput name=\"slug[nl]\"\u003e\n```\n\nWe need to validate the entire array in this case. Mind the `slug.*` key.\n\n```php\n$attributes = request()-\u003evalidate([\n    'slug.*' =\u003e 'unique_translation:posts',\n    // or...\n    'slug.*' =\u003e UniqueTranslationRule::for('posts'),\n]);\n```\n\n### ☑️ Specify a Column\n\nMaybe your form field has a name of `post_slug` and your database field `slug`:\n\n```php\n$attributes = request()-\u003evalidate([\n    'post_slug.*' =\u003e 'unique_translation:posts,slug',\n    // or...\n    'post_slug.*' =\u003e UniqueTranslationRule::for('posts', 'slug'),\n]);\n```\n\n### ☑️ Specify a Database Connection\n\nIf you are using multiple database connections, you can specify which one to use by prepending it to the table name, separated by a dot:\n\n```php\n$attributes = request()-\u003evalidate([\n    'slug.*' =\u003e 'unique_translation:db_connection.posts',\n    // or...\n    'slug.*' =\u003e UniqueTranslationRule::for('db_connection.posts'),\n]);\n```\n\n### ☑️ Ignore a Record with ID\n\nIf you're updating a record, you may want to ignore the post itself from the unique check.\n\n```php\n$attributes = request()-\u003evalidate([\n    'slug.*' =\u003e \"unique_translation:posts,slug,{$post-\u003eid}\",\n    // or...\n    'slug.*' =\u003e UniqueTranslationRule::for('posts')-\u003eignore($post-\u003eid),\n]);\n```\n\n### ☑️ Ignore Records with a Specific Column and Value\n\nIf your ID column has a different name, or you just want to use another column:\n\n```php\n$attributes = request()-\u003evalidate([\n    'slug.*' =\u003e 'unique_translation:posts,slug,ignore_value,ignore_column',\n    // or...\n    'slug.*' =\u003e UniqueTranslationRule::for('posts')-\u003eignore('ignore_value', 'ignore_column'),\n]);\n```\n\n### ☑️ Use Additional Where Clauses\n\nYou can add 4 types of where clauses to the rule.\n\n#### `where`\n\n```php\n$attributes = request()-\u003evalidate([\n    'slug.*' =\u003e \"unique_translation:posts,slug,null,null,column,value\",\n    // or...\n    'slug.*' =\u003e UniqueTranslationRule::for('posts')-\u003ewhere('column', 'value'),\n]);\n```\n\n#### `whereNot`\n\n```php\n$attributes = request()-\u003evalidate([\n    'slug.*' =\u003e \"unique_translation:posts,slug,null,null,column,!value\",\n    // or...\n    'slug.*' =\u003e UniqueTranslationRule::for('posts')-\u003ewhereNot('column', 'value'),\n]);\n```\n\n#### `whereNull`\n\n```php\n$attributes = request()-\u003evalidate([\n    'slug.*' =\u003e \"unique_translation:posts,slug,null,null,column,NULL\",\n    // or...\n    'slug.*' =\u003e UniqueTranslationRule::for('posts')-\u003ewhereNull('column'),\n]);\n```\n\n#### `whereNotNull`\n\n```php\n$attributes = request()-\u003evalidate([\n    'slug.*' =\u003e \"unique_translation:posts,slug,null,null,column,NOT_NULL\",\n    // or...\n    'slug.*' =\u003e UniqueTranslationRule::for('posts')-\u003ewhereNotNull('column'),\n]);\n```\n\n### ☑️ Laravel Nova\n\nIf you are using [Laravel Nova](https://nova.laravel.com/) in combination with  [`spatie/nova-translatable`](https://github.com/spatie/nova-translatable/), then you can add the validation rule like this:\n\n```php\nText::make(__('Slug'), 'slug')\n  -\u003ecreationRules('unique_translation:posts,slug')\n  -\u003eupdateRules('unique_translation:posts,slug,{{resourceId}}');\n```\n\n### ☑️ Filament\n\nIf you are using [Filament](https://filamentphp.com/) in combination with [`filamentphp/spatie-laravel-translatable-plugin`](https://github.com/filamentphp/spatie-laravel-translatable-plugin), then you can add the validation rule like this:\n\n```php\nTextInput::make('slug')\n  -\u003etitle(__('Slug'))\n  -\u003erules([\n    UniqueTranslationRule::for('posts', 'slug')\n  ])\n```\n\n```php\nTextInput::make('slug')\n  -\u003etitle(__('Slug'))\n  -\u003erules([\n    fn (Get $get) =\u003e UniqueTranslationRule::for('posts', 'slug')-\u003eignore($get('id'))\n  ])\n```\n\n## 🖥 Example\n\nYour existing `slug`  column (JSON) in a `posts` table:\n\n```json\n{\n  \"en\":\"not-abc\",\n  \"nl\":\"abc\"\n}\n```\n\nYour form input to create a new record:\n\n\n```html\n\u003cinput name=\"slug[en]\" value=\"abc\"\u003e\n\u003cinput name=\"slug[nl]\" value=\"abc\"\u003e\n```\n\nYour validation logic:\n\n```php\n$attributes = request()-\u003evalidate([\n    'slug.*' =\u003e 'unique_translation:posts',\n]);\n```\n\nThe result is that `slug[en]` is valid, since the only `en` value in the database is `not-abc`.\n\nAnd `slug[nl]` would fail, because there already is a `nl` value of `abc`.\n\n## ⚠️ Error Messages\n\nYou can pass your own error messages as normal.\n\nWhen validating a single form field:\n\n```html\n\u003cinput name=\"slug\"\u003e\n```\n\n```php\n$attributes = request()-\u003evalidate([\n    'slug' =\u003e 'unique_translation:posts',\n], [\n    'slug.unique_translation' =\u003e 'Your custom :attribute error.',\n]);\n```\n\nIn your view you can then get the error with `$errors-\u003efirst('slug')`.\n\nOr when validation an array:\n\n```html\n\u003cinput name=\"slug[en]\"\u003e\n```\n\n```php\n$attributes = request()-\u003evalidate([\n    'slug.*' =\u003e 'unique_translation:posts',\n], [\n    'slug.*.unique_translation' =\u003e 'Your custom :attribute error.',\n]);\n```\n\nIn your view you can then get the error with `$errors-\u003efirst('slug.en')` (`en` being your array key).\n\n## 🚧 Testing\n\n```\nvendor/bin/phpunit\n```\n\n## ☕️ Credits\n\n- [Ivan Vermeyen](https://byterider.io)\n- [All contributors](../../contributors)\n\n## 🔓 Security\n\nIf you discover any security related issues, please [e-mail me](mailto:ivan@codezero.be) instead of using the issue tracker.\n\n## 📑 Changelog\n\nA complete list of all notable changes to this package can be found on the\n[releases page](https://github.com/codezero-be/laravel-unique-translation/releases).\n\n## 📜 License\n\nThe MIT License (MIT). Please see [License File](https://github.com/codezero-be/laravel-unique-translation/blob/master/LICENSE.md) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodezero-be%2Flaravel-unique-translation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodezero-be%2Flaravel-unique-translation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodezero-be%2Flaravel-unique-translation/lists"}