---
title: "12 — Internationalization and Data Fetching Locations"
uid: i18n-data-fetching
tags: ["roadmap:nextjs", "i18n", "data-fetching", "server-components", "internationalization", "nextjs"]
excerpt: "Two paired concerns: i18n is routing-plus-rendering for multiple languages; data-fetching location is a server-vs-client choice driven by what the component needs."
date: 2026-08-13T03:28:00+0000
source: https://www.aveshina.my.id/en/blog/i18n-data-fetching
---

Internationalization and data-fetching locations pair naturally in the App Router, and both hinge on the same server-vs-client axis. The model that clicked: **i18n is the routing-plus-rendering problem of adapting the app to multiple languages and regions; data-fetching locations are a server-vs-client choice driven by whether the component needs SEO/pre-rendering or browser APIs/interactivity** [1][2][3].

## Internationalization — routing for many languages

Internationalization is designing and developing the app so it can be adapted to various languages and regions without engineering changes [1]. Next.js's part is configuring routing and rendering to support multiple locales. The two layers:

- **Localized content (localization)** — translating the actual strings and assets.
- **Internationalized routes** — the URL structure that serves each locale, typically /en/..., /id/... subdirectories.

The App Router doesn't ship a built-in i18n engine; it provides the routing primitives (middleware for locale detection, dynamic segments for the locale prefix, layouts that pass locale context), and the community standard is a library like next-intl layered on top. The pattern: middleware detects the user's preferred locale and rewrites to the right prefix; a [locale] dynamic segment at the route root holds locale-specific layouts and pages; Server Components read the locale from params and fetch content in the right language.

```figure
<svg viewBox="0 0 720 260" xmlns="http://www.w3.org/2000/svg" class="my-6 w-full max-w-2xl" role="img" aria-label="i18n routing. A request enters middleware, which detects locale and rewrites to /en/ or /id/. The [locale] segment then serves the right layout and page, fetching locale-specific content.">
  <defs>
    <marker id="i2arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
      <path d="M0,0 L10,5 L0,10 z" fill="#64748b"/>
    </marker>
  </defs>
  <g font-family="ui-sans-serif, system-ui, sans-serif" text-rendering="geometricPrecision">

    <rect x="30" y="60" width="120" height="60" rx="8" fill="#e0e7ff" stroke="#6366f1" stroke-width="1.5"/>
    <text x="90" y="86" font-size="11" font-weight="700" fill="#1e1b4b" text-anchor="middle">request</text>
    <text x="90" y="104" font-size="10" fill="#475569" text-anchor="middle">/about</text>

    <path d="M150,90 L210,90" fill="none" stroke="#64748b" stroke-width="1.5" marker-end="url(#i2arrow)"/>

    <rect x="210" y="60" width="140" height="60" rx="8" fill="#fef9c3" stroke="#ca8a04" stroke-width="1.5"/>
    <text x="280" y="84" font-size="11" font-weight="700" fill="#422006" text-anchor="middle">middleware</text>
    <text x="280" y="102" font-size="10" fill="#475569" text-anchor="middle">detects locale</text>

    <path d="M350,80 L420,40" fill="none" stroke="#16a34a" stroke-width="1.5" marker-end="url(#i2arrow)"/>
    <text x="395" y="48" font-size="10" fill="#052e16">en</text>
    <path d="M350,100 L420,140" fill="none" stroke="#db2777" stroke-width="1.5" marker-end="url(#i2arrow)"/>
    <text x="395" y="132" font-size="10" fill="#500724">id</text>

    <rect x="420" y="20" width="150" height="44" rx="8" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
    <text x="495" y="40" font-size="11" font-weight="700" fill="#052e16" text-anchor="middle">/en/about</text>
    <text x="495" y="56" font-size="10" fill="#475569" text-anchor="middle">English content</text>

    <rect x="420" y="120" width="150" height="44" rx="8" fill="#fce7f3" stroke="#db2777" stroke-width="1.5"/>
    <text x="495" y="140" font-size="11" font-weight="700" fill="#500724" text-anchor="middle">/id/about</text>
    <text x="495" y="156" font-size="10" fill="#475569" text-anchor="middle">Indonesian content</text>

    <text x="360" y="210" font-size="11" font-style="italic" fill="#64748b" text-anchor="middle">a [locale] segment serves both, with locale-specific layouts and data</text>
  </g>
</svg>
```

## Data fetching locations — server or client?

The other question this cluster raises is *where* data gets fetched. By default, layouts and pages in the App Router are Server Components, which fetch data on the server before rendering [2][3]. When I need interactivity or browser APIs, I opt into Client Components, which fetch on the client after mount. The roadmap frames these as **locations** rather than strategies [3]:

- **Server-side data fetching** (Server Components) — data is retrieved before the page renders. Faster initial load, better SEO, the data is available when the HTML is generated [4].
- **Client-side data fetching** (Client Components) — the browser fetches after the initial HTML loads. Useful when the page doesn't need SEO indexing, doesn't need pre-rendering, or the content updates frequently [5].

The trade-off is the same as the SPA-vs-SSR fork, just at the component level. Server Components give fast first paint and SEO because the data is already in the HTML; Client Components give interactivity and browser-API access at the cost of a later fetch. The App Router's win is that *both can coexist in one tree* — a page can be a Server Component that fetches the bulk of its data, with islands of Client Components for the interactive bits.

```
// Server Component — data fetched before render
export default async function Page() {
  const data = await fetchOnServer();
  return (
    <>
      <h1>{data.title}</h1>
      <InteractiveWidget initial={data.count} /> {/* client island */}
    </>
  );
}
```

## How I use this

For i18n, I lean on middleware for locale detection and a [locale] segment for routing, with a library (next-intl) handling the translation plumbing — the framework gives me the routing primitives; the library gives me the day-to-day convenience on top. For data fetching, my default is the server: every page starts as a Server Component that fetches what it needs inline. I reach for Client Components only when a piece genuinely needs interactivity or browser APIs, keeping it as a small island with server-fetched initial props. The principle: fetch as much as possible on the server, defer to the client only what the client must do.

## References

[1] Vercel, "How to implement internationalization in Next.js (App Router)," Next.js Docs, 2024. [Online]. Available: [https://nextjs.org/docs/app/guides/internationalization](https://nextjs.org/docs/app/guides/internationalization)

[2] Vercel, "Fetching data," Next.js Docs, 2024. [Online]. Available: [https://nextjs.org/docs/app/getting-started/fetching-data](https://nextjs.org/docs/app/getting-started/fetching-data)

[3] Vercel, "Fetching data — fetching locations," Next.js Docs, 2024. [Online]. Available: [https://nextjs.org/docs/app/getting-started/fetching-data](https://nextjs.org/docs/app/getting-started/fetching-data)

[4] Vercel, "Fetching data — server components," Next.js Docs, 2024. [Online]. Available: [https://nextjs.org/docs/app/getting-started/fetching-data#server-components](https://nextjs.org/docs/app/getting-started/fetching-data#server-components)

[5] Vercel, "Fetching data — client components," Next.js Docs, 2024. [Online]. Available: [https://nextjs.org/docs/app/getting-started/fetching-data#client-components](https://nextjs.org/docs/app/getting-started/fetching-data#client-components)

[6] "Next.js 15 tutorial — Data fetching," YouTube, 2024. [Video]. Available: [https://www.youtube.com/watch?v=DRsU93Lde2](https://www.youtube.com/watch?v=DRsU93Lde2)

```quiz
Q: In the App Router, layouts and pages are by default…
- Client Components
- Server Components
correct: 1
explain: App Router layouts and pages are Server Components by default. They fetch data on the server before rendering, opt into the client only with the 'use client' directive.

Q: When is client-side data fetching the right choice?
- When the page needs SEO and pre-rendering
- When the page doesn't need SEO, doesn't need pre-rendering, or updates frequently
correct: 1
explain: Client-side fetching runs after the initial HTML loads, so it loses SEO/pre-render benefits but suits frequently-updated or non-indexed content.

Q: What role does middleware play in i18n?
- It translates the strings
- It detects the user's preferred locale and rewrites to the correct locale-prefixed route
correct: 1
explain: Middleware handles locale detection and URL rewriting (e.g., /about → /en/about). Translating strings is the localization layer's job, typically handled by a library.

Q: Can a Server Component and a Client Component coexist in the same page tree?
- No — a page is one or the other
- Yes — the page can be a Server Component with Client Component islands for interactive bits
correct: 1
explain: The App Router composes them: a Server Component fetches the bulk of the data on the server, and Client Components handle the interactive islands, often receiving server-fetched initial props.
```
