Skip to content

Base Config

Everything lives in i18n inside pages/+config.ts.

ts
// +config
type I18nConfig = {
  defaultLocale: string
  locales: string[] | Record<string, { urlPrefix: string; meta?: Record<string, any> }>
  routes: Record<string, Record<string, string> | I18nRoutes>
  prefixDefaultLocale?: boolean
  domains?: Record<string, DomainConfig>
  domainDetector?: (pageContext) => string | null | undefined
  localeDetector?:
    | ((pageContext) => string | null | undefined)
    | {
        acceptLanguageHeader?: boolean
        localeCookie?: boolean
        queryParams?: boolean
        session?: boolean
      }
  debug?: boolean
  localeCookie?: string | false
}

locales

Simple form — locale code is also used as the URL prefix:

ts
// +config
locales: ['en', 'ru', 'fr']

Object form — use when the URL prefix should differ from the locale code:

ts
// +config
locales: {
  en: { urlPrefix: 'en' },
  'zh-Hans': { urlPrefix: 'zh' },  // /zh/... instead of /zh-Hans/...
}

Locale entries can also carry arbitrary metadata:

ts
// +config
locales: {
  en: { urlPrefix: 'en', meta: { currency: 'USD', region: 'us' } },
  de: { urlPrefix: 'de', meta: { currency: 'EUR', region: 'de' } },
}

routes

routes maps canonical route keys to localized public paths. See I18n Routes for full details.

ts
// +config
routes: {
  '/about': { en: '/about', ru: '/o-nas' },
}

The key on the left is what your app works with internally.

You can also group related routes by canonical prefix:

ts
// +config
routes: {
  '/blog': {
    '/:slug': { en: '/:slug', ru: '/:slug' },
    '/category/:category': {
      en: '/category/:category',
      ru: '/kategoriya/:category',
    },
  },
}

Grouped route values are relative to the group prefix, so /blog + /:slug becomes the canonical route /blog/:slug.

prefixDefaultLocale

When true:

ts
// +config
prefixDefaultLocale: true
  • /about redirects to /en/about
  • /en/about stays prefixed

When false:

ts
// +config
prefixDefaultLocale: false
  • /about stays /about
  • /en/about redirects to /about

Minimal config

ts
// +config
i18n: {
  defaultLocale: 'en',
  locales: ['en', 'ru'],
  routes: {
    '/': { en: '/', ru: '/' },
    '/about': { en: '/about', ru: '/o-nas' },
  },
}

Optional base settings

ts
// +config
i18n: {
  localeCookie: 'locale',
  localeDetector(pageContext) {
    return pageContext.session?.locale
  },
}

Built-in locale detection sources can also be toggled without replacing the detector:

ts
// +config
i18n: {
  localeCookie: 'locale',
  localeDetector: {
    acceptLanguageHeader: false,
    localeCookie: false,
    queryParams: false,
    session: true,
  },
}

Enable locale negotiation logs during development:

ts
// +config
i18n: {
  debug: true,
}

By default, locale negotiation logging is enabled on the dev server. Set debug: false to silence it.

When localeDetector is a function, the built-in detection sources still run after it unless it returns a valid locale code.

Next: Getting Current Locale