diff --git a/app/components/chat/CommandPalette.vue b/app/components/chat/CommandPalette.vue index 5c43dc4..e4d51e5 100644 --- a/app/components/chat/CommandPalette.vue +++ b/app/components/chat/CommandPalette.vue @@ -6,14 +6,9 @@ const searchTerm = ref('') const openMessageModal = ref(false) const openClearModal = ref(false) -const { t } = useI18n({ useScope: 'local' }) +const { t, locale, locales, setLocale } = useI18n() -const { isDark, toggleDark } = useTheme() -defineShortcuts({ - t: () => toggleDark({ clientX: window.innerWidth, clientY: 0 }), -}) - -const { messages, submitMessage } = useChat(t) +const { messages, submitMessage } = useChat() const { clearMessages, messages: storeMessages } = useChatStore() const loading = computed(() => storeMessages.some(msg => msg.state === ChatState.LOADING)) @@ -28,6 +23,13 @@ function onSelect(item: CommandPaletteItem) { submitMessage(item.type, item.prompt, item.fetchStates ?? []) } +const currentLocale = computed(() => locales.value.filter(l => l.code === locale.value)[0]) + +async function changeLocale() { + await setLocale(currentLocale.value!.code === 'en' ? 'fr' : currentLocale.value!.code === 'fr' ? 'es' : 'en') +} + +const { isDark, toggleDark } = useTheme() defineShortcuts({ meta_enter: () => { openMessageModal.value = !openMessageModal.value @@ -35,6 +37,8 @@ defineShortcuts({ meta_d: () => { openClearModal.value = !openClearModal.value }, + l: () => changeLocale(), + t: () => toggleDark({ clientX: window.innerWidth, clientY: 0 }), }) const modalUi = { @@ -55,8 +59,8 @@ const commandPaletteUi = {
- {{ item.label }} + {{ t(item.label) }}
- {{ item.prompt }} + {{ t(item.prompt) }} @@ -95,7 +99,7 @@ const commandPaletteUi = {
- + @@ -108,11 +112,10 @@ const commandPaletteUi = { - - + /> - + + + + + + - - -{ - "en": { - "clear": { - "button": "Clear", - "cancel": "Cancel", - "submit": "Delete", - "title": "Are you sure you want to delete this conversation?", - "description": "This action cannot be undone." - }, - "cmd": { - "send": "Send message", - "sending": "Sending..." - }, - "chat": { - "actions": "Components", - "arthur": "More about Arthur", - "interface": "Change the interface", - "theme": { - "label": "Change theme", - "prompt": "How can I change the theme?" - }, - "uses": { - "label": "View setup", - "prompt": "How can I view the setup of Arthur?" - }, - "stats": { - "label": "View statistics", - "prompt": "How can I view the statistics concerning Arthur?" - }, - "weather": { - "label": "View weather", - "prompt": "How can I view the weather conditions near Arthur?" - }, - "location": { - "label": "View location", - "prompt": "How can I view the location of Arthur?" - }, - "language": { - "label": "Change language", - "prompt": "How can I change the chat language?" - }, - "activity": { - "label": "Activity", - "prompt": "What are you currently doing?" - }, - "about": { - "label": "About Arthur", - "prompt": "I want you to tell me about yourself." - }, - "projects": { - "label": "Projects", - "prompt": "Tell me about your projects." - }, - "writings": { - "label": "Writings", - "prompt": "What are your latest articles?" - }, - "experiences": { - "label": "Experiences", - "prompt": "What experiences do you have in your career?" - }, - "skills": { - "label": "Skills", - "prompt": "What are your skills?" - }, - "status": { - "label": "Homelab status", - "prompt": "I saw you have a homelab, is it currently working?" - }, - "resume": { - "label": "Resume", - "prompt": "Can you send me your resume?" - }, - "contact": { - "label": "Contact", - "prompt": "How can I contact you?" - }, - "hobbies": { - "label": "Hobbies and passions", - "prompt": "What are your hobbies? Your passions? Your interests?" - }, - "credits": { - "label": "Credits", - "prompt": "How is this chat made?" - } - } - }, - "fr": { - "clear": { - "button": "Effacer", - "cancel": "Annuler", - "submit": "Supprimer", - "title": "Êtes-vous sûr de vouloir supprimer cette conversation ?", - "description": "Cette action ne peut pas être annulée." - }, - "cmd": { - "send": "Envoyer le message", - "sending": "Envoi..." - }, - "chat": { - "actions": "Composants", - "arthur": "En savoir plus sur Arthur", - "interface": "Changer l'interface", - "theme": { - "label": "Changer de thème", - "prompt": "Comment puis-je changer le thème ?" - }, - "uses": { - "label": "Voir la configuration", - "prompt": "Comment puis-je voir la configuration d'Arthur ?" - }, - "stats": { - "label": "Voir les statistiques", - "prompt": "Comment puis-je voir les statistiques concernant Arthur ?" - }, - "weather": { - "label": "Voir la météo", - "prompt": "Comment puis-je voir les conditions météorologiques près d'Arthur ?" - }, - "location": { - "label": "Voir la localisation", - "prompt": "Comment puis-je voir la localisation d'Arthur ?" - }, - "language": { - "label": "Changer de langue", - "prompt": "Comment puis-je changer la langue du chat ?" - }, - "activity": { - "label": "Activité", - "prompt": "Que fais-tu actuellement ?" - }, - "about": { - "label": "A propos d'Arthur", - "prompt": "Je veux que tu me parles de toi." - }, - "projects": { - "label": "Projets", - "prompt": "Je veux que tu me parles de tes projets." - }, - "writings": { - "label": "Écrits", - "prompt": "Quels sont tes derniers articles ?" - }, - "experiences": { - "label": "Expériences", - "prompt": "Quelles expériences as-tu lors de ta carrière ?" - }, - "skills": { - "label": "Compétences", - "prompt": "Quelles sont tes compétences ?" - }, - "status": { - "label": "Statut du homelab", - "prompt": "J'ai vu que tu avais un homelab, est-il actuellement fonctionnel ?" - }, - "resume": { - "label": "CV", - "prompt": "Peux-tu m'envoyer ton CV ?" - }, - "contact": { - "label": "Contact", - "prompt": "Comment puis-je te contacter ?" - }, - "hobbies": { - "label": "Loisirs et passions", - "prompt": "Quels sont tes loisirs ? Tes passions ? Tes intérêts ?" - }, - "credits": { - "label": "Crédits", - "prompt": "Comment est réalisé ce chat ?" - } - } - }, - "es": { - "clear": { - "button": "Borrar", - "cancel": "Cancelar", - "submit": "Eliminar", - "title": "¿Estás seguro de que deseas eliminar esta conversación?", - "description": "Esta acción no se puede deshacer." - }, - "cmd": { - "send": "Enviar el mensaje", - "sending": "Enviando..." - }, - "chat": { - "actions": "Componentes", - "arthur": "Más sobre Arthur", - "interface": "Cambiar la interfaz", - "theme": { - "label": "Cambiar tema", - "prompt": "¿Cómo puedo cambiar el tema?" - }, - "uses": { - "label": "Ver la configuración", - "prompt": "¿Cómo puedo ver la configuración de Arthur?" - }, - "stats": { - "label": "Ver estadísticas", - "prompt": "¿Cómo puedo ver las estadísticas sobre Arthur?" - }, - "weather": { - "label": "Ver el clima", - "prompt": "¿Cómo puedo ver las condiciones climáticas cerca de Arthur?" - }, - "location": { - "label": "Ver ubicación", - "prompt": "¿Cómo puedo ver la ubicación de Arthur?" - }, - "language": { - "label": "Cambiar idioma", - "prompt": "¿Cómo puedo cambiar el idioma del chat?" - }, - "activity": { - "label": "Actividad", - "prompt": "¿Qué estás haciendo actualmente?" - }, - "about": { - "label": "Sobre Arthur", - "prompt": "Quiero que me hables de ti." - }, - "projects": { - "label": "Proyectos", - "prompt": "Háblame de tus proyectos." - }, - "writings": { - "label": "Escritos", - "prompt": "¿Cuáles son tus últimos artículos?" - }, - "experiences": { - "label": "Experiencias", - "prompt": "¿Qué experiencias tienes en tu carrera?" - }, - "skills": { - "label": "Habilidades", - "prompt": "¿Cuáles son tus habilidades?" - }, - "status": { - "label": "Estado del homelab", - "prompt": "Vi que tienes un homelab, ¿está funcionando actualmente?" - }, - "resume": { - "label": "CV", - "prompt": "¿Puedes enviarme tu CV?" - }, - "contact": { - "label": "Contacto", - "prompt": "¿Cómo puedo contactarte?" - }, - "hobbies": { - "label": "Pasatiempos y pasiones", - "prompt": "¿Cuáles son tus pasatiempos? ¿Tus pasiones? ¿Tus intereses?" - }, - "credits": { - "label": "Créditos", - "prompt": "¿Cómo se ha hecho este chat?" - } - } - } -} - diff --git a/app/components/chat/Loading.vue b/app/components/chat/Loading.vue index d30ff66..88428b6 100644 --- a/app/components/chat/Loading.vue +++ b/app/components/chat/Loading.vue @@ -3,10 +3,9 @@ import type { ChatFetchState } from '~~/types' import { ChatState } from '~~/types' const props = defineProps<{ messageId: number, fetchStates: ChatFetchState[] }>() - const currentState = ref(props.fetchStates[0] ?? undefined) - const { setLoadingState } = useChatStore() +const { t } = useI18n() onMounted(() => { let index = 0 @@ -38,7 +37,7 @@ onMounted(() => { - {{ currentState }} + {{ t(currentState || '') }}
diff --git a/app/components/chat/MessageContainer.vue b/app/components/chat/MessageContainer.vue index 8a061d7..1551f68 100644 --- a/app/components/chat/MessageContainer.vue +++ b/app/components/chat/MessageContainer.vue @@ -8,9 +8,7 @@ const props = defineProps<{ const isArthur = computed(() => props.message.sender === ChatSender.ARTHUR) -const { locale, locales } = useI18n({ - useScope: 'local', -}) +const { t, locale, locales } = useI18n() const currentLocale = computed(() => locales.value.find((l: { code: string }) => l.code === locale.value)) const formatted = computed(() => useDateFormat(useNow(), 'D MMMM YYYY, HH:mm', { locales: currentLocale.value?.code ?? 'en' }).value) @@ -23,7 +21,7 @@ const formatted = computed(() => useDateFormat(useNow(), 'D MMMM YYYY, HH:mm', { class="rounded-xl mt-1 bg-sky-500 md:max-w-3/4 text-white font-medium" :ui="{ body: 'sm:p-2', header: 'sm:p-2', footer: 'sm:p-2' }" > - {{ message.content }} + {{ t(message.content || '') }}
@@ -47,7 +45,7 @@ const formatted = computed(() => useDateFormat(useNow(), 'D MMMM YYYY, HH:mm', { :ui="{ body: 'p-0 sm:p-0', header: 'p-0 sm:p-0', footer: 'p-0 sm:p-0' }" >
- {{ message.content }} + {{ t(message.content || '') }}
diff --git a/app/components/tool/Activity.vue b/app/components/tool/Activity.vue index cf1bf3b..e7ce939 100644 --- a/app/components/tool/Activity.vue +++ b/app/components/tool/Activity.vue @@ -3,10 +3,7 @@ import type { UseTimeAgoMessages } from '@vueuse/core' import type { Activity } from '~~/types' import { activityMessages, IDEs } from '~~/types' -const { locale, locales, t } = useI18n({ - useScope: 'local', -}) - +const { locale, locales, t } = useI18n() const { data: activity, refresh } = await useAsyncData('activity', () => $fetch('/api/activity')) useIntervalFn(async () => await refresh(), 5000) @@ -50,7 +47,7 @@ const getActivity = computed(() => { .trim() : '' - const stateWord = state && state.split(' ').length >= 2 ? state.split(' ')[1] : t('secret') + const stateWord = state && state.split(' ').length >= 2 ? state.split(' ')[1] : t('tool.activity.secret') const ago = useTimeAgo(timestamps.start, { messages: activityMessages[locale.value as keyof typeof activityMessages] as UseTimeAgoMessages, }).value @@ -74,16 +71,16 @@ const getActivity = computed(() => { - - -{ - "en": { - "offline": "I'm currently offline. Come back later to see what I'm working on. {maths}", - "working": "I'm actually online! Check what I'm working on just below.", - "idling": "I'm idling on my computer with {editor} running in background.", - "maths": "I am probably doing some maths or sleeping.", - "response": "The statistics are powered and saved by WakaTime.", - "tooltip": { - "online": "I'm online 👋", - "offline": "I'm offline 🫥", - "idling": "I'm sleeping 😴" - }, - "started": "Started the {date} at {hour}", - "secret": "Secret Project" - }, - "fr": { - "offline": "Je suis actuellement hors ligne. Revenez plus tard pour voir sur quoi je travaille. {maths}", - "working": "Je suis actuellement en ligne ! Découvrez ce sur quoi je travaille juste en dessous.", - "idling": "Je suis en veille sur mon ordinateur avec {editor} en arrière-plan.", - "maths": "Je suis probablement en train de faire des maths ou en train de dormir.", - "response": "Les statistiques sont propulsées et enregistrées par WakaTime.", - "tooltip": { - "online": "Je suis connecté 👋", - "offline": "Je suis déconnecté 🫥", - "idling": "Je dors 😴" - }, - "started": "Commencé le {date} à {hour}", - "secret": "Projet Secret" - }, - "es": { - "offline": "Ahora mismo estoy desconectado. Vuelve más tarde para ver en lo que estoy trabajando. {maths}", - "working": "Estoy trabajando en línea. ¡Mira lo que estoy haciendo justo debajo!", - "idling": "Estoy en reposo en mi ordenador con {editor} en segundo plano.", - "maths": "Estoy probablemente haciendo matemáticas o durmiendo.", - "response": "Las estadísticas son propulsadas y registradas por WakaTime.", - "tooltip": { - "online": "Estoy conectado 👋", - "offline": "Estoy desconectado 🫥", - "idling": "Estoy durmiendo 😴" - }, - "started": "Comenzado el {date} a {hour}", - "secret": "Proyecto Secreto" - } -} - diff --git a/app/components/tool/Contact.vue b/app/components/tool/Contact.vue index 89d1383..965d152 100644 --- a/app/components/tool/Contact.vue +++ b/app/components/tool/Contact.vue @@ -1,14 +1,14 @@ - - -{ - "en": { - "contact": "There are different ways to contact me. Here is a list:" - }, - "fr": { - "contact": "Il existe différents façons de me contacter. Voici une liste :" - }, - "es": { - "contact": "Existen diferentes formas de contactarme. Aquí hay una lista:" - } -} - diff --git a/app/components/tool/Duplicated.vue b/app/components/tool/Duplicated.vue index a09f466..334bf78 100644 --- a/app/components/tool/Duplicated.vue +++ b/app/components/tool/Duplicated.vue @@ -1,33 +1,10 @@ - - -{ - "en": { - "duplicated": { - "title": "⚠️ I detected duplicated messages", - "description": "I have therefore removed the older duplicated messages to lighten the application." - } - }, - "fr": { - "duplicated": { - "title": "⚠️ J'ai détecté des messages dupliqués", - "description": "J'ai donc supprimé les anciens messages dupliqués pour alléger l'application." - } - }, - "es": { - "duplicated": { - "title": "⚠️ He detectado mensajes duplicados", - "description": "Por lo tanto, eliminé los mensajes duplicados más antiguos para aligerar la aplicación." - } - } -} - diff --git a/app/components/tool/Language.vue b/app/components/tool/Language.vue index e4fe78b..2eb51cb 100644 --- a/app/components/tool/Language.vue +++ b/app/components/tool/Language.vue @@ -1,33 +1,20 @@ - - -{ - "en": { - "change": "Change language", - "response": { - "control": "I added the language switch control above so you can switch directly.", - "choose": "Choose English, French, or Spanish", - "kbd": "Press {kbd} on your keyboard" - } - }, - "fr": { - "change": "Changer de langue", - "response": { - "control": "J'ai ajouté le contrôle de changement de langue ci-dessus pour que vous puissiez changer directement.", - "choose": "Choisissez Anglais, Français ou Espagnol", - "kbd": "Appuyez sur {kbd} de votre clavier" - } - }, - "es": { - "change": "Cambiar idioma", - "response": { - "control": "He añadido el control de cambio de idioma arriba para que puedas cambiar directamente.", - "choose": "Elige Inglés, Francés o Español", - "kbd": "Presiona {kbd} en tu teclado" - } - } -} - diff --git a/app/components/tool/Location.vue b/app/components/tool/Location.vue index 176b0fc..f3045ed 100644 --- a/app/components/tool/Location.vue +++ b/app/components/tool/Location.vue @@ -1,11 +1,7 @@ - - - - -{ - "en": { - "location": "I'm currently based in {location}. See below for more details." - }, - "fr": { - "location": "Je suis actuellement basé à {location}. Voir ci-dessous pour plus de détails." - }, - "es": { - "location": "Actualmente estoy basado en {location}. Consulta más detalles a continuación." - } -} - diff --git a/app/components/tool/Stats.vue b/app/components/tool/Stats.vue index febc3ce..08c49aa 100644 --- a/app/components/tool/Stats.vue +++ b/app/components/tool/Stats.vue @@ -3,9 +3,7 @@ import type { Stats } from '~~/types' const { data: stats } = await useAsyncData('stats', () => $fetch('/api/stats')) -const { locale, locales, t } = useI18n({ - useScope: 'local', -}) +const { locale, locales, t } = useI18n() const currentLocale = computed(() => locales.value.find(l => l.code === locale.value)) const time = useTimeAgo(new Date(stats.value!.coding.data.range.start) ?? new Date()).value.split(' ')[0] @@ -17,7 +15,7 @@ const hours = usePrecision(stats.value!.coding.data.grand_total.total_seconds_in
    - - -{ - "en": { - "stats": "I collect some data for {time} years, started the {date}. I've coded for a total of {hours} hours.", - "editors": "My top editors are {editors}", - "os": "My best OS is {os}", - "languages": "My favorite languages are {languages}", - "separator": " and ", - "tooltip": { - "date": "That was so long ago 🫣", - "hours": "That's a lot 😮" - } - }, - "fr": { - "stats": "Je collecte des données depuis {time} ans, commencé le {date}. J'ai codé un total de {hours} heures.", - "editors": "Mes meilleurs éditeurs sont {editors}", - "os": "Mon meilleur OS est {os}", - "languages": "Mes langages préférés sont {languages}", - "separator": " et ", - "tooltip": { - "date": "C'était il y a si longtemps 🫣", - "hours": "C'est beaucoup 😮" - } - }, - "es": { - "stats": "Recopilo datos desde hace {time} años, empecé el {date}. He programado durante un total de {hours} horas.", - "editors": "Mis mejores editores son {editors}.", - "os": "Mi mejor OS es {os}.", - "languages": "Mis lenguajes favoritos son {languages}.", - "separator": " y ", - "tooltip": { - "date": "hace tato tiempo…🫣", - "hours": "es mucho 😮" - } - } -} - diff --git a/app/components/tool/Theme.vue b/app/components/tool/Theme.vue index 87034bb..2ef5fab 100644 --- a/app/components/tool/Theme.vue +++ b/app/components/tool/Theme.vue @@ -1,15 +1,15 @@ - -{ - "en": { - "switch": "Switch theme", - "light": "Light", - "dark": "Dark", - "response": { - "control": "I added the theme toggle control above so you can switch directly.", - "choose": "Choose Light (sun icon) or Dark (moon icon)", - "kbd": "Press {kbd} on your keyboard" - } - }, - "fr": { - "switch": "Changer de thème", - "light": "Clair", - "dark": "Sombre", - "response": { - "control": "J'ai ajouté le contrôle de basculement de thème ci-dessus afin que vous puissiez basculer directement.", - "choose": "Choisissez Clair (icône de soleil) ou Sombre (icône de lune)", - "kbd": "Appuyez sur {kbd} sur votre clavier" - } - }, - "es": { - "switch": "Cambiar tema", - "light": "Claro", - "dark": "Oscuro", - "response": { - "control": "He añadido el control de alternancia de tema arriba para que puedas cambiar directamente.", - "choose": "Elige Claro (icono de sol) u Oscuro (icono de luna)", - "kbd": "Presiona {kbd} en tu teclado" - } - } -} - -