Skip to content
Merged
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
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,38 @@ $validation_a = $validator->make($dataset_a, [
$validation_a->validate();
```

## Translation

Translation is different with custom messages.
Translation may needed when you use custom message for rule `in`, `not_in`, `mimes`, and `uploaded_file`.

For example if you use rule `in:1,2,3` we will set invalid message like "The Attribute only allows '1', '2', or '3'"
where part "'1', '2', or '3'" is comes from ":allowed_values" tag.
So if you have custom Indonesian message ":attribute hanya memperbolehkan :allowed_values",
we will set invalid message like "Attribute hanya memperbolehkan '1', '2', or '3'" which is the "or" word is not part of Indonesian language.

So, to solve this problem, we can use translation like this:

```php
// Set translation for words 'and' and 'or'.
$validator->setTranslations([
'and' => 'dan',
'or' => 'atau'
]);

// Set custom message for 'in' rule
$validator->setMessage('in', ":attribute hanya memperbolehkan :allowed_values");

// Validate
$validation = $validator->validate($inputs, [
'nomor' => 'in:1,2,3'
]);

$message = $validation->errors()->first('nomor'); // "Nomor hanya memperbolehkan '1', '2', atau '3'"
```

> Actually, our built-in rules only use words 'and' and 'or' that you may need to translates.

## Working with Error Message

Errors messages are collected in `Rakit\Validation\ErrorBag` object that you can get it using `errors()` method.
Expand Down
45 changes: 45 additions & 0 deletions src/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,4 +203,49 @@ public static function snakeCase(string $value, string $delimiter = '_'): string

return $value;
}

/**
* Join string[] to string with given $separator and $lastSeparator.
*
* @param array $pieces
* @param string $separator
* @param string|null $lastSeparator
* @return string
*/
public static function join(array $pieces, string $separator, string $lastSeparator = null): string
{
if (is_null($lastSeparator)) {
$lastSeparator = $separator;
}

$last = array_pop($pieces);

switch (count($pieces)) {
case 0:
return $last ?: '';
case 1:
return $pieces[0] . $lastSeparator . $last;
default:
return implode($separator, $pieces) . $lastSeparator . $last;
}
}

/**
* Wrap string[] by given $prefix and $suffix
*
* @param array $strings
* @param string $prefix
* @param string|null $suffix
* @return array
*/
public static function wraps(array $strings, string $prefix, string $suffix = null): array
{
if (is_null($suffix)) {
$suffix = $prefix;
}

return array_map(function ($str) use ($prefix, $suffix) {
return $prefix . $str . $suffix;
}, $strings);
}
}
25 changes: 25 additions & 0 deletions src/Rule.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ abstract class Rule
/** @var array */
protected $params = [];

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

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

Expand Down Expand Up @@ -145,6 +148,28 @@ public function parameter(string $key)
return isset($this->params[$key])? $this->params[$key] : null;
}

/**
* Set parameter text that can be displayed in error message using ':param_key'
*
* @param string $key
* @param string $text
* @return void
*/
public function setParameterText(string $key, string $text)
{
$this->paramsTexts[$key] = $text;
}

/**
* Get $paramsTexts
*
* @return array
*/
public function getParametersTexts(): array
{
return $this->paramsTexts;
}

/**
* Check whether this rule is implicit
*
Expand Down
12 changes: 9 additions & 3 deletions src/Rules/In.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

namespace Rakit\Validation\Rules;

use Rakit\Validation\Helper;
use Rakit\Validation\Rule;

class In extends Rule
{

/** @var string */
protected $message = "The :attribute is not allowing :value";
protected $message = "The :attribute only allows :allowed_values";

/** @var bool */
protected $strict = false;
Expand Down Expand Up @@ -49,7 +50,12 @@ public function check($value): bool
{
$this->requireParameters(['allowed_values']);

$allowed_values = $this->parameter('allowed_values');
return in_array($value, $allowed_values, $this->strict);
$allowedValues = $this->parameter('allowed_values');

$or = $this->validation ? $this->validation->getTranslation('or') : 'or';
$allowedValuesText = Helper::join(Helper::wraps($allowedValues, "'"), ', ', ", {$or} ");
$this->setParameterText('allowed_values', $allowedValuesText);

return in_array($value, $allowedValues, $this->strict);
}
}
10 changes: 8 additions & 2 deletions src/Rules/Mimes.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@

namespace Rakit\Validation\Rules;

use Rakit\Validation\Rule;
use Rakit\Validation\Helper;
use Rakit\Validation\MimeTypeGuesser;
use Rakit\Validation\Rule;

class Mimes extends Rule
{
use Traits\FileTrait;

/** @var string */
protected $message = "The :attribute file type is not allowed";
protected $message = "The :attribute file type must be :allowed_types";

/** @var string|int */
protected $maxSize = null;
Expand Down Expand Up @@ -60,6 +61,11 @@ public function check($value): bool
{
$allowedTypes = $this->parameter('allowed_types');

if ($allowedTypes) {
$or = $this->validation ? $this->validation->getTranslation('or') : 'or';
$this->setParameterText('allowed_types', Helper::join(Helper::wraps($allowedTypes, "'"), ', ', ", {$or} "));
}

// below is Required rule job
if (!$this->isValueFromUploadedFiles($value) or $value['error'] == UPLOAD_ERR_NO_FILE) {
return true;
Expand Down
9 changes: 8 additions & 1 deletion src/Rules/NotIn.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

namespace Rakit\Validation\Rules;

use Rakit\Validation\Helper;
use Rakit\Validation\Rule;

class NotIn extends Rule
{

/** @var string */
protected $message = "The :attribute is not allowing :value";
protected $message = "The :attribute is not allowing :disallowed_values";

/** @var bool */
protected $strict = false;
Expand Down Expand Up @@ -48,7 +49,13 @@ public function strict($strict = true)
public function check($value): bool
{
$this->requireParameters(['disallowed_values']);

$disallowedValues = (array) $this->parameter('disallowed_values');

$and = $this->validation ? $this->validation->getTranslation('and') : 'and';
$disallowedValuesText = Helper::join(Helper::wraps($disallowedValues, "'"), ', ', ", {$and} ");
$this->setParameterText('disallowed_values', $disallowedValuesText);

return !in_array($value, $disallowedValues, $this->strict);
}
}
10 changes: 9 additions & 1 deletion src/Rules/UploadedFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class UploadedFile extends Rule implements BeforeValidate
use Traits\FileTrait, Traits\SizeTrait;

/** @var string */
protected $message = "The :attribute is not valid";
protected $message = "The :attribute is not valid uploaded file";

/** @var string|int */
protected $maxSize = null;
Expand Down Expand Up @@ -133,6 +133,11 @@ public function check($value): bool
$maxSize = $this->parameter('max_size');
$allowedTypes = $this->parameter('allowed_types');

if ($allowedTypes) {
$or = $this->validation ? $this->validation->getTranslation('or') : 'or';
$this->setParameterText('allowed_types', Helper::join(Helper::wraps($allowedTypes, "'"), ', ', ", {$or} "));
}

// below is Required rule job
if (!$this->isValueFromUploadedFiles($value) or $value['error'] == UPLOAD_ERR_NO_FILE) {
return true;
Expand All @@ -150,13 +155,15 @@ public function check($value): bool
if ($minSize) {
$bytesMinSize = $this->getBytesSize($minSize);
if ($value['size'] < $bytesMinSize) {
$this->setMessage('The :attribute file is too small, minimum size is :min_size');
return false;
}
}

if ($maxSize) {
$bytesMaxSize = $this->getBytesSize($maxSize);
if ($value['size'] > $bytesMaxSize) {
$this->setMessage('The :attribute file is too large, maximum size is :max_size');
return false;
}
}
Expand All @@ -167,6 +174,7 @@ public function check($value): bool
unset($guesser);

if (!in_array($ext, $allowedTypes)) {
$this->setMessage('The :attribute file type must be :allowed_types');
return false;
}
}
Expand Down
54 changes: 54 additions & 0 deletions src/Traits/TranslationsTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace Rakit\Validation\Traits;

trait TranslationsTrait
{

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

/**
* Given $key and $translation to set translation
*
* @param mixed $key
* @param mixed $translation
* @return void
*/
public function setTranslation(string $key, string $translation)
{
$this->translations[$key] = $translation;
}

/**
* Given $translations and set multiple translations
*
* @param array $translations
* @return void
*/
public function setTranslations(array $translations)
{
$this->translations = array_merge($this->translations, $translations);
}

/**
* Given translation from given $key
*
* @param string $key
* @return string
*/
public function getTranslation(string $key): string
{
return array_key_exists($key, $this->translations) ? $this->translations[$key] : $key;
}

/**
* Get all $translations
*
* @return array
*/
public function getTranslations(): array
{
return $this->translations;
}
}
3 changes: 2 additions & 1 deletion src/Validation.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

class Validation
{
use Traits\TranslationsTrait;

/** @var mixed */
protected $validator;
Expand Down Expand Up @@ -386,7 +387,7 @@ protected function resolveAttributeName(Attribute $attribute): string
protected function resolveMessage(Attribute $attribute, $value, Rule $validator): string
{
$primaryAttribute = $attribute->getPrimaryAttribute();
$params = $validator->getParameters();
$params = array_merge($validator->getParameters(), $validator->getParametersTexts());
$attributeKey = $attribute->getKey();
$ruleKey = $validator->getKey();
$alias = $attribute->getAlias() ?: $this->resolveAttributeName($attribute);
Expand Down
9 changes: 8 additions & 1 deletion src/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@

class Validator
{
use Traits\TranslationsTrait;

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

/** @var translations */
protected $translations = [];

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

Expand Down Expand Up @@ -102,7 +106,10 @@ public function validate(array $inputs, array $rules, array $messages = []): Val
public function make(array $inputs, array $rules, array $messages = []): Validation
{
$messages = array_merge($this->messages, $messages);
return new Validation($this, $inputs, $rules, $messages);
$validation = new Validation($this, $inputs, $rules, $messages);
$validation->setTranslations($this->getTranslations());

return $validation;
}

/**
Expand Down
24 changes: 24 additions & 0 deletions tests/HelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,28 @@ public function testArrayUnset()
'message' => "lorem ipsum",
]);
}

public function testJoin()
{
$pieces0 = [];
$pieces1 = [1];
$pieces2 = [1, 2];
$pieces3 = [1, 2, 3];

$separator = ', ';
$lastSeparator = ', and ';

$this->assertEquals(Helper::join($pieces0, $separator, $lastSeparator), '');
$this->assertEquals(Helper::join($pieces1, $separator, $lastSeparator), '1');
$this->assertEquals(Helper::join($pieces2, $separator, $lastSeparator), '1, and 2');
$this->assertEquals(Helper::join($pieces3, $separator, $lastSeparator), '1, 2, and 3');
}

public function testWraps()
{
$inputs = [1, 2, 3];

$this->assertEquals(Helper::wraps($inputs, '-'), ['-1-', '-2-', '-3-']);
$this->assertEquals(Helper::wraps($inputs, '-', '+'), ['-1+', '-2+', '-3+']);
}
}
Loading