Translating Custom Error Messages in Laravel Packages

Laravel

Let's say that you are writing a Laravel package that involves data validation with custom error messages. Let's also say that you are interested in allowing your package to be translated into other languages. How would you pass your custom error strings to your validator?

I ran into this issue when working on my Laravel/Sentry 2 bridge package Sentinel. (It is not related to Cartalyst's Sentinel Package.) This package uses a Validation system inspired by the book Implementing Laravel by Chris Fidao, and in several locations makes use of custom error messages.

When I switched to using language strings instead of strait text I wasn't quite sure how to pull the custom error messages from the language files and pass them to the Validator. Here is what I landed on:

First we need to make sure that the Package's namespace is passed to the Translator. Add this line to the Service Provider's boot function:

1// Package Service Provider
2class SentinelServiceProvider extends ServiceProvider
3{
4
5 // ...
6
7 public function boot()
8 {
9 // ...
10
11 // Add the Translator Namespace
12 $this->app['translator']->addNamespace('Sentinel', __DIR__.'/../lang');
13 }
14
15}

The addNamespace function informs Laravel's translator class of the location of our language files and allows for the use of the 'Sentinel' namespace when translating language strings. We can now reference the Sentinel Package language strings via the Illuminate\Translation\Translator class:

1echo Lang::get('Sentinel::users.noaccess')
2
3 // Result:
4 // You are not allowed to do that.

We can also use trans(), which is a helper function that aliases Lang::get().

1echo trans('Sentinel::users.noaccess')
2
3 // Result:
4 // You are not allowed to do that.

Now we need to feed our custom error message strings to the Validator. This may be different for you, depending on how you handle validation, but the basic idea should remain the same.

1
2
3
4namespace Sentinel\Service\Validation;
5
6use Illuminate\Validation\Factory;
7
8abstract class AbstractLaravelValidator implements ValidableInterface
9{
10
11 /**
12 * Validator
13 *
14 * @var \Illuminate\Validation\Factory
15 */
16 protected $validator;
17
18 /**
19 * Custom Validation Messages
20 *
21 * @var Array
22 */
23 protected $messages = array();
24
25 public function __construct(Factory $validator)
26 {
27 $this->validator = $validator;
28
29 // Retrieve Custom Validation Messages & Pass them to the validator.
30 $this->messages = array_dot(trans('Sentinel::validation.custom'));
31 }
32
33 // ...
34}
src/Sentinel/Service/Validation/AbstractLaravelValidator.php

Here we are establishing a $messages class member and loading our custom language strings when the abstract validator class is instantiated. The language files use Sentinel::validaton.custom to refer to the array of custom error message strings.

Now all that remains is to pass the messages to the validator when we are attempting to validate data:

1abstract class AbstractLaravelValidator implements ValidableInterface
2{
3
4 // ...
5
6 /**
7 * Validation passes or fails
8 *
9 * @return boolean
10 */
11 public function passes()
12 {
13 $validator = $this->validator->make($this->data, $this->rules, $this->messages);
14
15 if ($validator->fails() )
16 {
17 $this->errors = $validator->messages();
18 return false;
19 }
20
21 return true;
22 }
23}
src/Sentinel/Service/Validation/AbstractLaravelValidator.php

The validator takes three arguments:

  1. An array of data to be validated.
  2. An array of the validation rules for that data.
  3. Optional: An array of custom error messages.

The messages array uses the input and names as array keys, and the corresponding value is the desired message text.

Problem solved!

About the Author

Ryan Durham is a software developer who lives in Portland, Oregon, with his wife and daughter. His numerous areas of interest include PHP, Laravel, Elixir and PostgreSQL, as well as organizational efficiency and communications strategies.

You can find him on GitHub and LinkedIn.