Merged PR 109: Integrate i18n

Integrate i18n
This commit is contained in:
Dominic Villemure
2024-08-21 02:29:13 +00:00
8 changed files with 213 additions and 1 deletions

167
package-lock.json generated
View File

@@ -13,10 +13,12 @@
"@vueuse/core": "^10.11.0", "@vueuse/core": "^10.11.0",
"@xtiannyeto/vue-auth-social": "^0.1.9", "@xtiannyeto/vue-auth-social": "^0.1.9",
"axios": "^1.6.7", "axios": "^1.6.7",
"i18n": "^0.15.1",
"jwt-decode": "^4.0.0", "jwt-decode": "^4.0.0",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"uuid": "^10.0.0", "uuid": "^10.0.0",
"vue": "^3.4.15", "vue": "^3.4.15",
"vue-i18n": "^9.14.0",
"vue-router": "^4.2.5", "vue-router": "^4.2.5",
"vue3-google-login": "^2.0.26", "vue3-google-login": "^2.0.26",
"vuetify": "^3.5.6" "vuetify": "^3.5.6"
@@ -555,6 +557,47 @@
"deprecated": "Use @eslint/object-schema instead", "deprecated": "Use @eslint/object-schema instead",
"dev": true "dev": true
}, },
"node_modules/@intlify/core-base": {
"version": "9.14.0",
"resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.14.0.tgz",
"integrity": "sha512-zJn0imh9HIsZZUtt9v8T16PeVstPv6bP2YzlrYJwoF8F30gs4brZBwW2KK6EI5WYKFi3NeqX6+UU4gniz5TkGg==",
"dependencies": {
"@intlify/message-compiler": "9.14.0",
"@intlify/shared": "9.14.0"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@intlify/message-compiler": {
"version": "9.14.0",
"resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.14.0.tgz",
"integrity": "sha512-sXNsoMI0YsipSXW8SR75drmVK56tnJHoYbPXUv2Cf9lz6FzvwsosFm6JtC1oQZI/kU+n7qx0qRrEWkeYFTgETA==",
"dependencies": {
"@intlify/shared": "9.14.0",
"source-map-js": "^1.0.2"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@intlify/shared": {
"version": "9.14.0",
"resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.14.0.tgz",
"integrity": "sha512-r+N8KRQL7LgN1TMTs1A2svfuAU0J94Wu9wWdJVJqYsoMMLIeJxrPjazihfHpmJqfgZq0ah3Y9Q4pgWV2O90Fyg==",
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@isaacs/cliui": { "node_modules/@isaacs/cliui": {
"version": "8.0.2", "version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -644,6 +687,45 @@
"resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz", "resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz",
"integrity": "sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw==" "integrity": "sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw=="
}, },
"node_modules/@messageformat/core": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/@messageformat/core/-/core-3.3.0.tgz",
"integrity": "sha512-YcXd3remTDdeMxAlbvW6oV9d/01/DZ8DHUFwSttO3LMzIZj3iO0NRw+u1xlsNNORFI+u0EQzD52ZX3+Udi0T3g==",
"dependencies": {
"@messageformat/date-skeleton": "^1.0.0",
"@messageformat/number-skeleton": "^1.0.0",
"@messageformat/parser": "^5.1.0",
"@messageformat/runtime": "^3.0.1",
"make-plural": "^7.0.0",
"safe-identifier": "^0.4.1"
}
},
"node_modules/@messageformat/date-skeleton": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@messageformat/date-skeleton/-/date-skeleton-1.0.1.tgz",
"integrity": "sha512-jPXy8fg+WMPIgmGjxSlnGJn68h/2InfT0TNSkVx0IGXgp4ynnvYkbZ51dGWmGySEK+pBiYUttbQdu5XEqX5CRg=="
},
"node_modules/@messageformat/number-skeleton": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@messageformat/number-skeleton/-/number-skeleton-1.2.0.tgz",
"integrity": "sha512-xsgwcL7J7WhlHJ3RNbaVgssaIwcEyFkBqxHdcdaiJzwTZAWEOD8BuUFxnxV9k5S0qHN3v/KzUpq0IUpjH1seRg=="
},
"node_modules/@messageformat/parser": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@messageformat/parser/-/parser-5.1.0.tgz",
"integrity": "sha512-jKlkls3Gewgw6qMjKZ9SFfHUpdzEVdovKFtW1qRhJ3WI4FW5R/NnGDqr8SDGz+krWDO3ki94boMmQvGke1HwUQ==",
"dependencies": {
"moo": "^0.5.1"
}
},
"node_modules/@messageformat/runtime": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@messageformat/runtime/-/runtime-3.0.1.tgz",
"integrity": "sha512-6RU5ol2lDtO8bD9Yxe6CZkl0DArdv0qkuoZC+ZwowU+cdRlVE1157wjCmlA5Rsf1Xc/brACnsZa5PZpEDfTFFg==",
"dependencies": {
"make-plural": "^7.0.0"
}
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -1378,6 +1460,11 @@
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"dev": true "dev": true
}, },
"node_modules/boolean": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
"integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw=="
},
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -2028,6 +2115,17 @@
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true "dev": true
}, },
"node_modules/fast-printf": {
"version": "1.6.9",
"resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz",
"integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==",
"dependencies": {
"boolean": "^3.1.4"
},
"engines": {
"node": ">=10.0"
}
},
"node_modules/fast-text-encoding": { "node_modules/fast-text-encoding": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz",
@@ -2449,6 +2547,25 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/i18n": {
"version": "0.15.1",
"resolved": "https://registry.npmjs.org/i18n/-/i18n-0.15.1.tgz",
"integrity": "sha512-yue187t8MqUPMHdKjiZGrX+L+xcUsDClGO0Cz4loaKUOK9WrGw5pgan4bv130utOwX7fHE9w2iUeHFalVQWkXA==",
"dependencies": {
"@messageformat/core": "^3.0.0",
"debug": "^4.3.3",
"fast-printf": "^1.6.9",
"make-plural": "^7.0.0",
"math-interval-parser": "^2.0.1",
"mustache": "^4.2.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/mashpie"
}
},
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.3.2", "version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -2757,6 +2874,19 @@
"@jridgewell/sourcemap-codec": "^1.5.0" "@jridgewell/sourcemap-codec": "^1.5.0"
} }
}, },
"node_modules/make-plural": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/make-plural/-/make-plural-7.4.0.tgz",
"integrity": "sha512-4/gC9KVNTV6pvYg2gFeQYTW3mWaoJt7WZE5vrp1KnQDgW92JtYZnzmZT81oj/dUTqAIu0ufI2x3dkgu3bB1tYg=="
},
"node_modules/math-interval-parser": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/math-interval-parser/-/math-interval-parser-2.0.1.tgz",
"integrity": "sha512-VmlAmb0UJwlvMyx8iPhXUDnVW1F9IrGEd9CIOmv+XL8AErCUUuozoDMrgImvnYt2A+53qVX/tPW6YJurMKYsvA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/merge2": { "node_modules/merge2": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -2824,11 +2954,24 @@
"node": ">=16 || 14 >=14.17" "node": ">=16 || 14 >=14.17"
} }
}, },
"node_modules/moo": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz",
"integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q=="
},
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"node_modules/mustache": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz",
"integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==",
"bin": {
"mustache": "bin/mustache"
}
},
"node_modules/mz": { "node_modules/mz": {
"version": "2.7.0", "version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
@@ -3520,6 +3663,11 @@
} }
] ]
}, },
"node_modules/safe-identifier": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz",
"integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w=="
},
"node_modules/semver": { "node_modules/semver": {
"version": "7.6.3", "version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
@@ -4089,6 +4237,25 @@
"eslint": ">=6.0.0" "eslint": ">=6.0.0"
} }
}, },
"node_modules/vue-i18n": {
"version": "9.14.0",
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.14.0.tgz",
"integrity": "sha512-LxmpRuCt2rI8gqU+kxeflRZMQn4D5+4M3oP3PWZdowW/ePJraHqhF7p4CuaME52mUxdw3Mmy2yAUKgfZYgCRjA==",
"dependencies": {
"@intlify/core-base": "9.14.0",
"@intlify/shared": "9.14.0",
"@vue/devtools-api": "^6.5.0"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
},
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/vue-router": { "node_modules/vue-router": {
"version": "4.4.3", "version": "4.4.3",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.3.tgz", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.3.tgz",

View File

@@ -14,10 +14,12 @@
"@vueuse/core": "^10.11.0", "@vueuse/core": "^10.11.0",
"@xtiannyeto/vue-auth-social": "^0.1.9", "@xtiannyeto/vue-auth-social": "^0.1.9",
"axios": "^1.6.7", "axios": "^1.6.7",
"i18n": "^0.15.1",
"jwt-decode": "^4.0.0", "jwt-decode": "^4.0.0",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"uuid": "^10.0.0", "uuid": "^10.0.0",
"vue": "^3.4.15", "vue": "^3.4.15",
"vue-i18n": "^9.14.0",
"vue-router": "^4.2.5", "vue-router": "^4.2.5",
"vue3-google-login": "^2.0.26", "vue3-google-login": "^2.0.26",
"vuetify": "^3.5.6" "vuetify": "^3.5.6"

15
src/i18n.js Normal file
View File

@@ -0,0 +1,15 @@
import { createI18n } from 'vue-i18n';
import en from './locales/en.json';
import fr from './locales/fr.json';
const messages = {
en,
fr,
};
const i18n = createI18n({
legacy: false,
locale: 'fr',
fallbackLocale: 'en',
messages,
});
export default i18n;

5
src/locales/en.json Normal file
View File

@@ -0,0 +1,5 @@
{
"footer": {
"allRightsReserved": "All rights reserved"
}
}

5
src/locales/fr.json Normal file
View File

@@ -0,0 +1,5 @@
{
"footer": {
"allRightsReserved": "Tout droits réservés"
}
}

View File

@@ -12,6 +12,7 @@ import vueGoogleOauth from 'vue3-google-login'
import {useSubscriptionStore} from "@/stores/subscriptionStore.js"; import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
import {useAuthStore} from "@/stores/authStore.js"; import {useAuthStore} from "@/stores/authStore.js";
import {useUserStore} from "@/stores/userStore.js"; import {useUserStore} from "@/stores/userStore.js";
import i18n from './i18n.js';
const vuetify = createVuetify({ const vuetify = createVuetify({
components, components,
@@ -25,6 +26,10 @@ const app = createApp(App)
.use(vueGoogleOauth, { .use(vueGoogleOauth, {
clientId: import.meta.env.VITE_GOOGLE_CLIENT_ID, clientId: import.meta.env.VITE_GOOGLE_CLIENT_ID,
}) })
.use(i18n)
// Make $t globally available
app.config.globalProperties.$t = i18n.global.t;
// this force the creation of the stores // this force the creation of the stores
const subscriptionStore = useSubscriptionStore() const subscriptionStore = useSubscriptionStore()

View File

@@ -2,7 +2,7 @@
<footer> <footer>
<div class="p-4 text-center font-sans"> <div class="p-4 text-center font-sans">
Hutopy &copy;{{ new Date().getFullYear() }} - Tout droits réservés Hutopy &copy;{{ new Date().getFullYear() }} - {{ $t('footer.allRightsReserved') }}
</div> </div>
</footer> </footer>

View File

@@ -70,6 +70,9 @@
<v-icon class="mx-2">mdi-bell-outline</v-icon> <v-icon class="mx-2">mdi-bell-outline</v-icon>
<v-btn variant="text" @click="changeLanguage('fr')">Français</v-btn>
<v-btn variant="text" class="mx-2" @click="changeLanguage('en')">English</v-btn>
<div class="text-center"> <div class="text-center">
<v-menu open-on-hover> <v-menu open-on-hover>
<template v-slot:activator="{ props }"> <template v-slot:activator="{ props }">
@@ -138,7 +141,9 @@ import {useRouter} from 'vue-router';
import {useSideBarStore} from '@/stores/sideBarStore.js'; import {useSideBarStore} from '@/stores/sideBarStore.js';
import {useUserStore} from "@/stores/userStore.js"; import {useUserStore} from "@/stores/userStore.js";
import {useAuthStore} from "@/stores/authStore.js"; import {useAuthStore} from "@/stores/authStore.js";
import { useI18n } from 'vue-i18n';
const { locale } = useI18n();
const authStore = useAuthStore() const authStore = useAuthStore()
const userStore = useUserStore() const userStore = useUserStore()
const sideBarStore = useSideBarStore() const sideBarStore = useSideBarStore()
@@ -147,6 +152,14 @@ const router = useRouter();
const searchQuery = ref(""); const searchQuery = ref("");
const showSearch = ref(false); const showSearch = ref(false);
// List of available languages
const selectedLanguage = ref(locale.value);
function changeLanguage(lang) {
locale.value = lang;
selectedLanguage.value = lang;
}
const onSearch = () => { const onSearch = () => {
const query = searchQuery.value.trim(); const query = searchQuery.value.trim();
if (!query) { if (!query) {