nuxt / ui

A UI Library for Modern Web Apps, powered by Vue & Tailwind CSS.
https://ui.nuxt.com
MIT License
4.15k stars 554 forks source link

HeaderLinks i18n #1633

Open IgorKha opened 7 months ago

IgorKha commented 7 months ago

Description

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

DrxcoDev commented 7 months ago

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

<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>

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
      }
    }
  }
}
IgorKha commented 7 months ago

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

DrxcoDev commented 7 months ago
<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

benjamincanac commented 7 months ago

@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.

mrazek-honza5 commented 7 months ago

@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.

IgorKha commented 7 months ago

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

mrazek-honza5 commented 7 months ago

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.