🌊
Inertia.js + breeze + react環境での日本語化したものを作った
以下。セットアップは一般的なlaravelのdeployに従う。特に難しい事はしてない。
ログイン画面
とか
Profile更新画面
とか
以下作成ログ
laravel-react-i18n
これはバックエンドのものでは無いため、composerというかpackagistには存在していない。githubのREADMEにあるようにnpmでinstallする。
npm i laravel-react-i18n
vite.config.jsの変更
@@ -1,6 +1,7 @@
import { defineConfig, loadEnv } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';
+import i18n from 'laravel-react-i18n/vite';
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
@@ -20,6 +21,7 @@ export default defineConfig(({ mode }) => {
refresh: true,
}),
react(),
+ i18n(),
],
};
});
こんな感じでpluginにてi18n()
をcallしてロード。
resources/js/app.jsxの変更
これは素のreactであった場合
breezeで展開されただけのresources/js/app.jsx
resources/js/app.jsx
import '../css/app.css';
import './bootstrap';
import { createInertiaApp } from '@inertiajs/react';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { createRoot } from 'react-dom/client';
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) =>
resolvePageComponent(
`./Pages/${name}.jsx`,
import.meta.glob('./Pages/**/*.jsx')
),
setup({ el, App, props }) {
const root = createRoot(el);
root.render(<App {...props} />);
},
progress: {
color: '#4B5563',
},
});
変更
import './bootstrap';
import { createInertiaApp } from '@inertiajs/react';
+import { LaravelReactI18nProvider } from 'laravel-react-i18n';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { createRoot } from 'react-dom/client';
@@ -17,7 +18,15 @@ createInertiaApp({
setup({ el, App, props }) {
const root = createRoot(el);
- root.render(<App {...props} />);
+ root.render(
+ <LaravelReactI18nProvider
+ locale={'ja'}
+ fallbackLocale={'en'}
+ files={import.meta.glob('/lang/*.json')}
+ >
+ <App {...props} />
+ </LaravelReactI18nProvider>
+ );
},
progress: {
color: '#4B5563',
まあ用するに
<LaravelReactI18nProvider>
<App />
</LaravelReactI18nProvider>
のようにwrapするという事になりますね。
ログインページを書き換えてみる
breezeで展開した場合 resources/js/Pages/Auth/Login.jsx に存在しているはずだ。
これを以下のように書き換えていく。
--- a/resources/js/Pages/Auth/Login.jsx
+++ b/resources/js/Pages/Auth/Login.jsx
@@ -5,8 +5,10 @@ import PrimaryButton from '@/Components/PrimaryButton';
import TextInput from '@/Components/TextInput';
import GuestLayout from '@/Layouts/GuestLayout';
import { Head, Link, useForm } from '@inertiajs/react';
+import { useLaravelReactI18n } from 'laravel-react-i18n';
export default function Login({ status, canResetPassword }) {
+ const { t } = useLaravelReactI18n();
const { data, setData, post, processing, errors, reset } = useForm({
email: '',
password: '',
@@ -23,7 +25,7 @@ export default function Login({ status, canResetPassword }) {
return (
<GuestLayout>
- <Head title='Log in' />
+ <Head title={t('Log in')} />
{status && (
<div className='mb-4 text-sm font-medium text-green-600'>{status}</div>
@@ -31,7 +33,7 @@ export default function Login({ status, canResetPassword }) {
<form onSubmit={submit}>
<div>
- <InputLabel htmlFor='email' value='Email' />
+ <InputLabel htmlFor='email' value={t('Email')} />
<TextInput
id='email'
@@ -48,7 +50,7 @@ export default function Login({ status, canResetPassword }) {
</div>
<div className='mt-4'>
- <InputLabel htmlFor='password' value='Password' />
+ <InputLabel htmlFor='password' value={t('Password')} />
<TextInput
id='password'
@@ -70,7 +72,9 @@ export default function Login({ status, canResetPassword }) {
checked={data.remember}
onChange={(e) => setData('remember', e.target.checked)}
/>
- <span className='ms-2 text-sm text-gray-600'>Remember me</span>
+ <span className='ms-2 text-sm text-gray-600'>
+ {t('Remember me')}
+ </span>
</label>
</div>
@@ -80,12 +84,12 @@ export default function Login({ status, canResetPassword }) {
href={route('password.request')}
className='rounded-md text-sm text-gray-600 underline hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2'
>
- Forgot your password?
+ {t('Forgot your password?')}
</Link>
)}
<PrimaryButton className='ms-4' disabled={processing}>
- Log in
+ {t('Log in')}
</PrimaryButton>
</div>
</form>
laravel-langを導入する
言語ファイルを自力で展開してもいいんだけど、面倒なのでここはlaravel-lang
を使う
composer require laravel-lang/lang
php artisan lang:add ja
LaravelReactI18nProviderをハードコードしない場合
実は、ドキュメントもあるように
<LaravelReactI18nProvider
// locale={'ja'}
fallbackLocale={'en'}
files={import.meta.glob('/lang/*.json')}
>
こんな具合にすると<html lang="">
の値から読みこまれる。これは resources/views/app.blade.php という雛形から読みこまれるが
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
このように定義されているので、結局 .envで
APP_LOCALE=ja
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US
APP_PORT=8000
この辺をしっかりセットしておけばハードコードする必要はない(fallbackは不明だけどまあenになるんじゃないかな...興味あれば調べてみてください)
なお
const { t, currentLocale } = useLaravelReactI18n();
として、適当なところで
<strong>{currentLocale()}</strong>
とかすれば現在のlocaleの設定は見られます(もちろんconsoleに送ってもok)
その他のページ
イチイチ全部書き換えていくのは相当面倒なので冒頭のソースを参考にしてください。まあ、半分以上AIにやらせてます。
Discussion