next.jsnext-intl

next-intl getMessageFallback in Client Component throws "Functions cannot be passed directly" error


I'm using next-intl in my Next.js 14 app to handle localization.

I want to implement a fallback method for missing translations, so that if a translation like AssetDescriptions.NOT_EXISTS_TEST is not available, it should return NOT_EXISTS_TEST as value.

According to the documentation, I should be able to pass onError and getMessageFallback to the NextIntlClientProvider to customize how missing translations and errors are handled.

This is my code src/app/[locale]/layout.js:

import { NextIntlClientProvider, useMessages, IntlErrorCode } from "next-intl";

function getMessageFallback({ namespace, key, error }) {
  const path = [namespace, key].filter((part) => part != null).join(".");

  if (error.code === IntlErrorCode.MISSING_MESSAGE) {
    return path + " is not yet translated";
  } else {
    return "Dear developer, please fix this message: " + path;
  }
}

export default function LocaleLayout({ children, params }) {
  const { locale } = params;
  const messages = useMessages();

  return (
    <NextIntlClientProvider
      locale={locale}
      messages={messages}
      getMessageFallback={getMessageFallback}
    >
      {children}
    </NextIntlClientProvider>
  );
}

Error:

Unhandled Runtime Error
Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Or maybe you meant to call this function rather than return it.
  <... locale="it" now={Date} timeZone=... messages=... getMessageFallback={function getMessageFallback} children=...>
                   

Solution

  • I think you should be using IntlProvider because NextIntlClientProvider is a client component and data passed in props to a client component must be serializable but functions are not serializable

    import { IntlProvider } from "next-intl";
    

    this is its type:

    function IntlProvider(
                 { children, defaultTranslationValues, formats, getMessageFallback, locale, messages, now, onError, timeZone }
                                                                                   :Props): React.JSX.Element
    

    see it accepts getMessageFallback:

    getMessageFallback?(info: {
            error: IntlError;
            key: string;
            namespace?: string;
        }): string;