ui icon indicating copy to clipboard operation
ui copied to clipboard

HeaderLinks i18n

Open IgorKha opened this issue 1 year ago • 7 comments

Description

Hello! How can I use localized links i18n (<NuxtLinkLocale>) to <UHeaderLinks> and children components?

IgorKha avatar Apr 07 '24 12:04 IgorKha

@IgorKha ¡Hola! Para utilizar enlaces localizados i18n con <NuxtLinkLocale> dentro de componentes secundarios como <UHeaderLinks>, primero necesitas asegurarte de tener configurada la internacionalización (i18n) en tu aplicación Nuxt.js. Luego, puedes usar <NuxtLinkLocale> dentro de tus componentes secundarios como lo harías en cualquier otro lugar de tu aplicación.

  • En tu archivo de plantilla (UHeaderLinks.vue o similar), asegúrate de importar <NuxtLinkLocale> de la siguiente manera:
<template>
  <nav>
    <NuxtLinkLocale to="/ruta" locale="es">Inicio</NuxtLinkLocale>
    <NuxtLinkLocale to="/about" locale="es">Acerca de</NuxtLinkLocale>
    <!-- Otros enlaces -->
  </nav>
</template>

<script>
import { NuxtLinkLocale } from '@nuxtjs/i18n'
export default {
  components: {
    NuxtLinkLocale
  }
}
</script>
  • Asegúrate de tener configurada la internacionalización (i18n) en tu aplicación Nuxt.js. Esto generalmente se hace en el archivo nuxt.config.js. Aquí hay un ejemplo básico de configuración:

export default {
  modules: [
    '@nuxtjs/i18n',
  ],
  i18n: {
    locales: [
      {
        code: 'es',
        iso: 'es-ES',
        name: 'Español'
      },
      // Otros idiomas que desees admitir
    ],
    defaultLocale: 'es',
    vueI18n: {
      fallbackLocale: 'es',
      messages: {
        es: require('./locales/es.json'),
        // Otros archivos de idioma
      }
    }
  }
}

DrxcoDev avatar Apr 07 '24 12:04 DrxcoDev

@DrxcoDev yes, thank you, localized links work for me, but my question is about nuxtui How can I use localized links in <UHeaderLinks>? )

IgorKha avatar Apr 07 '24 13:04 IgorKha

<template>
  <UHeaderLinks>
    <NuxtLinkLocale to="/ruta" locale="es">Inicio</NuxtLinkLocale>
    <NuxtLinkLocale to="/about" locale="es">Acerca de</NuxtLinkLocale>
    <!-- Otros enlaces -->
  </UHeaderLinks>
</template>

<script>
import { NuxtLinkLocale } from '@nuxtjs/i18n'
export default {
  components: {
    NuxtLinkLocale
  }
}
</script>

@IgorKha Entonces prueba el codigo que acabo de adjuntar

DrxcoDev avatar Apr 07 '24 14:04 DrxcoDev

@IgorKha This is unfortunately not possible at the moment as HeaderLinks uses https://ui.nuxt.com/components/link underneath which uses NuxtLink. We have to find a way to handle this globally.

The only way to handle this at the moment is with the useLocalePath() composable.

benjamincanac avatar Apr 08 '24 09:04 benjamincanac

@IgorKha I found a workaround regarding link translation while creating breadcrumb navigation in NuxtUI. It is not very pretty, but I use it to create localized breadcrumb navigation and it is responsive to changing localization. Principles I used may be applicable to you use case, so if you are interested, I could share some snippets I used to create this. But as I said, it is more of a hacky solution to that problem.

mrazek-honza5 avatar Apr 13 '24 11:04 mrazek-honza5

@mrazek-honza5 Yeah, sure, I'd like to see your solution) maybe it'll work for me

IgorKha avatar Apr 15 '24 07:04 IgorKha

Ok. What I have created is a pinia store that stores Pages, represented by the SosPage type. This type is a little more specific to our usecase, but basically it serves as a wrapper for location, translation key / label and the translatable flag, that simply tells the store to either translate the label using the key, or just use the label. I set these on every page. Then the breadcrumbs computed ref transforms these into translated Nuxt UIs BreadcrumbLink. The pinia store part depends on your use case, but if you handle these on one page only, or the links are not changing in the whole app, a simple composable or even computed ref stored in the component, that translates and returns these translated links should do.

type SosPage {
  to: string;
  key: string;
  translatable: boolean;
}

export const useBreadcrumbsStore = defineStore("breadcrumbs", () => {
  const { t } = useI18n({
    useScope: "global",
  });
  const sosPages = ref<SosPage[]>([Pages.Home()]);

  const breadcrumbs = computed<BreadcrumbLink[]>(() => {
    return sosPages.value.map((sosPage) => {
      const breadcrumbLink: BreadcrumbLink = {
        label: sosPage.translatable ? t(`pages.${sosPage.key}`) : sosPage.label,
        to: sosPage.to,
      };
      return breadcrumbLink;
    });
  });

  const setPages = (newPages: SosPage[]) => {
    sosPages.value = [Pages.Home(), ...newPages];
  };

  return {
    breadcrumbs,
    setPages,
  };
});

Then, in my breadcrumbs I simply pull the breadcrumbs from the store and use them inside the Nuxt UI breadcrumb component

<script setup>
const breadcrumbsStore = useBreadcrumbsStore();
const { breadcrumbs } = storeToRefs(breadcrumbsStore);
</script>

<template>
        <UBreadcrumb :links="breadcrumbs" class="hidden md:flex">
          <template #divider>
            <span class="mx-1.5 text-lg text-gray-200"> > </span>
          </template>
          <template #default="{ link, isActive }">
            <span
              class="text-lg"
              :class="isActive ? 'font-bold text-white' : 'text-gray-200'"
            >
              {{ link.label }}
            </span>
          </template>
        </UBreadcrumb>
</template>

I think that you could modify the composable to not only translate the name of the link, but also provide a localized path based on the selected locale. Perhaps replace the to parameter with an object with keys corresponding to your locale and select it based on the active locale. This is not handled in our usecase, but it should not be too hard to handle.

I hope that this will be helpful to you. As I said, it is not the most elegant solution, but it served me well.

mrazek-honza5 avatar Apr 16 '24 07:04 mrazek-honza5