content icon indicating copy to clipboard operation
content copied to clipboard

i18n - How I'm supposed to get the correct page linked to correct locale ?

Open Pamavoc opened this issue 2 years ago • 3 comments

Environment

Classic nuxt 3 project with this as nuxt.config :

modules: ["@nuxt/content", "@nuxtjs/i18n", '@nuxt/devtools'],
  content: {
    locales:[
      'en', 'fr'
    ],
    defaultLocale: 'fr'
  },
  i18n: { 
    strategy: 'prefix',
    defaultLocale: 'fr',
    baseUrl: process.env.BASE_URL || 'https://localhost:3000',
    detectBrowserLanguage: {
      useCookie: true,
      cookieKey: 'i18n_redirected',
      redirectOn: 'root',  // recommended
    },
    locales: [
      {
        code: 'en',
        iso: 'en-US'
      },
      {
        code: 'fr',
        iso: 'fr-FR'
      }
    ]
  }

This is the content folder : image

Reproduction

Use a catchall page [...slug].vue in the pages directory with the same structure as me & same nuxt config

Try to fetch all pages :

const data = await queryContent().where({ _locale: locale.value }).find() 
console.log(data)

You'll get this : image

But when you will use :

const { path } = useRoute()
const { locale } = useI18n()
const data = await queryContent().where({ _locale: locale.value, _path: path }).findOne()
console.log(data)

You will normally get this : image

Describe the bug

where query parameter is maybe broken with multi lang. It won't fetch the correct page but will fetch correctly multiples pages in the folder.

I believe it is not linked to the module i18n.

Additional context

No response

Logs

No response

Pamavoc avatar Feb 16 '23 19:02 Pamavoc

What is the value of path? Note that you should remove locale from path before passing it to queryContent.

Also do you ming creating a simple reproduction using Content Starter?

farnabaz avatar Feb 23 '23 15:02 farnabaz

@Pamavoc I had some issues as well.
This works for me:

<template>
  <NuxtLayout>
    <h1>{{ data.title }}</h1>
    <div>{{ data.description }}</div>
    <ContentRenderer :key="data._id" :value="data.body">
      <ContentRendererMarkdown :value="data" />
    </ContentRenderer>
  </NuxtLayout>
</template>

<script setup>
const { locale: { value: localCode }} = useI18n()
const { data } = await useAsyncData(`/${localCode}`, () => queryContent(`/`).where({ _locale: localCode }).findOne())
</script>

But I'm not sure is the most elegant solution.

learntheropes avatar Apr 03 '23 19:04 learntheropes

Thanks for your insights, after a few try, I think I got it right working also with hierachy /locale/../.../page.md

<script setup lang="ts">
import type { ParsedContent } from "@nuxt/content/dist/runtime/types";

const {
  params: { slug },
} = useRoute();
const { locale } = useI18n();

function redirect404() {
  const router = useRouter();
  router.push("/404");
}

interface ContentError extends Error {
  statusCode: number;
}

const { data, pending, error, refresh } = await useAsyncData<
  ParsedContent,
  ContentError
>(`nuxt-content:${useRoute().fullPath}`, () =>
  queryContent("/")
    .where({ _locale: locale.value, _path: `/${(slug as string[]).join("/")}` })
    .findOne()
);

if (error.value && error.value.statusCode === 404) {
  redirect404();
}
</script>

<template>
  <pre>
    {{ data }}
  </pre>

  <main v-if="data">
    <ContentRenderer v-if="data" :value="data" />
  </main>
</template>

CharlesBT avatar Oct 29 '23 21:10 CharlesBT