laravel-react-i18n is a React plugin that allows to connect your Laravel Framework translation files with React. It uses the same logic used on Laravel Localization.
- Laravel >= 9
- NodeJS >= 16
- Vite
With npm:
npm i laravel-react-i18n
or with yarn:
yarn add laravel-react-i18n
app.tsx:
import './bootstrap';
import '../css/app.css';
import { createRoot } from 'react-dom/client';
import { createInertiaApp } from '@inertiajs/react';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { LaravelReactI18nProvider } from 'laravel-react-i18n';
const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'Laravel';
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.tsx`, import.meta.glob('./Pages/**/*.tsx')),
setup({ el, App, props }) {
const root = createRoot(el);
root.render(
<LaravelReactI18nProvider
locale={'uk'}
fallbackLocale={'en'}
files={import.meta.glob('/lang/*.json')}
>
<App {...props} />
</LaravelReactI18nProvider>
);
},
progress: {
color: '#4B5563',
},
});
ssr.tsx:
import ReactDOMServer from 'react-dom/server';
import { createInertiaApp } from '@inertiajs/react';
import createServer from '@inertiajs/react/server';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import route from '../../vendor/tightenco/ziggy/dist/index.m';
import { LaravelReactI18nProvider } from 'laravel-react-i18n';
const appName = 'Laravel';
createServer((page) =>
createInertiaApp({
page,
render: ReactDOMServer.renderToString,
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.tsx`, import.meta.glob('./Pages/**/*.tsx')),
setup: ({ App, props }) => {
global.route = (name, params, absolute) =>
route(name, params, absolute, {
// @ts-expect-error
...page.props.ziggy,
// @ts-expect-error
location: new URL(page.props.ziggy.location),
});
return (
<LaravelReactI18nProvider
locale={'uk'}
fallbackLocale={'en'}
files={import.meta.glob('/lang/*.json', { eager: true })}
>
<App {...props} />
</LaravelReactI18nProvider>
);
},
})
);
In order to load php
translations, you can use this Vite
plugin.
vite.config.js:
import i18n from 'laravel-react-i18n/vite'; // <-- add this
export default defineConfig({
plugins: [
laravel([
'resources/css/app.css',
'resources/js/app.js'
]),
react(),
i18n(), // <-- add this
],
});
During the
npm run dev
execution time, the plugin will create some files like thisphp_{lang}.json
on your lang folder. And to avoid that to be commited to your code base, I suggest to your.gitignore
this like:
lang/php_*.json
locale
(optional): If not provided it will try to find from the<html lang="">
tag or seten
.fallbackLocale
(optional): If thelocale
was not provided or is invalid, it will try reach for thisfallbackLocale
instead, default it will try to find from the<html lang="">
tag or seten
.files
(required): The way to reach your language files.
<LaravelReactI18nProvider
locale={'ro'}
files={import.meta.glob('/lang/*.json')}
>
...
...
import { useLaravelReactI18n } from 'laravel-react-i18n';
export default function Component() {
const { t, tChoice, currentLocale, setLocale, getLocales, isLocale, loading } = useLaravelReactI18n();
...
}
The t()
method can translate a given message.
lang/pt.json:
{
"Welcome!": "Bem-vindo!",
"Welcome, :name!": "Bem-vindo, :name!"
}
welcome.tsx:
...
const { t } = useLaravelReactI18n();
t('Welcome!'); // Bem-vindo!
t('Welcome, :name!', { name: 'Francisco' }); // Bem-vindo Francisco!
t('Welcome, :NAME!', { name: 'Francisco' }); // Bem-vindo FRANCISCO!
t('Some untranslated'); // Some untranslated
...
The tChoice()
method can translate a given message based on a count,
there is also available an trans_choice
alias, and a mixin called $tChoice()
.
lang/pt.json:
{
"There is one apple|There are many apples": "Existe uma maça|Existe muitas maças",
"{0} There are none|[1,19] There are some|[20,*] There are many": "Não tem|Tem algumas|Tem muitas",
"{1} :count minute ago|[2,*] :count minutes ago": "{1} há :count minuto|[2,*] há :count minutos",
}
choice.tsx:
...
const { tChoice } = useLaravelReactI18n()
tChoice('There is one apple|There are many apples', 1); // Existe uma maça
tChoice('{0} There are none|[1,19] There are some|[20,*] There are many', 19); // Tem algumas
tChoice('{1} :count minute ago|[2,*] :count minutes ago', 10); // Há 10 minutos.
...
The currentLocale()
returns the locale that is currently being used.
const { currentLocale } = useLaravelReactI18n()
currentLocale(); // en
The setLocale()
can be used to change the locale during the runtime.
const { currentLocale, setLocale } = useLaravelReactI18n();
function handler() {
setLocale('it')
}
return (
<div>
<h1>Current locale: `{currentLocale()}`</h1>
<button onClick={handler}>Change locale to `it`</button>
</div>
)
The getLocales()
return string array with all locales available in folder /lang/*
.
/lang/..
de.json
en.json
nl.json
uk.json
myLocales.tsx:
const { getLocales } = useLaravelReactI18n();
getLocales(); // ['de', 'en', 'nl', 'uk']
The isLocale()
method checks the locale is available in folder /lang/*
.
const { isLocale } = useLaravelReactI18n();
isLocale('uk'); // true
isLocale('fr'); // false
The loading
show current loading state, only on client side where you change the locale.
const { loading, currentLocale, setLocale } = useLaravelReactI18n();
function handler() {
setLocale('it')
}
if (loading) return <p>Loading...</p>;
return (
<div>
<h1>Current locale: `{currentLocale()}`</h1>
<button onClick={handler}>Change locale to `it`</button>
</div>
)