Commit ed6f012e authored by Agate's avatar Agate 💬 Committed by Ciarán Ainsworth

I18n

parent 986ce6e6
......@@ -19,3 +19,6 @@ yarn-error.log*
*.njsproj
*.sln
*.sw?
src/translations
locales/**/*.po~
msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: easygettext\n"
"Project-Id-Version: \n"
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: en_US\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: easygettext\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: easygettext\n"
"Project-Id-Version: \n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
......@@ -3,13 +3,16 @@
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"serve": "scripts/i18n-compile.sh && vue-cli-service serve",
"build": "scripts/i18n-compile.sh && vue-cli-service build",
"i18n-compile": "scripts/i18n-compile.sh",
"i18n-extract": "scripts/i18n-extract.sh",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^2.6.5",
"vue": "^2.6.10",
"vue-gettext": "^2.1.5",
"vue-router": "^3.0.3"
},
"devDependencies": {
......@@ -18,6 +21,7 @@
"@vue/cli-service": "^3.11.0",
"@vue/eslint-config-prettier": "^5.0.0",
"babel-eslint": "^10.0.1",
"easygettext": "^2.7.0",
"eslint": "^5.16.0",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-vue": "^5.0.0",
......
#!/bin/bash -eux
locales=$(tail -n +2 src/locales.js | sed -e 's/module.exports = //' | jq '.locales[].code' | xargs echo)
mkdir -p src/translations
for locale in $locales; do
$(yarn bin)/gettext-compile locales/$locale/LC_MESSAGES/app.po --output src/translations/$locale.json
done
#!/bin/bash -eux
locales=$(tail -n +2 src/locales.js | sed -e 's/module.exports = //' | jq '.locales[].code' | xargs echo)
locales_dir="locales"
sources=$(find src -name '*.vue' -o -name '*.html' 2> /dev/null)
js_sources=$(find src -name '*.vue' -o -name '*.js')
touch $locales_dir/app.pot
# Create a main .pot template, then generate .po files for each available language.
# Extract gettext strings from templates files and create a POT dictionary template.
$(yarn bin)/gettext-extract --attribute v-translate --quiet --output $locales_dir/app.pot $sources
xgettext --language=JavaScript --keyword=npgettext:1c,2,3 \
--from-code=utf-8 --join-existing --no-wrap \
--package-name=$(node -e "console.log(require('./package.json').name);") \
--package-version=$(node -e "console.log(require('./package.json').version);") \
--output $locales_dir/app.pot $js_sources \
--no-wrap
# Generate .po files for each available language.
echo $locales
for lang in $locales; do \
po_file=$locales_dir/$lang/LC_MESSAGES/app.po; \
echo "msgmerge --update $po_file "; \
mkdir -p $(dirname $po_file); \
[ -f $po_file ] && msgmerge --lang=$lang --update $po_file $locales_dir/app.pot --no-wrap || msginit --no-wrap --no-translator --locale=$lang --input=$locales_dir/app.pot --output-file=$po_file; \
msgattrib --no-wrap --no-obsolete -o $po_file $po_file; \
done;
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
<router-link :to="{ name: 'home', params: { locale: $language.current } }"
>Home</router-link
>
|
<router-link
:to="{ name: 'about', params: { locale: $language.current } }"
>About</router-link
>
</div>
<router-view />
<language-switcher></language-switcher>
</div>
</template>
<script>
import LanguageSwitcher from "./components/LanguageSwitcher";
export default {
components: {
LanguageSwitcher
}
};
</script>
<style lang="scss">
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
......
<script>
import Vue from "vue";
import locales from "./locales";
export default {
props: ["locale"],
created() {
this.autodetectLanguage();
},
methods: {
autodetectLanguage() {
let userLanguage =
this.locale || navigator.language || navigator.userLanguage;
let available = locales.locales.map(e => {
return e.code;
});
let candidate;
let matching = available.filter(a => {
return userLanguage.replace("-", "_") === a;
});
let almostMatching = available.filter(a => {
return userLanguage.replace("-", "_").split("_")[0] === a.split("_")[0];
});
if (matching.length > 0) {
candidate = matching[0];
} else if (almostMatching.length > 0) {
candidate = almostMatching[0];
} else {
return;
}
this.switchLanguage(candidate);
},
switchLanguage(newValue) {
let self = this;
import(`./translations/${newValue}.json`)
.then(response => {
Vue.$translations[newValue] = response.default[newValue];
})
.finally(() => {
// set current language twice, otherwise we seem to have a cache somewhere
// and rendering does not happen
self.$language.current = "noop";
self.$language.current = newValue;
if (
self.$route.params.locale &&
self.$route.params.locale !== newValue
) {
self.$router.push({ params: { locale: newValue } });
}
self.$emit("updateHead");
});
}
},
watch: {
"$route.params.locale"(newValue) {
if (newValue) {
this.switchLanguage(newValue);
}
}
}
};
</script>
<template>
<select
id="language"
name="language"
:value="$language.current"
@change="$router.push({ params: { locale: $event.target.value } })"
>
<option
v-for="(language, key) in $language.available"
:key="key"
:value="key"
>{{ language }}</option
>
</select>
</template>
/* eslint-disable */
module.exports = {
"locales": [
{
"code": "en_US",
"label": "English (United-States)"
},
{
"code": "fr_FR",
"label": "Français"
}
]
}
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import GetTextPlugin from "vue-gettext";
import locales from "@/locales";
Vue.config.productionTip = false;
let availableLanguages = (function() {
let l = {};
locales.locales.forEach(c => {
l[c.code] = c.label;
});
return l;
})();
let defaultLanguage = "en_US";
Vue.use(GetTextPlugin, {
availableLanguages: availableLanguages,
defaultLanguage: defaultLanguage,
languageVmMixin: {
computed: {
currentKebabCase: function() {
return this.current.toLowerCase().replace("_", "-");
}
}
},
translations: {},
silent: true
});
new Vue({
router,
render: h => h(App)
......
......@@ -9,12 +9,13 @@ export default new Router({
base: process.env.BASE_URL,
routes: [
{
path: "/",
path: "/:locale?/",
props: true,
name: "home",
component: Home
},
{
path: "/about",
path: "/:locale?/about",
name: "about",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
......
......@@ -3,3 +3,10 @@
<h1>This is an about page</h1>
</div>
</template>
<script>
import PageMixin from "../PageMixin";
export default {
mixins: [PageMixin],
}
......@@ -8,9 +8,10 @@
<script>
// @ is an alias to /src
import HelloWorld from "@/components/HelloWorld.vue";
import PageMixin from "../PageMixin";
export default {
name: "home",
mixins: [PageMixin],
components: {
HelloWorld
}
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment