add 'settings' store with action to mutate locales & add lazy loading of translations

This commit is contained in:
Axolotle 2020-08-28 18:54:18 +02:00
parent d3f112ac06
commit 179511be17
7 changed files with 182 additions and 4 deletions

View file

@ -68,16 +68,19 @@ import { mapGetters } from 'vuex'
export default {
name: 'App',
data: () => {
data () {
return {
// isReady blocks the rendering of the rooter-view until we have a true info
// about the connected state of the user.
isReady: false
}
},
computed: {
...mapGetters(['connected', 'yunohost'])
},
methods: {
async logout () {
this.$store.dispatch('LOGOUT').then(() => {
@ -85,9 +88,14 @@ export default {
})
}
},
// This hook is only triggered at page reload so the value of state.connected
// always come from the localStorage
// This hook is only triggered at page first load
async created () {
// Save user locales in store
const { locale, fallbackLocale } = this.$i18n
this.$store.dispatch('INIT_LOCALES', { locale, fallbackLocale })
// From this hook the value of `connected` always come from the localStorage.
if (!this.connected) {
// user is not connected: allow the login view to be rendered.
this.isReady = true

64
app/src/i18n/helpers.js Normal file
View file

@ -0,0 +1,64 @@
import i18n from '@/i18n'
import supportedLocales from './supportedLocales'
const loadedLanguages = []
/**
* Returns the first two supported locales that can be found in the `localStorage` or
* in the user browser settings.
*
* @return {string[]}
*/
function getDefaultLocales () {
const locale = localStorage.getItem('locale')
const fallbackLocale = localStorage.getItem('fallbackLocale')
if (locale && fallbackLocale) return [locale, fallbackLocale]
const navigatorLocales = navigator.languages || [navigator.language]
const defaultLocales = []
const supported = Object.keys(supportedLocales)
for (const locale of navigatorLocales) {
if (supported.includes(locale) && !defaultLocales.includes(locale)) {
defaultLocales.push(locale)
} else {
const lang = locale.split('-')[0]
if (supported.includes(lang) && !defaultLocales.includes(lang)) {
defaultLocales.push(lang)
}
}
if (defaultLocales.length === 2) break
}
return defaultLocales
}
function updateDocumentLocale (locale) {
document.documentElement.lang = locale
// FIXME can't currently change document direction easily since bootstrap still doesn't handle rtl.
// document.dir = locale === 'ar' ? 'rtl' : 'ltr'
}
/**
* Loads a translation file and adds its content to the i18n plugin `messages`.
*
* @return {Promise<string>} Promise that resolve the given locale string
*/
function loadLocaleMessages (locale) {
if (loadedLanguages.includes(locale)) {
return Promise.resolve(locale)
}
return import(
/* webpackChunkName: "lang-[request]" */ `@/locales/${locale}.json`
).then(messages => {
i18n.setLocaleMessage(locale, messages.default)
loadedLanguages.push(locale)
return locale
})
}
export {
getDefaultLocales,
updateDocumentLocale,
loadLocaleMessages
}

25
app/src/i18n/index.js Normal file
View file

@ -0,0 +1,25 @@
/**
* i18n plugin module.
* @module i18n
*/
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import { getDefaultLocales, loadLocaleMessages } from './helpers'
// Plugin Initialization
Vue.use(VueI18n)
// Get defined locales from `localStorage` or `navigator`
const [locale, fallbackLocale] = getDefaultLocales()
export default new VueI18n({
locale,
fallbackLocale: fallbackLocale ? [fallbackLocale, 'en'] : ['en'],
messages: {}
})
// Load default locales translations files
loadLocaleMessages(locale)
loadLocaleMessages(fallbackLocale)
loadLocaleMessages('en')

View file

@ -0,0 +1,26 @@
export default {
ar: 'عربي',
bn_BD: 'বাংলা',
br: 'Brezhoneg',
ca: 'Català',
de: 'Deutsch',
el: 'Eλληνικά',
en: 'English',
eo: 'Esperanto',
es: 'Español',
eu: 'Euskara',
fr: 'Français',
hi: 'हिन्दी',
hu: 'Magyar',
it: 'Italiano',
nb_NO: 'Norsk bokmål',
ne: 'नेपाली',
nl: 'Nederlands',
oc: 'Occitan',
pl: 'Polski',
pt: 'Português',
ru: 'Русский',
sv: 'Svenska',
tr: 'Türkçe',
zh_Hans: '简化字'
}

View file

@ -1,7 +1,7 @@
import Vue from 'vue'
import App from './App.vue'
import './plugins/bootstrap-vue'
import i18n from './plugins/i18n'
import i18n from './i18n'
import router from './plugins/router'
import store from './store'

View file

@ -2,6 +2,7 @@ import Vue from 'vue'
import Vuex from 'vuex'
import info from './info'
import settings from './settings'
import data from './data'
Vue.use(Vuex)
@ -9,6 +10,7 @@ Vue.use(Vuex)
export default new Vuex.Store({
modules: {
info,
settings,
data
}
})

53
app/src/store/settings.js Normal file
View file

@ -0,0 +1,53 @@
/**
* Settings module store.
* @module store/settings
*/
import i18n from '@/i18n'
import { loadLocaleMessages, updateDocumentLocale } from '@/i18n/helpers'
export default {
state: {
locale: undefined,
fallbackLocale: undefined
},
mutations: {
'SET_LOCALE' (state, locale) {
localStorage.setItem('locale', locale)
state.locale = locale
},
'SET_FALLBACK_LOCALE' (state, locale) {
localStorage.setItem('fallbackLocale', locale)
state.fallbackLocale = locale
}
},
actions: {
'UPDATE_LOCALE' ({ commit }, locale) {
loadLocaleMessages(locale).then(() => {
i18n.locale = locale
updateDocumentLocale(locale)
commit('SET_LOCALE', locale)
})
},
'UPDATE_FALLBACK_LOCALE' ({ commit }, locale) {
loadLocaleMessages(locale).then(() => {
i18n.fallbackLocale = [locale, 'en']
commit('SET_FALLBACK_LOCALE', locale)
})
},
'INIT_LOCALES' ({ commit }, { locale, fallbackLocale }) {
commit('SET_LOCALE', locale)
commit('SET_FALLBACK_LOCALE', fallbackLocale[0])
}
},
getters: {
locale: state => (state.locale),
fallbackLocale: state => (state.fallbackLocale)
}
}