After some research on this topic, I found out that none of the existing solutions satisfy my needs. Most of them required either recompilation of JS assets or running some artisan command after editing or adding new translations and I don't like that approach. Maybe there are already some solutions, but I remember that I have seen something that I need in Laravel Nova.
So I checked the sources of Laravel Nova and found out that Laravel translations were loaded as JSON from translation files and then passed to the Blade template. In the Blade it was a simple assignment to global config variable.
The problem with that solution was, that it loaded only JSON translations and Laravel also has support for PHP phrases.
After some googling, I found an article, where the author showed how to load PHP language phrases to JS.
I mixed both approaches from Laravel Nova sources and from the article above and in the end I got, I think, the simplest way to use Laravel translation strings in JS files.
First of all create a translations service provider:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;
class TranslationServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
Cache::rememberForever('translations', function () {
$translations = collect();
foreach (['en', 'kg', 'ru'] as $locale) { // suported locales
$translations[$locale] = [
'php' => $this->phpTranslations($locale),
'json' => $this->jsonTranslations($locale),
];
}
return $translations;
});
}
private function phpTranslations($locale)
{
$path = resource_path("lang/$locale");
return collect(File::allFiles($path))->flatMap(function ($file) use ($locale) {
$key = ($translation = $file->getBasename('.php'));
return [$key => trans($translation, [], $locale)];
});
}
private function jsonTranslations($locale)
{
$path = resource_path("lang/$locale.json");
if (is_string($path) && is_readable($path)) {
return json_decode(file_get_contents($path), true);
}
return [];
}
}
Register it in config/app.php file:
'providers' => [
// your other providers
App\Providers\TranslationServiceProvider::class,
],
Then you have to pass translation strings to JS in blade template. I did it in the default layouts/app.blade.php file:
<script>
window._locale = '{{ app()->getLocale() }}';
window._translations = {!! cache('translations') !!};
</script>
Now you need some js function to retrieve translations and apply replacements. To do that I have created a trans.js file:
module.exports = {
methods: {
/**
* Translate the given key.
*/
__(key, replace) {
let translation, translationNotFound = true
try {
translation = key.split('.').reduce((t, i) => t[i] || null, window._translations[window._locale].php)
if (translation) {
translationNotFound = false
}
} catch (e) {
translation = key
}
if (translationNotFound) {
translation = window._translations[window._locale]['json'][key]
? window._translations[window._locale]['json'][key]
: key
}
_.forEach(replace, (value, key) => {
translation = translation.replace(':' + key, value)
})
return translation
}
},
}
It's a bit modified version of base.js from Laravel Nova which also loads PHP translations. In short, the logic is: First try to find translation string in PHP translations, if not found, then try to find in JSON translations. If translation was not found at all, then it will show the key itself.
And the last step is to include the method as a mixin:
Vue.mixin(require('./trans'))
That's it. Now you can use translations in Vue components like so:
<template>
<div class="card">
<div class="card-header">{{ __('Example Component') }}</div>
<div class="card-body">
{{ __("I'm an example component.") }}
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log(this.__('Component mounted.'))
}
}
</script>
With this solution, the only thing you have to do after editing/adding new translations is to run cache:clear artisan command. Laravel Nova (which we use in our projects) has packages, that allow executing such commands right from the admin panel, so that is not an issue at all.
Update 25.02.2020
The previous solution was working fine only on single locale. Thanks to @morpheus_ro to pointing out. Now the solution covers all the locales specified in the app.
Latest comments (31)
Hi @4unkur ,
I've used your code for about 3 years now and I'm very grateful for your solution!
I'm trying to upgrade my Laravel 9 app to Laravel 11, but when using your service provider, I'm now getting the following error:
Do you know what could be the issue? Would you have a working example for Laravel 11?
Thank you!
Thanks! Works perfectly!
This is so helpfull, thank you guys! So beautiful!
Hey guys, it seems like I'm in the right path but I still have two questions because it is not working for me yet. 1. How to call the trans.js file? In the app.js? 2. Where exactly should I add the mixin? Thank you!
Hi, I am using this code in my app ans It's all Ok, but I need to know how can I translate the placeholder for a input
this code in laravel crash the compilation
Thanks for all
This one works inside the component element:
__("I'm an example component.")
But in the script doesn't.
What did I miss?
Exactly the solution I was looking for! Thank you!
<3
Great post !
I had just need edit this line to be supported by windows too :
Before : $path = resource_path("lang/$locale");
After : $path = resource_path("lang" . DIRECTORY_SEPARATOR . $locale);
(markdown of the hell, 10 minutes lost for nothing...)
Hello bro,

i'm trying to use your solution but i got some errors like
this error comes from this block of code
if (translationNotFound) {translation = window._translations[window._locale]['json'][key]
? window._translations[window._locale]['json'][key]
: key
}
i have the same error how did you solved?
thanks
you should just check if
window._translationsis set or notdev-to-uploads.s3.amazonaws.com/i/...
thanks this fixed the console error. Another problem i get window._translations undefined and con't understand what i make wrong is like is not passing window._translations from blade to JS. You have some advise?
did you put this in app.blade.php, but sometimes the
{!! cache('translations') !!}is not returning any data so thewindow._translationsis nullDo you have any updates so far? I've struggling with that particular issue and it's occur totally random. I would very appreciate if so!
i used same package but i found a lot of issus and i have updated the code many times to work for me. and i dont know how to explain my method to you unless i see your code and the error your are having
Great guide, it's super beneficial to know and also works great, thank you for this!
I did however need to adjust the provider a little, to automatically detect which languages the transliteration should support. I achieved this by recursively scanning every folder within resources/lang, and get the locales from there.
App/Providers/TranslationServiceProvider.php
This enables me to not having to edit the provider every time we add support for a new language.
In case you are using json files which should be inside the /resources/lang/ directory, you should add the GLOB_ONLYDIR option to the glob function in the code above.