Skip to content

Commit a498fa4

Browse files
committed
Enabled multilingual support for locale using i18next
1 parent 95895a4 commit a498fa4

14 files changed

Lines changed: 499 additions & 317 deletions

File tree

frontend/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5-
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
5+
<link rel="icon" type="image/svg+xml" href="/registered.svg" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<title>Re:Fuel</title>
88
</head>

frontend/package-lock.json

Lines changed: 354 additions & 294 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616
"dependencies": {
1717
"@tanstack/react-query": "^5.80.6",
1818
"@tanstack/react-query-devtools": "^5.80.7",
19+
"i18next": "^25.2.1",
20+
"i18next-browser-languagedetector": "^8.2.0",
1921
"react": "^19.1.0",
2022
"react-dom": "^19.1.0",
2123
"react-hook-form": "^7.57.0",
24+
"react-i18next": "^15.5.3",
2225
"react-router-dom": "^7.6.2",
2326
"styled-components": "^6.1.18",
2427
"zustand": "^5.0.5"
10.3 KB
Binary file not shown.

frontend/public/registered.svg

Lines changed: 7 additions & 0 deletions
Loading

frontend/public/vite.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

frontend/src/assets/react.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

frontend/src/components/common/molecules/Header.tsx

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22
import styled from 'styled-components';
3+
import { useTranslation } from 'react-i18next';
34
import Button from '../atoms/Button';
45

56
const HeaderWrapper = styled.header`
@@ -28,18 +29,50 @@ const Logo = styled.h1`
2829
color: #1d1d1f;
2930
`;
3031

32+
const LanguageSwitcher = styled.div`
33+
margin-left: 1rem;
34+
display: flex;
35+
gap: 0.5rem;
36+
`;
37+
3138
interface HeaderProps {
3239
onAddNewComplex: () => void;
3340
}
3441

3542
const Header: React.FC<HeaderProps> = ({ onAddNewComplex }) => {
43+
const { t, i18n } = useTranslation();
44+
45+
const changeLanguage = (lng: string) => {
46+
i18n.changeLanguage(lng);
47+
};
48+
3649
return (
3750
<HeaderWrapper>
3851
<NavContainer>
39-
<Logo>Re:Fuel</Logo>
40-
<Button variant="primary" size="small" onClick={onAddNewComplex}>
41-
新しいコンプレックスを登録
42-
</Button>
52+
<Logo>{t('headerTitle')}</Logo>
53+
<div style={{ display: 'flex', alignItems: 'center' }}>
54+
<Button variant="primary" size="small" onClick={onAddNewComplex}>
55+
{t('addNewComplexButton')}
56+
</Button>
57+
<LanguageSwitcher>
58+
<Button
59+
size="small"
60+
variant="secondary"
61+
onClick={() => changeLanguage('ja')}
62+
disabled={i18n.resolvedLanguage === 'ja'}
63+
>
64+
JA
65+
</Button>
66+
<Button
67+
size="small"
68+
variant="secondary"
69+
onClick={() => changeLanguage('en')}
70+
disabled={i18n.resolvedLanguage === 'en'}
71+
>
72+
EN
73+
</Button>
74+
</LanguageSwitcher>
75+
</div>
4376
</NavContainer>
4477
</HeaderWrapper>
4578
);

frontend/src/components/complexes/organisms/NoComplexesMessage.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22
import styled from 'styled-components';
3+
import { useTranslation } from 'react-i18next';
34
import Button from '../../common/atoms/Button';
45

56
const MessageWrapper = styled.div`
@@ -41,6 +42,7 @@ interface NoComplexesMessageProps {
4142
const NoComplexesMessage: React.FC<NoComplexesMessageProps> = ({
4243
onAddNewComplex,
4344
}) => {
45+
const { t } = useTranslation();
4446
return (
4547
<MessageWrapper>
4648
<IconWrapper>
@@ -59,13 +61,11 @@ const NoComplexesMessage: React.FC<NoComplexesMessageProps> = ({
5961
/>
6062
</svg>
6163
</IconWrapper>
62-
<Title>コンプレックスがまだありません</Title>
63-
<Subtitle>
64-
最初のコンプレックスを登録して、自己分析を始めましょう。
65-
</Subtitle>
64+
<Title>{t('noComplexesTitle')}</Title>
65+
<Subtitle>{t('noComplexesSubtitle')}</Subtitle>
6666
<ButtonWrapper>
6767
<Button variant="primary" onClick={onAddNewComplex}>
68-
コンプレックスを登録する
68+
{t('registerComplexButton')}
6969
</Button>
7070
</ButtonWrapper>
7171
</MessageWrapper>

frontend/src/i18n.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import i18n from 'i18next';
2+
import { initReactI18next } from 'react-i18next';
3+
import LanguageDetector from 'i18next-browser-languagedetector';
4+
5+
// 翻訳JSONファイルのインポート
6+
import translationEN from './locales/en/translation.json';
7+
import translationJA from './locales/ja/translation.json';
8+
9+
const resources = {
10+
en: {
11+
translation: translationEN,
12+
},
13+
ja: {
14+
translation: translationJA,
15+
},
16+
};
17+
18+
i18n
19+
.use(LanguageDetector) // ブラウザの言語設定を検出
20+
.use(initReactI18next) // react-i18nextの初期化
21+
.init({
22+
resources,
23+
fallbackLng: 'ja', // デフォルトの言語
24+
// eslint-disable-next-line no-undef
25+
debug: process.env.NODE_ENV === 'development', // 開発モード時のみデバッグ情報を出力
26+
27+
interpolation: {
28+
escapeValue: false, // ReactはXSS対策済みなのでfalse
29+
},
30+
31+
detection: {
32+
// 言語検出の順序と方法
33+
order: [
34+
'querystring',
35+
'cookie',
36+
'localStorage',
37+
'sessionStorage',
38+
'navigator',
39+
'htmlTag',
40+
'path',
41+
'subdomain',
42+
],
43+
caches: ['localStorage', 'cookie'], // 検出された言語を保存する場所
44+
},
45+
});
46+
47+
export default i18n;

0 commit comments

Comments
 (0)