fusic/valii
fusic/valii is a Laravel/PHP package focused on validation. It offers reusable rules and helpers for common form and input checks, integrating with Laravel's validator to keep validation logic clean, consistent, and easy to maintain across applications.
fusic/valii gives Laravel apps Japanese validation error messages and Japanese attribute names without hand-writing every lang/ja/validation.php entry. 0.6.19 is a compatibility release (Laravel 12/13, PHP 8.4/8.5) with no API changes — the workflow below is unchanged from 0.6.18.
composer require fusic/valii
php artisan vendor:publish --tag=valii # ships lang/ja/*.php + config/valii.php
Look first at:
config/valii.php — the locale/language switch and whether attribute-name replacement is enabled.lang/ja/validation.php — the message bodies you'll be overriding.lang/ja/attributes.php — the human-readable attribute names used in :attribute substitution.First use case: a FormRequest on a signup form. Before the package you get The email field is required.; after, メールアドレスは必須です。 with zero changes to your controller or rules. Verify with:
php artisan tinker
>>> app('translator')->get('validation.required', ['attribute' => 'email']);
If that returns Japanese, the publish + locale wiring is correct and you can move on to naming attributes.
Locale is the switch, not a facade call. The package resolves messages through Laravel's translator, so the only thing that has to be true at validation time is that the active locale maps to the published Japanese files.
// config/app.php
'locale' => 'ja',
'fallback_locale' => 'en',
For a per-request or per-user locale, set it in middleware before the request reaches the controller — App::setLocale() inside a controller is too late once a FormRequest has already run its rules.
Name attributes in one place. Keep lang/ja/attributes.php as the single source of truth and mirror it in FormRequest::attributes() only for form-specific overrides:
public function attributes(): array
{
return [
'email' => 'メールアドレス',
'password' => 'パスワード',
'company.name' => '会社名', // dot notation for nested input
];
}
Custom rules slot in normally. Add the rule's message to the published lang/ja/validation.php and reference the attribute key; the package is a translation layer, so anything Laravel's validator understands works.
'phone_number' => ':attributeは電話番号の形式で入力してください。',
Pair with a JSON/API error shape. In App\Exceptions\Handler (or Laravel 11+/12 bootstrap/app.php), leave ValidationException alone so the bag renders from the Japanese files, and translate the message only if the client needs it:
->withExceptions(function (Exceptions $exceptions) {
$exceptions->render(function (ValidationException $e, $request) {
return $request->expectsJson()
? response()->json(['errors' => $ e->errors()], 422)
: null;
});
})
Test the Japanese, not just the failure. Assertions on session errors catch locale regressions that unit tests on rules never will:
$this->post('/signup', [])->assertSessionHasErrors([
'email' => 'メールアドレスは必須です。',
]);
composer update.vendor:publish, Laravel reads your lang/ja/validation.php, not the package's. Upgrading valii will not deliver new or corrected messages. Diff the package's stub against yours on every minor bump, or publish to a separate namespace and merge.setLocale() in a service provider's boot() fires before the session/user is known; a FormRequest resolves messages during validation, so the locale must be settled in middleware or a request-scoped provider.php artisan config:cache and the absence of lang:cache interact confusingly: a stale config/valii.php will silently keep an old locale. Run php artisan optimize:clear before debugging "the messages reverted to English."company.name needs the fully-qualified key in attributes.php; a bare name entry will not match nested input, and you'll get the raw key printed in the message.fallback_locale => 'en', a missing Japanese key renders English instead of erroring. Set fallback_locale to ja in testing/local to surface gaps, or write a test that asserts no message contains :attribute unresolved.between accept ['string' => ..., 'array' => ...]. Overriding only the string key leaves collection inputs in English — check both when editing.config/valii.php's language option at it. That keeps upgrades mechanical.How can I help you explore Laravel packages today?