Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add rules support for per translations #21

Open
wants to merge 4 commits into
base: 3.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,3 +275,39 @@ If you wish to translate the package, you may publish the language files using:
```bash
php artisan vendor:publish --tag=filament-spatie-laravel-translatable-plugin-translations
```

## Form Validation

You can define and use form validation rules according to the locale as follows.

```php
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')
->label(__('Category Name'))
->helperText(__('This is the name of the category.'))
->rules(function (?Category $record) {
return [
'tr' => [
'required',
'string',
'max:100',
Rule::unique('tags', 'name->tr')
->where('type', 'category')
->ignore($record?->id, 'id')
],
'en' => [
'required',
'string',
'max:100',
Rule::unique('tags', 'name->en')
->where('type', 'category')
->ignore($record?->id, 'id')
],
];
})
]);
}
```
27 changes: 27 additions & 0 deletions src/Resources/Pages/Concerns/HasTranslatableValidation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Filament\Resources\Pages\Concerns;

use Filament\Forms\Components\Contracts\HasValidationRules;

trait HasTranslatableValidation
{
/**
* Set the validation rules for the active locale.
*/
public function setLocaleByRules(string $locale): void
{
$components = array_filter(
$this->form->getFlatComponents(),
fn ($component) => $component instanceof HasValidationRules
);

foreach ($components as $component) {
$rules = $component->getValidationRules();
if (! empty($rules[$locale])) {
$component->rule($rules[$locale]);
break;
}
}
}
}
44 changes: 43 additions & 1 deletion src/Resources/Pages/CreateRecord/Concerns/Translatable.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
namespace Filament\Resources\Pages\CreateRecord\Concerns;

use Filament\Facades\Filament;
use Filament\Forms\Components\Contracts\HasValidationRules;
use Filament\Resources\Concerns\HasActiveLocaleSwitcher;
use Filament\Resources\Pages\Concerns\HasTranslatableValidation;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Validation\ValidationException;
Expand All @@ -12,6 +14,7 @@
trait Translatable
{
use HasActiveLocaleSwitcher;
use HasTranslatableValidation;

protected ?string $oldActiveLocale = null;

Expand All @@ -28,6 +31,30 @@ public function getTranslatableLocales(): array
return static::getResource()::getTranslatableLocales();
}

public function beforeFill()
{
/**
* For the rules assigned to the locales to work properly,
* an empty form state must be created for each local.
*/
if (empty($this->otherLocaleData)) {
$components = $this->form->getFlatComponents();
$formData = collect($components)
->filter(
fn ($component) => $component instanceof HasValidationRules
)
->mapWithKeys(
fn ($component) => [$component->getName() => null]
)
->toArray();
foreach ($this->getTranslatableLocales() as $locale) {
$this->otherLocaleData[$locale] = [];

$this->otherLocaleData[$locale] = $formData;
}
}
}

protected function handleRecordCreation(array $data): Model
{
$record = app(static::getModel());
Expand All @@ -42,7 +69,17 @@ protected function handleRecordCreation(array $data): Model

$originalData = $this->data;

/**
* Set the data for the active locale.
*/
$this->otherLocaleData[$this->activeLocale] = Arr::only($this->data, $translatableAttributes);

foreach ($this->otherLocaleData as $locale => $localeData) {
/**
* Set the validation rules for the active locale.
*/
$this->setLocaleByRules($locale);

$this->data = [
...$this->data,
...$localeData,
Expand All @@ -51,7 +88,12 @@ protected function handleRecordCreation(array $data): Model
try {
$this->form->validate();
} catch (ValidationException $exception) {
continue;
/**
* If the validation fails for the active locale, set the active locale
*/
$this->activeLocale = $locale;

throw $exception;
}

$localeData = $this->mutateFormDataBeforeCreate($localeData);
Expand Down
14 changes: 13 additions & 1 deletion src/Resources/Pages/EditRecord/Concerns/Translatable.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Filament\Resources\Concerns\HasActiveLocaleSwitcher;
use Filament\Resources\Pages\Concerns\HasTranslatableFormWithExistingRecordData;
use Filament\Resources\Pages\Concerns\HasTranslatableRecord;
use Filament\Resources\Pages\Concerns\HasTranslatableValidation;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Validation\ValidationException;
Expand All @@ -14,6 +15,7 @@ trait Translatable
use HasActiveLocaleSwitcher;
use HasTranslatableFormWithExistingRecordData;
use HasTranslatableRecord;
use HasTranslatableValidation;

protected ?string $oldActiveLocale = null;

Expand All @@ -34,9 +36,19 @@ protected function handleRecordUpdate(Model $record, array $data): Model

$originalData = $this->data;

/**
* Set the data for the active locale.
*/
$this->otherLocaleData[$this->activeLocale] = Arr::only($this->data, $translatableAttributes);

$existingLocales = null;

foreach ($this->otherLocaleData as $locale => $localeData) {
/**
* Set the locale for the validation rules.
*/
$this->setLocaleByRules($locale);

$existingLocales ??= collect($translatableAttributes)
->map(fn (string $attribute): array => array_keys($record->getTranslations($attribute)))
->flatten()
Expand All @@ -51,7 +63,7 @@ protected function handleRecordUpdate(Model $record, array $data): Model
try {
$this->form->validate();
} catch (ValidationException $exception) {
if (! array_key_exists($locale, $existingLocales)) {
if (! in_array($locale, $existingLocales, true)) {
continue;
}

Expand Down