Skip to content

How to have localized links in ContentSearch? #5359

@MartinLednar

Description

@MartinLednar

Package

v4.x

Description

I’m using @nuxt/content, @nuxt/ui, and @nuxtjs/i18n together, and I’m trying to have localized URLs in the search results rendered by the component.

Currently, the component works fine and fetches all the correct results, but the item.path values are always non-localized (e.g. /blog/my-post instead of /sk/blog/my-post).
Even though my site is fully localized and I’m correctly fetching content from language-specific collections like blogs_en and blogs_sk.

I couldn’t find a built-in way to localize the links inside the search results.
Is there a recommended approach to make output localized URLs?

What I tried

  1. Transforming the urls when fetching the navigation and searchSections, which works but, all the results are highlighted by default, because my guess is that NuxtLinks is-active is not set to exact url path.

  2. Setting locale prefix to nuxt/content collection, for example for sk locale it would be /sk/blog. This worked as well but the result was as in the point 1.

This is how I fetch the data ( Version with the transformations )

const { locale, t } = useI18n();
const localePath = useLocalePath();
const route = useRoute();

const normalizedPath = computed(() =>
  withLeadingSlash(joinURL("blog", ...(Array.isArray(route.params.slug) ? route.params.slug : [route.params.slug])))
);

const { data: page } = await useAsyncData(
  normalizedPath.value,
  () => queryCollection(`blogs_${locale.value}`).path(normalizedPath.value).first(),
  { watch: [locale, route] }
);

const { data: navigation } = await useAsyncData(
  `navigation-${locale.value}-${normalizedPath.value}`,
  async () => {
    const nav = await queryCollectionNavigation(`blogs_${locale.value}`).where(
      "path",
      "LIKE",
      `%${normalizedPath.value}%`
    );

    const transformNav = (items) =>
      items.map((item) => ({
        ...item,
        path: localePath(item.path),
        children: item.children ? transformNav(item.children) : undefined,
      }));

    return transformNav(nav);
  },
  { watch: [locale, route] }
);

const { data: searchSections } = await useLazyAsyncData(
  `search-sections-${locale.value}-${normalizedPath.value}`,
  () =>
    queryCollectionSearchSections(`blogs_${locale.value}`).where(
      "path",
      "LIKE",
      `%${normalizedPath.value}%`
    ),
  {
    watch: [locale, route],
    server: false,
  }
);

This is how I render the ContentSearch

<ClientOnly>
    <UContentSearch
      shortcut="meta_shift_k"
      :navigation="navigation"
      :files="searchSections"
      autofocus
      :fuse="{ resultLimit: 20 }"
      :placeholder="$t('blogDetail.searchInArticle')"
      :color-mode="false"
      :ui="{}"
    >
      <template #empty="{ searchTerm }">
        <template v-if="searchTerm">
          {{ $t("blogDetail.searchEmpty") }}
          "{{ searchTerm }}"
        </template>
      </template>
    </UContentSearch>
</ClientOnly>

Thank you in advance for any suggestions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requestedv4#4488

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions