changeset 141:0fd572582ab8 vue-gettext

POC
author Thomas Junk <thomas.junk@intevation.de>
date Fri, 29 Jun 2018 13:38:28 +0200
parents f4523620ba5d
children edce32db775a
files client/.env.sample client/Makefile client/package.json client/src/locale/de_DE/LC_MESSAGES/app.po client/src/locale/de_DE/LC_MESSAGES/app.po~ client/src/locale/en_GB/LC_MESSAGES/app.po client/src/locale/it_IT/LC_MESSAGES/app.po client/src/locale/it_IT/LC_MESSAGES/app.po~ client/src/main.js client/src/store.js client/src/stores/language.js client/src/translations.json client/src/views/Login.vue client/yarn.lock
diffstat 14 files changed, 471 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/client/.env.sample	Thu Jun 28 17:26:38 2018 +0200
+++ b/client/.env.sample	Fri Jun 29 13:38:28 2018 +0200
@@ -9,3 +9,6 @@
 
 #Path of vendored images is copied during a webpack build
 VUE_APP_VENDOR_IMG_PATH=
+
+#Default Language, e.g. de_DE, en_GB
+VUE_APP_DEFAULT_LANGUAGE=
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/Makefile	Fri Jun 29 13:38:28 2018 +0200
@@ -0,0 +1,55 @@
+# On OSX the PATH variable isn't exported unless "SHELL" is also set, see: http://stackoverflow.com/a/25506676
+SHELL = /bin/bash
+NODE_BINDIR = ./node_modules/.bin
+export PATH := $(NODE_BINDIR):$(PATH)
+
+# Where to write the files generated by this makefile.
+OUTPUT_DIR = src
+
+# Available locales for the app.
+LOCALES = de_DE en_GB it_IT
+
+# Name of the generated .po files for each available locale.
+LOCALE_FILES ?= $(patsubst %,$(OUTPUT_DIR)/locale/%/LC_MESSAGES/app.po,$(LOCALES))
+
+GETTEXT_HTML_SOURCES = $(shell find $(OUTPUT_DIR) -name '*.vue' -o -name '*.html' 2> /dev/null)
+GETTEXT_JS_SOURCES = $(shell find $(OUTPUT_DIR) -name '*.vue' -o -name '*.js')
+
+# Makefile Targets
+.PHONY: clean makemessages translations
+
+clean:
+	rm -f /tmp/template.pot $(OUTPUT_DIR)/translations.json
+
+makemessages: /tmp/template.pot
+
+translations: ./$(OUTPUT_DIR)/translations.json
+
+# Create a main .pot template, then generate .po files for each available language.
+# Thanx to Systematic: https://github.com/Polyconseil/systematic/blob/866d5a/mk/main.mk#L167-L183
+/tmp/template.pot: $(GETTEXT_HTML_SOURCES)
+# `dir` is a Makefile built-in expansion function which extracts the directory-part of `$@`.
+# `$@` is a Makefile automatic variable: the file name of the target of the rule.
+# => `mkdir -p /tmp/`
+	mkdir -p $(dir $@)
+	which gettext-extract
+# Extract gettext strings from templates files and create a POT dictionary template.
+	gettext-extract --attribute v-translate --quiet --output $@ $(GETTEXT_HTML_SOURCES)
+# Extract gettext strings from JavaScript files.
+	xgettext --language=JavaScript --keyword=npgettext:1c,2,3 \
+		--from-code=utf-8 --join-existing --no-wrap \
+		--package-name=$(shell node -e "console.log(require('./package.json').name);") \
+		--package-version=$(shell node -e "console.log(require('./package.json').version);") \
+		--output $@ $(GETTEXT_JS_SOURCES)
+# Generate .po files for each available language.
+	@for lang in $(LOCALES); do \
+		export PO_FILE=$(OUTPUT_DIR)/locale/$$lang/LC_MESSAGES/app.po; \
+		echo "msgmerge --update $$PO_FILE $@"; \
+		mkdir -p $$(dirname $$PO_FILE); \
+		[ -f $$PO_FILE ] && msgmerge --lang=$$lang --update $$PO_FILE $@ || msginit --no-translator --locale=$$lang --input=$@ --output-file=$$PO_FILE; \
+		msgattrib --no-wrap --no-obsolete -o $$PO_FILE $$PO_FILE; \
+	done;
+
+$(OUTPUT_DIR)/translations.json: clean /tmp/template.pot
+	mkdir -p $(OUTPUT_DIR)
+	gettext-compile --output $@ $(LOCALE_FILES)
--- a/client/package.json	Thu Jun 28 17:26:38 2018 +0200
+++ b/client/package.json	Fri Jun 29 13:38:28 2018 +0200
@@ -29,9 +29,11 @@
     "babel-jest": "^23.0.1",
     "concurrently": "^3.5.1",
     "copy-webpack-plugin": "^4.5.1",
+    "easygettext": "^2.4.0",
     "node-sass": "^4.9.0",
     "pretty-quick": "^1.6.0",
     "sass-loader": "^7.0.1",
+    "vue-gettext": "^2.0.31",
     "vue-template-compiler": "^2.5.16"
   },
   "browserslist": [
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/locale/de_DE/LC_MESSAGES/app.po	Fri Jun 29 13:38:28 2018 +0200
@@ -0,0 +1,27 @@
+# German translations for wamosjs package
+# German translation for wamosjs.
+# Copyright (C) 2018 THE wamosjs'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the wamosjs package.
+# Automatically generated, 2018.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: wamosjs 0.1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-06-29 13:24+0200\n"
+"PO-Revision-Date: 2018-06-29 13:23+0200\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: de_DE\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/views/Login.vue:23
+msgid "Forgot password"
+msgstr "Passwort vergessen?"
+
+#: src/views/Login.vue:22
+msgid "Login"
+msgstr "Einloggen"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/locale/de_DE/LC_MESSAGES/app.po~	Fri Jun 29 13:38:28 2018 +0200
@@ -0,0 +1,27 @@
+# German translations for wamosjs package
+# German translation for wamosjs.
+# Copyright (C) 2018 THE wamosjs'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the wamosjs package.
+# Automatically generated, 2018.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: wamosjs 0.1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-06-29 13:23+0200\n"
+"PO-Revision-Date: 2018-06-29 13:23+0200\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/views/Login.vue:23
+msgid "Forgot password"
+msgstr "Passwort vergessen?"
+
+#: src/views/Login.vue:22
+msgid "Login"
+msgstr "Einloggen"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/locale/en_GB/LC_MESSAGES/app.po	Fri Jun 29 13:38:28 2018 +0200
@@ -0,0 +1,26 @@
+# English translations for wamosjs package.
+# Copyright (C) 2018 THE wamosjs'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the wamosjs package.
+# Automatically generated, 2018.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: wamosjs 0.1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-06-29 13:23+0200\n"
+"PO-Revision-Date: 2018-06-29 13:23+0200\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: en_GB\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/views/Login.vue:23
+msgid "Forgot password"
+msgstr "Forgot password"
+
+#: src/views/Login.vue:22
+msgid "Login"
+msgstr "Login"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/locale/it_IT/LC_MESSAGES/app.po	Fri Jun 29 13:38:28 2018 +0200
@@ -0,0 +1,27 @@
+# Italian translations for wamosjs package
+# Traduzioni italiane per il pacchetto wamosjs..
+# Copyright (C) 2018 THE wamosjs'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the wamosjs package.
+# Automatically generated, 2018.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: wamosjs 0.1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-06-29 13:24+0200\n"
+"PO-Revision-Date: 2018-06-29 13:23+0200\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: it_IT\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/views/Login.vue:23
+msgid "Forgot password"
+msgstr ""
+
+#: src/views/Login.vue:22
+msgid "Login"
+msgstr ""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/locale/it_IT/LC_MESSAGES/app.po~	Fri Jun 29 13:38:28 2018 +0200
@@ -0,0 +1,27 @@
+# Italian translations for wamosjs package
+# Traduzioni italiane per il pacchetto wamosjs..
+# Copyright (C) 2018 THE wamosjs'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the wamosjs package.
+# Automatically generated, 2018.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: wamosjs 0.1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-06-29 13:23+0200\n"
+"PO-Revision-Date: 2018-06-29 13:23+0200\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/views/Login.vue:23
+msgid "Forgot password"
+msgstr ""
+
+#: src/views/Login.vue:22
+msgid "Login"
+msgstr ""
--- a/client/src/main.js	Thu Jun 28 17:26:38 2018 +0200
+++ b/client/src/main.js	Fri Jun 29 13:38:28 2018 +0200
@@ -2,6 +2,20 @@
 import App from "./App.vue";
 import router from "./router";
 import store from "./store";
+import GetTextPlugin from "vue-gettext";
+import translations from "./translations.json";
+
+const defaultLanguage = process.env.VUE_APP_DEFAULT_LANGUAGE || "de_DE";
+
+Vue.use(GetTextPlugin, {
+  translations: translations,
+  availableLanguages: {
+    en_GB: "British English",
+    de_DE: "Deutsch"
+  },
+  defaultLanguage: defaultLanguage
+});
+
 import "../node_modules/bootstrap/dist/css/bootstrap.min.css";
 import "../node_modules/font-awesome/css/font-awesome.min.css";
 import "../node_modules/ol/ol.css";
--- a/client/src/store.js	Thu Jun 28 17:26:38 2018 +0200
+++ b/client/src/store.js	Fri Jun 29 13:38:28 2018 +0200
@@ -1,7 +1,6 @@
 import Vue from "vue";
 import Vuex from "vuex";
 import Application from "./stores/application";
-import i18n from "./stores/language";
 import user from "./stores/user";
 
 Vue.use(Vuex);
@@ -9,7 +8,6 @@
 export default new Vuex.Store({
   modules: {
     application: Application,
-    i18n: i18n,
     user: user
   }
 });
--- a/client/src/stores/language.js	Thu Jun 28 17:26:38 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-const i18n = {
-  namespaced: true,
-  state: {
-    signinHeader: "Please sign in",
-    emailLabel: "Email address",
-    passwordLabel: "Password",
-    loginButtonLabel: "Log In",
-    loginAttemptFailed: "Login Failed\n(try other email & passphrase)",
-    passPhraseForgotten: "Passphrase forgotten?"
-  },
-  getters: {
-    signinHeader: state => {
-      return state.signinHeader;
-    },
-    emailLabel: state => {
-      return state.emailLabel;
-    },
-    passwordLabel: state => {
-      return state.passwordLabel;
-    },
-    loginAttemptFailed: state => {
-      return state.loginAttemptFailed;
-    },
-    loginButtonLabel: state => {
-      return state.loginButtonLabel;
-    },
-    passPhraseForgotten: state => {
-      return state.passPhraseForgotten;
-    }
-  },
-  mutations: {},
-  actions: {}
-};
-
-export default i18n;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/translations.json	Fri Jun 29 13:38:28 2018 +0200
@@ -0,0 +1,1 @@
+{"de_DE":{"Forgot password":"Passwort vergessen?","Login":"Einloggen"},"en_GB":{"Forgot password":"Forgot password","Login":"Login"},"it_IT":{}}
\ No newline at end of file
--- a/client/src/views/Login.vue	Thu Jun 28 17:26:38 2018 +0200
+++ b/client/src/views/Login.vue	Fri Jun 29 13:38:28 2018 +0200
@@ -9,20 +9,19 @@
     <div class="login-wrapper d-flex flex-row justify-content-center">
       <form class="loginform form-signin" @submit.prevent="login">
            <div v-if="loginFailed" class="loginerrormessage alert alert-danger" role="alert">
-             <span class="loginerror">{{ loginAttemptFailed }}</span>
+             <span class="loginerror">Fehler</span>
            </div>
         <div class="input-group mb-3 emailgroup">
-          <input type="text" v-model="username" id="inputEmail" class="form-control" :placeholder="emailLabel" required autofocus>
+          <input type="text" v-model="username" id="inputEmail" class="form-control" placeholder="emailLabel" required autofocus>
         </div>
         <div class="input-group mb-3 passwordgroup">
-
-          <input :type="isPasswordVisible" v-model="password" id="inputPassword" class="form-control" :placeholder="passwordLabel" required>
+          <input :type="isPasswordVisible" v-model="password" id="inputPassword" class="form-control" placeholder="passwordLabel" required>
           <div class="input-group-append">
             <span class="input-group-text" id="basic-addon2" @click="showPassword"><i :class="eyeIcon"></i></span>
           </div>
         </div>
-        <button class="submitbutton btn btn-primary btn-block" :disabled="submitted" type="submit">{{ loginButtonLabel }}</button>
-        <div class="forgottenlink small"><a href="#">{{ passPhraseForgotten }}</a></div>
+        <button class="submitbutton btn btn-primary btn-block" :disabled="submitted" type="submit"><translate>Login</translate></button>
+        <div class="forgottenlink small"><a href="#"><translate>Forgot password</translate></a></div>
         <div class="secondary-logo"><img :src="secondaryLogo"></div>
       </form>
     </div>
@@ -131,15 +130,7 @@
         rounded: true
       };
     },
-    ...mapGetters("application", ["appTitle", "secondaryLogo"]),
-    ...mapGetters("i18n", [
-      "signinHeader",
-      "emailLabel",
-      "passwordLabel",
-      "loginButtonLabel",
-      "loginAttemptFailed",
-      "passPhraseForgotten"
-    ])
+    ...mapGetters("application", ["appTitle", "secondaryLogo"])
   },
   methods: {
     login() {
--- a/client/yarn.lock	Thu Jun 28 17:26:38 2018 +0200
+++ b/client/yarn.lock	Fri Jun 29 13:38:28 2018 +0200
@@ -743,6 +743,20 @@
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz#50c1e2260ac0ed9439a181de3725a0168d59c48a"
 
+"@types/babel-types@*", "@types/babel-types@^7.0.0":
+  version "7.0.4"
+  resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.4.tgz#bfd5b0d0d1ba13e351dff65b6e52783b816826c8"
+
+"@types/babylon@^6.16.2":
+  version "6.16.3"
+  resolved "https://registry.yarnpkg.com/@types/babylon/-/babylon-6.16.3.tgz#c2937813a89fcb5e79a00062fc4a8b143e7237bb"
+  dependencies:
+    "@types/babel-types" "*"
+
+"@types/node@*":
+  version "10.5.1"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.1.tgz#d578446f4abff5c0b49ade9b4e5274f6badaadfc"
+
 "@types/strip-bom@^3.0.0":
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2"
@@ -1056,6 +1070,12 @@
   dependencies:
     acorn "^5.0.0"
 
+acorn-globals@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf"
+  dependencies:
+    acorn "^4.0.4"
+
 acorn-globals@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.1.0.tgz#ab716025dbe17c54d3ef81d32ece2b2d99fe2538"
@@ -1068,10 +1088,14 @@
   dependencies:
     acorn "^3.0.4"
 
-acorn@^3.0.4:
+acorn@^3.0.4, acorn@^3.1.0:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
 
+acorn@^4.0.4, acorn@~4.0.2:
+  version "4.0.13"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787"
+
 acorn@^5.0.0, acorn@^5.3.0, acorn@^5.5.0, acorn@^5.5.3, acorn@^5.6.2:
   version "5.6.2"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.6.2.tgz#b1da1d7be2ac1b4a327fb9eab851702c5045b4e7"
@@ -1264,6 +1288,10 @@
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
 
+asap@~2.0.3:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
+
 asn1.js@^4.0.0:
   version "4.10.1"
   resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0"
@@ -1975,10 +2003,27 @@
     escape-string-regexp "^1.0.5"
     supports-color "^5.3.0"
 
+character-parser@^2.1.1:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0"
+  dependencies:
+    is-regex "^1.0.3"
+
 chardet@^0.4.0:
   version "0.4.2"
   resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
 
+cheerio@^1.0.0-rc.2:
+  version "1.0.0-rc.2"
+  resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db"
+  dependencies:
+    css-select "~1.2.0"
+    dom-serializer "~0.1.0"
+    entities "~1.1.1"
+    htmlparser2 "^3.9.1"
+    lodash "^4.15.0"
+    parse5 "^3.0.1"
+
 chokidar@^2.0.0, chokidar@^2.0.2:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.3.tgz#dcbd4f6cbb2a55b4799ba8a840ac527e5f4b1176"
@@ -2037,7 +2082,7 @@
     isobject "^3.0.0"
     static-extend "^0.1.1"
 
-clean-css@4.1.x:
+clean-css@4.1.x, clean-css@^4.1.11:
   version "4.1.11"
   resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.1.11.tgz#2ecdf145aba38f54740f26cefd0ff3e03e125d6a"
   dependencies:
@@ -2272,6 +2317,15 @@
   dependencies:
     bluebird "^3.1.1"
 
+constantinople@^3.0.1:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-3.1.2.tgz#d45ed724f57d3d10500017a7d3a889c1381ae647"
+  dependencies:
+    "@types/babel-types" "^7.0.0"
+    "@types/babylon" "^6.16.2"
+    babel-types "^6.26.0"
+    babylon "^6.18.0"
+
 constants-browserify@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
@@ -2442,7 +2496,7 @@
     postcss-value-parser "^3.3.0"
     source-list-map "^2.0.0"
 
-css-select@^1.1.0:
+css-select@^1.1.0, css-select@~1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
   dependencies:
@@ -2760,13 +2814,17 @@
   dependencies:
     esutils "^2.0.2"
 
+doctypes@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9"
+
 dom-converter@~0.1:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.1.4.tgz#a45ef5727b890c9bffe6d7c876e7b19cb0e17f3b"
   dependencies:
     utila "~0.3"
 
-dom-serializer@0:
+dom-serializer@0, dom-serializer@~0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
   dependencies:
@@ -2777,7 +2835,7 @@
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
 
-domelementtype@1:
+domelementtype@1, domelementtype@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2"
 
@@ -2797,6 +2855,12 @@
   dependencies:
     domelementtype "1"
 
+domhandler@^2.3.0:
+  version "2.4.2"
+  resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
+  dependencies:
+    domelementtype "1"
+
 domutils@1.1:
   version "1.1.6"
   resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.1.6.tgz#bddc3de099b9a2efacc51c623f28f416ecc57485"
@@ -2810,6 +2874,13 @@
     dom-serializer "0"
     domelementtype "1"
 
+domutils@^1.5.1:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
+  dependencies:
+    dom-serializer "0"
+    domelementtype "1"
+
 dot-prop@^4.1.1:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
@@ -2829,6 +2900,18 @@
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/easy-stack/-/easy-stack-1.0.0.tgz#12c91b3085a37f0baa336e9486eac4bf94e3e788"
 
+easygettext@^2.4.0:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/easygettext/-/easygettext-2.4.0.tgz#03e6b97f87beb6fc493ad156f4b619120bf318f0"
+  dependencies:
+    "@vue/component-compiler-utils" "^1.2.1"
+    acorn "^5.5.3"
+    cheerio "^1.0.0-rc.2"
+    minimist "^1.2.0"
+    pofile "^1.0.10"
+    pug "^2.0.3"
+    vue-template-compiler "^2.5.16"
+
 ecc-jsbn@~0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
@@ -2887,7 +2970,7 @@
     memory-fs "^0.4.0"
     tapable "^1.0.0"
 
-entities@~1.1.1:
+entities@^1.1.1, entities@~1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
 
@@ -3978,6 +4061,17 @@
     toposort "^1.0.0"
     util.promisify "1.0.0"
 
+htmlparser2@^3.9.1:
+  version "3.9.2"
+  resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
+  dependencies:
+    domelementtype "^1.3.0"
+    domhandler "^2.3.0"
+    domutils "^1.5.1"
+    entities "^1.1.1"
+    inherits "^2.0.1"
+    readable-stream "^2.0.2"
+
 htmlparser2@~3.3.0:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.3.0.tgz#cc70d05a59f6542e43f0e685c982e14c924a9efe"
@@ -4275,6 +4369,13 @@
   dependencies:
     is-primitive "^2.0.0"
 
+is-expression@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-3.0.0.tgz#39acaa6be7fd1f3471dc42c7416e61c24317ac9f"
+  dependencies:
+    acorn "~4.0.2"
+    object-assign "^4.0.1"
+
 is-extendable@^0.1.0, is-extendable@^0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
@@ -4405,7 +4506,7 @@
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
 
-is-promise@^2.1.0:
+is-promise@^2.0.0, is-promise@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
 
@@ -4413,7 +4514,7 @@
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
 
-is-regex@^1.0.4:
+is-regex@^1.0.3, is-regex@^1.0.4:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
   dependencies:
@@ -4884,6 +4985,10 @@
   dependencies:
     easy-stack "^1.0.0"
 
+js-stringify@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db"
+
 js-tokens@^3.0.0, js-tokens@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
@@ -5006,6 +5111,13 @@
     json-schema "0.2.3"
     verror "1.10.0"
 
+jstransformer@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/jstransformer/-/jstransformer-1.0.0.tgz#ed8bf0921e2f3f1ed4d5c1a44f68709ed24722c3"
+  dependencies:
+    is-promise "^2.0.0"
+    promise "^7.0.1"
+
 killable@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.0.tgz#da8b84bd47de5395878f95d64d02f2449fe05e6b"
@@ -5177,7 +5289,7 @@
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
 
-lodash@4.x, lodash@^4.0.0, lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1, lodash@~4.17.10:
+lodash@4.x, lodash@^4.0.0, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1, lodash@~4.17.10:
   version "4.17.10"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
 
@@ -6047,6 +6159,12 @@
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
 
+parse5@^3.0.1:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c"
+  dependencies:
+    "@types/node" "*"
+
 parseurl@~1.3.2:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
@@ -6174,6 +6292,10 @@
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
 
+pofile@^1.0.10:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.0.11.tgz#35aff58c17491d127a07336d5522ebc9df57c954"
+
 portfinder@^1.0.13, portfinder@^1.0.9:
   version "1.0.13"
   resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9"
@@ -6539,6 +6661,12 @@
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
 
+promise@^7.0.1:
+  version "7.3.1"
+  resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
+  dependencies:
+    asap "~2.0.3"
+
 proto-list@~1.2.1:
   version "1.2.4"
   resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
@@ -6576,6 +6704,99 @@
     parse-asn1 "^5.0.0"
     randombytes "^2.0.1"
 
+pug-attrs@^2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-2.0.3.tgz#a3095f970e64151f7bdad957eef55fb5d7905d15"
+  dependencies:
+    constantinople "^3.0.1"
+    js-stringify "^1.0.1"
+    pug-runtime "^2.0.4"
+
+pug-code-gen@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-2.0.1.tgz#0951ec83225d74d8cfc476a7f99a259b5f7d050c"
+  dependencies:
+    constantinople "^3.0.1"
+    doctypes "^1.1.0"
+    js-stringify "^1.0.1"
+    pug-attrs "^2.0.3"
+    pug-error "^1.3.2"
+    pug-runtime "^2.0.4"
+    void-elements "^2.0.1"
+    with "^5.0.0"
+
+pug-error@^1.3.2:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-1.3.2.tgz#53ae7d9d29bb03cf564493a026109f54c47f5f26"
+
+pug-filters@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-3.1.0.tgz#27165555bc04c236e4aa2b0366246dfa021b626e"
+  dependencies:
+    clean-css "^4.1.11"
+    constantinople "^3.0.1"
+    jstransformer "1.0.0"
+    pug-error "^1.3.2"
+    pug-walk "^1.1.7"
+    resolve "^1.1.6"
+    uglify-js "^2.6.1"
+
+pug-lexer@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/pug-lexer/-/pug-lexer-4.0.0.tgz#210c18457ef2e1760242740c5e647bd794cec278"
+  dependencies:
+    character-parser "^2.1.1"
+    is-expression "^3.0.0"
+    pug-error "^1.3.2"
+
+pug-linker@^3.0.5:
+  version "3.0.5"
+  resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-3.0.5.tgz#9e9a7ae4005682d027deeb96b000f88eeb83a02f"
+  dependencies:
+    pug-error "^1.3.2"
+    pug-walk "^1.1.7"
+
+pug-load@^2.0.11:
+  version "2.0.11"
+  resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.11.tgz#e648e57ed113fe2c1f45d57858ea2bad6bc01527"
+  dependencies:
+    object-assign "^4.1.0"
+    pug-walk "^1.1.7"
+
+pug-parser@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-5.0.0.tgz#e394ad9b3fca93123940aff885c06e44ab7e68e4"
+  dependencies:
+    pug-error "^1.3.2"
+    token-stream "0.0.1"
+
+pug-runtime@^2.0.4:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/pug-runtime/-/pug-runtime-2.0.4.tgz#e178e1bda68ab2e8c0acfc9bced2c54fd88ceb58"
+
+pug-strip-comments@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/pug-strip-comments/-/pug-strip-comments-1.0.3.tgz#f1559592206edc6f85310dacf4afb48a025af59f"
+  dependencies:
+    pug-error "^1.3.2"
+
+pug-walk@^1.1.7:
+  version "1.1.7"
+  resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.7.tgz#c00d5c5128bac5806bec15d2b7e7cdabe42531f3"
+
+pug@^2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.3.tgz#71cba82537c95a5eab7ed04696e4221f53aa878e"
+  dependencies:
+    pug-code-gen "^2.0.1"
+    pug-filters "^3.1.0"
+    pug-lexer "^4.0.0"
+    pug-linker "^3.0.5"
+    pug-load "^2.0.11"
+    pug-parser "^5.0.0"
+    pug-runtime "^2.0.4"
+    pug-strip-comments "^1.0.3"
+
 pump@^2.0.0, pump@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
@@ -7025,6 +7246,12 @@
   version "1.1.7"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
 
+resolve@^1.1.6:
+  version "1.8.1"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26"
+  dependencies:
+    path-parse "^1.0.5"
+
 resolve@^1.3.2:
   version "1.7.1"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3"
@@ -7823,6 +8050,10 @@
     regex-not "^1.0.2"
     safe-regex "^1.1.0"
 
+token-stream@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a"
+
 topo@2.x.x:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/topo/-/topo-2.0.2.tgz#cd5615752539057c0dc0491a621c3bc6fbe1d182"
@@ -7932,7 +8163,7 @@
     commander "~2.15.0"
     source-map "~0.6.1"
 
-uglify-js@^2.6:
+uglify-js@^2.6, uglify-js@^2.6.1:
   version "2.8.29"
   resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
   dependencies:
@@ -8139,6 +8370,10 @@
   dependencies:
     indexof "0.0.1"
 
+void-elements@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
+
 vue-eslint-parser@^2.0.3:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz#c268c96c6d94cfe3d938a5f7593959b0ca3360d1"
@@ -8150,6 +8385,10 @@
     esquery "^1.0.0"
     lodash "^4.17.4"
 
+vue-gettext@^2.0.31:
+  version "2.0.31"
+  resolved "https://registry.yarnpkg.com/vue-gettext/-/vue-gettext-2.0.31.tgz#0f113bea6aed747e2a809ae4a0db83eaac0b07fc"
+
 vue-hot-reload-api@^2.3.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.0.tgz#97976142405d13d8efae154749e88c4e358cf926"
@@ -8413,6 +8652,13 @@
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
 
+with@^5.0.0:
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/with/-/with-5.1.1.tgz#fa4daa92daf32c4ea94ed453c81f04686b575dfe"
+  dependencies:
+    acorn "^3.1.0"
+    acorn-globals "^3.0.0"
+
 wordwrap@0.0.2:
   version "0.0.2"
   resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"