Coder Social home page Coder Social logo

next-app-dir-i18next-example's Introduction

Next.js 13/14 app directory feature in combination with i18next

This example shows a basic way to use i18next (and react-i18next) in a Next.js 13 app with the new app directory features. next-i18next is not needed anymore for this setup.

It shows i18next integration on some server side pages and some client side pages.

There is also an example middleware with language detection and persistence via cookie.

This example has been created out of this discussion.

There's also a blog post describing this with more detail information.

Static Side Generation (SSG)

If you like to have all this hosted on a static server, you can add the output: 'export' options and optionally the trailingSlash: true option:

/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'export',
  trailingSlash: true,
  reactStrictMode: true,
  swcMinify: true,
  experimental: {
    // Required:
    appDir: true
  }
}
module.exports = nextConfig

And the just run npm run build and you should see the out folder.

Additionally, I recommend adding a root index.html file that detects the browser language and redirects to the corresponding sub-page. i.e.:

<!-- out/index.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charSet="utf-8"/>
    <meta name="viewport" content="width=device-width"/>
    <title>redirect</title>
  </head>
  <body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/i18next-browser-languagedetector/7.0.2/i18nextBrowserLanguageDetector.min.js"></script>
    <!-- <script src="https://unpkg.com/[email protected]/dist/umd/i18nextBrowserLanguageDetector.min.js"></script> -->
    <script>
      var lngDetector = new window.i18nextBrowserLanguageDetector()
      var lng = lngDetector.detect()
      if (lng.indexOf('it') === 0) window.location.href = '/it/'
      else if (lng.indexOf('de') === 0) window.location.href = '/de/'
      else window.location.href = '/en/'
    </script>
  </body>
</html>

next-app-dir-i18next-example's People

Contributors

adrai avatar axendeveloper avatar codehwl avatar davidknezic avatar itjesse avatar omar2205 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

next-app-dir-i18next-example's Issues

client.js - does not work as expected

If change lng with switcher all client components don't work correctly.

Custom error page

๐Ÿš€ Feature Proposal

Custom error page implementation

Motivation

I have searched for documentation to solve the detail but there is no clear solution where customized and translated error messages are implemented.

Example

An example would be when using search for a route that does not exist within the project.

useTranslation for client issue

๐Ÿ› Bug Report

I have several client components where I get lng with useParams (next/navigation') hook. seems i18n instance updates resolvedLanguage too long if to change the lang with switcher.

Expected behavior

I fixed that issue with:

export function useTranslation(lng, ns, options) {
  const ret = useTranslationOrg(ns, options);
  const { i18n } = ret;
  const [activeLng, setActiveLng] = useState(i18n.resolvedLanguage)

  useEffect(() => {
    if (activeLng !== i18n.resolvedLanguage) {
      setActiveLng(i18n.resolvedLanguage);
    }
  }, [i18n.resolvedLanguage]);

  if (runsOnServerSide && lng && i18n.resolvedLanguage !== lng) {
    i18n.changeLanguage(lng)
  } else {
    // eslint-disable-next-line react-hooks/rules-of-hooks
    useEffect(() => {
      if (!lng || activeLng === lng){
        return
      }
      i18n.changeLanguage(lng)
    }, [lng, activeLng])
  }
  return ret
}

question

I have encountered a problem where my server is requesting English language and the client is requesting two resources, one in French and one in English. Currently, I have found that only this user has this issue. I noticed that they will default the value of i18nextLng to fr in LocalStorage. May I ask why this is happening

https://www.dsers.com

https://www.dsers.com/fr

Only effective for pages that use "use client" and otherwise do not show the language.

๐Ÿ› Bug Report

I've been trying for a few days now with this example. I found the "use client" page to use the useTranslation function in the ./i18n/client.js file to be effective. For pages that don't use "use client" i.e. use server using useTranslation function in file ./i18n/index.js cannot translate language. Even though I copied the example code, the pages still don't work.

Change the name of useTranslation() in the code to avoid confusion

๐Ÿ› Bug Report

Related to #22

When using the "hook" useTranslation, ESLint should throw an error: ESLint: React Hook "useTranslation" cannot be called in an async function. (react-hooks/rules-of-hooks)

This issue arises because useTranslation is considered a hook by ESLint due to its use prefix. However, useTranslation is not a Hook; it's a function. This could lead to misunderstanding, especially for beginners who copy-paste the code.

To Reproduce

To reproduce the issue, simply call useTranslation in an async server component:

const ServerSideComponent = async ({ lng }: Props) => {
  const { t } = await useTranslation(lng);

  // ...
}

Expected behavior

To address this, consider renaming useTranslation to a name that follows React's naming conventions:

const ServerSideComponent = async ({ lng }: Props) => {
  const { t } = await translate(lng); // for example

 // ...
}

getStaticProps & serverSideTranslations

It's an example of a page directory:

export const getStaticProps: GetStaticProps = async ({ locale }) => {
  const res = await fetch(`${wpApiUrl}/posts?per_page=3&page=1&lang=${locale}`);

  const posts = await res.json();

  return {
    props: {
      posts,
      ...(await serverSideTranslations(locale!, ['index', 'common'])),
    },
    revalidate: 10,
  };
};

But I'm using the app directory, how can I do that with the app directory, how can I implement serverSideTranslations with the app directory?

Use i18next with app folder and without locale in url

Question

I can't use this example without locale in the router.

I have to mask the locale in URL to avoid override the website language when url is sharing.
It's not working when i remove the (lng) folder in the /app directory.

Also, i think why we use the redirect on /${lng} for locale switcher instead of the changeLanguage function of i18n ?

I don't really understand this approach..

Thank you for your help :)

question

I don't want to redirect to/en by default. Is there a way to not redirect when using the default en language? Just use the/mode, such as www.ex.com. Redirect other languages at www.ex.comfr/xxx

Usage with typescript

Following the blog article from inside my next JS project setup with Typescript, I get the hint:
Type instantiation is excessively deep and possibly infinite.ts(2589)
at multiple places. I switched the i18n/index and client files back to .js, but now for every usage of the t('...') function, it complains about the same issue.

Do you have a hint for fellow Typescript enjoyers what steps do we need to take to prevent this? :-) (Or maybe an example repo using Typescript (not sure if there is a big need for it, or in scope for you)

Thank you in advance!

outside of react component does not work ?

// 'lng' how to get it
// Do not use cookies
http.js
const isServer = typeof window === 'undefined';
const http = axios.create({
baseURL: process.env.REACT_APP_API_PATH,
timeout: 60000,
});
http.interceptors.response.use( async (response) => {
if (error.response?.status === 4005) {
if(isServer){
const { useTranslation } = (await import('@/app/i18n/index'));
// 'lng' how to get it
const { t } = useTranslation(lng, 'h-page');
message.error(t('K9')); // please login again
}else{
const { useTranslation } = (await import('@/app/i18n/client'));
// 'lng' how to get it
const { t } = useTranslation(lng, 'h-page');
message.error(t('K9')); // please login again
}
}
})

order.tsx
import http from '@/app/http';
import React from 'react'
export default function Order() {
http.get('/api/order/list').then(res => {})
return (


)
}

Cannot update a component (`Footer`) while rendering a different component (`Page`) (Update: Minified React error #425/418;)

๐Ÿ› Bug Report

Warning: Cannot update a component (Footer) while rendering a different component (Page). To locate the bad setState() call inside Page

To Reproduce

ezgif com-gif-maker

In this example "client side", if we switch languages, we will get an error.

Apparently, this is due to the fact that we are loading the state again.

export function useTranslation(lng, ns, options) {
  if (i18next.resolvedLanguage !== lng) i18next.changeLanguage(lng)
  return useTranslationOrg(ns, options)
}

UPDATE
I continued to research and found "Minified React error" see below.

Screenshot 2023-01-22 at 22 10 49

This error occurs after the build at startup if you go to the client side and reload the page. The problem with this error is that the client side freezes;
I think this is a consequence of what I wrote earlier; The problem disappears if you remove the useTranslation hook.

Unfortunately, it is not possible to use this in production, you need to study the problem and look for a solution.

Uncaught Error: Minified React error #425; visit https://reactjs.org/docs/error-decoder.html?invariant=425 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
Uncaught Error: Minified React error #418; visit https://reactjs.org/docs/error-decoder.html?invariant=418 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.

Your Environment

  • this package.json
  • runtime version: i.e. node v19.1.0, browser chrome Version 109.0.5414.87
  • i18next version: i.e. 22.4.9
  • os: MacOS 13.1

Hydration error

๐Ÿ› Bug Report

There is currently an hydration error on the first load of a page with a language other than the fallback language.
I believe that this is due to the fact that the i18next client in app/i18n/client.js is initialised with the fallback language and later on changed in useTranslation using i18next.changeLanguage(lng) which is asynchronous. Therefore the first render is made using the translation of the fallback language which doesn't match the language pre-rendered by the server.

Warning: Text content did not match. Server: "Se connecter" Client: "Login"

Language Change Issue Causing Rendering Errors

I am encountering an issue within a substantial project, which I am unable to reproduce in a CodeSandbox environment. Nevertheless, I have diligently followed the provided tutorial and can confirm full compatibility with the package.json configuration. Regrettably, due to the project's complexity, I am unable to share the entire codebase at this time.

The issue at hand pertains to a language switch from the default English to a secondary language. Upon refreshing the page, inconsistencies emerge with respect to the translation of certain forms. Additionally, I am encountering three distinct errors, which collectively disrupt the functionality of the application:

Unhandled Runtime Error:

Error: Text content does not match server-rendered HTML.
Error: Unknown root exit status.

Error: There was an error while hydrating. Since this error occurs outside of a Suspense boundary, the entire root transitions to client rendering.

I am curious if any other users have faced a similar challenge and would greatly appreciate any insights or guidance on resolving this issue.

Thank you for your attention and assistance.

EDIT1: Suspense worked and fixed the issue, the thing is that the supervisor of my supervisor do not want to use Suspense for some reason. Any alternative?

[Middleware] Cookie issue

Hello,

I followed this tutorial to implement i18next in my app.

I experience issues with the middleware, especially with the cookie trick.

I'm testing it in dev environment (yarn run dev).
I haven't tried to reproduce this bug in prod.

Example :
From /fr/path-a/dynamic-path-a
go to /en/path-a/dynamic-path-a

Then:
i18next cookie's value is still 'fr'

I hotfixed it via a "Phantom component".
Tirraa/dashboard_rtm@d9dd2e8#diff-fefb53a70f936a7e9c3813f461bd606e0dc82951b038e65faecf46e5f8314810

Tirraa/dashboard_rtm@d9dd2e8#diff-dba7cf22cde03dd91b0905d83a648c01df8cf862f9ad93558286cc5850ce3ec7

You can watch when it triggers, just doing so:

if (cookies[cookieName] !== langFlag) {
  console.log("lol");
  setCookie(cookieName, langFlag);
}

I just hope this is the good repo to report it.

Next 13 server actions not working

๐Ÿ› Bug Report

Following the Nex13 tutorial breaks server actions. The server actions work as intended on my main branch.

I followed the tutorial closely and double-checked my code against the samples in the tutorial. I suspected something in the middleware function, so I added a bunch of console logs.

To Reproduce

I created a minimal example demonstrating the issue. Clone the repo and check out the minimal-example branch. Then install dependencies and start the dev server: npm install; npm run dev. You shouldn't need to set any environment variables. Open http://localhost:3000/. Enter any email/password combination and try to "log in". I expect to see a console.log output of the credentials in the terminal window that is running the development server. (The server action createSession is defined in src/app/[locale]/actions.ts.) I suspect something about the configuration interferes with the server action routing.

Expected behavior

The browser should redirect to /profile/welcome and show a brief message. Instead the server action response is 405 method not allowed. Examining the development terminal indicates the server action is not run.

Your Environment

  • runtime version: node v18.7.0; Chrome Version 115.0.5790.182 (Official Build) (64-bit)
  • i18next version: 23.4.6
  • os: ChromeOS Version 115.0.5790.182 (Official Build) (64-bit)

Typescript error "Type instantiation is excessively deep and possibly infinite."

๐Ÿ› Bug Report

Following the guide exactly except with Typescript component, I'm getting the error when using the t() function:

Type instantiation is excessively deep and possibly infinite.

To Reproduce

Create a typescript tsx component and use the t() function

import { createInstance } from 'i18next';
import resourcesToBackend from 'i18next-resources-to-backend';
import { initReactI18next } from 'react-i18next/initReactI18next';
import { getOptions } from './settings';

const initI18next = async (lng, ns) => {
  const i18nInstance = createInstance();
  await i18nInstance
    .use(initReactI18next)
    .use(resourcesToBackend((language, namespace) => import(`./locales/${language}/${namespace}.json`)))
    .init(getOptions(lng, ns));
  return i18nInstance;
};

export async function useTranslation(lng, ns = 'global', options = {}) {
  const i18nextInstance = await initI18next(lng, ns);
  return {
    t: i18nextInstance.getFixedT(lng, Array.isArray(ns) ? ns[0] : ns, options.keyPrefix),
    i18n: i18nextInstance,
  };
}

...

import { Inter } from 'next/font/google';
import style from './page.module.css';
import Container from '@/components/util/container/Container';
import Heading from '@/components/atoms/typography/heading/Heading';
import { useTranslation } from '../i18n';

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

export default async function Home({ params: { lng } }) {
  const { t } = await useTranslation(lng);

  return (
    <main className={style.main}>
      <Container>
        <div className={style.inner}>
          <Heading as="h1" size="xxlarge">
            {t('title')}
          </Heading>
        </div>
      </Container>
    </main>
  );
}

Your Environment

  • runtime version: node v16
  • *i18next version 22.5.0
  • *os: Mac

Middleware bucle?

Hi!. I was debugging something in the middleware.js file and I put a console.log() inside the middleware and I noticed that there is a kind of bucle related to socket.io. The middleware receives a request with a href http://localhost:3000/socket.io and then it tries to redirect to http://localhost:3000/en/socket.io.
Is that normal? ๐Ÿ˜…. And thanks I really appreciate your help ๐Ÿ™Œ

Do we still need middleware.js ?

Hello
According documentation, we dont need anymore to use a middleware: https://nextjs.org/docs/pages/building-your-application/routing/internationalization

With the above configuration en-US, fr, and nl-NL will be available to be routed to, 
and en-US is the default locale. 
If you have a pages/blog.js the following urls would be available:

/blog
/fr/blog
/nl-nl/blog
When a user visits the application root (generally /), Next.js will try to automatically detect which locale the user prefers based on the [Accept-Language](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language) header and the current domain.

If a locale other than the default locale is detected, the user will be redirected to either:

When using Sub-path Routing: The locale prefixed path
When using Domain Routing: The domain with that locale specified as the default
When using Domain Routing, if a user with the Accept-Language header fr;q=0.9 visits example.com, they will be redirected to example.fr since that domain handles the fr locale by default.

When using Sub-path Routing, the user would be redirected to /fr.

Am i understanding it wrong ?

Error: Text content did not match

๐Ÿ› Bug Report

nextJs 13.4 (App Router).
Installed i18next according to instructions https://locize.com/blog/next-13-app-dir-i18n/.
The problem is that in the client components (use client), the default language (most likely) comes first, then the selected language is already connected, which leads to a content mismatch problem on the server and client (Text content did not match.). However, the problem does not always appear.

To Reproduce

An example to reproduce. Select another (Russian) language, refresh the page
codesandbox

Environment

  • runtime version: i.e. node v16.13
  • i18next version: i.e. 22.5
  • os: Windows, and Linux

With not-found.tsx

๐Ÿ› Bug Report

I follow the code and do a test:

  1. i add not-found.tsx in /app/[lng]/ folder.
  2. /i18n/settings has:
    export const fallbackLng = "zh-tw";
    export const languages = [fallbackLng, "en", "zh-cn"];
  3. try visit some url path that's not exit in my project or lng code. like:
    http://localhost:3000/abcd/
    http://localhost:3000/abcd/adddd

but it didnt redirect to not-found.tsx that i wish it will redirect to.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.