Technology

Building Multilingual Sites with Next.js: Expand Your Global Reach Tenfold

The Complete Guide to URL Design, Directory Structure, and Language Detection with App Router

2025-04-03
26 min
Next.js
App Router
Multilingual Support
Internationalization
Web Development
AI Collaborative Development
Content Strategy
Ryosuke Yoshizaki

Ryosuke Yoshizaki

CEO, Wadan Inc. / Founder of KIKAGAKU Inc.

Building Multilingual Sites with Next.js: Expand Your Global Reach Tenfold

A Voice for the World — The Potential and Value of Going Multilingual

“I want to share my ideas with people all around the world.”

I have held onto this thought for a long time. Yet, to be honest, making a personal blog multilingual used to feel like a far-off dream. Translating every page into English, localizing UI elements, redesigning the URLs… The sheer amount of work is staggering if you try to do it alone.

However, the evolution of AI changed my situation dramatically. I thought, “Perhaps I can actually do this,” and the possibility alone made my heart flutter. Though uncertain, I decided to take the plunge and see how far I could go.

In this article, I want to share the trials and errors I personally went through—my failures and successes—and the lessons I learned from implementing multilingual functionality using the Next.js App Router. Rather than just a technical breakdown, I also hope to convey the sense of wonder and surprise I experienced.

The Distribution of Languages on the Web and the Power of Going Multilingual

My first motivation to prioritize multilingual support came from looking at data on the distribution of languages on the web. Various studies made me realize how essential it is to have an English version of any site.

グラフを読み込み中...

According to W3Techs research 1, nearly half (49.1%) of top websites are in English, whereas Japanese accounts for only about 5.1%. Other studies confirm the dominance of English 23.

Seeing these numbers was astonishing. In other words, if I only publish content in Japanese, I’m only reaching about one-tenth of the potential audience. Just by adding English support, you could theoretically expand your readership by tenfold. That’s not something an individual blogger can afford to ignore.

A Turning Point: Dramatic Improvements in AI Translation

The biggest hurdle in going multilingual has always been the cost of translation. I once spent hours translating even a single post into English, and machine translation felt clumsy. Hiring a professional translator would blow my budget…

But recently, I’ve noticed that AI tools like Claude Sonnet 3.7 have made remarkable strides in translation quality. When I tried having my own articles translated by an AI, I was surprised to find the English text sounding more natural than what I could write myself. That level of quality really took me aback.

However, I soon realized that plain translation alone wasn’t enough. Language and culture are intertwined, so unstated norms don’t carry over. For instance, the Japanese expression “猫の手も借りたい” (literally “I’d even borrow a cat’s paw,” meaning “I’m desperate for any help I can get”) simply doesn’t make sense in English if translated word-for-word。

So I gave the AI a more explicit instruction: “Don’t just translate the language—factor in cultural background, and either add context or rephrase as necessary.” That made all the difference.

For example, I asked it to address the following concerns:

• Adjusting currency references:
  When mentioning “数十万円” in Japanese, I translated it as “several thousand dollars” in English.
  I avoided quoting a specific dollar figure while still conveying the rough scale.

• Adding cultural background:
  For topics like Japan’s new-graduate hiring practices, which might not be common knowledge abroad, I tried to ensure the context would still make sense even without prior awareness.

• Clarifying references:
  For instance, if I mention “Kikagaku,” I might add a brief note like “Kikagaku, the company I founded” to clarify context for overseas readers.

• Explaining SES:
  SES (System Engineering Services), a business model often found in Japan, needed an extra note so non-Japanese readers could follow.

• Paraphrasing idioms:
  Expressions like “付け焼き刃” (literally “temporary patch”) or “猫の手も借りたい” were adapted into English idioms that convey the same nuance.

• Explaining Japan’s educational system:
  Mentions of Kyoto University and graduate schools were reframed so that international readers could understand the context.

• Preserving style:
  I tried to keep the same “declarative tone” (in Japanese) in the English translation, using direct sentence endings and introspective reflections wherever possible.

• Ensuring technical accuracy:
  When referencing specialized terms like “Vibe Coding,” I kept them intact while adding succinct explanations for clarity.

This experience taught me just how crucial it is to go beyond simple translation and bring cultural contexts into the process. If you’re considering a multilingual approach, be sure to pay attention to these factors.

The Shock of Finishing My Multilingual Site in Just Six Hours

I’ll be honest: at first, I was thinking, “If I can finish this somehow over a weekend, that’ll be a win.” Typically, building a multilingual site can take weeks.

But in reality, I completed the entire English version for all pages—plus all checks and revisions—in just six hours. Even I was stunned.

I started in the late afternoon, planning out the directory structure, designing the URL scheme, implementing a language switcher… Working side by side with AI, it went faster than I could have imagined.

The cost factor was also incredible. Using Claude Sonnet 3.7 cost me roughly 60 US dollars (under 10,000 yen). If I had hired a development firm, the same work might have cost hundreds of thousands of yen, if not more. Of course, my own labor is a separate cost, but even so, the cost-performance ratio was unbelievable.

As I tested things late into the night, I wondered, “Is this really working?” Once I confirmed the results, though, I was convinced. It was a moment that made me truly feel the potential of AI-assisted development.

Strategic Decisions for Multilingual Implementation with Next.js App Router

When I set out to make my site multilingual, the first big challenge was designing the URL structure. This is critical for SEO, user experience, and future scalability.

Evaluating URL Structure Options: My Decision-Making Process

I initially hesitated over which approach to adopt. I drew a diagram of potential solutions to better understand each one:

図表を生成中...

At first, I was drawn to subdomains (ja.example.com / en.example.com), which many large websites use and which give a neat impression. But as I tested it, I found dealing with DNS settings and SSL certificates more complicated than expected. Plus, implementing this approach on the App Router turned out to be trickier than I’d hoped.

Next, I considered content negotiation (serving different languages on the same URL based on browser settings), but that creates SEO problems. When multiple languages share a single URL, search engines can get confused.

Ultimately, I chose the subpath approach for these reasons:

  1. Clear SEO: Each language version has a unique URL, letting search engines cleanly index the content.
  2. Good synergy with Next.js App Router: It integrates smoothly with file-based routing.
  3. Simplicity: Dynamic routes and middleware handle the logic efficiently.
  4. Scalability: Adding more languages in the future is relatively straightforward.

This decision proved vital in streamlining the rest of the implementation. If you’re building a multilingual site, I recommend carefully evaluating your URL structure from the start.

Transforming Directory Structures—From Old to New

Having decided on the URL scheme, the next big task was redesigning the directory layout. With the Next.js App Router, routing is based on the file system, so the directory structure directly shapes the URL.

I sketched out diagrams comparing the old and new setups:

Before

図表を生成中...

After

図表を生成中...

As a result, the first segment of the URL is now the language code (e.g., /ja/ or /en/). For example:

  • Japanese tech article: /ja/tech/article-slug
  • English version: /en/tech/article-slug

The biggest challenge here was migrating existing components and pages into the new structure. Specifically:

  1. Moving page components: Every existing page had to be moved into the new setup.
  2. Updating reference paths: All import paths had to be adjusted.
  3. Propagating the language parameter: Every page needed to handle language parameters properly.

It was especially tricky that the internal logic of certain components also had to be updated. For example, any logic that generated links or fetched data had to factor in language now.

Some pages threw an error like this:

Error: Page "/[lang]/tech/page" is missing exported function "generateMetadata".

This happened because the new route structure included language parameters, but I hadn’t updated the metadata generation function to handle them. With help from the AI, I adjusted those functions across the board:

// Before
export async function generateMetadata(): Promise<Metadata> {
  return {
    title: "技術記事 | Wadan Blog",
    // ...
  };
}
 
// After
export async function generateMetadata({
  params,
}: {
  params: { lang: string };
}): Promise<Metadata> {
  const title = params.lang === "en" ? "Tech Articles" : "技術記事";
  return {
    title: `${title} | Wadan Blog`,
    // ...
  };
}

Using Middleware for URL Transformations

A key feature in Next.js that underpinned multilingual routing was middleware—special functions that run before the server responds to each request. Middleware is perfect for rewriting URLs or detecting languages.

My middleware has three major functions:

  1. Language detection and auto-redirect: When a user accesses the root URL, they’re redirected to the appropriate language.
  2. Converting old URLs into new ones: Redirect older URL patterns to the new subpath system.
  3. Validating and normalizing language parameters: Handling invalid or missing language codes.
// middleware.ts (core excerpt)
export function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname;
 
  // Redirect the root path (/) to the user’s preferred language
  if (pathname === "/") {
    const preferredLocale = getPreferredLocale(request);
    return NextResponse.redirect(new URL(`/${preferredLocale}`, request.url));
  }
 
  // Convert old URLs (/tech/article) to new (/ja/tech/article)
  if (isLegacyUrlPattern(pathname)) {
    const segments = pathname.split("/").filter(Boolean);
    const category = segments[0];
    const slug = segments[1];
    const preferredLocale = getPreferredLocale(request);
 
    // Use a 301 (permanent redirect) to preserve SEO
    return NextResponse.redirect(
      new URL(`/${preferredLocale}/${category}/${slug}`, request.url),
      { status: 301 }
    );
  }
 
  // Check and add language codes
  // ...
}

The biggest pitfall was avoiding infinite redirect loops. In my initial attempt, certain conditions caused the redirect target URL to match another redirect rule, creating a loop.

For example, I hit this error:

Too many redirects: Possible infinite redirect loop detected.
URL: http://localhost:3000/en

Upon investigation, I realized my conditions were too broad. The same rule was firing again for the already-redirected URL. The fix involved tightening up the logic and marking URLs already processed.

I also used @formatjs/intl-localematcher and negotiator to detect the user’s browser language settings. That let me automatically redirect users to the best language for them:

import { match } from "@formatjs/intl-localematcher";
import Negotiator from "negotiator";
 
function getPreferredLocale(request: NextRequest): string {
  // The default language and supported language list
  const defaultLocale = "en";
  const locales = ["en", "ja"];
 
  // Negotiator helps identify the user’s preferred language from headers
  const headers = {
    "accept-language": request.headers.get("accept-language") || "",
  };
  const negotiator = new Negotiator({ headers });
 
  // If the browser language is missing, default to English
  let languages = negotiator.languages();
  if (!languages || languages.length === 0) {
    return defaultLocale;
  }
 
  // Use intl-localematcher to pick the best match
  const locale = match(languages, locales, defaultLocale);
  return locale;
}

The hardest part was handling edge cases—when the browser sends no language headers or sends an unsupported one. After extensive testing and fine-tuning, I got it all running smoothly.

In the end, this middleware became the heart of my multilingual site, delivering a smoother user experience and better SEO.

Innovative Testing with Playwright MCP

Once I finished building a multilingual site, the next hurdle was verifying that each page actually displayed and linked correctly in both languages. That’s more complicated than it sounds: Are all links valid? Are UI elements properly translated? Do the URLs look right?

Traditionally, you’d open each page in a browser, check everything manually, and repeat for dozens of pages—a huge time sink.

That’s when I discovered Microsoft Playwright Multiple Client Protocol (MCP) via Twitter, and decided to give it a try. It was a revolutionary experience.

Surprisingly Simple Setup

At first, I worried it might be complicated, but setting up Playwright MCP was shockingly easy. I just had to add the following snippet to the Claude (Roo Code) configuration:

{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest"]
    }
  }
}

And that was it. Suddenly, my AI tool could drive a browser and test my site. “Seriously, just this?” I double-checked multiple times because it seemed too easy.

Text-Log-Based Testing and AI Collaboration

The biggest revelation was that Playwright MCP produces text logs of the page contents, not just screenshots. Most browser automation tools rely on images, but this one flags issues by interpreting the page text itself.

Here’s an example log:

[Playwright] Navigating to http://localhost:3000/en/tech/nextjs-app-router-basics
[Playwright] Current URL: http://localhost:3000/en/tech/nextjs-app-router-basics
[Playwright] Page title: "Next.js App Router Basics | Wadan Blog"
[Playwright] Checking links on page...
[Playwright] Found link with text: "Read more" [OK]
[Playwright] Found link with text: "続きを読む" [ERROR - Japanese text on English page]
[Playwright] Link href="/tags/Next.js" [ERROR - Missing language prefix]
[Playwright] Link href="/en/tags/App-Router" [OK]

I was amazed. The tool identified the leftover Japanese text “続きを読む” on an English page as an error, as well as a missing language prefix in a link to “/tags/Next.js.” Issues that might otherwise slip by in a purely visual check became crystal clear in the text log。

On top of that, I could feed this log directly back to the AI, letting it analyze the problems and propose fixes. For instance, seeing that “続きを読む” remained on an English page or that a tag link lacked a language prefix, the AI immediately suggested a uniform approach to i18n to fix everything consistently:

// Example fix for Japanese text on an English page
const readMoreText = lang === 'en' ? 'Read more' : '続きを読む';
// ...
<Link ...>{readMoreText}</Link>
 
// Example fix for missing language prefix
<Link href={`/${lang}/tags/${tag}`}>{tag}</Link>

By centralizing these patterns, it became far easier to fix repeated hard-coded strings and maintain consistency.

Typical Issues Found by the “Monkey Test”

Running a broad test with Playwright MCP uncovered three main categories of errors:

  1. Untranslated UI elements

    • Buttons like “続きを読む” or “共有する”
    • Labels such as “記事” (“Article”) or “その他” (“Other”)
      These are simple oversights but are easy to miss if you rely solely on code reviews, especially when text is hard-coded in components.
  2. URL generation mistakes

    • Missing language prefixes
    • Mixed language links (English page linking to Japanese content)
      URL generation is often the trickiest part of a multilingual site. The test revealed how commonly issues arise when components directly build URLs.

Surprisingly, these issues did not break page layout, so a quick glance wouldn’t have caught them. Without Playwright MCP, I might not have noticed until after launching. Thanks to the tool, I identified these problems early and fixed them before production.

Behind the Scenes of Radical Efficiency with AI

Building a multilingual site with Next.js App Router and collaborating with AI were two experiments that transformed my development workflow. What specific techniques helped me achieve such dramatic efficiency? Let me share some concrete examples.

Concrete Approaches for Effective AI Collaboration

It became clear that the key to leveraging AI effectively is to provide it with specific, accurate information. Three approaches that proved especially helpful:

  1. Sharing detailed error messages
    Early in the multilingual project, I encountered an error:

    Error: ./lib/i18n/utils.ts:10:1 Module not found: Cannot resolve 'fs/promises'
    

    This happened because a client component tried accessing server-only filesystem APIs. When I gave the AI the exact error context, it quickly suggested “separating client and server code” as a solution.

  2. Feeding the Playwright MCP test results back
    As mentioned, supplying the AI with logs from the test tool let it propose precise fixes. When it saw leftover Japanese UI text on an English page (like “続きを読む”), the AI suggested a single i18n function to manage both languages.

  3. Staged implementation reviews
    Before large-scale work, I asked the AI to review my plan. For instance, I showed it the new directory structure design and asked if anything was missing or risky. This often led to valuable advice on details I might have overlooked.

Through these interactions, I discovered what AI does well and what it doesn’t:

What AI excels at:

  • Applying repetitive patterns (making the same fix across many files)
  • Analyzing error messages and suggesting solutions
  • Proposing refactoring ideas or programming patterns

What it struggles with:

  • Designing complex architectures from scratch
  • Making subjective judgments (e.g., aesthetic design choices)
  • Solving problems with little to no context

Based on this, I took charge of strategic decisions and architecture, while delegating repetitive tasks and pattern-based fixes to AI. This proved to be the most efficient collaboration model.

Lessons Learned About AI in Multilingual Projects

The biggest lessons I gained about collaborating with AI through this multilingual project are:

  1. Provide concrete context
    Generic questions like “How do I implement i18n in Next.js?” yield generic answers. Instead, ask something like, “How do I implement subpath-based URL structures (/ja /en) in Next.js App Router using middleware?” Then supply relevant code, error logs, or directory structures. The more specific the data you give, the better AI’s assistance.

  2. Solve problems in stages
    Multilingual support is a large undertaking—split it into smaller steps: deciding on the URL scheme, planning directory structures, setting up middleware, building a language switcher, localizing components, then testing. At each stage, I got feedback from the AI, which sped up my workflow and ensured fewer mistakes.

  3. Know AI’s strengths and weaknesses
    AI collaboration works best when you understand what it does well. Delegate tasks like repetitive code changes and pattern spotting. Keep strategic, holistic decisions under your control. This synergy can produce far better results than either approach alone.

Conclusion: The Possibilities of Multilingual Support and Future Outlook

Reflecting on this journey, I see two major experiments—building a multilingual site with the Next.js App Router, and collaborating with AI—both dramatically reshaped my approach to development.

The Most Valuable Takeaways

  1. The Importance of URL Structure and Directory Design
    The first thing I learned is the crucial nature of foundational design. Deciding on your URL scheme and directory structure upfront sets the stage for the entire implementation. Balancing SEO and user experience can make a huge difference over the long run.
    By taking the time to carefully plan out my URL structure before diving into the code, I avoided many pitfalls. I recommend resisting the temptation to “just get started” and instead investing time in this foundational step.

  2. The Innovation of Playwright MCP
    A text-log-based testing approach is revolutionary. When your development workflow includes AI, having text logs of errors and page content—rather than relying on screenshots—makes it much easier to share, analyze, and fix problems.

  3. A Productive Model for AI Collaboration
    By feeding specific data to the AI and iterating stage by stage, I was amazed at how quickly we could solve problems. Understanding AI’s strengths and weaknesses proved key. Splitting tasks so I handled strategy and the AI handled repetitive coding or error analysis was especially effective.

Next Steps in Multilingual Content Strategy

After this experience, I’m convinced more than ever of the importance of multilingual functionality. In our globally connected world, going multilingual is no longer an optional enhancement; it’s an essential strategy for reaching international audiences.
For solo developers or small teams, AI collaboration drastically lowers the bar. What used to require a team of translators and developers can now be done by one person.

If you’ve been wanting to share your content with the world, now is a perfect time to explore that possibility. Yes, there are technical hurdles, but with the right tools and approach, you’ll find it’s more manageable than you might think.

Above all, remember that multilingual support is more than just a technical challenge—it’s a way to share your voice with people around the globe. Don’t lose sight of the real goal: enabling genuine communication on a global scale.

For my part, I’m excited to see my blog connecting not only with readers in Japan but also around the world. It’s only the beginning, but the possibilities feel endless. If you’ve ever thought about delivering your message to the world, why not start that journey now?

Citations

Footnotes

  1. W3Techs, “Usage statistics of content languages for websites,” 2025. Survey of the top 10 million sites.

  2. DataProvider, “Language distribution across 136M websites,” 2023. Analysis of 136 million sites worldwide.

  3. Observatory of Linguistic and Cultural Diversity on Internet (OBDILCI), “Web language distribution,” 2024. Statistical estimates of all web languages.

Ryosuke Yoshizaki

Ryosuke Yoshizaki

CEO, Wadan Inc. / Founder of KIKAGAKU Inc.

I am working on structural transformation of organizational communication with the mission of 'fostering knowledge circulation and driving autonomous value creation.' By utilizing AI technology and social network analysis, I aim to create organizations where creative value is sustainably generated through liberating tacit knowledge and fostering deep dialogue.

Get the latest insights

Subscribe to our regular newsletter for the latest articles and unique insights on the intersection of technology and business.