Skip to main content

How to translate slugs with Nuxt.js and Storyblok

    Try Storyblok

    Storyblok is the first headless CMS that works for developers & marketers alike.

    In this article I explain how to use a translated slug with nuxt. I also show you a really simple real life example with Storyblok.

    Use cases

    You can use Storyblok for basically everything! Use it for e-commerce, a personal website, blog, etc. As you may know, these days SEO is really important. Having a translated URL for your website will boost your SEO performance. Check out the google documentation, it encourages you to do that.

    Let's create the project

    If you already have a project with nuxt and nuxt-i18n skip to the next point. Or check out the code directly. (Live demo)


    npx create-nuxt-app myproject

    Make sure to select axios. From here you need to install nuxt-i18n.


    npm install --save-dev nuxt-i18n

    You need to create a file store/index.js to activate the store in your NuxtJS project and make Nuxt i18n work.

    Static page with translated slugs

    For the static pages, you can check the docs. You can configure it in the module configuration inside your nuxt.config.js or directly in components. Here is an example of how to use it in a component:


      <div>Contact me</div>
    export default {
      nuxtI18n: {
        paths: {
          en: '/contact-me',
          fr: '/me-contacter',

    Important: If the filename is different from the default lang use this example to navigate to it.

    <nuxt-link :to="localePath({ name: 'contact' })">

    Let's use dynamic URLs with Storyblok.

    For dynamic URLs I could have used Nuxt content. But as I have worked on a lot of eCommerce websites, I prefer doing it with Storyblok.

    First, let's see how to use dynamic routes parameters with nuxt-i18n. You will need to use 'i18n/setRouteParams' actions from your Vuex store. Your file will look like pages/_articleId.vue .


        <h1>{{ content.seo.title }}</h1>
          {{ content.seo.description }}
    import { translatedSlugs } from '~/helpers/translated_slug'
    export default {
      name: 'PageArticle',
      async asyncData(ctx) {
        const locale = === 'en' ? '' : 'fr'
        const param = ctx.params.articleId
        try {
          const article = await$storyapi.get(
              version: process.env.STORYBLOK_VERSION || 'draft',
          const story =
          await'i18n/setRouteParams', translatedSlugs(story))
          return story
        } catch (e) {
    	   // your error handler
      data: () => ({
        content: { seo: {} },

    And that's it! Now your visitors can enjoy URLs in their native language.

    Thanks for reading this article and if you want to support me you can buymeacoffee.

    Thank's to Josh Deltener for reviewing the article.