Skip to content

Commit

Permalink
Merge pull request #91 from spatie/3.x-add-per-locale-rules
Browse files Browse the repository at this point in the history
Backport per-locale field rules
  • Loading branch information
bram-pkg authored Jul 31, 2023
2 parents afca412 + b0ea13b commit b430b7e
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 0 deletions.
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,33 @@ Translatable::make([

Using the code about above the name for the `title` field will be "My title ['en']".

### Customizing the rules of a translatable

You may use the regular Nova functionality to define rules on the fields inside your Translatable fields collection. However, this will apply those rules to all locales. If you wish to define different rules per locale you can do so on the Translatable collection.

```php
Translatable::make([
Text::make('My title', 'title'),
Trix::make('text'),
])->rules([
'title' => ['en' => 'required', 'nl' => 'nullable'],
'text' => ['en' => 'required|min:10', 'nl' => 'nullable|min:10'],
]
),
```

You may also use the more fluent `rulesFor()` method, which allows you to define rules per field per locale.

```php
Translatable::make([
Text::make('My title', 'title'),
Trix::make('text'),
])->rulesFor('title', 'en', 'required')
->rulesFor('title', 'nl', 'nullable'),
```

There are also methods for update and creation rules called `creationRules()`, `updateRules()`, `creationRulesFor()` and `updateRulesFor()`. They function in the same way as the `rules()` and `rulesFor()` methods.

## On customizing the UI

You might wonder why we didn't render the translatable fields in tabs, panels or with magical unicorns displayed next to them. The truth is that everybody wants translations to be displayed a bit different. That's why we opted to keep them very simple for now.
Expand Down
85 changes: 85 additions & 0 deletions src/Translatable.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ class Translatable extends MergeValue
/** @var \Closure */
protected $displayLocalizedNameUsingCallback;

/** @var array */
protected $rules = [];

/** @var array */
protected $creationRules = [];

/** @var array */
protected $updateRules = [];

/**
* The field's assigned panel.
*
Expand Down Expand Up @@ -79,6 +88,60 @@ public function locales(array $locales)
return $this;
}

public function rules(array $rules)
{
$this->rules = $rules;

$this->createTranslatableFields();

return $this;
}

public function creationRules(array $rules)
{
$this->creationRules = $rules;

$this->createTranslatableFields();

return $this;
}

public function updateRules(array $rules)
{
$this->updateRules = $rules;

$this->createTranslatableFields();

return $this;
}

public function rulesFor(string $field, string $locale, $rules)
{
$this->rules[$field][$locale] = $rules;

$this->createTranslatableFields();

return $this;
}

public function creationRulesFor(string $field, string $locale, $rules)
{
$this->creationRules[$field][$locale] = $rules;

$this->createTranslatableFields();

return $this;
}

public function updateRulesFor(string $field, string $locale, $rules)
{
$this->updateRules[$field][$locale] = $rules;

$this->createTranslatableFields();

return $this;
}

public static function displayLocalizedNameByDefaultUsing(Closure $displayLocalizedNameByDefaultUsingCallback = null)
{
static::$displayLocalizedNameByDefaultUsingCallback = $displayLocalizedNameByDefaultUsingCallback;
Expand Down Expand Up @@ -141,6 +204,28 @@ protected function createTranslatedField(Field $originalField, string $locale):
$model->setTranslation($originalAttribute, $locale, $request->get($requestAttribute));
});

if (isset($this->rules[$originalAttribute][$locale])) {
$translatedField->rules(
is_string($this->rules[$originalAttribute][$locale])
? explode('|', $this->rules[$originalAttribute][$locale])
: $this->rules[$originalAttribute][$locale]
);
}
if (isset($this->creationRules[$originalAttribute][$locale])) {
$translatedField->creationRules(
is_string($this->creationRules[$originalAttribute][$locale])
? explode('|', $this->creationRules[$originalAttribute][$locale])
: $this->creationRules[$originalAttribute][$locale]
);
}
if (isset($this->updateRules[$originalAttribute][$locale])) {
$translatedField->updateRules(
is_string($this->updateRules[$originalAttribute][$locale])
? explode('|', $this->updateRules[$originalAttribute][$locale])
: $this->updateRules[$originalAttribute][$locale]
);
}

return $translatedField;
}

Expand Down
45 changes: 45 additions & 0 deletions tests/TranslatableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,49 @@ private function assertTrixField(Trix $field, string $disk, string $path)
$this->assertEquals($disk, $field->getStorageDisk());
$this->assertEquals($path, $field->getStorageDir());
}

/** @test */
public function it_accepts_different_rules_for_different_locales()
{
$translatable = Translatable::make([
new Text('title'),
])->rules(['title' => ['en' => 'required', 'fr' => 'min:3']]);

$this->assertEquals($translatable->data[0]->rules, ['required']);
$this->assertEquals($translatable->data[1]->rules, ['min:3']);

$translatable->rulesFor('title', 'en', 'max:3');

$this->assertEquals($translatable->data[0]->rules, ['max:3']);
}

/** @test */
public function it_accepts_different_creation_rules_for_different_locales()
{
$translatable = Translatable::make([
new Text('title'),
])->creationRules(['title' => ['en' => 'required', 'fr' => 'min:3']]);

$this->assertEquals($translatable->data[0]->creationRules, ['required']);
$this->assertEquals($translatable->data[1]->creationRules, ['min:3']);

$translatable->creationRulesFor('title', 'en', 'max:3');

$this->assertEquals($translatable->data[0]->creationRules, ['max:3']);
}

/** @test */
public function it_accepts_different_update_rules_for_different_locales()
{
$translatable = Translatable::make([
new Text('title'),
])->updateRules(['title' => ['en' => 'required', 'fr' => 'min:3']]);

$this->assertEquals($translatable->data[0]->updateRules, ['required']);
$this->assertEquals($translatable->data[1]->updateRules, ['min:3']);

$translatable->updateRulesFor('title', 'en', 'max:3');

$this->assertEquals($translatable->data[0]->updateRules, ['max:3']);
}
}

0 comments on commit b430b7e

Please sign in to comment.