Skip to content

Commit b430b7e

Browse files
authored
Merge pull request #91 from spatie/3.x-add-per-locale-rules
Backport per-locale field rules
2 parents afca412 + b0ea13b commit b430b7e

File tree

3 files changed

+157
-0
lines changed

3 files changed

+157
-0
lines changed

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,33 @@ Translatable::make([
128128

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

131+
### Customizing the rules of a translatable
132+
133+
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.
134+
135+
```php
136+
Translatable::make([
137+
Text::make('My title', 'title'),
138+
Trix::make('text'),
139+
])->rules([
140+
'title' => ['en' => 'required', 'nl' => 'nullable'],
141+
'text' => ['en' => 'required|min:10', 'nl' => 'nullable|min:10'],
142+
]
143+
),
144+
```
145+
146+
You may also use the more fluent `rulesFor()` method, which allows you to define rules per field per locale.
147+
148+
```php
149+
Translatable::make([
150+
Text::make('My title', 'title'),
151+
Trix::make('text'),
152+
])->rulesFor('title', 'en', 'required')
153+
->rulesFor('title', 'nl', 'nullable'),
154+
```
155+
156+
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.
157+
131158
## On customizing the UI
132159

133160
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.

src/Translatable.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ class Translatable extends MergeValue
3434
/** @var \Closure */
3535
protected $displayLocalizedNameUsingCallback;
3636

37+
/** @var array */
38+
protected $rules = [];
39+
40+
/** @var array */
41+
protected $creationRules = [];
42+
43+
/** @var array */
44+
protected $updateRules = [];
45+
3746
/**
3847
* The field's assigned panel.
3948
*
@@ -79,6 +88,60 @@ public function locales(array $locales)
7988
return $this;
8089
}
8190

91+
public function rules(array $rules)
92+
{
93+
$this->rules = $rules;
94+
95+
$this->createTranslatableFields();
96+
97+
return $this;
98+
}
99+
100+
public function creationRules(array $rules)
101+
{
102+
$this->creationRules = $rules;
103+
104+
$this->createTranslatableFields();
105+
106+
return $this;
107+
}
108+
109+
public function updateRules(array $rules)
110+
{
111+
$this->updateRules = $rules;
112+
113+
$this->createTranslatableFields();
114+
115+
return $this;
116+
}
117+
118+
public function rulesFor(string $field, string $locale, $rules)
119+
{
120+
$this->rules[$field][$locale] = $rules;
121+
122+
$this->createTranslatableFields();
123+
124+
return $this;
125+
}
126+
127+
public function creationRulesFor(string $field, string $locale, $rules)
128+
{
129+
$this->creationRules[$field][$locale] = $rules;
130+
131+
$this->createTranslatableFields();
132+
133+
return $this;
134+
}
135+
136+
public function updateRulesFor(string $field, string $locale, $rules)
137+
{
138+
$this->updateRules[$field][$locale] = $rules;
139+
140+
$this->createTranslatableFields();
141+
142+
return $this;
143+
}
144+
82145
public static function displayLocalizedNameByDefaultUsing(Closure $displayLocalizedNameByDefaultUsingCallback = null)
83146
{
84147
static::$displayLocalizedNameByDefaultUsingCallback = $displayLocalizedNameByDefaultUsingCallback;
@@ -141,6 +204,28 @@ protected function createTranslatedField(Field $originalField, string $locale):
141204
$model->setTranslation($originalAttribute, $locale, $request->get($requestAttribute));
142205
});
143206

207+
if (isset($this->rules[$originalAttribute][$locale])) {
208+
$translatedField->rules(
209+
is_string($this->rules[$originalAttribute][$locale])
210+
? explode('|', $this->rules[$originalAttribute][$locale])
211+
: $this->rules[$originalAttribute][$locale]
212+
);
213+
}
214+
if (isset($this->creationRules[$originalAttribute][$locale])) {
215+
$translatedField->creationRules(
216+
is_string($this->creationRules[$originalAttribute][$locale])
217+
? explode('|', $this->creationRules[$originalAttribute][$locale])
218+
: $this->creationRules[$originalAttribute][$locale]
219+
);
220+
}
221+
if (isset($this->updateRules[$originalAttribute][$locale])) {
222+
$translatedField->updateRules(
223+
is_string($this->updateRules[$originalAttribute][$locale])
224+
? explode('|', $this->updateRules[$originalAttribute][$locale])
225+
: $this->updateRules[$originalAttribute][$locale]
226+
);
227+
}
228+
144229
return $translatedField;
145230
}
146231

tests/TranslatableTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,49 @@ private function assertTrixField(Trix $field, string $disk, string $path)
130130
$this->assertEquals($disk, $field->getStorageDisk());
131131
$this->assertEquals($path, $field->getStorageDir());
132132
}
133+
134+
/** @test */
135+
public function it_accepts_different_rules_for_different_locales()
136+
{
137+
$translatable = Translatable::make([
138+
new Text('title'),
139+
])->rules(['title' => ['en' => 'required', 'fr' => 'min:3']]);
140+
141+
$this->assertEquals($translatable->data[0]->rules, ['required']);
142+
$this->assertEquals($translatable->data[1]->rules, ['min:3']);
143+
144+
$translatable->rulesFor('title', 'en', 'max:3');
145+
146+
$this->assertEquals($translatable->data[0]->rules, ['max:3']);
147+
}
148+
149+
/** @test */
150+
public function it_accepts_different_creation_rules_for_different_locales()
151+
{
152+
$translatable = Translatable::make([
153+
new Text('title'),
154+
])->creationRules(['title' => ['en' => 'required', 'fr' => 'min:3']]);
155+
156+
$this->assertEquals($translatable->data[0]->creationRules, ['required']);
157+
$this->assertEquals($translatable->data[1]->creationRules, ['min:3']);
158+
159+
$translatable->creationRulesFor('title', 'en', 'max:3');
160+
161+
$this->assertEquals($translatable->data[0]->creationRules, ['max:3']);
162+
}
163+
164+
/** @test */
165+
public function it_accepts_different_update_rules_for_different_locales()
166+
{
167+
$translatable = Translatable::make([
168+
new Text('title'),
169+
])->updateRules(['title' => ['en' => 'required', 'fr' => 'min:3']]);
170+
171+
$this->assertEquals($translatable->data[0]->updateRules, ['required']);
172+
$this->assertEquals($translatable->data[1]->updateRules, ['min:3']);
173+
174+
$translatable->updateRulesFor('title', 'en', 'max:3');
175+
176+
$this->assertEquals($translatable->data[0]->updateRules, ['max:3']);
177+
}
133178
}

0 commit comments

Comments
 (0)