Logo

dev-resources.site

for different kinds of informations.

How next-intl Works

Published at
3/28/2024
Categories
nextjs
intl
i18n
i18next
Author
suhaotian
Categories
4 categories in total
nextjs
open
intl
open
i18n
open
i18next
open
Author
9 person written this
suhaotian
open
How next-intl Works

Understanding how next-intl functions is crucial for two key reasons:

  1. Effective Utilization: By comprehending its inner workings, you can leverage next-intl's capabilities more effectively in your Next.js applications.
  2. Customization: With this knowledge, you gain the ability to tailor your own internationalization(i18n) library for specific needs, such as dynamically loading locales or custom logics within the Next.js App Router.

Four Key Aspects of next-intl

1. Conditional Exports (default/react-server):

  • This mechanism enables separation of code based on where it's executed (client or server).
  • The "default" export is utilized for all components, while "react-server" caters to server components when have.

Example (package.json):

{
  "name": "conditional-exports-example",
  "version": "1.0.0",
  "exports": {
    ".": {
      "react-server": "./src/hello.server.ts",
      "default": "./src/hello.client.ts"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

src/hello.server.ts:

const msg = 'Hi from `src/hello.server.ts`';
export default msg;
Enter fullscreen mode Exit fullscreen mode

src/hello.client.ts:

const msg = 'Hi from `src/hello.client.ts`';
export default msg;
Enter fullscreen mode Exit fullscreen mode

Testing with Next.js:

  • Create a Next.js project using pnpx create-next-app@latest(here using pnpm).
  • Set up app/server/page.tsx and app/client/page.tsx.
// app/server/page.tsx
import hi from 'conditional-exports-example';

export default function ServerPage() {
  return <div>{hi}</div>;
}
Enter fullscreen mode Exit fullscreen mode
'use client';

// app/client/page.tsx
import hi from 'conditional-exports-example';

export default function ClientPage() {
  return <div>{hi}</div>;
}
Enter fullscreen mode Exit fullscreen mode

Accessing these pages:

  • http://localhost:3000/server will displays Hi from src/hello.server.ts.

  • http://localhost:3000/client will displays Hi from src/hello.client.ts.

2. React's use hook

The use hook is restricted to regular components (client or server components without the async prefix). You cannot use it within async server components.

Incorrect Example:

Error: Expected a suspended thenable. This is a bug in React. Please file an issue.

export default async function Hello() {
  const msg = use(
    new Promise((resolve) => {
      setTimeout(() => {
        resolve('hi');
      }, 1000);
    })
  );

  return <div>{msg}</div>;
}
Enter fullscreen mode Exit fullscreen mode

Correct Example:

export default function Hello() {
  const msg = use(
    new Promise((resolve) => {
      setTimeout(() => {
        resolve('hi');
      }, 1000);
    })
  );

  return <div>{msg}</div>;
}
Enter fullscreen mode Exit fullscreen mode

In next-intl, distinct modules are imported for translation functions based on the component type:

Example: non-async server component (Server Component without async Prefix):

import { useTranslations } from 'next-intl';

export default function UserDetails({ user }) {
  const t = useTranslations('UserProfile');

  return (
    <section>
      <h2>{t('title')}</h2>
      <p>{t('followers', { count: user.numFollowers })}</p>
    </section>
  );
}
Enter fullscreen mode Exit fullscreen mode

Example: client component:

(Client components are considered non-async components)

'use client';

import { useTranslations } from 'next-intl';

export default function UserDetails({ user }) {
  const t = useTranslations('UserProfile');

  return (
    <section>
      <h2>{t('title')}</h2>
      <p>{t('followers', { count: user.numFollowers })}</p>
    </section>
  );
}
Enter fullscreen mode Exit fullscreen mode

Example: async server components:

import { getTranslations } from 'next-intl/server';

export default async function UserDetails({ user }) {
  const t = await getTranslations('UserProfile');

  return (
    <section>
      <h2>{t('title')}</h2>
      <p>{t('followers', { count: user.numFollowers })}</p>
    </section>
  );
}
Enter fullscreen mode Exit fullscreen mode

3. Customizing next.config.mjs for different Runtime-Specific Configurations

Managing configurations for both server and client runtimes can be challenging. next-intl addresses this using the Module Path Aliases feature to establish a flexible configuration file. For details, refer to the source code:

https://github.com/amannn/next-intl/blob/main/packages/next-intl/src/plugin.tsx

4. Redirecting URLs for Language Detection in middleware.ts

The core concept for language-based URL redirection can be found in the Official Next.js Internationalization Docs: https://nextjs.org/docs/app/building-your-application/routing/internationalization#routing-overview.

Challenge: Sharing Messages in Client Components

A key challenge involves sharing i18n messages fetched in server components with client components to avoid redundant fetches and potential hydration errors occur when the server-rendered HTML content and the client-side JavaScript do not match.

Ideal Resolution:

  • Fetch i18n data messages from an API on the server.
  • Serialize and pass them to client components, eliminating the need for client-side fetching.

Layout.tsx:

import { NextIntlClientProvider, useMessages } from 'next-intl';
import { notFound } from 'next/navigation';

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

  return (
    <html lang={locale}>
      <body>
        <NextIntlClientProvider locale={locale} messages={messages}>
          {children}
        </NextIntlClientProvider>
      </body>
    </html>
  );
}
Enter fullscreen mode Exit fullscreen mode

Client-Side Provider (NextIntlClientProvider):

It's designed to consume locale and message data on the client:

'use client';

export default function NextIntlClientProvider({
  locale,
  resource,
  children,
}: {
  locale: string;
  resource: Record<string, any>;
  children: React.ReactNode;
}) {
  // do something with `locale` / `resource` here
  return children;
}
Enter fullscreen mode Exit fullscreen mode

Next Steps

After understanding of the key aspects of next-intl, the next step involves building our own i18n library to meet specific requirements.

We will refer to part of the code of next-intl and combine it with the popular i18n library i18next to develop a new library that called "next-i18next-v2" for in-depth exploration.

For the example source code, you can refer to:

https://github.com/suhaotian/next-i18next-v2

i18next Article's
30 articles in total
Favicon
Automating i18n Localization with AI: The Prismy Approach
Favicon
react internationalization i18n
Favicon
Localization in Nextjs with App Router
Favicon
Trans component in react-i18next. Multilingual website
Favicon
i18n in React Native with Expo
Favicon
How to Easily Add Translations to Your React Apps with i18next
Favicon
Automatically sentence-case i18next translations
Favicon
How next-intl Works
Favicon
React: How to support multi-language service (Internationalization)
Favicon
React localization with i18next and react-i18next libraries
Favicon
App translation with React-i18next
Favicon
i18Next's default locale and next build command
Favicon
Localize your React app with i18next and Gridly
Favicon
Translation in React Applications
Favicon
How implementation a i18n in React App
Favicon
react-i18next useTranslation Does not Get Same Provider
Favicon
How to Create React Multi Language Website Using i18Next
Favicon
Embedding the formatting of currencies, dates and much more in i18next
Favicon
Generate dts type definition for i18next json configuration file
Favicon
How to refresh next-i18next content update automatically?
Favicon
React Project: HashTags for Posts with Auth — Part #1
Favicon
JavaScript app localization with i18next and Localazy
Favicon
Easy Localization: 7 tips to make your work faster
Favicon
React: automatic date formatting in translations (i18next + date-fns)
Favicon
React Localization with i18next and Google Translate
Favicon
Using i18Next with Svelte
Favicon
Internationalization using React-i18next legacy version (v9)
Favicon
Internationalisation in React
Favicon
React-Native Internationalization
Favicon
i18n Slides for tech speakers with mdx-deck

Featured ones: