Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Kimmer's avatar

Translations with Laravel and Inertia.

I am searching for the best way to make my Laravel/Inertia app multi language. Preferably without using a 3rd party package.

I have found two different explanations but they seem to differ from one and other.

1: https://tallpad.com/series/inertiajs-laravel-misc/lessons/handling-translations-in-laravel-and-inertiajs-applications

2: https://devonmather.xyz/localizing-a-laravel-app-using-vue-js-and-inertia-js-without-any-dependencies/

It seems one of the major differences is that the first one uses a blade component to prevent props that rarely change be sent with every request. However the second one also explains how to build a language switcher.

Now I am wondering which one I should follow. Any opinions? Or maybe a third one?

1 like
19 replies
Kimmer's avatar

@Tray2 I've read the docs. While they are very intersting they don't really cover how to use localisation with Intertia.

6 likes
Sinnbeck's avatar

Personally I generate a json file with all the translations (from laravel localization) by running a command. Then I load this file directly. Works like a charm

4 likes
DanielRønfeldt's avatar

@Sinnbeck I know this is an old thread, but I was hoping that you could share in more detail your approach at handling translations in Inertia. Any suggestions are much appreciated.

1 like
Sinnbeck's avatar

@DanielRønfeldt Sure. I use langjs

https://github.com/rmariuzzo/Lang.js/

and set it up like this in javascript

import Lang from 'lang.js'
import messages from '@/i18n.json'

export const lang = new Lang({messages, fallback: 'da'})

I also added some helper functions to make it more laravel like

import {lang} from '@/helpers/lang'

export function trans(key, params = null) {
    return lang.get(key, params)
}

export function trans_choice(key, count, params = null) {
    return lang.choice(key, count, params)
}

To generate the json file I use this package from the same author https://github.com/rmariuzzo/Laravel-JS-Localization

And run

php artisan lang:js --json

For this to work you need to set up the path in the config file for the package

'path' => resource_path('js/i18n.json'),
2 likes
drfcozapata's avatar

@GankSt That's fine, but I don't think it's really useful for a large website with a lot of text to translate. Ideally make switch from locale and use the translations that already exist from Laravel, and just include additional files with your own texts, which is different than including the texts inside each Vue component. It is much easier to maintain and scale.

1 like
taekunger's avatar

I built a dynamic blade directive to inject a global translations helper like the one laravel uses to load its lang files __(key, paramerers)

Just load this service provider and include the directive within your layout file in the head section and enjoy the translation will be updated once you add new tokens to it.

Source: https://gist.github.com/nadyshalaby/669e6f251b942e7d91576f49cda6e879

1 like
Snapey's avatar

@taekunger isnt this something you would want to cache, or have as an artisan command you run when there are new translations?

2 likes
secondman's avatar

@kimmer

I have a package that handles Laravel style translations to Javascript.

https://github.com/jetstreamlabs/zora

It works very much like Ziggy but without the Blade directive.

It will load all your php or json languages, then compile them into a javascript file which you then use in your Inertia app.

It requires 2 aliases in vite config:

zora: resolve(__dirname, 'vendor/jetstreamlabs/zora/dist/vue.js'),
'zora-js': resolve(__dirname, 'vendor/jetstreamlabs/zora/dist/index.js'),

Compile the translations to resources/js in your dev and build steps in package.json:

"build:assets": "php artisan zora:generate",

Import zora and your compiled translations in app.js or wherever you implement your Inertia setup:

import { ZoraVue } from 'zora'
import { Zora } from '../zora.js'

Then use it in your app:

...
.use(ZoraVue, Zora)
...

Then in your Vue components you can use {{ __('Dashboard') }} or {{ trans('app.whatever') }}

I also have a composable for use in the script portion of components if you need a translation there:

// composables/useTrans.js

import { trans } from 'zora-js'
import { Zora } from '../zora.js'

export default function useTrans(key, replace) {
  return trans(key, replace, Zora)
}

I hope you find it useful.

1 like
mikield's avatar

@secondman awesome library. Good to mention you should also add

<script>
        window.locale = '{{ app()->getLocale() }}';
</script>

to your app.blade.php so that lib trans function will catch current locale.

1 like
Databee's avatar

@mikield Doesn't seem to work properly.

The keyed translations seem to work, but translations in individual json files don't.

I have en.json placed at lang/en.json.

The file loaded in the browser doesn't have it's contents, hence it is working as if there is no translation for the object:

const Lingua = {
    translations: {
        "en": {
            "php": {
                ...
                "en": {
                    "json": "en.json"
                },
                ...                
            },
            "json": []
        }
    }
}

export {Lingua}
1 like
mltefive's avatar

I just share translation lang/en.json

<?php

   'translation' => function () {
    return json_decode(file_get_contents(base_path('lang/'. app()->getLocale() .'.json')), true);
  },

3 likes
paulomfr's avatar

Hi all! I just released this one today. Hope that can help you all, and I appreciate if you can give a feedback.

https://github.com/linguijs/i18n

Note that you have a Laravel package to export your translations: https://github.com/linguijs/lingui-laravel

Plus a vite-plugin responsible to listen and re-generate your translations when you modify/add/remove it: https://github.com/linguijs/vite-plugin

I’m trying to build a complete solution for i18n on JavaScript side of Laravel.

I’m updating the docs to have some examples, but for now you can use a i18n.on(“changedLocale”, (locale) => {}) to change the App::setLocale on your back-side from a router.

1 like
vincent15000's avatar

I have developed a multi-language application with Laravel and VueJS.

Here is what I have done.

You will necessarily need a 3rd party package for the internationalization.

npm install vue-i18n

Then I have created these files to declare the different languages.

// languages/index.js

import action from './action.js';
import branch from './branch.js';
import user from './user.js';

const languages = {
    en: {
        action: action.en,
        branch: branch.en,
        user: user.en,
    },
    fr: {
        action: action.fr,
        branch: branch.fr,
        user: user.fr,
    }
};

export default languages;

And the translations files (here example with user.js).

You have to use this package in your Vue application and load the languages.

import { createI18n } from 'vue-i18n';
import languages from './languages';

let locale = localStorage.getItem('locale');

if (!locale) {
    localStorage.setItem('locale', 'fr');
    locale = 'fr';
}

const i18n = createI18n({
    locale: locale,
    fallbackLocale: 'fr',
    messages: languages,
});  

// Application
app.use(i18n);

And I have created a LanguageComponent to switch from one language to another.

<template>
    <form>
        <select class="outline-none appearence-none rounded px-2 py-1" id="language" v-model="$i18n.locale">
            <option value="en">{{ $t('language.english') }}</option>

            <option value="fr">{{ $t('language.french') }}</option>
        </select>
    </form>
</template>

<script setup>
</script>

And you can then use this in your different templates.

For example, this refers to the user.js file and the name property. The locale is selected via the global configuration of $i18n.locale.

<div>{{ $t('user.name') }}</div>
sergioluis's avatar

🌍 Reactive i18n Integration with Inertia.js, Vue 3, and Laravel

Hey everyone 👋

I’d like to share how I’m using vue-i18n in a reactive way within an Inertia.js + Vue 3 + Laravel stack.

The key is that usePage() from Inertia is reactive by default, and we use it to sync the frontend’s language and translations with Laravel’s backend automatically — no page reloads, no remounts.


⚙️ Laravel: 

HandleInertiaRequests.php

Below is the critical part of the middleware that shares locale and translation data reactively with Inertia.

🧠 What happens here

  • locale sends the current Laravel locale to Vue.

  • languages provides all supported language options.

  • translations dynamically calls getTranslations() to load the proper language files for the current page.

Together, these three lines keep the backend and frontend perfectly synchronized.

When Laravel’s locale changes, Vue detects it reactively via usePage() and updates all translations automatically.


🔍 The getTranslations() Method

This method dynamically loads the right translation files for each Inertia page.


🧩 Frontend:  useI18nSetup.ts

Here’s how the frontend picks up and reacts to those shared props from Laravel using vue-i18n and Inertia’s usePage().


🚀  app.ts

Finally, here’s how it’s initialized and made reactive after Inertia mounts.


💡 Result

  • When Laravel sends a new locale or updated translations through Inertia,

    Vue automatically detects the change via usePage() and updates all translated content.

  • The connection between backend and frontend stays fully reactive and seamless.

  • No page reloads, no re-mounting components — just pure reactivity.


In summary:

The combination of

'locale', 'languages', 'translations'

(lines 58–60 in HandleInertiaRequests.php)

and the watch() in useI18nSetup.ts makes vue-i18n + Inertia.js fully reactive across Laravel and Vue.

2 likes

Please or to participate in this conversation.