Skip to content
Vue package

Laravel Localizer Vue

Use Laravel translations in Vue 3 and Inertia apps with a useLocalizer composable, reactive locale data and a Vite plugin that regenerates types.

pnpm add @devwizard/laravel-localizer-vue
View on GitHub
On this page

Overview

Laravel Localizer Vue is the Vue 3 frontend for Laravel Localizer. The Laravel package turns your language files into generated TypeScript; this package reads them in components through a useLocalizer() composable and ships a Vite plugin that re-runs the generator whenever a language file changes.

Locale, text direction and the list of available locales come from Inertia’s shared locale prop and are exposed as computed refs, so templates update when the server switches language. If you build with React instead, use Laravel Localizer React. The package is MIT licensed and maintained by the DevWizard core team.

Features

  • useLocalizer() composable returning __, trans, lang, has, choice, locale, dir, availableLocales, translations and getLocales.
  • locale, dir, availableLocales and translations are ComputedRef values.
  • Placeholder replacement in both :name and {name} styles.
  • Optional fallback text for missing keys.
  • Vite plugin, exported from the /vite entry, that regenerates the TypeScript files on build start and when language files change.
  • Exported types: Replacements, LocaleData, PageProps and UseLocalizerReturn.
  • ESM build with sideEffects disabled.

Requirements

  • Vue 3.
  • @inertiajs/vue3 1, 2 or 3.
  • Vite 5, 6, 7 or 8 for the plugin.
  • The Laravel Localizer backend package, with the middleware registered so the locale prop is shared.

Installation

Terminal
pnpm add @devwizard/laravel-localizer-vue

Other package managers:

Terminal
npm install @devwizard/laravel-localizer-vue
yarn add @devwizard/laravel-localizer-vue

Install the backend first if you have not already:

Terminal
composer require devwizardhq/laravel-localizer
php artisan localizer:install --framework=vue

Configuration

Generate the TypeScript files once, then wire up the Vite plugin and the global translations object.

Terminal
php artisan localizer:generate --all

Add the plugin to vite.config.ts:

TypeScript
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import laravel from 'laravel-vite-plugin';
import { laravelLocalizer } from '@devwizard/laravel-localizer-vue/vite';

export default defineConfig({
  plugins: [
    laravel({ input: ['resources/js/app.ts'], refresh: true }),
    vue(),
    laravelLocalizer(),
  ],
});

The plugin options, all optional:

Option Default Description
patterns ['lang/**', 'resources/lang/**'] Globs, relative to the project root, that trigger regeneration
command 'php artisan localizer:generate --all' Shell command to run
debug false Log extra messages about detected changes

The composable reads translations from window.localizer, so set it in your entry file before mounting the app:

TypeScript
import * as translations from './lang';

window.localizer = { translations };

Optionally declare the global type:

TypeScript
declare global {
  interface Window {
    localizer: {
      translations: typeof translations;
    };
  }
}

Usage

Call the composable in script setup:

Vue
<script setup lang="ts">
import { useLocalizer } from '@devwizard/laravel-localizer-vue';

const { __, dir } = useLocalizer();
</script>

<template>
  <section :dir="dir">
    <h1>{{ __('welcome') }}</h1>
    <p>{{ __('greeting', { name: 'Sam' }) }}</p>
  </section>
</template>

Replacements work with :name and {name} placeholders in the translation string. A missing key returns the fallback you pass as the third argument, or the key itself:

TypeScript
__('might.not.exist', {}, 'Default text');

Use has() to test for a key and choice() to pass a count into the string:

TypeScript
const { has, choice } = useLocalizer();

has('welcome');
choice('apples', 5, { unit: 'kg' });

API Reference

useLocalizer()

Member Type Description
__, trans, lang (key, replacements?, fallback?) => string Translate a key; the three are the same function
has (key) => boolean Whether the key exists for the current locale
choice (key, count, replacements?) => string Translate and substitute count
locale ComputedRef<string> Current locale, 'en' if the prop is missing
dir ComputedRef of 'ltr' or 'rtl' Text direction, 'ltr' if missing
availableLocales ComputedRef of label, flag and dir Locales from the shared prop
translations ComputedRef<Record<string, string>> All strings for the current locale
getLocales () => string[] Locale codes

choice() adds count to the replacements and translates the key. It does not split pipe-separated plural forms, so the string itself must contain the wording you want, for example You have :count apples.

Vite plugin

laravelLocalizer(options) from @devwizard/laravel-localizer-vue/vite, also its default export. It runs command on build start and on hot updates of files matching patterns. The command runs asynchronously and errors are reported through Vite.

Examples

A locale switcher built from the shared props. It assumes the backend middleware reads the locale query parameter:

Vue
<script setup lang="ts">
import { router } from '@inertiajs/vue3';
import { useLocalizer } from '@devwizard/laravel-localizer-vue';

const { locale, availableLocales } = useLocalizer();

const change = (code: string) => router.get(window.location.pathname, { locale: code });
</script>

<template>
  <select :value="locale" @change="change(($event.target as HTMLSelectElement).value)">
    <option v-for="(meta, code) in availableLocales" :key="code" :value="code">
      {{ meta.flag }} {{ meta.label }}
    </option>
  </select>
</template>

Handle a right-to-left layout by binding dir:

Vue
<main :dir="dir"><slot /></main>

Point the plugin at a custom command, for example when PHP runs in a container:

TypeScript
laravelLocalizer({
  command: 'docker compose exec app php artisan localizer:generate --all',
  debug: true,
});

FAQ & Troubleshooting

The console warns that translations are not initialized. Set window.localizer = { translations } in your entry file before mounting, using the index generated by localizer:generate.

Keys show instead of text. Check that the locale prop is shared (the Laravel middleware must be registered) and that a generated file exists for the current locale.

Do I need .value on locale and dir? In script code yes, because they are computed refs. In templates they unwrap automatically.

Does choice() handle singular and plural forms? No. It only substitutes count. Provide a string such as :count apples or choose the wording in your component.

Translations do not update during development. Confirm the plugin is in vite.config.ts and that php is on the path where Vite runs. Turn on debug to see the change detection messages.

Changelog & Support

Release history is in the CHANGELOG and on the GitHub releases page. Open bugs and feature requests in GitHub issues. Source: DevWizardHQ/laravel-localizer-vue. Using React instead? See Laravel Localizer React. For help with multilingual products, the DevWizard team takes project contracts and monthly retainers through the contact page.