From 005fb9055634c493460c203faddde067f5533c93 Mon Sep 17 00:00:00 2001 From: Thomas Citharel <tcit@tcit.fr> Date: Mon, 30 Nov 2020 17:57:08 +0100 Subject: [PATCH] Allow to pick language unlogged and format fallback messages Closes #479 Signed-off-by: Thomas Citharel <tcit@tcit.fr> --- js/src/components/Footer.vue | 41 +++++++++++++++++++++++++++++++++++- js/src/utils/auth.ts | 4 ++++ js/src/utils/i18n.ts | 11 +++++++--- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/js/src/components/Footer.vue b/js/src/components/Footer.vue index 657b4cae2..50d4eaf7f 100644 --- a/js/src/components/Footer.vue +++ b/js/src/components/Footer.vue @@ -2,6 +2,17 @@ <footer class="footer" ref="footer"> <img :src="`/img/pics/footer_${random}.jpg`" alt="" /> <ul> + <li> + <b-select + v-if="$i18n" + v-model="locale" + :placeholder="$t('Select a language')" + > + <option v-for="(language, lang) in langs" :value="lang" :key="lang"> + {{ language }} + </option> + </b-select> + </li> <li> <router-link :to="{ name: RouteName.ABOUT }">{{ $t("About") @@ -38,17 +49,40 @@ </footer> </template> <script lang="ts"> -import { Component, Vue } from "vue-property-decorator"; +import { Component, Vue, Watch } from "vue-property-decorator"; +import { saveLocaleData } from "@/utils/auth"; +import { loadLanguageAsync } from "@/utils/i18n"; import RouteName from "../router/name"; +import langs from "../i18n/langs.json"; @Component export default class Footer extends Vue { RouteName = RouteName; + locale: string | null = this.$i18n.locale; + + langs: Record<string, string> = langs; + // eslint-disable-next-line class-methods-use-this get random(): number { return Math.floor(Math.random() * 4) + 1; } + + @Watch("locale") + // eslint-disable-next-line class-methods-use-this + async updateLocale(locale: string): Promise<void> { + if (locale) { + await loadLanguageAsync(locale); + saveLocaleData(locale); + } + } + + @Watch("$i18n.locale", { deep: true }) + updateLocaleFromI18n(locale: string): void { + if (locale) { + this.locale = locale; + } + } } </script> <style lang="scss" scoped> @@ -92,5 +126,10 @@ footer.footer { text-decoration: underline; text-decoration-color: $secondary; } + + ::v-deep span.select select { + background: $background-color; + color: $white; + } } </style> diff --git a/js/src/utils/auth.ts b/js/src/utils/auth.ts index 4af15e4d5..52354432a 100644 --- a/js/src/utils/auth.ts +++ b/js/src/utils/auth.ts @@ -32,6 +32,10 @@ export function saveLocaleData(locale: string): void { localStorage.setItem(USER_LOCALE, locale); } +export function getLocaleData(): string | null { + return localStorage.getItem(USER_LOCALE); +} + export function saveActorData(obj: IPerson): void { localStorage.setItem(AUTH_USER_ACTOR_ID, `${obj.id}`); } diff --git a/js/src/utils/i18n.ts b/js/src/utils/i18n.ts index e9a1c9f01..06f722087 100644 --- a/js/src/utils/i18n.ts +++ b/js/src/utils/i18n.ts @@ -1,26 +1,30 @@ import Vue from "vue"; import VueI18n from "vue-i18n"; import { DateFnsPlugin } from "@/plugins/dateFns"; -import { USER_LOCALE } from "@/constants"; import en from "../i18n/en_US.json"; import langs from "../i18n/langs.json"; +import { getLocaleData } from "./auth"; const DEFAULT_LOCALE = "en_US"; let language = - localStorage.getItem(USER_LOCALE) || - (document.documentElement.getAttribute("lang") as string); + getLocaleData() || (document.documentElement.getAttribute("lang") as string); +console.log("lang1", language); + language = language || ((window.navigator as any).userLanguage || window.navigator.language).replace( /-/, "_" ); +console.log("language2", language); + export const locale = language && Object.prototype.hasOwnProperty.call(langs, language) ? language : language.split("-")[0]; +console.log("lang3", locale); Vue.use(VueI18n); export const i18n = new VueI18n({ @@ -29,6 +33,7 @@ export const i18n = new VueI18n({ // @ts-ignore messages: en, // set locale messages fallbackLocale: DEFAULT_LOCALE, + formatFallbackMessages: true, }); const loadedLanguages = [DEFAULT_LOCALE];