Never give up

React - localization without library 본문

WEB

React - localization without library

대기만성 개발자 2023. 11. 18. 17:11
반응형

이번에 포트폴리오를 새로 만들면서 다국어 처리를 할 필요가 있었는데

 

라이브러리 없이 간단하게 만들어 봤습니다

 

상태관리 라이브러리를 사용하면 조금 더 코드가 간단해지는데

 

각각 사용하는 라이브러리가 다를테니 공용으로 사용할 수 있는 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
Comments