Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot use translations in async server components #179

Closed
ardauzan opened this issue Feb 2, 2023 · 9 comments
Closed

Cannot use translations in async server components #179

ardauzan opened this issue Feb 2, 2023 · 9 comments
Labels
bug Something isn't working

Comments

@ardauzan
Copy link

ardauzan commented Feb 2, 2023

Description

Hi, I found that if a server component is async (to fetch data) I cannot use anything from this package. UseTranslations will not work, other hooks exported by this package also fail (Im sure that useLocale also causes a crash).

Reproduction URL (CodeSandbox)

Don't have time but its easy to reproduce

Reproduction description

Steps to reproduce:

  1. try making a server component async and using translations in it

Expected behaviour

I expect it to work

@ardauzan ardauzan added the bug Something isn't working label Feb 2, 2023
@amannn
Copy link
Owner

amannn commented Feb 2, 2023

Hi!

Are you using the Server Components preview? This is a known bug upstream in React / Next.js. Did you read the error message? It should suggest an alternative how you can fix this.

@amannn amannn closed this as completed Feb 2, 2023
@jetschni
Copy link

jetschni commented Feb 2, 2023

I am having the same issue! I use the Server Components (beta) of next-intl.

I receive the following error (no suggestion how to solve it)

Error: Cannot read properties of null (reading 'useMemo')

Any ideas?

Edit:
I am using the following versions

"next": "13.1.3",
"next-intl": "^2.11.0-beta.4"

@amannn
Copy link
Owner

amannn commented Feb 2, 2023

Can you sure a reproduction? You can use this as a template: https://github.com/amannn/next-intl-example-next-13

@jetschni
Copy link

jetschni commented Feb 2, 2023

If I add an async to page.tsx I receive the same error as I had before.

export default async function Index() {
  const t = useTranslations("Index");

  return (
    <PageLayout title={t("title")}>
      <p>{t("description")}</p>
      <LocaleSwitcher />
    </PageLayout>
  );
}

image

@jetschni
Copy link

jetschni commented Feb 2, 2023

As a solution for the issue I am using the following now

let messages;
try {
    messages = (await import(`@/dictionaries/${locale}.json`)).default;
} catch (error) {
    notFound();
}

const t = createTranslator({ locale, messages });

@amannn
Copy link
Owner

amannn commented Feb 3, 2023

Thanks for providing more details! There was indeed some additional handling missing in the latest beta to display a more helpful error message.

next-intl@2.11.0-beta.7 now includes this error message:

Screenshot 2023-02-03 at 09 43 14

I still have hope that this will be resolved upstream in React / Next.js, but hopefully this serves as a workaround in the meantime.

@jupapios
Copy link

While there is a resolution for the upstream React/Next.js issue, you can use this one that's a drop-in replacement for useTranslations with its type-safety.

(It uses the deprecated getLocale tho 😅)

import { type NamespaceKeys, type NestedKeyOf } from "next-intl";
import { getLocale, getTranslator } from "next-intl/server";

type IntlMessages = typeof import("@/messages/en.json");

export function getTranslations<
  NestedKey extends NamespaceKeys<
    IntlMessages,
    NestedKeyOf<IntlMessages>
  > = never,
>(namespace?: NestedKey) {
  const locale = getLocale();
  return getTranslator(locale, namespace);
}

You might not need the IntlMessages type.

Here's how yo use it,

-export function RSCNonAsync() {
-  const t = useTranslations("TranslationNamespace");
-  const copy = t("something");
+
+export async function AsyncRSC() {
+  const t = getTranslations("TranslationNamespace");
+. const copy = t("something"); // still type-safe

@Alexiafe
Copy link

Alexiafe commented Oct 19, 2023

I found this solution which is simple and working fine for me:

export default async function ProfilePage() {
  const t = await getTranslator(useLocale(), "ProfilePage")

  return <div>{t('title')}</div>
}

@amannn
Copy link
Owner

amannn commented Oct 19, 2023

There's some more discussion on this topic in #406 btw.!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants