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 2 ways of configuring custom paths for your Module configuration or your pages Page component.

Custom paths are not supported when using the no-prefixstrategy.

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 relative file-based path (excluding .vue file extension) of the route within your pages/ directory excluding the leading /.

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

In addition, the localePath specified for custom paths resolution must be a named route.

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

<template>
  <NuxtLink :to="localePath({ name: 'about' })">{{ t('about') }}</NuxtLink>
</template>
Specifying a path to localePath is not supported, currently.

Example 1: Basic URL localization

You have some routes with the following pages directory:

pages/
├── about.vue
├── me.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: {
      about: {
        fr: '/a-propos',
      },
      me: {
        fr: '/je',
      },
      'services/index': {
        fr: '/offres',
      }
      'services/advanced': {
        fr: '/offres/avancee',
      }
    }
  },

  // ...
})

If you want customize the URL of a static vue file, you should use the file's name. If the view is in a sub-directory you should use folder name and vue files name with trailing slash.

All the URL should start with /

Example 2: Localize the part of URL

You have some routes with the following pages directory:

pages/
├── about.vue
├── services/
├──── coaching.vue
├──── index.vue
├──── development/
├────── app.vue
├────── website.vue
├────── index.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/index': {
        fr: '/offres',
      },
      'services/development/index': {
        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

You can use the defineI18nRoute compiler macro to set some 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-shaked out at build time and is not included in the dist files.