Next.js Discord

Discord Forum

Directories and I18N

Answered
Terrier Brasileiro posted this in #help-forum
Open in Discord
Avatar
Terrier BrasileiroOP
Hello, I'm a rookie to nextJS, still learning how's everything working. I've ran into an issue.
I have a folder structure src/app where the layout.tsx and page.tsx is located. I added my custom _app.tsx to the src/pages/_app.tsx folder, but it seems that my components aren't working with I18N translations this way.
Image
Answered by not-milo.tsx
next-i18next looks a little outdated to me. A native approach is better in my opinion, and if you really need an external library to do this then I'd suggest using [next-intl](https://next-intl-docs.vercel.app/docs/getting-started)
View full answer

38 Replies

Avatar
Terrier BrasileiroOP
I'm trying to use useTranslation() inside of components folder.
Image
Page loads, but I get an error react-i18next:: You will need to pass in an i18next instance by using initReactI18next.
Avatar
not-milo.tsx
i18n is not trivial to set up and it gets even harder if you use both the app and pages router. I suggest you migrate all your pages to use the app router and then try implementing i18n as shown in Next.js' official examples here: https://github.com/vercel/next.js/tree/canary/examples%2Fapp-dir-i18n-routing
Long term it will be very beneficial to your codebase
Avatar
Terrier BrasileiroOP
How's the hierarchy would look like doing so?
I cannot move my _app.tsx to the src/app directory, because it will not work
Avatar
not-milo.tsx
You can't use _app.tsx directly inside the app router
Avatar
Terrier BrasileiroOP
Understood, but how do I wrap my layout.tsx like the _app.tsx?

import { appWithTranslation } from 'next-i18next';
import type { AppProps } from 'next/app';

import '@styles/globals.scss';

const MyApp = ({ Component, pageProps }: AppProps) => {
    return <Component {...pageProps} />
}
export default appWithTranslation(MyApp);
const inter = Inter({ subsets: ['latin'] });

export const metadata: Metadata = {
  title: 'Alsteo',
  description: 'Generated by create next app',
}

export async function generateStaticParams() {
  return i18n.locales.map((lng) => ({ lng }));
}

const RootLayout = ({ children, params }: { children: React.ReactNode, params: { lang: string } }) => {
  return (
    <html lang={params.lang}>
      <body className={inter.className}>
        <main>
          <Navigation />
          {children}
        </main>
      </body>
    </html>
  );
}

export default RootLayout;
Avatar
not-milo.tsx
I'm not familiar with next-i18next but they have a blog post detailing how to use it inside the app directory here: https://locize.com/blog/next-13-app-dir-i18n/
The app router works quite a bit differently from the pages router so you might also give a thorough read to [Next.js' documentation](https://nextjs.org/docs/app) about it
Avatar
Terrier BrasileiroOP
I'm not receiving any params, but the function works, what could be an issue?

import '@styles/globals.scss';
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';

import Navigation from '@/components/navigation/Nav';
import { i18n } from '../../next-i18next.config';

const inter = Inter({ subsets: ['latin'] });

export const metadata: Metadata = {
  title: 'Alsteo',
  description: 'Generated by create next app',
}

export async function generateStaticParams() {
  return i18n.locales.map((lng) => {
    return { lng }
  });
}

const RootLayout = ({ children, params }: { children: React.ReactNode, params: { lng: string } }) => {
  console.log(params);
  return (
    <html lang={params.lng}>
      <body className={inter.className}>
        <main>
          <Navigation />
          {children}
        </main>
      </body>
    </html>
  );
}

export default RootLayout;
Avatar
not-milo.tsx
That's strange, how does your folder structure look like right now?
Avatar
Terrier BrasileiroOP
Image
Avatar
not-milo.tsx
Ooh, the generateStaticParams function needs to be inside the dynamic route. Create a layout.tsx file inside /[lng] and export it from there.
Avatar
Terrier BrasileiroOP
Yeah, but I'm trying to render a page that's in app/page.tsx
it's rendering, but that page doesn't receive any of the params
but when I open app/[lng]/page.tsx, it displays the params there
Avatar
not-milo.tsx
If you're internationalising pages by using dynamic routes then all of your pages need to be inside that directory. Including the home page.
You can't see those params outside a dynamic route
Avatar
Terrier BrasileiroOP
Do you mean that I should remove app/page.tsx?
Avatar
not-milo.tsx
Not remove it, but just place it inside /[lng]
Avatar
Terrier BrasileiroOP
Do I create the layout.tsx for the /[lng]?
Avatar
not-milo.tsx
Take [this](https://github.com/milovangudelj/milovangudelj.com/tree/master/app) as an example. You'll see there's no pages.tsx file inside /app. Everything that needs to be internationalised sits under /[lang]
Yes
Avatar
Terrier BrasileiroOP
Right now there's another issue.
Home page / is getting an error, that there's no page.
After entering http://localhost:3000/en, I still get an error (no page).
After entering http://localhost:3000/hello or anything, that's not the locale, it loads the page.
Avatar
not-milo.tsx
This is likely due to a misconfiguration of your middleware
Avatar
Terrier BrasileiroOP
Is middleware neccessary?
https://locize.com/blog/next-13-app-dir-i18n/
Step 2.0, it has a cookie export, but in settings there's none.
But that's the part of middleware
Avatar
not-milo.tsx
Is this a brand bew application/website you're building?
Avatar
Terrier BrasileiroOP
Yeah
Avatar
not-milo.tsx
Cause if it is, it would be way easier for you to follow the official example and not use any external i18n libraries
Avatar
not-milo.tsx
next-i18next looks a little outdated to me. A native approach is better in my opinion, and if you really need an external library to do this then I'd suggest using [next-intl](https://next-intl-docs.vercel.app/docs/getting-started)
Answer
Avatar
not-milo.tsx
Avatar
Terrier BrasileiroOP
Thank you, that helped me a lot
Avatar
not-milo.tsx
I'm glad it did 😎