Unit Testing Translation Strings in Laravel
Leonel Elimpe
by Leonel Elimpe
1 min read

Tags

  • Laravel
  • Unit Testing

If your Laravel app uses multiple locales, it can get tedious keeping track of translations that are yet to be added to the appropriate translation files, e.g English translations in resources/lang/en/validation.php and French translations in resources/lang/fr/validation.php.

To automatically make these checks so I know when a translation is missing, I add unit tests.

It’s been tricky however given I started out by trying to use the trans() and __() helpers to retrieve translation strings as below.

<?php

// Using __() helper
$englishText = __('validation.is_tall', [], 'en');

$frenchText = __('validation.is_tall', [], 'fr');

// Using trans() helper
$englishText = trans('validation.is_tall', [], 'en');

$frenchText = __('validation.is_tall', [], 'fr');

The issue with using these helpers is that they’re written to automatically fallback to a default translation if the requested translation is not found, and further, return the translation key if a default translation is not found.

Notice we’re using a custom validation rule, is_tall, for which translation strings are to be added as follows.

In resources/lang/en/validation.php file:

<?php

return [
  // ...
  
  'is_tall' => 'You must be tall',
  
  // ...
];

And in resources/lang/fr/validation.php file:

<?php

return [
  // ...
  
  'is_tall' => 'Tu dois être grand',
  
  // ...
];

I later came across this Laracasts answer by Bobby Bouwmann in which he mentions he made a pull request to the Laravel repository to address the above problem, and it was merged. He added the method hasLocaleFor().

<?php

    /**
     * Determine if a translation exists for a given locale.
     *
     * @param  string  $key
     * @param  string  $locale
     * @return bool
     */
    public function hasForLocale($key, $locale = null)
    {
        return $this->has($key, $locale, false);
    }

Which does exactly what we want, check if a translation exists for a given locale. We can now go ahead and write the unit tests as below.

<?php

namespace Tests\Unit;

use Tests\TestCase;

class IsTallRuleTest extends TestCase
{
    /** @test */
    public function it_has_an_english_validation_message()
    {
        $this->assertTrue(
            \Lang::hasForLocale('validation.is_tall', 'en'),
            'English validation message not found'
        );
    }

    /** @test */
    public function it_has_a_french_validation_message()
    {
        $this->assertTrue(
            \Lang::hasForLocale('validation.is_tall', 'fr'),
            'French validation message not found'
        );
    }
}