QuiiBz / next-international

Type-safe internationalization (i18n) for Next.js
https://next-international.vercel.app
MIT License
1.26k stars 59 forks source link

TypeError: locales[locale] is not a function #193

Closed JaViLuMa closed 11 months ago

JaViLuMa commented 11 months ago

I am getting the following error:

 ⨯ node_modules\.pnpm\next-international@1.0.1\node_modules\next-international\dist\app\server\index.js (175:61) @ eval
 ⨯ TypeError: locales[locale] is not a function
    at Generator.next (<anonymous>)
    at new Promise (<anonymous>)
    at Home (./src/app/[locale]/page.tsx:21:73)
    at async Promise.all (index 0)
    at async Promise.all (index 0)
digest: "1167234640"
null

and I can't seem to figure out what is causing it.

This is my setup:

// middleware.ts file that is placed at the root of the src folder

import { createI18nMiddleware } from 'next-international/middleware';
import type { NextRequest, NextResponse } from 'next/server';
import { DEFAULT_LOCALE, LOCALES } from './constants/locale';

const I18nMiddleware = createI18nMiddleware({
  locales: LOCALES,
  defaultLocale: DEFAULT_LOCALE,
  urlMappingStrategy: 'rewriteDefault',
});

export function middleware(request: NextRequest): NextResponse {
  return I18nMiddleware(request);
}

export const config = {
  matcher: ['/((?!api|static|.*\\..*|_next|favicon.ico|robots.txt).*)'],
};
// locale/client.ts at the root of the project

import { createI18nClient } from 'next-international/client';

export const { useI18n, useScopedI18n, I18nProviderClient, useCurrentLocale } =
  createI18nClient({
    en: () => import('./messages/en'),
    hr: () => import('./messages/hr'),
  });
// locale/server.ts at the root of the project

import { createI18nServer } from 'next-international/server';

export const { getI18n, getScopedI18n, getStaticParams, getCurrentLocale } =
  createI18nServer({
    en: () => import('./messages/en'),
    hr: () => import('./messages/hr'),
  });

This is how my app tree looks like:

.
└── app
    └── [locale]
        ├── [...slug]
        │   ├── layout.tsx
        │   └── page.tsx
        ├── layout.tsx
        └── page.tsx

The page.tsx under the [locale] looks like this:

import { setStaticParamsLocale } from 'next-international/server';
import { getI18n, getScopedI18n, getStaticParams } from 'server-intl';
import type { PageProps } from '@/types/pageTypes';

export function generateStaticParams(): Record<string, string>[] {
  return getStaticParams();
}

// eslint-disable-next-line import/no-default-export
export default async function Home(props: PageProps): Promise<JSX.Element> {
  const { params } = props;

  setStaticParamsLocale(params.locale);

  const t = await getI18n();
  const scopedT = await getScopedI18n('hello');

  return (
    <div>
      <p>{t('hello')}</p>
      <p>{scopedT('world')}</p>
    </div>
  );
}

Did I setup something wrong or am I missing a step?

JaViLuMa commented 11 months ago

I also created minimal reproducible example: https://github.com/JaViLuMa/next-international-type-error

Sadly I didn't manage to get it to work in Codesandbox

JaViLuMa commented 11 months ago

I managed to narrow down the issue to setStaticParamsLocale function.

When I comment it out, it works perfectly fine, without any errors

QuiiBz commented 11 months ago

Thanks for the reproduction. I've just tried and you have to move the favicon.ico file from src/app/[locale]/favicon.ico to src/app/favicon.ico.