[Next] next-export-i18n 사용 시 lang 쿼리 파라미터 자동으로 붙이기
환경
- react 18 사용
- nextJS 사용
- 번역 기능이 필요하여 next-export-i18n 사용
문제
보통 nextJS를 사용하는 경우 국제화 기능(다중 언어 지원)을 위해 next-i18next 라이브러리를 사용할 것이다.
문제는 이 라이브러리를 쓸 경우 빌드 시 아래 명령어를 사용할 수 없다. export를 지원하지 않는다.
"build": "next build && next export"
그래서 찾게 된 것이 export를 지원하는 next-export-i18n 라이브러리이다. 이 라이브러리의 문제점은, 현재 웹페이지에 보여줄 언어로
무엇을 사용할지를 판단할 때 url에 붙은 lang 쿼리파라미터로 판단한다. 즉 웹사이트 내의 모든 페이지 이동 시 lang=en 과 같은 쿼리 파라미터를 붙여줘야 하는 것이다.
그럼 router.push를 할 때마다, href에 경로를 입력할 때마다 {lang : en} 을 입력해줘야 한다는 건데.. 이건 좀 아닌듯 싶었다.
기존에 작성한 모든 페이지 이동 코드를 찾아서 수정해줘야 함은 물론, 앞으로 작성하는 코드에도 쿼리파라미터를 입력해줘야 하는데
새로운 개발자가 왔을 때 & 동료 개발자가 이 사실을 모를 때 & 알고 있지만 쿼리 붙이는걸 깜빡했을 때 등등의 상황에서 반드시 문제가 생길 것이다.. 그리고 자동화되지 않고 수기로 매번 작성해줘야 한다는게 가장 거슬렸다.
해결
가장 상위 컴포넌트인 _app.tsx에서 route가 변경될 때마다 useEffect에서 url을 replace해주는 방식으로 해결했다.
참고로 사용의 편의를 위해서 사용자가 언어 스위치로 언어를 변경할 때마다 localStorage에 해당 언어 정보를 저장해두었다.
그래서 완성한 코드이다.
//in _app.tsx
function MyApp({ Component, pageProps }: AppProps) {
const router = useRouter()
useEffect(() => {
const detectedLng = localStorage.getItem('lang') || 'en'
const { query } = router //query는 string으로 올 수도 string[]으로 올 수도 있음.
if (
query?.lang === detectedLng ||
query?.lang?.includes(detectedLng) ||
) {
return
} else {
router.replace({
pathname: router.pathname,
query: { ...query, lang: detectedLng },
})
}
}, [router])
return (
<QueryClientProvider client={queryClient}>
<Hydrate state={pageProps.dehydratedState}>
<Seo />
<Scripts />
<GlobalStyle />
<Layout>
<Component {...pageProps} />
</Layout>
</Hydrate>
</QueryClientProvider>
)
}
query가 단순 string으로 올 수도 있고 string 배열로 올 수도 있기 때문에 현재 url에 detectedLng(현재 보여져야 할 언어)이 쿼리로 포함되어 있는지 검사할 때 2가지로 검사했다.
query?.lang === detectedLng || query?.lang?.includes(detectedLng)
만약 detectedLng이 이미 쿼리 파라미터에 포함되어 있는 경우 url을 replace하지 않고 return하고
그렇지 않을 경우에는 url에 lang 파라미터를 추가해준다. url에 다른 여러가지 파라미터들이 붙어있을 수도 있으므로
{... query, lang : detectedLng} 으로 기존의 query도 유실되지 않도록 붙여준다.
이제는 페이지를 이동할 때 경로만 입력해줘도 자동으로 lang 파라미터가 붙는다! 해결 ㅎㅎ
'프론트엔드' 카테고리의 다른 글
[React] React Hook이란? (0) | 2023.02.12 |
---|---|
[NextJS] Next에서 페이지에 심은 meta태그가 pre-render되지 않는 문제 해결. (1) | 2022.12.17 |
[Next][Error] Hydration failed because the initial UI does not match what was rendered on the server. 발생 시 (0) | 2022.10.10 |
[MDN] MIME 타입이란? (1) | 2022.10.08 |
[React] 클라이언트에서 pagination 구현하기 2. (복잡버전) (0) | 2022.09.27 |