From cc020fefbc262c15c2469b6572ea864be4b90de3 Mon Sep 17 00:00:00 2001 From: Tor-Einar Skog <tor-einar.skog@nibio.no> Date: Wed, 3 Feb 2021 09:34:15 +0100 Subject: [PATCH] Added translation support --- .env | 2 + README.md | 35 ++++ package-lock.json | 297 +++++++++++++++++++++++++++++ package.json | 17 +- src/components/ObservationList.vue | 6 +- src/i18n.js | 23 +++ src/locales/en.json | 3 + src/locales/nb.json | 3 + src/main.js | 28 ++- vue.config.js | 10 + 10 files changed, 404 insertions(+), 20 deletions(-) create mode 100644 .env create mode 100644 src/i18n.js create mode 100644 src/locales/en.json create mode 100644 src/locales/nb.json create mode 100644 vue.config.js diff --git a/.env b/.env new file mode 100644 index 0000000..a492d13 --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +VUE_APP_I18N_LOCALE=nb +VUE_APP_I18N_FALLBACK_LOCALE=en diff --git a/README.md b/README.md index 2e93379..36d8d54 100644 --- a/README.md +++ b/README.md @@ -67,3 +67,38 @@ The router components (the "pages" in the Single Page Application that you manag ### Checking out new code Remember to always run `npm install` after checking out new code from the repository. That way, new dependencies will be installed. + +### Translation +[This tutorial](https://www.codeandweb.com/babeledit/tutorials/how-to-translate-your-vue-app-with-vue-i18n) has been used to enable translation. + +I couldn't get the per-component translation thing working (where you embed it in `<i18n>` tags), +so all translations go into the `/locales/[languagecode].json` files. + + +There's a simple translation example in /components/ObservationList.js: + +``` html +<template> + <div class="hello"> + <h1>{{ $t('startpage') }}</h1> + <router-link to="/observation" custom v-slot="{navigate}"> + <button type="button" class="btn btn-primary" @click="navigate">+</button> + </router-link> + + </div> +</template> +``` + +(TODO: Update this documentation when code in ObservationList changes) + +Change the startup language in the app here in `/i18n.js`: + +``` javascript +export default new VueI18n({ + locale: process.env.VUE_APP_I18N_LOCALE || 'nb', // Here you can customize + fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en', + messages: loadLocaleMessages() +}) +``` + + diff --git a/package-lock.json b/package-lock.json index 551dde8..63819ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,43 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@intlify/vue-i18n-loader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@intlify/vue-i18n-loader/-/vue-i18n-loader-1.0.0.tgz", + "integrity": "sha512-y7LlpKEQ01u7Yq14l4VNlbFYEHMmSEH1QXXASOMWspj9ZcIdCebhhvHCHqk5Oy5Epw3PtoxyRJNpb6Wle5udgA==", + "dev": true, + "requires": { + "js-yaml": "^3.13.1", + "json5": "^2.1.1" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } + } + }, "@netflix/nerror": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@netflix/nerror/-/nerror-1.1.3.tgz", @@ -1815,6 +1852,17 @@ "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==", "dev": true }, + "cli-table3": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", + "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", + "dev": true, + "requires": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + } + }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", @@ -3466,6 +3514,12 @@ "regexp.prototype.flags": "^1.2.0" } }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -3713,6 +3767,24 @@ "domelementtype": "1" } }, + "dot-object": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/dot-object/-/dot-object-1.9.0.tgz", + "integrity": "sha512-7MPN6y7XhAO4vM4eguj5+5HNKLjJYfkVG1ZR1Aput4Q4TR6SYeSjhpVQ77IzJHoSHffKbDxBC+48aCiiRurDPw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "glob": "^7.1.4" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, "dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -3722,6 +3794,12 @@ "is-obj": "^2.0.0" } }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", + "dev": true + }, "duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -3798,6 +3876,12 @@ } } }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", @@ -4021,6 +4105,12 @@ "estraverse": "^4.1.1" } }, + "esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "dev": true + }, "esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", @@ -4482,6 +4572,12 @@ "locate-path": "^2.0.0" } }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, "flatten": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", @@ -5501,6 +5597,12 @@ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -11249,6 +11351,48 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz", "integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==" }, + "vue-cli-plugin-i18n": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vue-cli-plugin-i18n/-/vue-cli-plugin-i18n-1.0.1.tgz", + "integrity": "sha512-sLo6YzudaWgn5dOMvrKixE5bb/onYGxcxm+0YexqoOx0QtR+7hZ/P5WPFBMM9v/2i1ec2YYe2PvKTBel7KE+tA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "deepmerge": "^4.2.0", + "dotenv": "^8.2.0", + "flat": "^5.0.0", + "rimraf": "^3.0.0", + "vue": "^2.6.11", + "vue-i18n": "^8.17.0", + "vue-i18n-extract": "1.0.2" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "vue-hot-reload-api": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", @@ -11260,6 +11404,159 @@ "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.22.4.tgz", "integrity": "sha512-XLI5s0AdqMP2Lf4I4CmdmOq8kjb5DDFGR77wAuxCfpEuYSfhTRyyx6MetgZMiL6Lxa0DasjBOiOcciU3NkL3/Q==" }, + "vue-i18n-extract": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vue-i18n-extract/-/vue-i18n-extract-1.0.2.tgz", + "integrity": "sha512-+zwDKvle4KcfloXZnj5hF01ViKDiFr5RMx5507D7oyDXpSleRpekF5YHgZa/+Ra6Go68//z0Nya58J9tKFsCjw==", + "dev": true, + "requires": { + "cli-table3": "^0.5.1", + "dot-object": "^1.7.1", + "esm": "^3.2.13", + "glob": "^7.1.3", + "is-valid-glob": "^1.0.0", + "yargs": "^13.2.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "vue-loader": { "version": "13.7.3", "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-13.7.3.tgz", diff --git a/package.json b/package.json index e123358..690d801 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,14 @@ { "name": "vipsobservationapp", "version": "1.0.0", + "private": true, "description": "The Field Pest Observation App for VIPS users", "author": "Tor-Einar Skog <tor-einar.skog@nibio.no>", - "private": true, "scripts": { + "build": "node build/build.js", "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", - "start": "npm run dev", - "build": "node build/build.js" + "i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'", + "start": "npm run dev" }, "dependencies": { "vue": "^2.5.2", @@ -15,6 +16,7 @@ "vue-router": "^3.0.1" }, "devDependencies": { + "@intlify/vue-i18n-loader": "^1.0.0", "autoprefixer": "^7.1.2", "babel-core": "^6.22.1", "babel-helper-vue-jsx-merge-props": "^2.0.3", @@ -48,6 +50,7 @@ "shelljs": "^0.7.6", "uglifyjs-webpack-plugin": "^1.1.1", "url-loader": "^0.5.8", + "vue-cli-plugin-i18n": "~1.0.1", "vue-loader": "^13.3.0", "vue-style-loader": "^3.0.1", "vue-template-compiler": "^2.5.2", @@ -56,10 +59,6 @@ "webpack-dev-server": "^2.9.1", "webpack-merge": "^4.1.0" }, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - }, "browserslist": [ "> 1%", "last 2 versions", @@ -79,5 +78,9 @@ "ANDROID_SUPPORT_V4_VERSION": "27.+" } } + }, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" } } diff --git a/src/components/ObservationList.vue b/src/components/ObservationList.vue index a467c7c..07bba50 100644 --- a/src/components/ObservationList.vue +++ b/src/components/ObservationList.vue @@ -1,6 +1,6 @@ <template> <div class="hello"> - <h1>{{ msg }}</h1> + <h1>{{ $t('startpage') }}</h1> <router-link to="/observation" custom v-slot="{navigate}"> <button type="button" class="btn btn-primary" @click="navigate">+</button> </router-link> @@ -13,7 +13,7 @@ export default { name: 'ObservationList', data () { return { - msg: 'Startsiden' + /*msg: 'Startsiden'*/ } } } @@ -35,4 +35,4 @@ li { a { color: #42b983; } -</style> +</style> \ No newline at end of file diff --git a/src/i18n.js b/src/i18n.js new file mode 100644 index 0000000..313e372 --- /dev/null +++ b/src/i18n.js @@ -0,0 +1,23 @@ +import Vue from 'vue' +import VueI18n from 'vue-i18n' + +Vue.use(VueI18n) + +function loadLocaleMessages () { + const locales = require.context('./locales', true, /[A-Za-z0-9-_,\s]+\.json$/i) + const messages = {} + locales.keys().forEach(key => { + const matched = key.match(/([A-Za-z0-9-_]+)\./i) + if (matched && matched.length > 1) { + const locale = matched[1] + messages[locale] = locales(key) + } + }) + return messages +} + +export default new VueI18n({ + locale: process.env.VUE_APP_I18N_LOCALE || 'nb', // Here you can customize + fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en', + messages: loadLocaleMessages() +}) diff --git a/src/locales/en.json b/src/locales/en.json new file mode 100644 index 0000000..9e9f5c7 --- /dev/null +++ b/src/locales/en.json @@ -0,0 +1,3 @@ +{ + "startpage": "Start page" +} \ No newline at end of file diff --git a/src/locales/nb.json b/src/locales/nb.json new file mode 100644 index 0000000..d2862dd --- /dev/null +++ b/src/locales/nb.json @@ -0,0 +1,3 @@ +{ + "startpage": "Startsiden" +} \ No newline at end of file diff --git a/src/main.js b/src/main.js index 0823a9a..eeb5de6 100644 --- a/src/main.js +++ b/src/main.js @@ -3,24 +3,31 @@ import Vue from 'vue' import App from './App' import router from './router' +import i18n from './i18n' Vue.config.productionTip = false /* eslint-disable no-new */ const init = () => { new Vue({ - el: '#app', - router, - components: { App }, - template: '<App/>', - data: { + el: '#app', + router, + components: { App }, + template: '<App/>', + + data: { }, - methods: { + + methods: { }, - created() { - console.info("Vue is ready") + + i18n, + + created() { + console.info("Vue is ready"); + console.info("User's preferred language is " + navigator.language); } - }); + }); }; /** @@ -29,7 +36,8 @@ const init = () => { */ new Vue({ el: '#vipsobsappmenu', - router + router, + i18n, }); // Wait for the deviceready event to start the render diff --git a/vue.config.js b/vue.config.js new file mode 100644 index 0000000..93ef04a --- /dev/null +++ b/vue.config.js @@ -0,0 +1,10 @@ +module.exports = { + pluginOptions: { + i18n: { + locale: 'nb', + fallbackLocale: 'en', + localeDir: 'locales', + enableInSFC: false + } + } +} -- GitLab