npm i i18next react-i18next @types/i18next @types/react-i18next
//locales/en/main.json
{
"test": "Helo",
"mainMenu": [
{
"title": "main",
"href": "/home",
"list": [
{ "title": "🐰", "href": "/housework" },
{ "title": "♥️🐇", "href": "/wandb" },
{ "title": "recipe", "href": "/address" },
{ "title": "hobby", "href": "/address" },
{ "title": "party", "href": "/address" },
{ "title": "travel", "href": "/address" },
{ "title": "community", "href": "/address" },
{ "title": "store", "href": "/address" }
]
}
]
}
//Layouts.tsx
export const MenuBar = ({ selected, setSelected }: BarProp) => {
return (
<>
{mainMenu[0].list.map((el, idx) => (
<<Main key={idx} idx={idx}>
...
</Main>
))}
</>
);
};
를
//Layouts.tsx
import { useTranslation } from 'react-i18next';
export const MenuBar = ({ selected, setSelected }: BarProp) => {
const {t} = useTranslation();
return (
<>
{t('main:mainMenu')[0].list.map((el, idx) => (
<Main key={idx} idx={idx}>
...
</Main>
))}
</>
);
};
단순히 바꿔서 써보았더니
🟥 Property 'list' does not exist on type 'string'이라는 에러가 나온다: t('main:mainMenu') 부분이 string으로 나타나서 사용할 수 없다는 것 같아 해당 값을 화면에 출력해보니
🟥 값은 key 'mainMenu (ko-KR)' returned an object instead of string.이라 나오고,
콘솔로그에는 accessing an object 라는 메세지가 나온다.
공식문서를 참조 후, 다음과 같이 옵션을 추가했다.
t('main:mainMenu',{ returnObjects: true })
이번에는 콘솔로그에는 정상적으로 object가 찍히는데 화면에서 출력하려고 했을 때는 다음과 같은 에러가 발생했다.
🟥 Objects are not valid as a React child ...
{JSON.stringify(t('main:mainMenu', { returnObjects: true }))}
객체를 stringify해서 렌더링하니까 성공적으로 출력되었다.
하지만 string이라서 그 다음 코드(객체의 map 활용)를 제대로 활용할 수 없어서, object로 출력하는 JSON.parse()를 사용했다.
{JSON.parse(JSON.stringify(t('main:mainMenu', { returnObjects: true })))}
즉, JSON을 객체로 온전히 활용하려면 우선 JSON.stringify로 string화 시켜준 후, 다시 객체로 변형하는 JSON.parse 순으로 진행하면 된다.
stringify하지 않고 바로 JSON.parse만 한다면
🟥 Uncaught SyntaxError: "[object Object]" is not valid JSON
콘솔로그 에러를 볼 수 있다.
stringify하고 JSON.parse를 하지 않고 객체 활용을 한다면
또다시 🟥 Property 'list' does not exist on type 'string'. 에러를 만난다.
결과적으로 다음과 같이 파싱 후, 변수로 바꿔치기해서 기존 결과를 유지하게 되었다.
//MenuBar.tsx
import { useTranslation } from 'react-i18next';
export const MenuBar = ({ selected, setSelected }: BarProp) => {
const { t } = useTranslation();
const objectParsed = JSON.parse(
JSON.stringify(t('main:mainMenu', { returnObjects: true }))
);
return (
<>
<Horizontal margin={DEFAULT.MENU_MARGIN}>
{objectParsed.list.map((el: any, idx: number) => (
<Main key={idx} idx={idx}>
{el.title}
... (기존 코드)
</Main>
))}
</Horizontal>
</>
);
};
text.ts -> i18n.json 으로 변환하며 느낀 점
🟥 콘솔에러 : i18next::translator: missingKey en-US basic cycle cycle
//발생 코드
const cycleMenu = JSON.parse(
JSON.stringify(t('basic:cycle', { returnObjects: true }))
);
en-US 모드일 때 basic.json에서 해당 key (basic)을 찾을 수 없다고 나오는 에러
파일 이름을 item.json으로 변경한 것이 원인이었다: translation할 파일 이름이 없거나, 그에 맞는 key 값이 없으면 같은 에러를 발생시킨다.
코드를 다음과 같이 수정하니까 잘 되었다.
//발생 코드
const cycleMenu = JSON.parse(
JSON.stringify(t('item:cycle', { returnObjects: true }))
);