{"id":677,"date":"2019-06-05T09:11:12","date_gmt":"2019-06-05T13:11:12","guid":{"rendered":"http:\/\/salzlechner.com\/dev\/?p=677"},"modified":"2019-08-10T11:44:37","modified_gmt":"2019-08-10T15:44:37","slug":"vue-js-and-internationalization","status":"publish","type":"post","link":"http:\/\/salzlechner.com\/dev\/2019\/06\/05\/vue-js-and-internationalization\/","title":{"rendered":"Vue.js and Internationalization"},"content":{"rendered":"<p>In this short post we will look into adding Internationalization to a Vue.js project. This will allow us to support multiple languages for all our text elements<\/p>\n<p>to start we will create a simple Vue project using the Vue cli as follows<\/p>\n<pre class=\"lang:default decode:true \">vue init webpack i18nSample\n<\/pre>\n<p>we can test the application by going to the directory created and starting the project<\/p>\n<pre class=\"lang:default decode:true \">cd i18nSample\nnpm run dev\n<\/pre>\n<p>Now lets add internationalization to this project<\/p>\n<h1>vue-i18n Plugin<\/h1>\n<p>We will be using the vue-i18n plugin to support language translations<\/p>\n<p>to install the plugin via npm run the following command line<\/p>\n<pre class=\"lang:default decode:true\">npm install vue-i18n --save<\/pre>\n<p>next we will create a folder called &#8216;plugins&#8217; under the &#8216;src&#8217; folder and create a new file called i18n.js with the following content<\/p>\n<pre class=\"lang:default decode:true\">import VueI18n from 'vue-i18n'\nimport Vue from 'vue'\n\nimport { DEFAULT_LANGUAGE, FALLBACK_LANGUAGE } from '@\/constants\/translations'\n\nimport en from '@\/lang\/en.json'\nimport es from '@\/lang\/es.json'\nimport de from '@\/lang\/de.json'\n\nVue.use(VueI18n)\n\nexport const i18n = new VueI18n({\n  locale: DEFAULT_LANGUAGE, \/\/ set locale\n  fallbackLocale: FALLBACK_LANGUAGE,\n  messages: { en, es, de }\/\/ set locale messages\n})<\/pre>\n<p>we need to create the folder and file for our constants. Lets create a folder called constants and a file called translations.js<\/p>\n<pre class=\"lang:default decode:true \">export const DEFAULT_LANGUAGE = 'en'\nexport const FALLBACK_LANGUAGE = 'en'\nexport const SUPPORTED_LANGUAGES = ['en', 'es', 'de']<\/pre>\n<p>in addition we create a folder called &#8216;lang&#8217; to keep our translation data<\/p>\n<p>in the lang folder create a file called en.json as follows<\/p>\n<pre class=\"lang:default decode:true \">&lt;h1&gt;{{ $t(helloMessage) }}&lt;\/h1&gt;<\/pre>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">{\n    \n}\n<\/pre>\n<p>then create two more files just like it called es.json and de.json<\/p>\n<p>now lets tell Vue to use the plugin. Add the following line to your main.js file<\/p>\n<pre class=\"lang:default decode:true\">import { i18n } from '@\/plugins\/i18n'<\/pre>\n<p>and then add it to your Vue instance<\/p>\n<pre class=\"lang:default decode:true\">new Vue({\n  el: '#app',\n  i18n,\n  components: { App },\n  template: '&lt;App\/&gt;'\n})<\/pre>\n<p>running the project should again produce the same sample program without any errors<\/p>\n<p>Now lets add some translations<\/p>\n<p>edit the helloworld.vue file and change the content of the H1 tag to<\/p>\n<pre class=\"lang:default decode:true \">&lt;h1&gt;{{ $t('helloMessage') }}&lt;\/h1&gt;<\/pre>\n<p>running the app now will show the text helloMessage but will also show the following warnings in the console<\/p>\n<pre class=\"lang:default decode:true\">[vue-i18n] Cannot translate the value of keypath 'helloMessage'. Use the value of keypath as default.\n[vue-i18n] Value of key 'helloMessage' is not a string!\n[vue-i18n] Value of key 'helloMessage' is not a string!\n<\/pre>\n<p>now lets provide a translation in the main language which is english in our file en.json<\/p>\n<pre class=\"lang:default decode:true \">{\n    \"helloMessage\": \"Hello to our first Vue App with translations\"\n}<\/pre>\n<p>after saving the title of our app should instantly change to the text provided in the translation and the warnings will go away as well.<\/p>\n<p>to test our translations we will need to add a feature to switch languages. Lets add the following 3 buttons to our helloWorld.vue component<\/p>\n<pre class=\"lang:default decode:true\">    &lt;button @click=\"changeToEnglish\"&gt;English&lt;\/button&gt;\n    &lt;button @click=\"changeToSpanish\"&gt;Espanol&lt;\/button&gt;\n    &lt;button @click=\"changeToGerman\"&gt;Deutsch&lt;\/button&gt;<\/pre>\n<p>we need to import the plugin<\/p>\n<pre class=\"lang:default decode:true \">import {i18n} from '@\/plugins\/i18n';<\/pre>\n<p>and then add the following methods<\/p>\n<pre class=\"lang:default decode:true \">methods: {\n    changeToEnglish: function () {\n      i18n.locale = 'en';\n    },\n    changeToSpanish: function () {\n      i18n.locale = 'es';\n    },\n    changeToGerman: function () {\n      i18n.locale = 'de';\n    },\n  }<\/pre>\n<p>now if we run the app it will show the 3 buttons at the top. When clicking one of the other languages we get the following warnings and the text will not change<\/p>\n<pre class=\"lang:default decode:true \">[vue-i18n] Fall back to translate the keypath 'helloMessage' with 'en' locale.\n[vue-i18n] Value of key 'helloMessage' is not a string!\n<\/pre>\n<p>of course we didnt supply any translation for our message. Lets modify the es.json and de.json files as follows<\/p>\n<pre class=\"lang:default decode:true \">{\n    \"helloMessage\": \"Hola a nuestra primera aplicaci\u00f3n Vue con traducciones.\"\n}\n<\/pre>\n<pre class=\"lang:default decode:true \">{\n    \"helloMessage\": \"Willkommen zu unserer ersten Vue App mit \u00dcbersetzungen\"\n}<\/pre>\n<p>these are automated translations but for our test this will be good enough<\/p>\n<p>Now lets run the app again and test the different languages<\/p>\n<p>we can make the language switching even nicer. There is a vue package with flag icons called vue-flag-icon that contains all flags in an SVG collection.<\/p>\n<p>we can install that package using the following command line<\/p>\n<pre class=\"lang:default decode:true \">npm install vue-flag-icon --save<\/pre>\n<p>Once installed we have to important and use them<\/p>\n<pre class=\"lang:default decode:true \">import FlagIcon from 'vue-flag-icon'\nVue.use(FlagIcon)<\/pre>\n<p>lets add a constant for our supported languages to translations.js in our constants folder<\/p>\n<pre class=\"lang:default decode:true \">export const LANGUAGES_INFO = [ { flagIcon: 'us', language: 'en', Name: 'English' },            \n                                { flagIcon: 'es', language: 'es', Name: 'Espa\u00f1ol' },\n                                { flagIcon: 'de', language: 'de', Name: 'Deutsch' }        \n                              ]<\/pre>\n<p>in the helloworld component we import the constants<\/p>\n<pre class=\"lang:default decode:true \">import { LANGUAGES_INFO } from '@\/constants\/translation'<\/pre>\n<p>then then add a data element for them<\/p>\n<pre class=\"lang:default decode:true \">data () {\n    return {\n      langs: LANGUAGES_INFO,\n    }\n  },<\/pre>\n<p>this will give us an array of supported languages that we can use to create our buttons<\/p>\n<p>lets remove the 3 buttons we created earlier and add the following<\/p>\n<pre class=\"lang:default decode:true \">    &lt;button v-for=\"lang in langs\" \n          @click=\"changeLanguage(lang.language)\"&gt;\n          &lt;flag :iso=\"lang.flagIcon\" \/&gt; {{ lang.Name }}\n    &lt;\/button&gt;<\/pre>\n<p>then remove the 3 methods and add the following<\/p>\n<pre class=\"lang:default decode:true \">changeLanguage(lang) {\n      i18n.locale = lang;\n    },<\/pre>\n<p>and to make the buttons look nicer lets add the following style<\/p>\n<pre class=\"lang:default decode:true \">button {\n  padding: 8px;\n  margin: 6px;\n}<\/pre>\n<p>Now when running the app we should get 3 buttons with flags and the name of the language<\/p>\n\n\t\t<div class='author-shortcodes'>\n\t\t\t<div class='author-inner'>\n\t\t\t\t<div class='author-image'>\n\t\t\t<img src='http:\/\/salzlechner.com\/dev\/wp-content\/uploads\/sites\/2\/2016\/02\/mike5crop-566174_60x60.jpg' alt='' \/>\n\t\t\t<div class='author-overlay'><\/div>\n\t\t<\/div> \n\t\t<div class='author-info'>\n\t\t\tMichael Salzlechner is the CEO of StarZen Technologies, Inc.<\/p>\n<p>He was part of the Windows Team at Data Access Worldwide that created the DataFlex for Windows Product before joining&nbsp;<a href=\"http:\/\/starzen.com\">StarZen Technologies<\/a>. StarZen Technologies provides consulting services as well as custom Application development and third party products<\/p>\n\t\t<\/div>\n\t\t\t<\/div>\n\t\t<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this short post we will look into adding Internationalization to a Vue.js project. This will allow us to support multiple languages for all our text elements to start we will create a simple Vue project using the Vue cli as follows vue init webpack i18nSample we can test the application by going to the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":727,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","ngg_post_thumbnail":0,"footnotes":""},"categories":[38],"tags":[],"class_list":["post-677","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-vue-js"],"_links":{"self":[{"href":"http:\/\/salzlechner.com\/dev\/wp-json\/wp\/v2\/posts\/677","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/salzlechner.com\/dev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/salzlechner.com\/dev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/salzlechner.com\/dev\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/salzlechner.com\/dev\/wp-json\/wp\/v2\/comments?post=677"}],"version-history":[{"count":4,"href":"http:\/\/salzlechner.com\/dev\/wp-json\/wp\/v2\/posts\/677\/revisions"}],"predecessor-version":[{"id":728,"href":"http:\/\/salzlechner.com\/dev\/wp-json\/wp\/v2\/posts\/677\/revisions\/728"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/salzlechner.com\/dev\/wp-json\/wp\/v2\/media\/727"}],"wp:attachment":[{"href":"http:\/\/salzlechner.com\/dev\/wp-json\/wp\/v2\/media?parent=677"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/salzlechner.com\/dev\/wp-json\/wp\/v2\/categories?post=677"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/salzlechner.com\/dev\/wp-json\/wp\/v2\/tags?post=677"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}