Skip to content

Repository files navigation

create nextjs

npx create-next-app@latest intlayer

install dependencies

npm install intlayer next-intlayer

create intlayer.config.ts

  • declares the diff languages of app
import { Locales, type IntlayerConfig } from "intlayer";

const config: IntlayerConfig = {
  internationalisation: {
    locales: [
      Locales.ENGLISH,
      Locales.CHINESE,
      // Your other locales
    ],
    defaultLocale: Locales.ENGLISH,
  },
};

export default config;

next.config.ts

  • wrap export using withIntlayer
import type { NextConfig } from "next";
import { withIntlayer } from "next-intlayer/server";

const nextConfig: NextConfig = {
  /* config options here */
};

export default withIntlayer(nextConfig);

src/app/layout

  • return just children
import type { PropsWithChildren, FC } from "react";
import "./globals.css";

const RootLayout: FC<PropsWithChildren> = ({ children }) => {
  return children;
};

export default RootLayout;

src/app/[locale]/layout

  • note: export generateStaticParams -> allows Intlayer to statically generate each of the pages
import type { NextLayoutIntlayer } from "next-intlayer";
import { Inter } from "next/font/google";
import { getHTMLTextDir } from "intlayer";
export { generateStaticParams } from "next-intlayer"; // Line to insert

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

const LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {
  const { locale } = await params;
  return (
    <html lang={locale} dir={getHTMLTextDir(locale)}>
      <body className={inter.className}>{children}</body>
    </html>
  );
};

export default LocaleLayout;

src/app/[locale]/page.tsx

  • add the IntlayerServerProvider, and IntlayerClientProvider
  • import <MyComponent /> from src/app/components/
  • import <LocaleSwitcher /> from src/app/components/
    • this is language switching buttons
import type { FC } from "react";
import { type NextPageIntlayer, IntlayerClientProvider } from "next-intlayer";
import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";
import { MyComponent } from "@/components/MyComponent";
import { LocaleSwitcher } from "@/components/LocaleSwitcher";

const Page: NextPageIntlayer = async ({ params }) => {
  const { locale } = await params;

  return (
    <IntlayerServerProvider locale={locale}>
      <IntlayerClientProvider locale={locale}>
        <MyComponent />
        <LocaleSwitcher />
      </IntlayerClientProvider>
    </IntlayerServerProvider>
  );
};

export default Page;

add src/middleware.ts

  • picks up default locale
export { intlayerMiddleware as middleware } from "next-intlayer/middleware";

export const config = {
  matcher:
    "/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
};

src/app/components/MyComponent.tsx

  • from this folder: src/app/components/MyComponent.tsx
  • in vscode: CTRL + SHIFT + P -> Intlayer create dictionary file (typescript)
    • this creates: myComponent.content.ts
  • useIntLayer() references the 'key' we created with dictionary - myComponent.content.ts
"use client";

import { useIntlayer } from "next-intlayer";

// CTRL + SHIFT + P: Intlayer create dictionary file (typescript)

("use client");
import Image from "next/image";
import { useIntlayer } from "next-intlayer";
// import { useIntlayer } from "next-intlayer/server"; for server components

import styles from "./MyComponent.module.css";

// CTRL + SHIFT + P: Intlayer create dictionary file (typescript)

export const MyComponent = () => {
  const content = useIntlayer("my-component");

  return (
    <div className={styles.tattoo}>
      <Image src={"/clean-arm.jpg"} alt="logo" width="600" height="430" />
      <p className={styles["tattoo-word"]}>{content.title}</p>
    </div>
  );
};

src/app/components/myComponent.content.ts

  • create the content declaration file
  • these files can be anywhere in the codebase (.content.*)
import { t, type Dictionary } from "intlayer";

const myComponentContent = {
  key: "my-component",
  content: {
    title: t({
      en: "salmon",
      zh: "鮭魚",
    }),
  },
} satisfies Dictionary;

export default myComponentContent;

.gitignore

  • add to .gitignore: .intlayer

tsconfig.json

  • add types generated by intlayer
  • "include": [".intlayer/**/*.ts"]
{
  "compilerOptions": {
    "target": "ES2017",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    ".next/types/**/*.ts",
    ".intlayer/**/*.ts"
  ],
  "exclude": ["node_modules"]
}

server components

  • with 'use client' removed
  • update the import path import { useIntlayer } from "next-intlayer/server
import Image from "next/image";
import { useIntlayer } from "next-intlayer/server"; for server components

import styles from "./MyComponent.module.css";

// CTRL + SHIFT + P: Intlayer create dictionary file (typescript)

export const MyComponent = () => {
  const content = useIntlayer("my-component");

  return (
    <div className={styles.tattoo}>
      <Image src={"/clean-arm.jpg"} alt="logo" width="600" height="430" />
      <p className={styles["tattoo-word"]}>{content.title}</p>
    </div>
  );
};

Releases

Packages

Used by

Contributors

Languages