Building Thai/English Multilingual Websites with Next.js
11 May 2026 · by Yunmin Shin
Why Multilingual Matters for Bangkok Businesses
Bangkok is an international city, but "international" doesn't mean "English works fine." A clinic near Thonglor might see Thai regulars booking through LINE, English-speaking expats finding it on Google Maps, and Korean or Chinese medical tourists who found it through a referral site. A restaurant discovery site needs to serve Thai users searching in Thai and tourists searching in English for the same พาด (spot) with completely different vocabulary. A website that only works in one language quietly turns away whichever audience it ignores.
The mistake we see most often isn't "no English version" — it's a site that bolted on a language switcher with machine-translated copy and called it done. Google notices. Users notice faster. A properly built multilingual site serves both audiences with real, separately-optimized content, ranks independently in Google for Thai and English queries, and reads as though it was written by someone who understands both markets — because it should be.
What Library Should You Use?
next-intl is the recommended internationalization library for the Next.js App Router. It integrates directly with the router's segment structure, supports Server Components (most i18n libraries only handle client-side translation, which is the wrong default for a mostly-static marketing site or clinic homepage), and handles locale detection, message formatting, and SEO metadata correctly out of the box.
npm install next-intl
How Do You Structure Multilingual Routing?
next-intl adds the locale as a URL prefix by default: yoursite.com/th/about for Thai and yoursite.com/en/about for English. This is the SEO-correct approach — separate, crawlable URLs per language let Google index Thai and English pages independently and serve the right one based on the searcher's language and location, rather than guessing from a single URL with a cookie-based toggle.
The file structure uses a [locale] dynamic segment in the App Router:
app/
[locale]/
layout.tsx
page.tsx
about/
page.tsx
treatments/
page.tsx
Configure supported locales and the default locale in i18n/routing.ts. For most Bangkok-facing sites we build, that's ["th", "en"] — with a third locale (ko or zh) added later if the business specifically serves Korean or Chinese medical tourists, which is common for aesthetic clinics in the Sukhumvit/Thonglor area.
How Do You Manage Translation Files?
Store translations as JSON files in a messages/ directory:
messages/
th.json
en.json
Each file contains key-value pairs organized by page or feature:
{
"home": {
"hero_title": "ยินดีต้อนรับ",
"hero_subtitle": "บริการออกแบบเว็บไซต์ในกรุงเทพฯ"
}
}
Use useTranslations in client components and getTranslations in server components:
const t = await getTranslations("home");
return <h1>{t("hero_title")}</h1>;
The part that actually determines whether this works is not the tooling — it's the content. Do not machine-translate your English copy into Thai and publish it as-is. Thai has different sentence structure, different levels of formality (a clinic's booking page should read as polite and reassuring, not stiffly literal), and idioms that don't survive translation. For any client-facing page — treatment descriptions, pricing, FAQs — we write or heavily edit the Thai copy separately rather than translating sentence-by-sentence from English. The English version, in turn, should be written for the audience actually reading it (expats and tourists), not translated back from formal Thai.
How Do You Handle Locale Detection and Switching?
next-intl's middleware detects the user's preferred locale from the Accept-Language header and redirects accordingly, configured in middleware.ts. For Bangkok-based businesses, default to Thai — most visitors without a strong signal are local, and a Thai-first default matches expectations.
One detail that trips people up: a large share of Thai mobile traffic arrives through in-app browsers — LINE's built-in browser when someone taps a link shared in a LINE chat or from a LINE OA broadcast, or Facebook's in-app browser from an ad. These in-app browsers sometimes send unreliable or missing Accept-Language headers, and they don't always persist cookies the way a normal mobile browser does. Don't rely solely on header-based detection; store the user's locale choice in a cookie with a long expiry once they switch, and make the language switcher itself obvious and one tap away — don't bury it in a hamburger menu on a page that's mostly being viewed inside LINE.
What About Thai Typography and Mobile Rendering?
Thai script has no spaces between words within a sentence, and Thai vowel and tone marks stack above and below the consonant line. This causes two concrete problems if you don't plan for it:
- Line-height needs to be larger for Thai text than the English equivalent, or stacked vowel/tone marks get clipped or overlap the line above. A
line-heightof 1.5–1.75 works well for body copy; test with real Thai text, not lorem ipsum. - Word wrapping breaks mid-word by default because there are no spaces to break on. Use
word-break: break-wordor, better, a proper Thai line-breaking library (Intl.Segmenterwithgranularity: "word"works in modern browsers) for anything with tight column widths, like pricing tables or card layouts.
Use a font stack that actually renders Thai glyphs well — Noto Sans Thai or IBM Plex Sans Thai pair cleanly with most Latin display fonts and are free. Given that 70%+ of Thai web traffic is mobile, often on mid-range Android devices, test your Thai type on an actual Android phone, not just a MacBook — Thai rendering quality varies more across platforms than Latin text does.
What Are the SEO Requirements for Multilingual Sites?
For each page, include hreflang tags telling search engines about the language alternatives:
<link rel="alternate" hreflang="th" href="https://site.com/th/about" />
<link rel="alternate" hreflang="en" href="https://site.com/en/about" />
<link rel="alternate" hreflang="x-default" href="https://site.com/th/about" />
next-intl generates these automatically when configured correctly, but verify them in Google Search Console — register both language sections and watch their indexing status separately, since a Thai page and its English counterpart can perform very differently even on the same site. Set up two Google Business Profile listings' worth of care too: your Google Maps name, category, and description should exist in both Thai and English, since "near me" search in Bangkok is heavily bilingual and Maps traffic often converts better than organic search for local businesses like clinics and restaurants.
Ready to Build Something Multilingual?
Get a free quote. We reply within 24 hours.
Ready to build something fast and scalable?
Get a free project quote. We reply within 24 hours.
Get a Free Quote →