Skip to content
This repository has been archived by the owner on Mar 30, 2023. It is now read-only.

Commit

Permalink
feat: add i18next
Browse files Browse the repository at this point in the history
  • Loading branch information
w3labkr committed Aug 11, 2022
1 parent fd5b85a commit 740f082
Show file tree
Hide file tree
Showing 20 changed files with 192 additions and 32 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,5 @@ yarn add @mui/icons-material
## react-i18next

```shell
npm install react-i18next i18next --save
yarn add react-i18next i18next
```
1 change: 1 addition & 0 deletions craco.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module.exports = {
'@images': path.resolve(__dirname, 'src/assets/images'),
'@components': path.resolve(__dirname, 'src/components'),
'@contexts': path.resolve(__dirname, 'src/contexts'),
'@locales': path.resolve(__dirname, 'src/locales'),
'@pages': path.resolve(__dirname, 'src/pages'),
'@store': path.resolve(__dirname, 'src/store'),
'@templates': path.resolve(__dirname, 'src/templates')
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^14.4.2",
"i18next": "^21.9.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^11.18.3",
"react-scripts": "5.0.1",
"recoil": "^0.7.4",
"web-vitals": "^2.1.4"
Expand Down
2 changes: 1 addition & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ThemeProvider, createTheme } from "@mui/material/styles";
import CssBaseline from "@mui/material/CssBaseline";
import { modeState } from "@store/theme";
import { ColorModeContext } from "@contexts/theme";
import Page from "@pages";
import Page from "@pages/home";

function App() {
const [mode, setMode] = useRecoilState(modeState);
Expand Down
36 changes: 36 additions & 0 deletions src/components/header/ChangeLanguage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as React from 'react';
import { useRecoilState } from "recoil";
import { useTranslation } from 'react-i18next';
import MuiToggleButton from '@mui/material/ToggleButton';
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
import { styled } from "@mui/material/styles";
import { languageState } from "@store/theme";

const ToggleButton = styled(MuiToggleButton)({
"&.Mui-selected, &.Mui-selected:hover": {
color: "white"
}
});

export default function ChangeLanguage() {
const { i18n } = useTranslation();
const [language, setLanguage] = useRecoilState(languageState);
const handleChangeLanguage = (event, newLanguage) => {
if (newLanguage) {
i18n.changeLanguage(newLanguage);
setLanguage(newLanguage);
}
};

return (
<ToggleButtonGroup
size="small"
value={language}
exclusive
onChange={handleChangeLanguage}
>
<ToggleButton value="en">EN</ToggleButton>
<ToggleButton value="ko">KO</ToggleButton>
</ToggleButtonGroup>
);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import IconButton from "@mui/material/IconButton";
import MoreIcon from "@mui/icons-material/MoreVert";

export default function MoreButton() {
export default function MoreActions() {
return (
<IconButton aria-label="display more actions" edge="end" color="inherit">
<MoreIcon />
Expand Down
14 changes: 8 additions & 6 deletions src/components/main/CharactersLength.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import * as React from "react";
import { useTranslation } from "react-i18next";
import Typography from "@mui/material/Typography";
import Slider from "@mui/material/Slider";

export default function CharactersLength() {
const { t } = useTranslation();

return (
<React.Fragment>
<Typography>
Characters Length: 0 - 9
{t("characters length")}: 10
</Typography>
<Slider
getAriaLabel={() => "Temperature range"}
// value={value}
// onChange={handleChange}
defaultValue={10}
aria-label="Small"
valueLabelDisplay="auto"
// getAriaValueText={valuetext}
disableSwap
min={0}
max={20}
/>
</React.Fragment>
);
Expand Down
5 changes: 4 additions & 1 deletion src/components/main/CharactersUsed.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import * as React from "react";
import { useTranslation } from "react-i18next";
import Typography from "@mui/material/Typography";
import FormGroup from "@mui/material/FormGroup";
import FormControlLabel from "@mui/material/FormControlLabel";
import Checkbox from "@mui/material/Checkbox";

export default function CharactersUsed() {
const { t } = useTranslation();

return (
<React.Fragment>
<Typography>
Characters Used:
{t("characters used")}:
</Typography>
<FormGroup sx={{ display: "flex", flexDirection: "row", mb: 1 }}>
<FormControlLabel
Expand Down
9 changes: 6 additions & 3 deletions src/components/main/Content.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import * as React from "react";
import { useTranslation } from "react-i18next";
import Grid from "@mui/material/Grid";
import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography";
import TextField from "@mui/material/TextField";

export default function Content() {
const { t } = useTranslation();

return (
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<Typography variant="h6" component="h3">
Input
{t("input")}
</Typography>
<TextField
required
Expand All @@ -22,7 +25,7 @@ export default function Content() {
</Grid>
<Grid item xs={12} sm={6}>
<Typography variant="h6" component="h3">
Output
{t("output")}
</Typography>
<TextField
multiline
Expand All @@ -37,7 +40,7 @@ export default function Content() {
</Grid>
<Grid item xs={12}>
<Button variant="contained" size="large">
Submit
{t("shuffle & copy")}
</Button>
</Grid>
</Grid>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import * as React from "react";
import { useTranslation } from "react-i18next";
import Switch from "@mui/material/Switch";
import Divider from "@mui/material/Divider";
import CharactersUsed from "@components/main/CharactersUsed";
import CharactersLength from "@components/main/CharactersLength";
import StopWords from "@components/main/StopWords";

export default function RandomWords() {
export default function RandomWord() {
const { t } = useTranslation();

return (
<React.Fragment>
<Divider sx={{ fontWeight: "700" }}>
Random Words <Switch />
{t("random word")} <Switch />
</Divider>
<CharactersUsed />
<CharactersLength />
Expand Down
19 changes: 11 additions & 8 deletions src/components/main/Settings.jsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,45 @@
import * as React from "react";
import { useTranslation } from "react-i18next";
import Typography from "@mui/material/Typography";
import Grid from "@mui/material/Grid";
import TextField from "@mui/material/TextField";
import Switch from "@mui/material/Switch";
import RandomWords from "@components/main/RandomWords";
import RandomWord from "@components/main/RandomWord";

export default function Settings() {
const { t } = useTranslation();

return (
<React.Fragment>
<Typography variant="h4" component="h2" sx={{ mb: 2, fontWeight: "700" }}>
Customize Prefix and Suffix
{t("set additional string")}
</Typography>
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<Typography variant="h6" component="h3">
Prefix <Switch defaultChecked />
{t("prepend to string")} <Switch defaultChecked />
</Typography>
<TextField
defaultValue=""
placeholder="Please enter text"
placeholder={t("please enter text")}
variant="outlined"
fullWidth
sx={{ mb: 1 }}
/>
<RandomWords />
<RandomWord />
</Grid>
<Grid item xs={12} sm={6}>
<Typography variant="h6" component="h3">
Suffix <Switch defaultChecked />
{t("append after string")} <Switch defaultChecked />
</Typography>
<TextField
defaultValue=""
placeholder="Please enter text"
placeholder={t("please enter text")}
variant="outlined"
fullWidth
sx={{ mb: 1 }}
/>
<RandomWords />
<RandomWord />
</Grid>
</Grid>
</React.Fragment>
Expand Down
9 changes: 6 additions & 3 deletions src/components/main/StopWords.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import * as React from "react";
import { useTranslation } from "react-i18next";
import Typography from "@mui/material/Typography";
import TextField from "@mui/material/TextField";

export default function StopWords() {
const { t } = useTranslation();

return (
<React.Fragment>
<Typography sx={{ mb: 1 }}>
Stop Words:
{t("stop words")}:
</Typography>
<TextField
multiline
fullWidth
rows={4}
variant="outlined"
placeholder="Please enter text"
helperText="Seperated by comma"
placeholder={t("please enter text")}
helperText={t("seperated by comma")}
/>
</React.Fragment>
);
Expand Down
3 changes: 2 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import '@css/App.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { RecoilRoot } from "recoil";
import '@locales/i18n';
import '@css/App.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
Expand Down
15 changes: 15 additions & 0 deletions src/locales/en/translation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"title": "Smart Shuffle Words",
"input": "Input",
"output": "Output",
"shuffle & copy": "Shuffle & Copy",
"set additional string": "Set additional string",
"prepend to string": "Prepend to string",
"append after string": "Append after string",
"random word": "Random Word",
"characters used": "Characters Used",
"characters length": "Characters Length",
"stop words": "Stop Words",
"please enter text": "Please enter text",
"seperated by comma": "Seperated by comma"
}
36 changes: 36 additions & 0 deletions src/locales/i18n.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import translationEn from "@locales/en/translation";
import translationKo from "@locales/ko/translation";

i18n
.use(initReactI18next) // passes i18n down to react-i18next
.init({
// the translations
// (tip move them in a JSON file and import them,
// or even better, manage them via a UI: https://react.i18next.com/guides/multiple-translation-files#manage-your-translations-with-a-management-gui)
resources: {
en: {
translations: translationEn
},
ko: {
translations: translationKo
}
},

lng: "ko", // if you're using a language detector, do not define the lng option
fallbackLng: "ko",

ns: "translations", // string or array of namespaces to load
defaultNS: "translations", // default namespace used if not passed to the translation function

// char to separate keys. If working with a flat JSON,
// it's recommended to set this to false.
keySeparator: false, // (default) '.'

interpolation: {
escapeValue: false // react already safes from xss => https://www.i18next.com/translation-function/interpolation#unescape
}
});

export default i18n;
15 changes: 15 additions & 0 deletions src/locales/ko/translation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"title": "스마트 셔플 워드",
"input": "상품명",
"output": "상품명 수정",
"shuffle & copy": "상품명 변경 후 자동 복사",
"set additional string": "추가 문자열 설정",
"prepend to string": "문자열 앞에 추가",
"append after string": "문자열 뒤에 추가",
"random word": "무작위 단어",
"characters used": "사용된 문자",
"characters length": "문자 길이",
"stop words": "금칙어",
"please enter text": "텍스트를 입력 하십시오",
"seperated by comma": "쉼표로 구분 합니다"
}
File renamed without changes.
7 changes: 6 additions & 1 deletion src/store/theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,10 @@ import { atom } from "recoil";

export const modeState = atom({
key: "modeState",
default: 'light'
default: "light",
});

export const languageState = atom({
key: "languageState",
default: "ko",
});
11 changes: 8 additions & 3 deletions src/templates/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import { useTranslation } from "react-i18next";
import AppBar from "@mui/material/AppBar";
import Toolbar from "@mui/material/Toolbar";
import Typography from "@mui/material/Typography";
import ToggleColorMode from "@components/header/ToggleColorMode";
import MoreButton from '@components/header/MoreButton';
import ChangeLanguage from "@components/header/ChangeLanguage";
// import MoreActions from "@components/header/MoreActions";

export default function Header() {
const { t } = useTranslation();

return (
<AppBar position="fixed">
<Toolbar>
<Typography variant="h6" noWrap component="h1" sx={{ flexGrow: 1 }}>
Smart Shuffle Words
{t("title")}
</Typography>
<ToggleColorMode />
<MoreButton />
<ChangeLanguage />
{/* <MoreActions /> */}
</Toolbar>
</AppBar>
);
Expand Down
Loading

0 comments on commit 740f082

Please sign in to comment.