Next.js Discord

Discord Forum

How can I make Metadata language specific? (i18n)

Answered
Satin Angora posted this in #help-forum
Open in Discord
Satin AngoraOP
I have the type Locale defined as
export const i18n = {
  defaultLocale: "tr",
  locales: ["tr", "en"]
} as const
export type Locale = (typeof i18n)["locales"][number]
and the dictionaries as
const dictionaries = {
  tr: () => import("./dictionaries/tr.json").then((module) => module.default),
  en: () => import("./dictionaries/en.json").then((module) => module.default)
}
export const getDictionary =
  async (locale: Locale) => dictionaries[locale]?.() ?? dictionaries.tr()


I am not sure where the generateMetadata takes it's parameters, but I thought they are same as RootLayout component, so I declared it as
export async function generateMetadata(
  { params }: {params: { lang: string }},
  parent?: ResolvingMetadata
): Promise<Metadata> {...
because in the [i18n example](https://github.com/vercel/next.js/blob/canary/examples/app-dir-i18n-routing/app/%5Blang%5D/layout.tsx) RootLayout takes lang as a string, which I believe is due to app structure app/[lang]/....

Now this makes things complicated; I can't index getDictionary with string type, because the dictionaries Object can't be indexed with string. I can't write type to dictionaries, because then I lose access to the key autocompletion.
Also I can't enumerate string type literal Locale.

But I want to get values for Metadata which is defined in language.json files which is used as dictionaries.

How can I solve this problem? Shouldn't I define language specific values for Metadata using my current i18n setup?
Answered by joulev
Now this makes things complicated; I can't index getDictionary with string type, because the dictionaries Object can't be indexed with string. I can't write type to dictionaries, because then I lose access to the key autocompletion.
Also I can't enumerate string type literal Locale.
if (!Object.keys(dictionaries).includes(params.lang)) {
  return {};
}

const lang = params.lang as keyof typeof dictionaries;
const data = dictionaries[lang];
View full answer

2 Replies

@Satin Angora I have the type `Locale` defined as ts export const i18n = { defaultLocale: "tr", locales: ["tr", "en"] } as const export type Locale = (typeof i18n)["locales"][number] and the `dictionaries` as ts const dictionaries = { tr: () => import("./dictionaries/tr.json").then((module) => module.default), en: () => import("./dictionaries/en.json").then((module) => module.default) } export const getDictionary = async (locale: Locale) => dictionaries[locale]?.() ?? dictionaries.tr() I am not sure where the `generateMetadata` takes it's parameters, but I thought they are same as `RootLayout` component, so I declared it as ts export async function generateMetadata( { params }: {params: { lang: string }}, parent?: ResolvingMetadata ): Promise<Metadata> {... because in the [i18n example](https://github.com/vercel/next.js/blob/canary/examples/app-dir-i18n-routing/app/%5Blang%5D/layout.tsx) `RootLayout` takes `lang` as a string, which I believe is due to app structure `app/[lang]/...`. Now this makes things complicated; I can't index `getDictionary` with `string` type, because the `dictionaries` Object can't be indexed with `string`. I can't write type to `dictionaries`, because then I lose access to the key autocompletion. Also I can't enumerate _string type literal_ `Locale`. But I want to get values for `Metadata` which is defined in `language.json` files which is used as _dictionaries_. How can I solve this problem? Shouldn't I define language specific values for `Metadata` using my current _i18n_ setup?
Now this makes things complicated; I can't index getDictionary with string type, because the dictionaries Object can't be indexed with string. I can't write type to dictionaries, because then I lose access to the key autocompletion.
Also I can't enumerate string type literal Locale.
if (!Object.keys(dictionaries).includes(params.lang)) {
  return {};
}

const lang = params.lang as keyof typeof dictionaries;
const data = dictionaries[lang];
Answer
Satin AngoraOP
TY @joulev I have learned new things about how TS works.