Install
openclaw skills install web-i18n-nextjsInternationalization (i18n) guide for Next.js / Node.js web applications using the App Router. Covers translation file structure, locale routing, SEO metadata per locale, hreflang, structured JSON-LD data, UI component translations, and multi-language sitemap generation. Use when the user asks to: add i18n support, add a new language, translate a page or component, add SEO metadata for multiple locales, implement hreflang, update the sitemap for new locales, or follow i18n best practices in a Next.js project.
openclaw skills install web-i18n-nextjs/products); other locales use a prefix (/es/products).Locale list lives in src/lib/i18n/locales.ts. Keep the sitemap script's locales array in sync with this file.
export const locales = ['en', 'es', 'fr', 'de', 'ja', 'zh-CN', /* ... add as needed */]
export const defaultLocale = 'en'
export type Locale = typeof locales[number]
src/app/[lang]/
├── dictionaries/ ← One JSON file per locale
│ ├── en.json
│ ├── es.json
│ └── ...
├── dictionaries.ts ← getDictionary(locale) server helper
├── layout.tsx ← Root layout: generateMetadata + hreflang + JSON-LD
└── <page>/
└── page.tsx ← generateMetadata + page content
See references/translation-files.md for:
page.section.key)getDictionary() usageuseDictionary() hook usage{count} substitution)See references/routing.md for:
src/middleware.ts — locale detection, redirect /en/* → /*, rewrite for default localeLocalizedLink component — automatically prefixes non-default localesuseLocale() hook — reads locale from URL params → pathname → localStorage → defaultgetLocalizedPath() / removeLocalePrefix() utilitiesSee references/seo-metadata.md for:
generateMetadata() pattern in layout/page filesgenerateAlternatesMetadata() from src/lib/i18n/seo.tsalternates.languages output (all locales + x-default)locale / alternateLocale fieldshtml lang attribute and LangSetter client componentSee references/structured-data.md for:
featureList, descriptioninLanguage fieldacceptedAnswer<Script> or <script> tagsSee references/sitemap.md for:
<url> entry per page with <xhtml:link> alternates for every locale<loc> uses the default-locale (clean) URL; x-default also points theresitemap.ts implementation patternsrc/app/[lang]/dictionaries/
const dict = await getDictionary(locale) → dict?.page?.section?.key || 'fallback'const dict = useDictionary() → same fallback patterngenerateMetadata() to the page file, calling generateAlternatesMetadata()inLanguage<LocalizedLink> for internal links and getLocalizedPath() for programmatic navigationlocales array in src/lib/i18n/locales.tsdictionaries/ as <code>.json (full translation of en.json)src/app/[lang]/dictionaries.ts import mapLanguageSwitcher languageNames maplocales array