laravel-vue-i18n keeps Laravel PHP translation files in charge of the Vue frontend
Allows to connect your `Laravel` Framework translation files with `Vue`.
At a glance
- What is it?
- laravel-vue-i18n is a Vue3 plugin that reads the same PHP language files Laravel already uses, with an optional Vite plugin that compiles them to JSON at build time. It removes the duplicate translation store, at the cost of a build step that parses PHP without executing it.
- Who is it for?
- This package fits a Laravel application whose frontend is Vue 3 and whose team wants one set of translation files rather than a JSON copy maintained alongside the PHP originals. It is a poor fit for a project that has already committed to static JSON bundles, for a backend that needs pluralisation rules the plugin cannot express, or for teams unwilling to run a PHP parsing step inside the frontend build.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 37 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One set of language files instead of a second store in JavaScript
Laravel keeps its translations as PHP files under a lang directory, and a Vue frontend normally wants JSON. That gap is where duplicate translation stores come from, and laravel-vue-i18n is a Vue3 plugin that closes it. The project describes itself as connecting Laravel Framework translation files with Vue, and states that it uses the same logic used on Laravel Localization, so plural and fallback behaviour should not feel like a translation API invented separately. The package is written in TypeScript and published on npm as laravel-vue-i18n under the MIT licence, with the repository on the main branch. The audience is a Laravel team that has already chosen Vue for the frontend and does not want to maintain a parallel set of JSON message files that drifts away from the PHP originals on every translation change.
The resolve callback is the only required option
The plugin is registered with the standard Vue plugin signature, and the options object is small. The resolve option is the only required one, and it is the seam where the frontend decides where translation JSON comes from. The lang option is optional: without it, the plugin looks for the lang attribute on the html tag, which is what most server rendered Laravel responses already provide. The fallbackLang option defaults to en and is consulted when the lang is missing or invalid, while fallbackMissingTranslations controls the different case where the language is valid but the requested key does not exist in it, falling back to the fallbackLang instead. That distinction between a missing language and a missing key is the part of the configuration worth reading carefully, because it decides whether a typo in a key silently renders English.
Setting up the plugin with Vite and import.meta.glob
With Vite, the resolver globs the JSON language files and imports the one matching the requested language. The plugin is installed with npm or yarn, and the same registration code works for a client side application.
import { createApp } from 'vue'
import { i18nVue } from 'laravel-vue-i18n'
createApp()
.use(i18nVue, {
resolve: async lang => {
const langs = import.meta.glob('../../lang/*.json');
return await langs[`../../lang/${lang}.json`]();
}
})
.mount('#app');The resolver returns a promise, and the glob pattern is what allows the bundler to know every candidate file at build time. In a Vite project the JSON files are the ones the plugin below generates, so the two halves of this setup are meant to be used together.
The Vite plugin parses PHP language files without running them
The Vite side of the package exists so the frontend can consume the PHP originals directly. It is added to vite.config.js as laravel-vue-i18n/vite, and for Laravel 9 or later it takes no arguments. For older layouts, where the lang folder sits inside the resources folder, the path is passed as a parameter instead. The documentation is precise about behaviour in several places. Relative translation paths resolve from the Vite root, which is the project directory by default, and absolute paths are supported. Nested PHP translations and configurations containing only additional translation paths are supported. During development, editing, adding or deleting a PHP translation in any configured directory regenerates the JSON files and reloads the page. Generated files are cleaned up when the server or build closes, and files that existed before generation are restored. Two constraints are stated for parallel work: parallel builds sharing an output directory should use the same translation configuration, and separate processes should run client and SSR builds sequentially.
Closures and function calls are skipped, so dynamic keys never arrive
The PHP loader extracts static strings and arrays, and it skips unsupported values such as closures, function calls and variable expressions. It does not execute PHP, and other files inside locale directories are ignored. That is a deliberate safety property, since a build step that ran application code would be a different kind of risk, but it also defines the boundary of the approach. A language file that builds a message with a helper function or a concatenation at runtime will not produce a usable JSON entry, and the failure appears as a missing translation rather than as a build error. Anyone adopting this should scan their lang files for dynamic construction before assuming the whole set can be compiled.
Additional paths, and which one wins when a key is duplicated
The Vite plugin accepts a langPath option and an additionalLangPaths list, which is the way to pull translations from a second location, for example an overriding package shipped in public/locales. When the same key is found in two configured paths, the documentation is explicit that priority goes to the last path given between the two. In the example configuration the comment says the key will be loaded from public/locales, because that path is listed last.
i18n({
// you can also change your langPath here
// langPath: 'locales'
additionalLangPaths: [
'public/locales' // Load translations from this path too!
]
}),One operational detail comes with this. During npm run dev the plugin creates files named php_{lang}.json inside the lang folder, which the README suggests excluding from version control with a gitignore entry.
lang/php_*.jsonServer side rendering flips the resolver from a promise to a value
The SSR path is the opposite of the client path and the difference trips people up. For server side rendering the resolve method should not receive a Promise, and instead should take advantage of the eager parameter, returning the default export of the globbed module directly. The plugin documentation notes that the setup shown for Vite+ stays the same, and that Vite+ itself is optional because the package does not install it. The Mix and Webpack story is thinner: Laravel Mix still has a plugin entry point, but the README presents the PHP translation pipeline only for the Vite plugin, and it does not describe a Mix equivalent for compiling PHP language files.
MIT licensed, packaged as dual ESM and CJS with a vite subpath
The package ships from the dist directory, with main pointing at dist/index.cjs and module at dist/index.mjs, and the exports map exposing both import and require conditions with separate type declarations for each. A wildcard subpath export lets consumers reach individual build outputs, and typesVersions maps the vite entry to dist/vite.d.ts. The build itself runs through tsdown, with tsdown.config.mts at the root, and the test tooling is vitest with separate type and integration test scripts. The licence is MIT, so the only obligation is retaining the notice in copies, and nothing in the packaging ties the runtime to a Laravel version. The release history shows steady work: v2.7.8 on 2024-10-28, v2.8.0 on 2025-03-29, and v2.9.0 on 2026-09-16, with the last push to the repository on 2026-09-16.
Editorial conclusion
This package fits a Laravel application whose frontend is Vue 3 and whose team wants one set of translation files rather than a JSON copy maintained alongside the PHP originals. It is a poor fit for a project that has already committed to static JSON bundles, for a backend that needs pluralisation rules the plugin cannot express, or for teams unwilling to run a PHP parsing step inside the frontend build. Verify three things before adopting it: that your language files use only static strings and arrays, since closures and function calls are skipped; that your build runs client and SSR bundles sequentially, which the plugin documentation requires; and that the fallback chain of lang, fallbackLang and fallbackMissingTranslations matches how your team handles missing keys. The last push was on 2026-09-16 and the current release is v2.9.0, so the code is being worked on, and the MIT licence carries no obligation beyond keeping the notice in place.
Frequently asked questions
How do I install laravel-vue-i18n in a Vue 3 application?
The package is published on npm, so it is installed with npm i laravel-vue-i18n or with yarn add laravel-vue-i18n. It is then registered on the Vue app with the i18nVue plugin, which requires a resolve option telling it where to load translation JSON from.
Can laravel-vue-i18n use my Laravel PHP translation files directly?
Yes, through the Vite plugin exposed as laravel-vue-i18n/vite, which compiles PHP language files into JSON files that the frontend resolver then loads. The PHP loader extracts static strings and arrays and does not execute PHP, so closures, function calls and variable expressions are skipped.
What happens when a translation key is missing in the current language?
The plugin falls back according to its options. fallbackLang, which defaults to en, is used when the lang is missing or invalid, and fallbackMissingTranslations makes the same fallback happen when the language is valid but the key does not exist in it.
Does laravel-vue-i18n work with server side rendering?
Yes, but the resolver changes shape. For SSR the resolve method should not return a Promise and should use the eager parameter, returning the default export of the globbed JSON module instead.
Why are php_*.json files appearing in my lang folder?
The Vite plugin generates files named php_{lang}.json in the lang folder during npm run dev, and the README suggests adding lang/php_*.json to your .gitignore so they are not committed.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/xico2k-laravel-vue-i18n)Was this useful?