From e37f00a196f300cc21c79d7541031c4289d709dc Mon Sep 17 00:00:00 2001 From: Pierre-Jean CHANCELLIER <paidge_cs@hotmail.com> Date: Sat, 8 Jan 2022 19:58:01 +0100 Subject: [PATCH] i18n --- components/badge/CertifStatus.vue | 2 +- components/badge/Status.vue | 13 +- components/certif/List.vue | 2 +- components/member/Card.vue | 22 +-- components/member/List.vue | 6 +- components/navigation/Bar.vue | 16 +- components/navigation/Breadcrumb.vue | 9 +- components/navigation/Language.vue | 24 +++ components/navigation/Loader.vue | 2 +- components/navigation/menu/Group.vue | 6 +- components/navigation/menu/Sidebar.vue | 2 +- graphql/index.js | 4 +- i18n/index.js | 10 ++ i18n/locales/dateTimeFormats.js | 47 ++++++ i18n/locales/en.json | 57 +++++++ i18n/locales/es.json | 57 +++++++ i18n/locales/fr.json | 57 +++++++ layouts/default.vue | 40 +++-- nuxt.config.js | 28 +++- package-lock.json | 146 +++++++++++++++++- package.json | 5 +- pages/chartjs.vue | 9 +- pages/index.vue | 14 +- pages/membres/_hash.vue | 19 ++- pages/membres/index.vue | 19 ++- pages/previsions/_hash.vue | 13 +- .../{newcomers.vue => futurs_membres.vue} | 29 ++-- pages/previsions/index.vue | 11 +- 28 files changed, 581 insertions(+), 88 deletions(-) create mode 100644 components/navigation/Language.vue create mode 100644 i18n/index.js create mode 100644 i18n/locales/dateTimeFormats.js create mode 100644 i18n/locales/en.json create mode 100644 i18n/locales/es.json create mode 100644 i18n/locales/fr.json rename pages/previsions/{newcomers.vue => futurs_membres.vue} (85%) diff --git a/components/badge/CertifStatus.vue b/components/badge/CertifStatus.vue index cee160b..b3ceae8 100644 --- a/components/badge/CertifStatus.vue +++ b/components/badge/CertifStatus.vue @@ -21,7 +21,7 @@ export default { } }, textWarning: function() { - return (this.$options.filters.dateStatus(this.limitDate) == 'danger') ? 'En manque de certifications' : 'Bientôt en manque de certifications' + return (this.$options.filters.dateStatus(this.limitDate) == 'danger') ? this.$i18n.t('statut.manquecertif') : this.$i18n.t('statut.bientotmanquecertif') } } } diff --git a/components/badge/Status.vue b/components/badge/Status.vue index 0301cf7..ed5e794 100644 --- a/components/badge/Status.vue +++ b/components/badge/Status.vue @@ -1,7 +1,6 @@ <template> <small> - <span class="badge" - :class="this.displayStatus(membre).class"> + <span class="badge" :class="this.displayStatus(membre).class"> {{ this.displayStatus(membre).str }} </span> </small> @@ -19,17 +18,17 @@ export default { displayStatus: function(member){ switch (member.status) { case 'NEWCOMER': - return {str: 'Futur membre',class: 'badge-info'} + return {str: this.$i18n.t('statut.newcomer'),class: 'badge-info'} case 'MISSING': - return {str: 'Adhésion perdue',class: 'badge-danger'} + return {str: this.$i18n.t('statut.missing'),class: 'badge-danger'} case 'MEMBER': if (this.$options.filters.dateStatus(member.limitDate) == 'warning') { - return {str: 'Adhésion à renouveler',class: 'badge-warning'} + return {str: this.$i18n.t('statut.renew'),class: 'badge-warning'} } else { - return {str: 'Membre',class: 'badge-success'} + return {str: this.$i18n.t('statut.member'),class: 'badge-success'} } case 'REVOKED': - return {str: 'Membre revoqué',class: 'badge-secondary'} + return {str: this.$i18n.t('statut.revoked'),class: 'badge-secondary'} default: return 'N/A' } diff --git a/components/certif/List.vue b/components/certif/List.vue index 659a542..378a7d0 100644 --- a/components/certif/List.vue +++ b/components/certif/List.vue @@ -3,7 +3,7 @@ <table class="table table-striped table-hover"> <tbody> <tr v-for="certif in certifsTriees" :key="getNeighbor(certif).uid" - @click="$router.push({ path: '/membres/' + getNeighbor(certif).hash })"> + @click="$router.push(localePath({name:'membres-hash', params: {hash: getNeighbor(certif).hash}}))"> <th scope="row"> {{ getNeighbor(certif).uid }} <BadgeCertifStatus :limitDate="getNeighbor(certif).received_certifications.limit" :memberStatus="getNeighbor(certif).status" /> diff --git a/components/member/Card.vue b/components/member/Card.vue index ce3c7cc..876a431 100644 --- a/components/member/Card.vue +++ b/components/member/Card.vue @@ -9,40 +9,40 @@ <table class="table table-sm table-borderless" v-if="hash.status != 'REVOKED'"> <tbody> <tr v-if="hash.status == 'MEMBER'"> - <th scope="row">Référent :</th> - <td :class="{'list-group-item-success': isReferent, 'list-group-item-warning': !isReferent}">{{ isReferent ? 'Oui' : 'Non' }}</td> + <th scope="row">{{ $t('membre.referent') }} :</th> + <td :class="{'list-group-item-success': isReferent, 'list-group-item-warning': !isReferent}">{{ isReferent ? $t('oui') : $t('non') }}</td> </tr> <tr v-if="hash.status != 'NEWCOMER'"> - <th scope="row">Qualité :</th> + <th scope="row">{{ $t('membre.qualite') }} :</th> <td :class="{ 'list-group-item-success': hash.quality.ratio >= 80, 'list-group-item-warning': hash.quality.ratio < 80, }">{{ Math.round(hash.quality.ratio*100)/100 }}</td> </tr> <tr v-if="hash.status != 'NEWCOMER'"> - <th scope="row">Distance :</th> + <th scope="row">{{ $t('membre.distance') }} :</th> <td :class="{ 'list-group-item-success': hash.distance.dist_ok, 'list-group-item-danger': !hash.distance.dist_ok, }">{{ Math.round(hash.distance.value.ratio*100)/100 }}</td> </tr> <tr> - <th scope="row">{{ hash.status != 'MISSING' ? "Date limite d'adhésion" : "Date limite avant révocation"}} :</th> - <td :class="hash.status != 'MISSING' ? 'list-group-item-'+ $options.filters.dateStatus(hash.limitDate) : 'list-group-item-danger'">{{ hash.limitDate | formatDate }}</td> + <th scope="row">{{ hash.status != 'MISSING' ? $t('membre.datelimadhesion') : $t('membre.datelimrevoc')}} :</th> + <td :class="hash.status != 'MISSING' ? 'list-group-item-'+ $options.filters.dateStatus(hash.limitDate) : 'list-group-item-danger'">{{ $d(new Date(hash.limitDate*1000), 'long') }}</td> </tr> <tr v-if="hash.status == 'MEMBER'"> - <th scope="row">Date avant de manquer de certifs :</th> - <td :class="'list-group-item-'+ $options.filters.dateStatus(hash.received_certifications.limit)">{{ hash.received_certifications.limit | formatDate }}</td> + <th scope="row">{{ $t('membre.datemanquecertifs') }} :</th> + <td :class="'list-group-item-'+ $options.filters.dateStatus(hash.received_certifications.limit)">{{ $d(new Date(hash.received_certifications.limit*1000), 'long') }}</td> </tr> <tr v-if="hash.status == 'MEMBER'"> - <th scope="row">Disponible pour certifier :</th> + <th scope="row">{{ $t('membre.dispocertif') }} :</th> <td :class="{ 'list-group-item-success': hash.minDatePassed, 'list-group-item-danger': !hash.minDatePassed, - }">{{ hash.minDatePassed ? 'Oui' : 'Non' }} <small v-if="!hash.minDatePassed">( > {{ hash.minDate | formatDate }} )</small></td> + }">{{ hash.minDatePassed ? $t('oui') : $t('non') }} <small v-if="!hash.minDatePassed">( > {{ hash.minDate | formatDate }} )</small></td> </tr> <tr v-if="hash.status == 'MEMBER'"> - <th scope="row">Nbre de certifs disponibles :</th> + <th scope="row">{{ $t('membre.nb_certifs') }} :</th> <td :class="{ 'list-group-item-success': hash.sent_certifications.length<=80, 'list-group-item-warning': hash.sent_certifications.length>80, diff --git a/components/member/List.vue b/components/member/List.vue index ccb5d49..5541d3d 100644 --- a/components/member/List.vue +++ b/components/member/List.vue @@ -9,7 +9,7 @@ </thead> <tbody> <tr v-for="member in members" :key="member.uid" - @click="redirect('/membres/' + member.hash)"> + @click="redirect(member.hash)"> <th scope="row"> {{ member.uid }} <BadgeCertifStatus :limitDate="member.received_certifications.limit" :memberStatus="member.status" /> @@ -39,8 +39,8 @@ export default { } }, methods: { - redirect(path) { - this.$router.push({ path: path }) + redirect(hash) { + this.$router.push(this.localePath({name:'membres-hash', params: {hash}})) } }, } diff --git a/components/navigation/Bar.vue b/components/navigation/Bar.vue index 05dfdd1..3c8f537 100644 --- a/components/navigation/Bar.vue +++ b/components/navigation/Bar.vue @@ -2,7 +2,7 @@ <header class="header position-fixed"> <div class="position-relative"> <button class="toggle btn border-secondary position-absolute p-1 m-1 ml-3" @click="toggleMenu"><span></span></button> - <NavigationBreadcrumb :breadcrumb="breadcrumb" class="breadcrumb p-1" /> + <NavigationBreadcrumb :breadcrumb="breadcrumb" /> </div> <NavigationMenuSidebar @toggleMenu="toggleMenu" :menus="menus" /> <div class="bg_overlay position-fixed" @click="toggleMenu"></div> @@ -42,14 +42,24 @@ $btn-width: 50px; } } -nav.breadcrumb { - margin: .5rem .5rem .5rem 5rem; +nav.breadcrumb-wrapper { + margin: 8px 15px 8px 80px; + display: flex; + flex-direction: column; + gap: 1rem; + background: var(--background-color-secondary); a {color: var(--text-primary-color)} .breadcrumb-item.active { opacity: .7; } + + @media (min-width:768px) { + flex-direction: row; + justify-content: space-between; + align-items: center; + } } %hamburger-line { diff --git a/components/navigation/Breadcrumb.vue b/components/navigation/Breadcrumb.vue index 6e40c09..2c0f0de 100644 --- a/components/navigation/Breadcrumb.vue +++ b/components/navigation/Breadcrumb.vue @@ -1,12 +1,15 @@ <template> - <nav aria-label="Fil d'Ariane" class="justify-content-between align-items-center"> - <ol class="breadcrumb m-0"> + <nav aria-label="Fil d'Ariane" class="breadcrumb-wrapper rounded p-3"> + <ol class="breadcrumb m-0 p-0"> <li class="breadcrumb-item" :class="{ 'active': item.active }" :aria-current="item.active ? 'page' : null" v-for="item in breadcrumb" :key="item.text"> <NuxtLink :to="item.to" v-if="item.to">{{ item.text }}</NuxtLink> <span v-else>{{ item.text }}</span> </li> </ol> - <BtnTheme /> + <div class="d-flex justify-content-between align-items-center"> + <NavigationLanguage class="mr-3" /> + <BtnTheme /> + </div> </nav> </template> diff --git a/components/navigation/Language.vue b/components/navigation/Language.vue new file mode 100644 index 0000000..6f1cf36 --- /dev/null +++ b/components/navigation/Language.vue @@ -0,0 +1,24 @@ +<template> +<div> + <select class="form-control" @change="saveLocale($event)" v-model="lang"> + <option v-for="lang in $i18n.locales" :key="lang.code" :value="lang.code">{{ lang.name }}</option> + </select> +</div> +</template> + +<script> +export default { + data() { + return { + lang: this.$i18n.locale + } + }, + methods: { + saveLocale(e) { + this.lang = e.target.value + this.$i18n.setLocaleCookie(e.target.value) + this.$router.push(this.switchLocalePath(e.target.value)) + } + } +} +</script> \ No newline at end of file diff --git a/components/navigation/Loader.vue b/components/navigation/Loader.vue index c12b53a..1e99a26 100644 --- a/components/navigation/Loader.vue +++ b/components/navigation/Loader.vue @@ -2,7 +2,7 @@ <transition name="fade"> <div class="loader overflow-hidden text-center position-absolute" v-if="isLoading"> <img src="~@/assets/img/loader.gif"> - <div class="text-center font-weight-bold my-3">Chargement...</div> + <div class="text-center font-weight-bold my-3">{{ $t('chargement') }}...</div> </div> </transition> </template> diff --git a/components/navigation/menu/Group.vue b/components/navigation/menu/Group.vue index 01943d3..967668c 100644 --- a/components/navigation/menu/Group.vue +++ b/components/navigation/menu/Group.vue @@ -1,8 +1,10 @@ <template> <div class="mb-4"> - <h2 class="small text-muted text-uppercase ml-4 mb-3 pb-3 border-bottom">{{ menu.title }}</h2> + <h2 class="small text-muted text-uppercase ml-4 mb-3 pb-3 border-bottom">{{ $t(menu.title) }}</h2> <div class="nav navbar-nav list-group list-group-flush"> - <NuxtLink class="list-group-item list-group-item-action p-0 pl-3" :to="item.path" v-for="item in menu.items" :key="item.path"><div class="position-relative py-3">{{ item.title }}</div></NuxtLink> + <NuxtLink class="list-group-item list-group-item-action p-0 pl-3" :to="localePath(item.path)" v-for="item in menu.items" :key="item.path"> + <div class="position-relative py-3">{{ $t(item.title) }}</div> + </NuxtLink> </div> </div> </template> diff --git a/components/navigation/menu/Sidebar.vue b/components/navigation/menu/Sidebar.vue index 3a493c5..4f599e4 100644 --- a/components/navigation/menu/Sidebar.vue +++ b/components/navigation/menu/Sidebar.vue @@ -1,7 +1,7 @@ <template> <aside class="menu shadow position-fixed"> <div class="nav_header pb-3 mb-5"> - <nuxt-link to="/"><h1 class="h2 d-flex"><img src="@/assets/img/logo.png" alt="Accueil" class="logo"> Wotwizard</h1></nuxt-link> + <nuxt-link :to="localePath('/')"><h1 class="h2 d-flex"><img src="@/assets/img/logo.png" alt="Accueil" class="logo"> Wotwizard</h1></nuxt-link> <button type="button" class="close position-absolute d-xl-none" aria-label="Close" @click="toggleMenu"> <span aria-hidden="true">×</span> </button> diff --git a/graphql/index.js b/graphql/index.js index c8e3991..178821e 100644 --- a/graphql/index.js +++ b/graphql/index.js @@ -21,6 +21,8 @@ export default ctx => { return { link, - cache + cache, + // https://github.com/nuxt-community/apollo-module/issues/306#issuecomment-607225431 + defaultHttpLink: false } } \ No newline at end of file diff --git a/i18n/index.js b/i18n/index.js new file mode 100644 index 0000000..e72ec82 --- /dev/null +++ b/i18n/index.js @@ -0,0 +1,10 @@ +import en from './locales/en.json' +import fr from './locales/fr.json' +import es from './locales/es.json' +import {dateTimeFormats} from './locales/dateTimeFormats' + +export default { + fallbackLocale: 'en', + dateTimeFormats, + messages: { en, fr, es } +} \ No newline at end of file diff --git a/i18n/locales/dateTimeFormats.js b/i18n/locales/dateTimeFormats.js new file mode 100644 index 0000000..4f6948e --- /dev/null +++ b/i18n/locales/dateTimeFormats.js @@ -0,0 +1,47 @@ +export const dateTimeFormats = { + 'fr': { + short: { + day: 'numeric', + month: 'long', + year: 'numeric' + }, + long: { + day: 'numeric', + month: 'long', + year: 'numeric', + }, + hour: { + hour: 'numeric' + } + }, + 'en': { + short: { + day: 'numeric', + month: 'long', + year: 'numeric' + }, + long: { + month: 'long', + day: 'numeric', + year: 'numeric', + }, + hour: { + hour: 'numeric' + } + }, + 'es': { + short: { + day: 'numeric', + month: 'long', + year: 'numeric' + }, + long: { + day: 'numeric', + month: 'long', + year: 'numeric', + }, + hour: { + hour: 'numeric' + } + } +} \ No newline at end of file diff --git a/i18n/locales/en.json b/i18n/locales/en.json new file mode 100644 index 0000000..7bbde18 --- /dev/null +++ b/i18n/locales/en.json @@ -0,0 +1,57 @@ +{ + "accueil": "Home", + "aurevoir": "Goodbye to", + "bienvenue": "Welcome to", + "certifications": { + "envoyees" : "Certificates sent", + "recues" : "Certificates received " + }, + "chargement" : "Loading", + "dev": "In development", + "futuremembers": "Future members", + "inout": "Entries and exits of the web of trust for the last 2 days", + "inpreparation": "In preparation", + "membre": { + "datelimadhesion": "Membership deadline", + "datelimrevoc" : "Deadline before revocation ", + "datemanquecertifs": "Date before running out of certs", + "dispocertif": "Available to certify", + "distance": "Distance", + "nb_certifs": "Nb of available certs", + "qualite": "Quality", + "referent": "Referent" + }, + "membres": "Members", + "non": "No", + "oui": "Yes", + "previsions" : { + "certificationsinternes": "No internal certification | 1 internal certification | {n} internal certifications", + "dossiersattente": "No pending files | 1 pending file | {n} pending files", + "pardate": "Forecasts by dates", + "parmembre": "Forecasts by members", + "permutations": "No permutation | 1 permutation | {n} permutations", + "title": "Forecasts" + }, + "recherche": { + "desc" : "Enter the start of a nickname or public key", + "title": "Your search" + }, + "revoila": "Here they are again", + "statut" : { + "bientotmanquecertif": "Needs certifications soon", + "manquecertif": "Needs certifications", + "member": "Member", + "missing": "Membership lost", + "newcomer": "Future member", + "renew": "Membership to renew", + "revoked": "Revoked member" + }, + "time": { + "a": "at" + }, + "tri": { + "pardate": "Sort by date", + "parmembres": "Sort by members" + }, + "wot": "Web of trust" +} \ No newline at end of file diff --git a/i18n/locales/es.json b/i18n/locales/es.json new file mode 100644 index 0000000..3c36da8 --- /dev/null +++ b/i18n/locales/es.json @@ -0,0 +1,57 @@ +{ + "accueil": "Página principal", + "aurevoir": "Adios a", + "bienvenue": "Bienvenido a", + "certifications": { + "envoyees" : "Certificados enviados", + "recues" : "Certificaciones recibidas " + }, + "chargement" : "Cargando", + "dev": "En desarrollo", + "futuremembers": "Futuros miembros", + "inout": "Entradas y salidas de la web de confianza de los últimos 2 dÃas", + "inpreparation": "En preparación", + "membre": { + "datelimadhesion": "Fecha lÃmite de membresÃa", + "datelimrevoc" : "Plazo antes de la revocación ", + "datemanquecertifs": "Fecha antes de quedarse sin certificados", + "dispocertif": "Disponible para certificar", + "distance": "Distancia", + "nb_certifs": "Núm de certificados disponibles", + "qualite": "Calidad", + "referent": "Referente" + }, + "membres": "Miembros", + "non": "No", + "oui": "SÃ", + "previsions" : { + "certificationsinternes": "Sin certificación interna | 1 certificación interna | {n} certificaciones internas", + "dossiersattente": "No hay expedientes pendientes | 1 expediente pendiente | {n} expedientes pendientes", + "pardate": "Previsiones por fecha", + "parmembre": "Previsiones por miembros", + "permutations": "Sin permutación | 1 permutación | {n} permutaciones", + "title": "Pronósticos" + }, + "recherche": { + "desc" : "Ingrese el inicio de un apodo o clave pública", + "title": "Tu búsqueda" + }, + "revoila": "Aquà están de nuevo", + "statut" : { + "bientotmanquecertif": "Pronto necesitará certificaciones", + "manquecertif": "A falta de certificaciones", + "member": "Miembro", + "missing": "MembresÃa perdida", + "newcomer": "Futuro miembro", + "renew": "MembresÃa para renovar", + "revoked": "Miembro revocado" + }, + "time": { + "a": "a" + }, + "tri": { + "pardate": "Ordenar por fecha", + "parmembres": "lasificar por miembros" + }, + "wot": "Web de confianza" +} \ No newline at end of file diff --git a/i18n/locales/fr.json b/i18n/locales/fr.json new file mode 100644 index 0000000..3dbf2b3 --- /dev/null +++ b/i18n/locales/fr.json @@ -0,0 +1,57 @@ +{ + "accueil": "Accueil", + "aurevoir": "Au revoir à ", + "bienvenue": "Bienvenue à ", + "certifications": { + "envoyees" : "Certifications envoyées", + "recues" : "Certifications reçues " + }, + "chargement" : "Chargement", + "dev": "En Développement", + "futuremembers": "Futurs membres", + "inout": "Entrées et sorties de la toile de confiance des 2 derniers jours", + "inpreparation": "En préparation", + "membre": { + "datelimadhesion": "Date limite d'adhésion", + "datelimrevoc" : "Date limite avant révocation ", + "datemanquecertifs": "Date avant de manquer de certifs", + "dispocertif": "Disponible pour certifier", + "distance": "Distance", + "nb_certifs": "Nbre de certifs disponibles", + "qualite": "Qualité", + "referent": "Référent" + }, + "membres": "Membres", + "non": "Non", + "oui": "Oui", + "previsions" : { + "certificationsinternes": "Aucune certification interne | 1 certification interne | {n} certifications internes", + "dossiersattente": "Aucun dossier en attente | 1 dossier en attente | {n} dossiers en attente", + "pardate": "Prévisions par date", + "parmembre": "Prévisions par membres", + "permutations": "Aucune permutation | 1 permutation | {n} permutations", + "title": "Prévisions" + }, + "recherche": { + "desc" : "Saisissez le début d'un pseudo ou d'une clé publique", + "title": "Votre recherche" + }, + "revoila": "Les revoilà ", + "statut" : { + "bientotmanquecertif": "Bientôt en manque de certifications", + "manquecertif": "En manque de certifications", + "member": "Membre", + "missing": "Adhésion perdue", + "newcomer": "Futur membre", + "renew": "Adhésion à renouveler", + "revoked": "Membre révoqué" + }, + "time": { + "a": "à " + }, + "tri": { + "pardate": "Tri par date", + "parmembres": "Tri par membres" + }, + "wot": "Toile de confiance" +} \ No newline at end of file diff --git a/layouts/default.vue b/layouts/default.vue index 382a848..80c65ee 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -10,22 +10,26 @@ export default { data() { return { breadcrumb: [], - menus : [{ - title: 'Prévisions', - items : [ - {path: '/previsions',title: 'En préparation'}, - {path: '/previsions/newcomers',title: 'Futurs membres'} - ]}, - { - title: 'Toile de confiance', - items : [ - {path: '/membres',title: 'Membres'} - ]}, - { - title: 'En Développement', + // Les title correspondent aux chaînes de traduction dans /i18n/locales + menus : [ + { + title: 'previsions.title', items : [ - {path: '/chartjs',title: 'ChartJS'}, - ]}, + {path: '/previsions/futurs_membres',title: 'futuremembers'} + ] + }, + { + title: 'wot', + items : [ + {path: '/membres',title: 'membres'} + ] + }, + { + title: 'dev', + items : [ + {path: '/previsions',title: 'inpreparation'} + ] + }, ] } }, @@ -60,8 +64,12 @@ export default { transition: margin .5s ease-in-out; } main { - padding-top: 5rem; + padding-top: 8rem; position: relative; + + @media (min-width:768px) { + padding-top: 5rem; + } } .fade-enter-active, .fade-leave-active { transition: opacity .5s; diff --git a/nuxt.config.js b/nuxt.config.js index d4c40bf..6ce6da7 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -1,3 +1,5 @@ +import i18n from './i18n' + export default { // Disable server-side rendering: https://go.nuxtjs.dev/ssr-mode ssr: false, @@ -41,9 +43,33 @@ export default { // Modules: https://go.nuxtjs.dev/config-modules modules: [ // https://github.com/nuxt-community/apollo-module - '@nuxtjs/apollo' + '@nuxtjs/apollo', + // https://i18n.nuxtjs.org + '@nuxtjs/i18n' ], + i18n : { + defaultLocale: 'fr', + locales: [ + { + code: 'en', + name: 'English' + }, + { + code: 'fr', + name: 'Français' + }, + { + code: 'es', + name: 'Español' + } + ], + detectBrowserLanguage: { + alwaysRedirect: true + }, + vueI18n: i18n + }, + // PWA module configuration: https://go.nuxtjs.dev/pwa pwa: { manifest: { diff --git a/package-lock.json b/package-lock.json index 34636c1..07c0c6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "dependencies": { "@nuxtjs/apollo": "^4.0.1-rc.5", + "@nuxtjs/i18n": "^7.2.0", "@nuxtjs/pwa": "^3.3.5", "bootstrap": "^4.6.1", "chart.js": "^3.6.2", @@ -3147,6 +3148,38 @@ "@hapi/hoek": "^8.3.0" } }, + "node_modules/@intlify/shared": { + "version": "9.1.9", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.1.9.tgz", + "integrity": "sha512-xKGM1d0EAxdDFCWedcYXOm6V5Pfw/TMudd6/qCdEb4tv0hk9EKeg7lwQF1azE0dP2phvx0yXxrt7UQK+IZjNdw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@intlify/vue-i18n-extensions": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@intlify/vue-i18n-extensions/-/vue-i18n-extensions-1.0.2.tgz", + "integrity": "sha512-rnfA0ScyBXyp9xsSD4EAMGeOh1yv/AE7fhqdAdSOr5X8N39azz257umfRtzNT9sHXAKSSzpCVhIbMAkp5c/gjQ==", + "dependencies": { + "@babel/parser": "^7.9.6" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/@intlify/vue-i18n-loader": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@intlify/vue-i18n-loader/-/vue-i18n-loader-1.1.0.tgz", + "integrity": "sha512-9LXiztMtYKTE8t/hRwwGUp+ofrwU0sxLQLzFEOZ38zvn0DonUIQmZUj1cfz5p1Lu8BllxKbCrn6HnsRJ+LYA6g==", + "dependencies": { + "@intlify/shared": "^9.0.0", + "js-yaml": "^3.13.1", + "json5": "^2.1.1" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/@josephg/resolvable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@josephg/resolvable/-/resolvable-1.0.1.tgz", @@ -3836,6 +3869,33 @@ "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-2.5.2.tgz", "integrity": "sha512-aHdl/y2N7PW2Sx7K+r3AxpJO+aDMcYzMQd60Qxefq3+EwhewSbTBqNumOsCE1JsCUNoyfGj5465N0sSf6hc/5w==" }, + "node_modules/@nuxtjs/i18n": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@nuxtjs/i18n/-/i18n-7.2.0.tgz", + "integrity": "sha512-fO/QRMxZ0t6LpYJ7ti6mHc0lsog4SMr7Xll3d45zdVSI7+5eBE1YcoG8yXv1sndGQZoq8k0iD1dXuAJA6UL5ww==", + "dependencies": { + "@babel/parser": "^7.16.2", + "@babel/traverse": "^7.16.0", + "@intlify/vue-i18n-extensions": "^1.0.2", + "@intlify/vue-i18n-loader": "^1.1.0", + "cookie": "^0.4.1", + "devalue": "^2.0.1", + "is-https": "^4.0.0", + "js-cookie": "^3.0.1", + "klona": "^2.0.5", + "lodash.merge": "^4.6.2", + "ufo": "^0.7.9", + "vue-i18n": "^8.26.7" + } + }, + "node_modules/@nuxtjs/i18n/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/@nuxtjs/pwa": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/@nuxtjs/pwa/-/pwa-3.3.5.tgz", @@ -12667,6 +12727,11 @@ "node": ">=0.10.0" } }, + "node_modules/is-https": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-https/-/is-https-4.0.0.tgz", + "integrity": "sha512-FeMLiqf8E5g6SdiVJsPcNZX8k4h2fBs1wp5Bb6uaNxn58ufK1axBqQZdmAQsqh0t9BuwFObybrdVJh6MKyPlyg==" + }, "node_modules/is-installed-globally": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", @@ -12988,6 +13053,14 @@ "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==", "peer": true }, + "node_modules/js-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", + "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==", + "engines": { + "node": ">=12" + } + }, "node_modules/js-message": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz", @@ -13135,7 +13208,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", - "dev": true, "engines": { "node": ">= 8" } @@ -20433,6 +20505,11 @@ "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==" }, + "node_modules/vue-i18n": { + "version": "8.26.8", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.26.8.tgz", + "integrity": "sha512-BN2OXolO15AKS95yNF8oOtARibaO6RxyKkAYNV4XpOmL7S4eVZYMIDtyvDv+XGZaiUmBJSH9mdNqzexvGMnK2A==" + }, "node_modules/vue-loader": { "version": "15.9.8", "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.8.tgz", @@ -23841,6 +23918,29 @@ "@hapi/hoek": "^8.3.0" } }, + "@intlify/shared": { + "version": "9.1.9", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.1.9.tgz", + "integrity": "sha512-xKGM1d0EAxdDFCWedcYXOm6V5Pfw/TMudd6/qCdEb4tv0hk9EKeg7lwQF1azE0dP2phvx0yXxrt7UQK+IZjNdw==" + }, + "@intlify/vue-i18n-extensions": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@intlify/vue-i18n-extensions/-/vue-i18n-extensions-1.0.2.tgz", + "integrity": "sha512-rnfA0ScyBXyp9xsSD4EAMGeOh1yv/AE7fhqdAdSOr5X8N39azz257umfRtzNT9sHXAKSSzpCVhIbMAkp5c/gjQ==", + "requires": { + "@babel/parser": "^7.9.6" + } + }, + "@intlify/vue-i18n-loader": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@intlify/vue-i18n-loader/-/vue-i18n-loader-1.1.0.tgz", + "integrity": "sha512-9LXiztMtYKTE8t/hRwwGUp+ofrwU0sxLQLzFEOZ38zvn0DonUIQmZUj1cfz5p1Lu8BllxKbCrn6HnsRJ+LYA6g==", + "requires": { + "@intlify/shared": "^9.0.0", + "js-yaml": "^3.13.1", + "json5": "^2.1.1" + } + }, "@josephg/resolvable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@josephg/resolvable/-/resolvable-1.0.1.tgz", @@ -24449,6 +24549,32 @@ } } }, + "@nuxtjs/i18n": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@nuxtjs/i18n/-/i18n-7.2.0.tgz", + "integrity": "sha512-fO/QRMxZ0t6LpYJ7ti6mHc0lsog4SMr7Xll3d45zdVSI7+5eBE1YcoG8yXv1sndGQZoq8k0iD1dXuAJA6UL5ww==", + "requires": { + "@babel/parser": "^7.16.2", + "@babel/traverse": "^7.16.0", + "@intlify/vue-i18n-extensions": "^1.0.2", + "@intlify/vue-i18n-loader": "^1.1.0", + "cookie": "^0.4.1", + "devalue": "^2.0.1", + "is-https": "^4.0.0", + "js-cookie": "^3.0.1", + "klona": "^2.0.5", + "lodash.merge": "^4.6.2", + "ufo": "^0.7.9", + "vue-i18n": "^8.26.7" + }, + "dependencies": { + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + } + } + }, "@nuxtjs/pwa": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/@nuxtjs/pwa/-/pwa-3.3.5.tgz", @@ -31431,6 +31557,11 @@ "is-extglob": "^2.1.1" } }, + "is-https": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-https/-/is-https-4.0.0.tgz", + "integrity": "sha512-FeMLiqf8E5g6SdiVJsPcNZX8k4h2fBs1wp5Bb6uaNxn58ufK1axBqQZdmAQsqh0t9BuwFObybrdVJh6MKyPlyg==" + }, "is-installed-globally": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", @@ -31656,6 +31787,11 @@ "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==", "peer": true }, + "js-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", + "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==" + }, "js-message": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz", @@ -31773,8 +31909,7 @@ "klona": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", - "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", - "dev": true + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==" }, "last-call-webpack-plugin": { "version": "3.0.0", @@ -37497,6 +37632,11 @@ "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==" }, + "vue-i18n": { + "version": "8.26.8", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.26.8.tgz", + "integrity": "sha512-BN2OXolO15AKS95yNF8oOtARibaO6RxyKkAYNV4XpOmL7S4eVZYMIDtyvDv+XGZaiUmBJSH9mdNqzexvGMnK2A==" + }, "vue-loader": { "version": "15.9.8", "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.8.tgz", diff --git a/package.json b/package.json index dfcddec..7c6fdf6 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ }, "dependencies": { "@nuxtjs/apollo": "^4.0.1-rc.5", + "@nuxtjs/i18n": "^7.2.0", "@nuxtjs/pwa": "^3.3.5", "bootstrap": "^4.6.1", "chart.js": "^3.6.2", @@ -25,8 +26,8 @@ "vue": "^2.6.14" }, "devDependencies": { + "npm-run-all": "^4.1.5", "sass": "^1.45.0", - "sass-loader": "^10.2.0", - "npm-run-all": "^4.1.5" + "sass-loader": "^10.2.0" } } diff --git a/pages/chartjs.vue b/pages/chartjs.vue index 70a37de..868f022 100644 --- a/pages/chartjs.vue +++ b/pages/chartjs.vue @@ -32,7 +32,7 @@ export default { data: {}, breadcrumb: [ { - text: 'Accueil', + text: this.$t('accueil'), to: "/" }, { @@ -77,6 +77,13 @@ export default { return Math.floor(Math.random() * (max - 5 + 1)) + 5 } }, + nuxtI18n: { + paths: { + fr: '/graphiques', + en: '/graphics', + es: '/graficos' + } + }, mounted () { // Mise à jour du fil d'ariane au chargement $nuxt.$emit('changeRoute',this.breadcrumb) diff --git a/pages/index.vue b/pages/index.vue index 39b3873..ec0a5b4 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -1,21 +1,23 @@ <template> <main class="container"> - <h2 class="text-center mb-5 font-weight-light">Entrées et sorties de la toile de confiance des 2 derniers jours</h2> + <h2 class="text-center mb-5 font-weight-light">{{ $t('inout') }}</h2> <NavigationLoader :isLoading="$apollo.queries.newMembers.loading" /> <transition name="fade"> <div class="alert alert-danger" v-if="error">{{ error }}</div> + </transition> + <transition name="fade"> <div class="result" v-if="newMembers"> <div class="row text-center"> <div class="col-lg-4"> - <h2 class="h4 text-success">Bienvenue à </h2> + <h2 class="h4 text-success">{{ $t('bienvenue') }}</h2> <MemberList :members="newMembers['entrees']" :displayPubkey="false" :displayHead="false" /> </div> <div class="col-lg-4"> - <h2 class="h4 text-danger">Au revoir à </h2> + <h2 class="h4 text-danger">{{ $t('aurevoir') }}</h2> <MemberList :members="newMembers['sorties']" :displayPubkey="false" :displayHead="false" /> </div> <div class="col-lg-4"> - <h2 class="h4 text-info">Les revoilà </h2> + <h2 class="h4 text-info">{{ $t('revoila') }}</h2> <MemberList :members="newMembers['renew']" :displayPubkey="false" :displayHead="false" /> </div> </div> @@ -34,7 +36,7 @@ export default { return { breadcrumb: [ { - text: 'Accueil', + text: this.$t('accueil'), to: '/' } ], @@ -61,8 +63,6 @@ export default { let member = data.membersCount[i].idList[j] member.member.inOut = member.inOut - console.log(member.member.uid + ' : ' + member.member.history.length) - if (member.member.history.length==1) { if (result['entrees'].filter(function(e) { return e.uid === member.member.uid }).length == 0) { result['entrees'].push(member.member) diff --git a/pages/membres/_hash.vue b/pages/membres/_hash.vue index f2a79ba..4ba30d5 100644 --- a/pages/membres/_hash.vue +++ b/pages/membres/_hash.vue @@ -3,6 +3,8 @@ <NavigationLoader :isLoading="$apollo.queries.idFromHash.loading" /> <transition name="fade"> <div class="alert alert-danger" v-if="error">{{ error }}</div> + </transition> + <transition name="fade"> <div v-if="idFromHash"> <div class="row"> <div class="col-md-10 col-lg-8 col-xl-6 mx-auto mt-3"> @@ -11,13 +13,13 @@ </div> <div class="row mt-3" v-if="idFromHash.status != 'REVOKED'"> <div class="col-12 col-md-6 mb-3"> - <h3>Certifications reçues + <h3>{{ $t('certifications.recues') }} <BadgeCertifStatus :limitDate="idFromHash.received_certifications.limit" :memberStatus="idFromHash.status" /> </h3> <CertifList :certifs="idFromHash.received_certifications.certifications" type="recieved" /> </div> <div class="col-12 col-md-6"> - <h3>Certifications envoyées</h3> + <h3>{{ $t('certifications.envoyees') }}</h3> <CertifList :certifs="idFromHash.sent_certifications" type="sent" /> </div> </div> @@ -35,11 +37,11 @@ export default { return { breadcrumb: [ { - text: 'Accueil', + text: this.$t('accueil'), to: '/' }, { - text: 'Membres', + text: this.$t('membres'), to: '/membres' }, { @@ -57,7 +59,14 @@ export default { query: SEARCH_MEMBER, variables() {return { hash: this.$route.params.hash }}, error (err) {this.error = err.message} - }, + } + }, + nuxtI18n: { + paths: { + fr: '/membres/:hash', + en: '/members/:hash', + es: '/miembros/:hash' + } }, computed: { classWarning: function() { diff --git a/pages/membres/index.vue b/pages/membres/index.vue index a5ac74c..d086e38 100644 --- a/pages/membres/index.vue +++ b/pages/membres/index.vue @@ -1,16 +1,18 @@ <template> <main class="container"> - <h2 class="text-center mb-5 font-weight-light">Membres</h2> + <h2 class="text-center mb-5 font-weight-light">{{ $t('membres') }}</h2> <div class="row mb-4"> <div class="col-6 m-auto text-center"> - <label for="rech" class="form-label">Votre recherche</label> + <label for="rech" class="form-label">{{ $t('recherche.title') }}</label> <input type="text" class="form-control" id="rech" aria-describedby="rechHelp" v-model="param" autocomplete="off" @keyup="save"> - <small id="rechHelp" class="form-text text-muted">Saisissez le début d'un pseudo ou d'une clé publique</small> + <small id="rechHelp" class="form-text text-muted">{{ $t('recherche.desc') }}</small> </div> </div> <NavigationLoader :isLoading="$apollo.queries.idSearch.loading" /> <transition name="fade"> <div class="alert alert-danger" v-if="error">{{ error }}</div> + </transition> + <transition name="fade"> <div class="row" v-if="idSearch && param.length>2 && !$apollo.queries.idSearch.loading"> <div class="col-8 m-auto"> <MemberList :members="idSearch.ids"/> @@ -28,11 +30,11 @@ export default { return { breadcrumb: [ { - text: 'Accueil', + text: this.$t('accueil'), to: '/' }, { - text: 'Membres', + text: this.$t('membres'), active: true } ], @@ -54,6 +56,13 @@ export default { error (err) {this.error = err.message} } }, + nuxtI18n: { + paths: { + fr: '/membres', + en: '/members', + es: '/miembros' + } + }, mounted () { // Mise à jour du fil d'ariane au chargement $nuxt.$emit('changeRoute',this.breadcrumb) diff --git a/pages/previsions/_hash.vue b/pages/previsions/_hash.vue index 4cfc380..66a8d7c 100644 --- a/pages/previsions/_hash.vue +++ b/pages/previsions/_hash.vue @@ -3,6 +3,8 @@ <NavigationLoader :isLoading="$apollo.queries.idFromHash.loading" /> <transition name="fade"> <div class="alert alert-danger" v-if="error">{{ error }}</div> + </transition> + <transition name="fade"> <div v-if="idFromHash"> <div class="row"> <div class="col-md-10 col-lg-8 col-xl-6 mx-auto mt-3"> @@ -24,11 +26,11 @@ export default { return { breadcrumb: [ { - text: 'Accueil', + text: this.$t('accueil'), to: '/' }, { - text: 'Prévisions', + text: this.$t('previsions.title'), to: '/previsions' }, { @@ -48,6 +50,13 @@ export default { error (err) {this.error = err.message} }, }, + nuxtI18n: { + paths: { + fr: '/previsions/:hash', + en: '/forecasts/:hash', + es: '/pronosticos/:hash' + } + }, computed: { classWarning: function() { return { diff --git a/pages/previsions/newcomers.vue b/pages/previsions/futurs_membres.vue similarity index 85% rename from pages/previsions/newcomers.vue rename to pages/previsions/futurs_membres.vue index 57df5cc..9a90ad8 100644 --- a/pages/previsions/newcomers.vue +++ b/pages/previsions/futurs_membres.vue @@ -3,12 +3,14 @@ <NavigationLoader :isLoading="$apollo.queries.wwResult.loading" /> <transition name="fade"> <div class="alert alert-danger" v-if="error">{{ error }}</div> + </transition> + <transition name="fade"> <div v-if="wwResult"> - <h2 class="text-center mb-5 font-weight-light">Prévisions <small><span class="badge badge-secondary">{{ wwResult.dossiers_nb }} dossiers en attente</span></small></h2> + <h2 class="text-center mb-5 font-weight-light">{{ $t('previsions.title') }} <small><span class="badge badge-secondary">{{ $tc('previsions.dossiersattente', wwResult.dossiers_nb) }}</span></small></h2> <div class="alert alert-info" role="alert"> <ul class="list-unstyled m-0"> - <li>{{ wwResult.certifs_nb }} certifications internes</li> - <li>{{ wwResult.permutations_nb }} permutations</li> + <li>{{ $tc('previsions.certificationsinternes', wwResult.certifs_nb) }}</li> + <li>{{ $tc('previsions.permutations', wwResult.permutations_nb) }}</li> </ul> </div> <div class="row"> @@ -16,19 +18,19 @@ <div class="form-check form-check-inline"> <input class="form-check-input" type="radio" id="forecastsByNames" value="forecastsByNames" checked v-model="display" @change="save"> <label class="form-check-label" for="forecastsByNames"> - Tri par membres + {{ $t('tri.parmembres') }} </label> </div> <div class="form-check form-check-inline"> <input class="form-check-input" type="radio" id="forecastsByDates" value="forecastsByDates" v-model="display" @change="save"> <label class="form-check-label" for="forecastsByDates"> - Tri par dates + {{ $t('tri.pardate') }} </label> </div> </div> <div class="col-lg-8 m-auto"> <div v-if="display=='forecastsByNames'"> - <h3>Prévisions par membres</h3> + <h3>{{ $t('previsions.parmembre') }}</h3> <div class="table-responsive"> <table class="table table-striped table-hover"> <tbody> @@ -39,7 +41,7 @@ </th> <td class="p-0"> <div class="d-flex justify-content-between p-3" v-for="date in forecast.forecasts" :key="date.date"> - <div>{{ date.date | formatDateHeure }}</div> + <div>{{ $d(new Date(date.date*1000), 'long') }} {{ $t('time.a') }} {{ $d(new Date(date.date*1000), 'hour') }}</div> <div>{{ date.proba * 100 }} %</div> </div> </td> @@ -49,7 +51,7 @@ </div> </div> <div v-if="display=='forecastsByDates'"> - <h3>Prévisions par dates</h3> + <h3>{{ $t('previsions.pardate') }}</h3> <div class="table-responsive"> <table class="table table-striped"> <tbody> @@ -83,11 +85,11 @@ export default { return { breadcrumb: [ { - text: 'Accueil', + text: this.$t('accueil'), to: '/' }, { - text: 'Prévisions', + text: this.$t('previsions.title'), to: '/previsions' }, { @@ -165,6 +167,13 @@ export default { error (err) {this.error = err.message} } }, + nuxtI18n: { + paths: { + fr: '/previsions/futurs_membres', + en: '/forecasts/future_members', + es: '/pronosticos/futuros_miembros' + } + }, mounted () { // Mise à jour du fil d'ariane au chargement $nuxt.$emit('changeRoute',this.breadcrumb) diff --git a/pages/previsions/index.vue b/pages/previsions/index.vue index 1481388..ba77d5d 100644 --- a/pages/previsions/index.vue +++ b/pages/previsions/index.vue @@ -22,11 +22,11 @@ export default { return { breadcrumb: [ { - text: 'Accueil', + text: this.$t('accueil'), to: '/' }, { - text: 'Prévisions', + text: this.$t('previsions.title'), active: true } ], @@ -48,6 +48,13 @@ export default { error (err) {this.error = err.message} } }, + nuxtI18n: { + paths: { + fr: '/previsions', + en: '/forecasts', + es: '/pronosticos' + } + }, mounted () { // Mise à jour du fil d'ariane au chargement $nuxt.$emit('changeRoute',this.breadcrumb) -- GitLab