Next.js Usage

Using @onruntime/translations with Next.js App Router

3 min read
423 words

Setup for App Router

1. Configure the Provider

Create a providers file to set up translations:

// app/providers.tsx
"use client";

import { TranslationsProvider } from "@onruntime/translations/react";
import { ReactNode } from "react";

import en from "@/locales/en";
import fr from "@/locales/fr";

const locales = { en, fr };

interface ProvidersProps {
  children: ReactNode;
  locale: string;
}

export function Providers({ children, locale }: ProvidersProps) {
  return (
    <TranslationsProvider locale={locale} locales={locales}>
      {children}
    </TranslationsProvider>
  );
}

2. Set Up the Root Layout

Use the provider in your root layout:

// app/[locale]/layout.tsx
import { Providers } from "../providers";

export default function LocaleLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: { locale: string };
}) {
  return (
    <Providers locale={params.locale}>
      {children}
    </Providers>
  );
}

Server Components

Use getTranslation for Server Components:

// app/[locale]/page.tsx
import { getTranslation } from "@/lib/translations.server";

export default async function HomePage() {
  const { t } = await getTranslation("common");

  return (
    <div>
      <h1>{t("title")}</h1>
      <p>{t("description")}</p>
    </div>
  );
}

Server vs Client

Use getTranslation in Server Components and useTranslation in Client Components.

Client Components

Use useTranslation for Client Components:

"use client";

import { useTranslation } from "@onruntime/translations/react";

export function LanguageSwitcher() {
  const { locale, setLocale } = useTranslation("common");

  return (
    <select value={locale} onChange={(e) => setLocale(e.target.value)}>
      <option value="en">English</option>
      <option value="fr">Français</option>
    </select>
  );
}

Locale-based Routing

Middleware Setup

Set up middleware to handle locale detection:

// middleware.ts
import { NextRequest, NextResponse } from "next/server";

const locales = ["en", "fr"];
const defaultLocale = "en";

export function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname;

  // Check if pathname has a locale
  const pathnameHasLocale = locales.some(
    (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
  );

  if (pathnameHasLocale) return;

  // Redirect to default locale
  return NextResponse.redirect(
    new URL(`/${defaultLocale}${pathname}`, request.url)
  );
}

export const config = {
  matcher: ["/((?!api|_next|.*\\..*).*)"],
};

Static Generation

Generate static pages for all locales:

// app/[locale]/page.tsx
export async function generateStaticParams() {
  return [{ locale: "en" }, { locale: "fr" }];
}

Use the translated Link component for navigation:

import { Link } from "@onruntime/translations/next";

function Navigation() {
  return (
    <nav>
      <Link href="/">Home</Link>
      <Link href="/about">About</Link>
    </nav>
  );
}

The Link component automatically handles locale prefixing.

Example Project Structure

layout.tsx
page.tsx
providers.tsx
middleware.ts
Last updated on 09/12/2026