Have you seen something like this __()
function in the code?
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400"> {{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }}</div>
These are Static Text, and in Laravel they can be translated with trans()
and __()
helper functions. In this lesson, we will see how to store translations and how to use those helpers.
To store the translations strings, we have a few options:
.php
file(s) for each language.json
file for each languageThey both contain translations but have some key differences. Let's discuss both.
This was the default way for quite a long time.
Example: we have a View file with a translation string using the __()
helper.
resources/views/auth/register.blade.php
<!-- Name --><div> <x-input-label for="name" :value="__('auth.register.name')" /> <x-text-input id="name" class="block mt-1 w-full" type="text" name="name" :value="old('name')" required autofocus autocomplete="name" /> <x-input-error :messages="$errors->get('name')" class="mt-2" /></div>
To translate this, we need to add a translation string to the /lang/en/auth.php
file:
/lang/en/auth.php
return [ 'register' => [ 'name' => 'Name', 'email' => 'Email', // ... ], 'login' => [ 'login' => 'Login', // ... ],];
Looking at that /lang/en/auth.php
file above, one thing you need to be aware of.
By default, Laravel static text translations are stored in the /lang
folder. But in Laravel 10 that lang
folder is not included in the beginning.
Running the following artisan
command will add it:
php artisan lang:publish
This will create a lang
folder in your root directory and add the en
folder inside with default translation strings from Laravel core.
In earlier Laravel versions, you may find that translations are stored in the /lang
folder. That will also work in the latest Laravel version but is considered an old/obsolete approach.
So, the code __('auth.register.name')
will load the translation string from the auth.php
file and return the Name
string.
See that auth.register.name
parameter? The first part of it is the filename: /lang/[language]/[filename].php
. All the other dot-separated parts are the keys of the array inside that specific file. In our case, it's register.name
.
If there is no translation with that key, or if that file doesn't exist - you won't get an error, you'll just get the same key back:
auth.php
, validation.php
, pagination.php
, etc. This will make it easier to find the translation you are looking for.__('auth.register.name')
and __('validation.name')
will both return the same translation but can be managed separately.JSON files are a bit different from .php files. They contain a single list with all the translation strings.
In our blade, the translation will look like this:
resources/views/auth/register.blade.php
<!-- Name --><div> <x-input-label for="name" :value="__('Name')" /> <x-text-input id="name" class="block mt-1 w-full" type="text" name="name" :value="old('name')" required autofocus autocomplete="name" /> <x-input-error :messages="$errors->get('name')" class="mt-2" /></div>
See that 'Name'
parameter? It's not the auth.register.name
key anymore, right? This is exactly the difference: the keys of JSON files are in a human-readable form.
So, even if Laravel doesn't find the key or the translation file - it will still display Name
in our UI because that's the key we passed to the __()
helper function.
But if we add a translation file - it will be used instead:
lang/en.json
{ "Name": "Your Name"}
This allows us to write complete text in the __()
function key and not worry about a path or missing translations.
__('Name')
in auth/register.blade.php
and auth/login.blade.php
will result in the same translation.__('auth.Name')
and have a JSON file with the auth
key and Name
key inside of it. But you can have "auth.Name": "Name"
in the same file which will load. This is not ideal, and you should only use it to translate the default Laravel translations as seen here
__('Name')
in auth/register.blade.php
and auth/login.blade.php
will result in the same translation. If different languages require different translations for the same word in different contexts - you won't be able to do that..json
files.This is not a simple question to answer. The good thing is that they are pretty much interchangeable. With some caveats, of course.
You can move from .php
files to .json
files relatively easily.
Moving from .json
files to .php
files is a bit more complicated as you will need to change all your keys to paths.
But it does not matter that much which one you will pick. As long as you are consistent - you can use either one or combine them.
Using both .php
and .json
files could lead you to a problem where you have a key in JSON that matches the filename in PHP. For example:
lang/en/auth.php
return [ 'name' => 'Name', 'failed' => 'These credentials do not match our records.', 'password' => 'The provided password is incorrect.', 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',];
lang/en.json
{ "Auth": "Authentication"}
Let's call the __()
helper function with a key of Auth
anywhere in our view template:
resources/views/auth/register.blade.php
{{ __('Auth') }}
Running this will result in an error:
Let's dump the __('Auth')
function to see what's going on:
As you can see, we got the content of the default /lang/en/auth.php
file and not our expected string of Authentication
.
This is because the __()
helper function will first look for a translation file with the same name as the key. If it finds it - it will return the whole file. If it doesn't find it - it will look for a translation string in the lang/en.json
file.
trans()
VS __()
: Which To Use?You might have noticed that some people prefer __()
over trans()
and that's okay. But have you ever looked at what the difference is?
__()
is a helper function that calls the trans()
function under the hood:
vendor/laravel/framework/src/Illuminate/Foundation/helpers.php
if (! function_exists('__')) { /** * Translate the given message. * * @param string|null $key * @param array $replace * @param string|null $locale * @return string|array|null */ function __($key = null, $replace = [], $locale = null) { if (is_null($key)) { return $key; } return trans($key, $replace, $locale); }}
The biggest difference here is what happens if you pass no value to __()
:
__()
will return null
.trans()
will return the Illuminate\Translation\Translator
instance. This allows you to chain more methods on it. For example, trans()->getLocale()
will return the current locale.So which should we use? It's up to you! I prefer __()
for translation strings and trans()
for other cases (like getting current locale, settings, etc).
In the next lesson, we'll work with locales and how to tell Laravel which is your primary language.