vue-i18n-loader
vue-i18n-loader - another webpack loader i18n solution for Vue (Nuxt) with auto generated keys.
Currently under development, pull requests and suggestions are welcome.
Why?
-
We need auto generated keys for texts to be translated
There are only two hard things in Computer Science: cache invalidation and naming things. -- Phil Karlton
Most i18n solutions ask developers to name each text with a unique key, like
$t("message.hello")
, naming is so annoying, it's not reasonable to waste time doing this job -
Text translations should be put just beside source codes
Some solutions extract all texts to a single json file, it's not conform to modularization
How it works?
- Find automatically texts to translate by two means: regex string or 'delimiter'(Refer to usage below).
- Keep first 8 characters of every matched text as key (and append 4 characters md5 hash to the key if the text is longer than 8)
- Replace texts by translator markups using regex
- Create or update
filename.messages.json
to store translations, import this file infilename.vue
!!! Attentions !!!
-
Since
this
at the top level of es6 module bind toundefined
, but not the vue instance.All target texts in script part should be put in functions(not fat arrow functions refer to this doc)
Usage
Config webpack
Config example based on Nuxt.js.
Given regString
, the loader will match all texts/attributes/string templates by new RegExp(regString)
Given delimiter
, the loader will ignore regString
, The loader will match all texts between delimiter
, for example ##text##
.
{
test: /\.vue$/,
exclude: [/node_modules/],
loader: 'vue-i18n-loader',
enforce: 'pre',
options: {
updateMessagesFile: ctx.isClient && ctx.isDev, // only update messages file when it's dev and client(when using ssr)
cacheTime: 3000,
// regString to match simplified chinese characters
regString: '[\u4e00-\u9fa5\u3002\uff1b\uff0c\uff1a\u2018\u2019\u201c\u201d\uff08\uff09\u3001\uff1f\uff01\ufe15\u300a\u300b]+',
// delimiter: '##', // match texts surrounded by '##', like '##text##'
// Loader will use existing translations, if there is not, will use text generated by translator
languages: [{
key: 'zh_Hans_CN',
translator: (matched) => {
// Delete repeat mark R, sometimes we need a text to be translated differentlyz`
return matched.replace(/^\[R\]+/, '')
}
}, {
key: 'zh_Hant_HK',
translator: (matched) => {
// example to auto translate simplified chinese to traditional
return chineseS2T.s2t(matched.replace(/^\[R\]+/, ''))
}
}, {
key: 'en_US',
// if translator is not given, the loader will use the default translator(translator of the first language, zh_Hans_CN here)
}],
}
}
Add a global plugin to tell our helper which language to show
An example of plugin can be:
import Vue from 'vue';
import {mapGetters} from 'vuex';
// !!! the key must be $lang, which will be referenced by the helper !!!
Vue.mixin({
computed: {
...mapGetters({'$lang': 'currentLang'}),
}
});
The helper will insert code automatically to refer this $lang
variable like this:
methods:{
$t(key){
if(!this.$lang && !messages["${defaultLang}"]) return key;
const trans = messages[this.$lang]||messages["${defaultLang}"]||{};
return trans[key];
},
}
defaultLang
is the first language key set in config, zh_Hans_CN
here in the example.
Demo
check the example directory:
- This example is based on Nuxt.js
- Download this example and start by
npm install
thennpm run dev
- Try changing texts and add some translations
Cli tool
We provide a cli tool to group all *.messages.json
and serve a web page for human translators Please refer to the github repo of viai18n-cli
Roadmap
- Support JSX
- Add tests