Let me explain what I'm looking for. If you're not familiar with next-intl
, it's a package designed to provide internationalization support for Next.js applications.
The Issue:
The developer of next-intl is working on a beta version that supports the app router in next.js. I have installed this beta version successfully.
The problem arises when using next-intl in async components, as developers are required to move the calling of the useTranslations
hook to a synchronous component instead.
Since I use async components extensively, I created a reusable component called <T />
(which stands for Text or Translation) to pass the translation key as a prop. For example:
<T k="home.hero.title" />
.
My Approach:
Assuming the translation file follows this structure:
{
"hello-world": "Hello World",
"home": {
"title": "Acme",
"hero": {
"description": "whatever"
}
},
"login": {
"button": "Login"
}
}
components/translation.tsx
import { useTranslations } from "next-intl";
export function T({ k }: {
k: TYPEME_LATER;
}) {
const translate = useTranslations();
return translate(k);
}
The crux of my question revolves around the TYPEME_LATER
issue.
1. Initial Attempt:
import { useTranslations } from "next-intl";
type TranslationKey = Parameters<ReturnType<typeof useTranslations>>[0];
export function T({ k }: {
k: TranslationKey;
}) {}
However, this approach only suggests nested keys like title
, hero.description
, button
, and hello-world
. Although TypeScript recognizes these keys, next-intl fails to locate them within the scope of home
and login
.
2. Alternative Solution:
import { useTranslations } from "next-intl";
type useTranslationsParam = Parameters<typeof useTranslations>[0];
type TranslationKey = Parameters<ReturnType<typeof useTranslations>>[0];
export function T({
scope,
k,
}: {
scope: useTranslationsParam;
k: TranslationKey;
}) {
const translate = useTranslations(scope);
return translate(k);
}
Surprisingly, this solution worked perfectly. Now, I can easily implement it anywhere in the codebase:
export default async function Page() {
return <>
<T scope="home" k="title" />
</>
}
While this renders correctly, there is a concern regarding the TranslationKey
type declaration, which currently accepts any key regardless of the specified scope. This could potentially lead to bugs if an incorrect key is used outside the designated scope.
My query is how to limit the suggestions for the k
prop to keys within the specified scope. Any alternative approaches would be greatly appreciated.
Thank you for your attention and assistance.