content icon indicating copy to clipboard operation
content copied to clipboard

Nuxt content & i18n translation

Open daishizenSensei opened this issue 5 years ago • 5 comments

Hello,

We build a Nuxt SSG app with Nuxt content. We use Nuxt i18n to translate our content. We follow this tutorial to achieve that: https://alvarosaburido.dev/blog/multi-language-blog-with-nuxt-content but it is not clean end solution 2 doesn't work. Apparently, we have to put a specific language switcher in content pages (different from our main switcher).

How can we achieve that? With a v-if with a specific switcher displayed only in content pages? We tried but doesn't work...

Thanks a lot, Kevin

daishizenSensei avatar Nov 17 '20 16:11 daishizenSensei

I'm facing the same issue, did you ever find a good solution?

StefanVDWeide avatar Apr 16 '21 19:04 StefanVDWeide

I'll share my solution for blog with i18n. It works with standard locale switcher, and also provides nice, locale-friendly urls for all blog posts.

For this to work you need to enable vuex store for Nuxt: https://nuxtjs.org/docs/2.x/directory-structure/store.

I have one folder with blog posts:

/content/blog/hello-world.md:

---
language: en
date: 2021-05-20
title: Hi
---

Hello world!

/content/blog/witaj-swiecie.md:

---
language: pl
date: 2021-05-20
title: Cześć
---

Witaj świecie!

In the folder all posts have the language attribute, and different language versions of same post are matched by publish date (you can of course match them by some unique ID to be more bulletproof).

And now rendering of those posts:

/pages/blog/index.vue:

<template>
  <div>
    <NuxtLink
      v-for="post in blogPosts"
      :to="localePath(post.path)"
      :key="post.path"
    >
      {{ post.title }}
    </NuxtLink>
  </div>
</template>

<script>

export default {
  async asyncData({ $content, i18n }) {
    const blogPosts = await $content("blog")
      .where({ language: i18n.locale })
      .fetch();
    return { blogPosts };
  }
};
</script>

/pages/blog/_slug.vue:

<template>
  <article>
      <h1>{{ article.title }}</h1>
      <nuxt-content :document="article" />
  </article>
</template>

<script>
const opposingLocale = currentLocale => {
  if (currentLocale === "pl") {
    return "en";
  }
  return "pl";
};

export default {
  async asyncData({ $content, params, store }) {
    const article = await $content("blog", params.slug).fetch();
    const articleOpposingLanguageList = await $content("blog")
      .where({
        date: {
          // hack, to get all articles with the same date
          $between: [
            new Date(article.date).valueOf(),
            new Date(article.date).valueOf()
          ]
        },
        language: opposingLocale(article.language)
      })
      .fetch();
    const articleOpposingLanguage = articleOpposingLanguageList[0];
    await store.dispatch("i18n/setRouteParams", {
      [article.language]: { slug: article.slug },
      [articleOpposingLanguage.language]: { slug: articleOpposingLanguage.slug }
    });
    return { article };
  }
};
</script>

szwacz avatar Apr 21 '21 15:04 szwacz

hi @szwacz thanks for this idea but do you have an idea how to fallback we have much languages but not every page is ready so we want to fallback until others are ready

cannap avatar Aug 13 '21 07:08 cannap

@cannap didn't try this, but for my node articleOpposingLanguageList should return empty list if given article is not found, and then you can substiture the link to article with default language.

szwacz avatar Aug 13 '21 15:08 szwacz

i made it like this @szwacz

export default {
  name: 'Privacy',

  async asyncData({ $content, i18n }) {
    let page = {}

    page = await $content(`legal`)
      .where({ language: i18n.locale, doc: 'privacy' })
      .fetch()

    if (page.length > 0) {
      return {
        page: page[0]
      }
    }
    // Fallback...
    page = await $content(`legal`)
      .where({ language: 'en', doc: 'privacy' })
      .fetch()

    return { page: page[0] }
  },
  data() {
    return {
      page: ''
    }
  }
}
</script>

cannap avatar Aug 13 '21 15:08 cannap