일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- Image Resize typescript
- code editor
- RouteObserver
- three.js
- identifierForVender
- jszip
- webrtc
- web track
- node
- Prism.js
- Game js
- Babel standalone
- Redux
- REST API
- Three-fiber
- swagger-typescript-api
- babel
- userevent_tracker
- uint8array
- Flutter
- androidId
- Excel
- Completer
- KakaoMap
- react
- methodChannel
- typescript
- Three js
- uint16array
- Raycasting
- Today
- Total
Never give up
React - localization without library 본문
이번에 포트폴리오를 새로 만들면서 다국어 처리를 할 필요가 있었는데
라이브러리 없이 간단하게 만들어 봤습니다
상태관리 라이브러리를 사용하면 조금 더 코드가 간단해지는데
각각 사용하는 라이브러리가 다를테니 공용으로 사용할 수 있는 context api를 사용해서 해봤습니다
(ps. 필자는 zustand를 좋아합니다)
src/localization/provider.tsx
import React, { createContext, useState } from "react";
import { CONTEXT_TYPE, LANG_CODE, LANG_TYPE } from "src/utils/constants";
export const LocalizationContext = createContext<CONTEXT_TYPE | undefined>(
undefined
);
const LocalizationProvider = ({ children }: { children: JSX.Element }) => {
const [code, setCode] = useState<LANG_TYPE>(LANG_CODE.kr);
const changeCode = (value: LANG_TYPE) => {
setCode(value);
};
return (
<LocalizationContext.Provider value={{ code, changeCode }}>
{children}
</LocalizationContext.Provider>
);
};
export default LocalizationProvider;
먼저 이름에 걸맞는(?) context를 정의 해주고
내부에 setState를 이용해서 필요할 때 값을 변경하는 형태로 만들어줬는데
url에 따라 분리를 하는 방법도 있습니다
useEffect(() => {
const urlParams = new URLSearchParams(window.location.search);
const param = urlParams.get("lang");
if (param === LANG_CODE.kr || param === LANG_CODE.en) {
setCode(param);
}
}, []);
url?lang=kr, url?lang=en 이런식으로 말이죠
(필자는 query string을 이용했는데, path param을 이용하셔도 무방합니다)
이후 App 에 provider를 넣어줍니다
const App = () => {
return (
<LocalizationProvider>
<Test />
</LocalizationProvider>
);
};
여타 프로바이더를 사용하는것과 동일합니다
src/hooks/useLocaleValue.ts
// json imported from somewhere
const jsonData = {
kr: textKR,
en: textEN,
};
export const useLocaleValue = () => {
const context = useContext(LocalizationContext);
const toggleLang = () => {
const value = context!.code === LANG_CODE.en ? LANG_CODE.kr : LANG_CODE.en;
context!.changeCode(value);
};
const getText = useCallback(
(name: string, replacer?: string) => {
const data: OBJ_TYPE = jsonData[context!.code];
const keys = name.split(".");
let obj = data;
keys.forEach((e) => {
obj = obj[e];
});
if (obj === undefined) {
return `Missing text json : ${name}`;
}
return replacer === undefined ? obj : obj.replace("{}", replacer);
},
[context!.code]
);
return { getText, langCode: context!.code, toggleLang };
};
먼저 국가별로 json 파일을 설정한 후 넣어줍니다
그 후 language code에 따라 jsonData를 가져와서 name에 따라 필요한 데이터를 가져옵니다
예를들어 다음과 같이 json에 설정을 하면
"a": {
"b": {
"c": "value"
}
}
a[b][c]로 value값을 받아오는 구조이고
value에 중괄호 {}가 있는경우 중괄호에 replacer가 들어가는 구조입니다
예제에 사용한 json은 다음과 같습니다
// kr.json
{
"example": {
"test1": "테스트1",
"test2": "{}번",
"toggle": "토글"
}
}
// en.json
{
"example": {
"test1": "test1",
"test2": "number {}",
"toggle": "toggle"
}
}
언어마다 어순이 다를 수 있어서 해당 replacer부분은 꼭 설정해주시는게 좋습니다
src/routes/Test/index.tsx
const Test = () => {
const { getText, toggleLang, langCode } = useLocaleValue();
return (
<div className={styles.div_test}>
<div>
<p>
langCode <strong>{langCode}</strong>
</p>
<p>
example.test1 <strong>{getText("example.test1")}</strong>
</p>
<p>
example.test2 <strong>{getText("example.test2", "2")}</strong>
</p>
</div>
<button onClick={toggleLang}>{getText("example.toggle")}</button>
</div>
);
};
getText 함수가 localization 처리 그리고 toggleLang 함수로 langCode를 변경하게 됩니다
src/utils/localizationUtil.ts
export const LANG_CODE = {
kr: "kr",
en: "en",
} as const;
export type LANG_TYPE = keyof typeof LANG_CODE;
export type CONTEXT_TYPE = {
code: LANG_TYPE;
changeCode: (code: LANG_TYPE) => void;
};
export type OBJ_TYPE = { [key: string]: any };
해당 파일은 타입이랑, 언어 코드를 넣어놨고 상황에 따라 변경될 여지가 있습니다
간단한 예제라 따로 깃헙에는 올리지 않았습니다
최근에 다른 준비를 하느라 블로그 업데이트를 못했는데
앞으로 하나씩 하나씩 다시 올릴 예정입니다

'WEB' 카테고리의 다른 글
React - code editor 2 (0) | 2023.12.15 |
---|---|
React - code editor 1(feat. babel standalone) (0) | 2023.12.13 |
React - image resize example (0) | 2023.07.16 |
React, Node - SSE example (0) | 2023.03.04 |
React - Axios common settings (0) | 2022.12.21 |