Internationalization (i18n)

Without pre-rendering

Without pre-rendering, we can simply determine the locale at the vite-plugin-ssr server middleware:

const renderPage = createPageRenderer(/* ... */)

// `vite-plugin-ssr` server middleware
app.get('*', async (req, res) => {
  let { url } = req
  const { locale, urlWithoutLocale } = extractLocale(url)

  // We set `pageContext.url` to `urlWithoutLocale` instead of `req.url`.
  // So that the locale `/en-US/` in the URL is stripped away.
  url = urlWithoutLocale

  const pageContext = {
    url,
    // We make `locale` available to pages as `pageContext.locale`
    locale
  }
  const result = await renderPage(pageContext)

  /* ... */
})

// We usually use a library instead of implementing our own locale retrieval mechanism
function extractLocale(url) {
  // We determine the locale, for example:
  //  extractLocale('/en-US/film/42').locale === 'en-US'
  //  extractLocale('/de-DE/film/42').locale === 'de-DE'
  const locale = /*...*/

  // We may also strip the language URL pathname, for example:
  //  extractLocale('/en-US/film/42').urlWithoutLocale === '/film/42'
  //  extractLocale('/de-DE/film/42').urlWithoutLocale === '/film/42'
  //  ...
  urlWithoutLocale = /*...*/

  return { locale, urlWithoutLocale }
}

We can then make pageContext.locale available to all our components, see Access pageContext anywhere.

This technique also works with:

  • Accept-Language: fr headers
  • ?lang=fr query parameters
  • domain.fr domain TLDs

Example:

With pre-rendering

When using pre-rendering, we can use the hooks onBeforeRoute() and onBeforePrerender().

// _default.page.route.js

export { onBeforeRoute }

function onBeforeRoute(pageContext) {
  let { url } = pageContext

  const { urlWithoutLocale, locale } = extractLocale(url)
  url = urlWithoutLocale

  return {
    pageContext: {
      // We make `locale` available as `pageContext.locale`.
      // We can then use https://vite-plugin-ssr.com/pageContext-anywhere
      // to access `pageContext.locale` in any React/Vue component.
      locale,
      // We overwrite the original URL
      url
    }
  }
}
// _default.page.server.js

export { onBeforePrerender }

function onBeforePrerender(globalContext) {
  const prerenderPageContexts = []
  globalContext.prerenderPageContexts.forEach((pageContext) => {
    prerenderPageContexts.push({
      ...pageContext,
      locale: localeDefault
    })
    // We add the localized pages to the list of pages that are going to be pre-rendered
    locales
      .filter((locale) => locale !== localeDefault)
      .forEach((locale) => {
        prerenderPageContexts.push({
          ...pageContext,
          url: `/${locale}${pageContext.url}`,
          locale
        })
      })
  })
  return {
    globalContext: {
      prerenderPageContexts,
    }
  }
}

Example:

Edit this page