Skip to content

Instantly share code, notes, and snippets.

@Kelin2025
Created March 3, 2017 17:12
Show Gist options
  • Save Kelin2025/d28e58048544790d5fcb9f319f6d6adf to your computer and use it in GitHub Desktop.
Save Kelin2025/d28e58048544790d5fcb9f319f6d6adf to your computer and use it in GitHub Desktop.
i18n for Vue.js + Vuex
<template lang="pug">
div.list
span {{translate('global.lang')}}
label(v-for="lang in available").item
input(type="radio",v-model="current",:value="lang")
img(:src="icon(lang)",:class="{active: lang === current}")
</template>
<script>
export default {
data: () => ({
icon: (lang) => 'https://lipis.github.io/flag-icon-css/flags/4x3/' + lang + '.svg'
}),
computed: {
current: {
get ({$store}) => $store.state.i18n.current,
set (val) {
this.$store.commit('i18n/toggle', val)
}
},
available: ({$store}) => $store.state.i18n.available
}
}
</script>
<style scoped lang="stylus">
.list
position absolute
top 15px
right 0
padding 10px
background lighten(#191924, 5)
.item
margin 0 5px
vertical-align middle
span
vertical-align 2px
margin-right 5px
text-transform uppercase
font-weight bold
color lighten(#191924, 30)
input
display none
img
width 24px
opacity .25
transition all .5s ease
cursor pointer
&.active
opacity 1
</style>
export default {
lang: {
ru: 'Язык',
gb: 'Language'
},
loading: {
ru: 'Загрузка',
gb: 'Loading'
},
// Support for nested by using path
// e.g. translate('global.buttons.open') -> Открыть || Open
buttons: {
open: {
ru: 'Открыть',
gb: 'Open'
},
close: {
ru: 'Закрыть',
gb: 'Close'
}
},
// Support for cases
// e.g. transkl(5, 'global.points') -> 5 очков || 5 points
points: {
ru: ['очко', 'очка', 'очков'],
gb: 'points'
},
}
import Vue from 'vue'
import { mapActions, mapState } from 'vuex'
Vue.mixin({
computed: mapState(['i18n']),
methods: {
// Default translation
translate (...name) {
let path = name.join('.').split('.')
let value = this.i18n.translations
for (let item of path) {
if (item in value) {
value = value[item]
} else {
return null
}
}
return this.i18n.current in value ? value[this.i18n.current] : value[this.i18n.default]
},
// Translation with cases (1 человек, 2 человека, 5 человек)
transkl (number, ...name) {
let cases = [2, 0, 1, 1, 1, 2]
let translation = this.translate(...name)
return typeof translation === 'object'
? translation[(number % 100 > 4 && number % 100 < 20) ? 2 : cases[(number % 10 < 5) ? number % 10 : 5]]
: translation
}
}
})
import example from 'i18n/example'
const state = {
translations: { example },
available: ['ru', 'gb'],
default: 'ru',
current: 'ru'
}
const mutations = {
toggle (state, lang) {
state.current = lang
localStorage.setItem('lang', lang)
}
}
const actions = {
detect ({state, commit}) {
let lang = localStorage.getItem('lang')
if (state.available.indexOf(lang) === -1) {
lang = state.default
}
commit('toggle', lang)
}
}
export default {
namespaced: true,
state,
actions,
mutations
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment