はじめに
こんにちは、エンジニアのkeitaMaxです。
Laravel11とInertia,React,TypeScriptで多言語化対応したいと思います。
PHP側の修正
まずPHPからReactに翻訳したいファイルを送れるように、
HandleInertiaRequests
に以下を追加します。
public function share(Request $request): array
{
// 追加 ↓
$fullLang = $request->getPreferredLanguage();
$lang = strtok($fullLang, '_');
$defaultLocale = config('app.locale');
$json = lang_path("{$lang}/front.json");
//NOTE: 用意していない言語ならデフォルトを使用
if (!file_exists($json)) {
$json = lang_path("{$defaultLocale}/front.json");
}
$content = file_get_contents($json);
if ($content === false) {
throw new Exception('ファイルの読み込みに失敗しました');
}
$translations = json_decode($content, true);
// 追加 ↑
return [
...parent::share($request),
// 追加 ↓
'translations' => $translations,
// 追加 ↑
'auth' => [
'user' => $request->user(),
],
'flash' => [
'message' => fn() => $request->session()->get('message'),
],
];
}
実際にの翻訳ファイルは以下のファイルにおきます。
今回は日本語と英語の2つで設定をします。
src/lang/en/front.json
src/lang/ja/front.json
{
"Good morning!": "Good morning"
}
{
"Good morning!": "こんにちは"
}
React側の修正
PHPから送られてきた翻訳ファイルを受け取るために、
src/resources/js/app.tsx
ファイルを以下のように修正します。
const appName = import.meta.env.VITE_APP_NAME || 'Laravel'
// 追加 ↓
declare global {
function __(key: string, replace?: Record<string, unknown>): string;
}
// 追加 ↑
createInertiaApp({
title: (title) => `${title} ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}/index.tsx`, import.meta.glob('./Pages/**/*.tsx')),
setup({ el, App, props }) {
const root = createRoot(el)
// 追加 ↓
const translations = Object(props.initialPage.props.translations)
window.__ = (key: string, replace?: Record<string, unknown>): string => {
let translatedText: string = translations[key] || key
for (const key in replace) {
const replacedText = String(replace[key as keyof typeof replace])
translatedText = translatedText.replace(`:${key}`, replacedText)
}
return translatedText
}
// 追加 ↑
root.render(<App {...props} />)
},
これで準備はOKです。
実際にやってみる
実際に多言語化対応をしたい時は、以下のようにReact側で書くとブラウザの言語によって変わります。
<p>{__('Good morning!')}</p>
こうすると英語の時はGood morning
,日本語の時はこんにちは
と表示されるようになります。
おわりに
この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。
最後まで読んでいただきありがとうございました!