On this page
Overview
Laravel Localizer React is the React frontend for Laravel Localizer. The Laravel package turns your language files into generated TypeScript; this package reads them in components through a useLocalizer() hook and ships a Vite plugin that re-runs the generator whenever a language file changes.
The hook reads the current locale and text direction from Inertia’s shared locale prop, so switching language on the server updates the whole UI. If you build with Vue instead, use Laravel Localizer Vue. The package is MIT licensed and maintained by the DevWizard core team.
Features
useLocalizer()hook returning__,trans,lang,has,choice,locale,dir,availableLocales,translationsandgetLocales.- Placeholder replacement in both
:nameand{name}styles. - Optional fallback text for missing keys.
- Locale and RTL direction taken from Inertia page props.
- Vite plugin, exported from the
/viteentry, that regenerates the TypeScript files on build start and when language files change. - Exported types:
Replacements,LocaleData,PagePropsandUseLocalizerReturn. - ESM build with
sideEffectsdisabled.
Requirements
- React 18 or 19.
@inertiajs/react1 or 2.- Vite 5, 6, 7 or 8 for the plugin.
- The Laravel Localizer backend package, with the middleware registered so the
localeprop is shared.
Installation
pnpm add @devwizard/laravel-localizer-reactOther package managers:
npm install @devwizard/laravel-localizer-react
yarn add @devwizard/laravel-localizer-reactInstall the backend first if you have not already:
composer require devwizardhq/laravel-localizer
php artisan localizer:install --framework=reactConfiguration
Generate the TypeScript files once, then wire up the Vite plugin and the global translations object.
php artisan localizer:generate --allAdd the plugin to vite.config.ts:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import laravel from 'laravel-vite-plugin';
import { laravelLocalizer } from '@devwizard/laravel-localizer-react/vite';
export default defineConfig({
plugins: [
laravel({ input: ['resources/js/app.tsx'], refresh: true }),
react(),
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 hook reads translations from window.localizer, so set it in your entry file before rendering:
import * as translations from './lang';
window.localizer = { translations };Optionally declare the global type:
declare global {
interface Window {
localizer: {
translations: typeof translations;
};
}
}Usage
Call the hook in any component under an Inertia page:
import { useLocalizer } from '@devwizard/laravel-localizer-react';
export function Welcome() {
const { __, dir } = useLocalizer();
return (
<section dir={dir}>
<h1>{__('welcome')}</h1>
<p>{__('greeting', { name: 'Sam' })}</p>
</section>
);
}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:
__('might.not.exist', {}, 'Default text');Use has() to test for a key and choice() to pass a count into the string:
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 |
string |
Current locale, 'en' if the prop is missing |
dir |
'ltr' or 'rtl' |
Text direction, 'ltr' if missing |
availableLocales |
Record of label, flag and dir |
Locales from the shared prop |
translations |
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-react/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 a route on your server that stores the chosen locale, such as a link with the locale query parameter that the backend middleware reads:
import { router } from '@inertiajs/react';
import { useLocalizer } from '@devwizard/laravel-localizer-react';
export function LocaleSwitcher() {
const { locale, availableLocales } = useLocalizer();
return (
<select
value={locale}
onChange={(e) => router.get(window.location.pathname, { locale: e.target.value })}
>
{Object.entries(availableLocales).map(([code, meta]) => (
<option key={code} value={code}>
{meta.flag} {meta.label}
</option>
))}
</select>
);
}Handle a right-to-left layout by reading dir:
const { dir } = useLocalizer();
return <main dir={dir}>{children}</main>;Point the plugin at a custom command, for example when PHP runs in a container:
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 the app renders, 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.
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.
Which Inertia version works? The peer range is @inertiajs/react 1.x or 2.x.
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-react. Using Vue instead? See Laravel Localizer Vue. For help with multilingual products, the DevWizard team takes project contracts and monthly retainers through the contact page.