Guide

Custom Route Paths

Customize the names of the paths for specific locale.

In some cases, you might want to translate URLs in addition to having them prefixed with the locale code. There are two methods of configuring custom paths, through Module configuration or from within each Page component.

Which method is used is configured by setting the customRoutes options this is set to 'page' by default. Using both methods at the same time is not possible.

Custom paths are not supported when using the no_prefixstrategy unless combined with differentDomains.

Module configuration

Make sure you set the customRoutes option to config and add your custom paths in the pages option:

nuxt.config.ts
export default defineNuxtConfig({
  i18n: {
    customRoutes: 'config', // disable custom route with page components
    pages: {
      about: {
        en: '/about-us', // -> accessible at /about-us (no prefix since it's the default locale)
        fr: '/a-propos', // -> accessible at /fr/a-propos
        es: '/sobre' // -> accessible at /es/sobre
      }
    }
  }
})

Note that each key within the pages object should correspond to the route name of the route to localize.

Customized route paths must start with a / and must not include the locale prefix.

You can now use the localePath function or the <NuxtLinkLocale> component but be sure to use named routes. For example route /services/advanced should be services-advanced:

<script setup>
const { t } = useI18n()
</script>

<template>
  <NuxtLinkLocale to="about"> {{ t('about') }} </NuxtLinkLocale>
  <NuxtLinkLocale to="services-advanced"> {{ t('advanced') }} </NuxtLinkLocale>
</template>

Or:

<script setup>
const { t } = useI18n()
const localePath = useLocalePath()
</script>

<template>
  <NuxtLink :to="localePath('about')"> {{ t('about') }} </NuxtLink>
  <NuxtLink :to="localePath('services-advanced')"> {{ t('advanced') }} </NuxtLink>
</template>
Passing a path to localePath is currently not supported.

Example 1: Basic URL localization

You have some routes with the following pages directory:

-| pages/
---| me.vue
---| about.vue
---| services/
-----| index.vue
-----| advanced.vue

You would need to set up your pages property as follows:

nuxt.config.ts
export default defineNuxtConfig({
  i18n: {
    customRoutes: 'config',
    pages: {
      me: {
        fr: '/moi',
      },
      about: {
        fr: '/a-propos',
      },
      services: {
        fr: '/offres',
      },
      'services-advanced': {
        fr: '/offres/avancee',
      }
    }
  }
})
All URLs must start with /

Example 2: Localize the part of URL

You have some routes with the following pages directory:

-| pages/
---| about.vue
---| services/
-----| index.vue
-----| coaching.vue
-----| development/
-------| app.vue
-------| index.vue
-------| website.vue

You would need to set up your pages property as follows:

nuxt.config.ts
export default defineNuxtConfig({
  i18n: {
    customRoutes: 'config',
    pages: {
      about: {
        fr: '/a-propos'
      },
      services: {
        fr: '/offres'
      },
      'services-development': {
        fr: '/offres/developement'
      },
      'services-development-app': {
        fr: '/offres/developement/app'
      },
      'services-development-website': {
        fr: '/offres/developement/site-web'
      },
      'services-coaching': {
        fr: '/offres/formation'
      }
    }
  }
})

If a custom path is missing for one of the locales, the defaultLocale custom path is used, if set.

Example 3: Dynamic Routes

Say you have some dynamic routes like:

-| pages/
---| blog/
-----| [date]/
-------| [slug].vue

Here's how you would configure these particular pages in the configuration:

nuxt.config.ts
export default defineNuxtConfig({
  i18n: {
    customRoutes: 'config',
    pages: {
      'blog-date-slug': {
        // params need to be put back here as you would with Nuxt Dynamic Routes
        // https://nuxt.com/docs/guide/directory-structure/pages#dynamic-routes
        ja: '/blog/tech/[date]/[slug]'
        // ...
      }
    }
  }
})

Page component

Note for those updating to v8.0.1 or higher

Path parameters parsing has been changed to match that of Nuxt 3, you will have to update your custom paths (e.g. /example/:param should now be /example/[param])

You can use the defineI18nRoute compiler macro to set custom paths for each page component.

pages/about.vue
<script setup>
  defineI18nRoute({
    paths: {
      en: '/about-us', // -> accessible at /about-us (no prefix since it's the default locale)
      fr: '/a-propos', // -> accessible at /fr/a-propos
      es: '/sobre' // -> accessible at /es/sobre
    }
  })
</script>

To configure a custom path for a dynamic route, you need to use it in double square brackets in the paths similarly to how you would do it in Nuxt Dynamic Routes:

pages/articles/[name].vue
<script setup>
  defineI18nRoute({
    paths: {
      en: '/articles/[name]',
      es: '/artículo/[name]'
    }
  })
</script>
defineI18nRoute compiler macro is tree-shaken out at build time and is not included in the dist files.

definePageMeta({ name: '...' }) caveat

By default Nuxt overwrites generated route values at build time which breaks custom named routes (setting name with definePageMeta) when resolving localized paths.

Nuxt v3.10 introduced the experimental feature scanPageMeta, this needs to be enabled for custom named routes to work when using Nuxt I18n.

This experimental feature can be enabled as shown here:

nuxt.config.ts
export default defineNuxtConfig({
  experimental: {
    scanPageMeta: true,
  }
})

Copyright © 2024