{"id":1487,"date":"2013-03-30T21:17:12","date_gmt":"2013-03-30T21:17:12","guid":{"rendered":"http:\/\/www.sitekickr.com\/blog\/?p=1487"},"modified":"2013-03-30T21:23:57","modified_gmt":"2013-03-30T21:23:57","slug":"global-javascript-translations","status":"publish","type":"post","link":"https:\/\/www.sitekickr.com\/blog\/global-javascript-translations\/","title":{"rendered":"Going global with JavaScript language translations"},"content":{"rendered":"<p>Every computer language out there, including JavaScript, has built-in internationalization capabilities, that is, the ability to translate language in order to produce a multilingual application. Can we say <kbd>translate(&#39;english&#39;, &#39;my multilingual JS app&#39;)<\/kbd>? Not quite. But we have data types at our disposal which make the job a lot easier than it sounds. In it&#39;s most basic form, language translation consists of a <em>mapping<\/em> of one word to another. In JavaScript a mapping is synonymous with an object and it&#39;s properties. Before I explain how to create a complete, albeit basic, language translation object in JavaScript, let&#39;s look at the stats:<\/p>\n<ul>\n<li>27% of the world&#39;s population speaks English. <em>source: Wikipedia<\/em><\/li>\n<li>34% of the world&#39;s population has internet access. <em>source: .internetworldstats.com<\/em><\/li>\n<li>Coincidentally, it also seems that the English speaking internet users also make up 27% of the global internet users. <em>source: internetworldstats.com<\/em><\/li>\n<\/ul>\n<p>For many of us, including myself, this is an alarming figure. It means that <strong>73% of human beings on the internet are baffled when looking at your website or app!<\/strong><\/p>\n<p>Granted, these statistics may not take into account English as a second language and many other &quot;micro-stats&quot;. But, let&#39;s not pick at the accuracy of the statistic, and instead agree that if our website is English-only, it is unusable to very large number of internet users.<\/p>\n<h3>Getting the User&#39;s Language<\/h3>\n<p>To start, we need to be able to determine what the user&#39;s current language is. This information is available to JavaScript via the <em>navigator<\/em> object, but not all browsers implement it the same way.<\/p>\n<p>Internet Explorer makes the browser language available via the <em>navigator.browserLanguage()<\/em> function. Other browsers provide the <em>navigator.language()<\/em> function.<\/p>\n<h3>How is the Language Returned<\/h3>\n<p>We get, in return an <a href=\"http:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes\" target=\"_blank\">ISO 639-1<\/a> formatted language code, along with a country code.<\/p>\n<p>For example, for English language users in the US, the returned value would be: <em>en-US<\/em>.<\/p>\n<h3>How can I test different languages?<\/h3>\n<p><a href=\"http:\/\/www.sitekickr.com\/blog\/wp-content\/uploads\/2013\/03\/chrome-language.png\"><img loading=\"lazy\" align=\"right\" alt=\"chrome language\" border=\"2\" class=\"alignright size-full wp-image-1494\" height=\"396\" src=\"http:\/\/www.sitekickr.com\/blog\/wp-content\/uploads\/2013\/03\/chrome-language.png\" style=\"padding:5px;margin-left: 5px;\" width=\"344\" srcset=\"https:\/\/www.sitekickr.com\/blog\/wp-content\/uploads\/2013\/03\/chrome-language.png 344w, https:\/\/www.sitekickr.com\/blog\/wp-content\/uploads\/2013\/03\/chrome-language-260x300.png 260w\" sizes=\"(max-width: 344px) 100vw, 344px\" \/><\/a>I&#39;ve actually found testing to be easiest within the Chrome browser. You are able to change the value returned by navigator.language simply by updating the browser settings as follows:<\/p>\n<p><kbd>Settings -&gt; Advanced -&gt; Languages -&gt; Language and input settings...<\/kbd><\/p>\n<p>Be sure to click the button labelled &quot;Display Google Chrome in this language&quot; before closing the window.<\/p>\n<h3>I&#39;m not a linguist, how do I translate my text?<\/h3>\n<p>For single words, use <a href=\"http:\/\/translate.google.com\/\" target=\"_blank\">Google Translate<\/a>. For anything more, try a translation service, such as <a href=\"http:\/\/www.onehourtranslation.com\/\" target=\"_blank\">One Hour Translation<\/a>. At time of writing, they are advertising just $.07\/word to translate to given language.<\/p>\n<p>&nbsp;<\/p>\n<h3>The Code<\/h3>\n<p>The most basic language translation object, as stated above, involves mapping a word in one language, to a word in another language. You might refer to it as the <em>key\/value<\/em> method. In the example below, we use English as the base language, that is, the <em>keys<\/em> are English words.<\/p>\n<p>I&#39;ve created a simple translation object for the Spanish language (ISO code: <em>es<\/em>), mapping eight English words to their Spanish equivalent using a simple JavaScript object.<\/p>\n<p>Everything is wrapped nicely inside a lang object, which contains a property to determine the user&#39;s language, the actual word mapping, and a small function to take care of the translation itself.<\/p>\n<p>If a language does not exist in the object, the original word is returned. Similarly, if a language does exist, but a translation isn&#39;t available for the provided word, the original word is returned. This is the expected behavior of a translation function, as we would not want a blank space to be inserted in place of a word which there is no translation for.<\/p>\n<p>And finally, instead of calling lang.translate() each time we need a translation, we &quot;clone&quot; this function under the name _ (underscore). This will allow us to perform translations without &quot;mucking up&quot; the code, i.e.<\/p>\n<p><code>var timeLeft = &#39;5 &#39; + _(&#39;days&#39;);<br \/>\n\t<\/code><\/p>\n<p>&nbsp;<\/p>\n<h3>Okay, okay, the actual code!<\/h3>\n<p><code>lang = {<br \/>\n\t&nbsp;&nbsp;&nbsp; language: (navigator.language || navigator.browserLanguage).split(&#39;-&#39;)[0],<br \/>\n\t&nbsp;&nbsp;&nbsp; translation: {<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &#39;es&#39; : { minute: &#39;minuto&#39;, minutes: &#39;minutos&#39;, second: &#39;segundo&#39;, seconds: &#39;segundos&#39;, <br \/>\n\t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hour: &#39;hora&#39;, hours: &#39;horas&#39;, day: &#39;d&iacute;a&#39;, days: &#39;d&iacute;as&#39; }<br \/>\n\t&nbsp;&nbsp;&nbsp; },&nbsp;&nbsp;&nbsp; <br \/>\n\t&nbsp;&nbsp;&nbsp; translate: function(word, language) {<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (!language) {<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; language = lang.language;<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (typeof lang.translation[language] === &#39;undefined&#39;) {<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return word;<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (typeof lang.translation[language][word] === &#39;undefined&#39;) {<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return word;<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return app.lang.translation[language][word];<br \/>\n\t&nbsp;&nbsp;&nbsp; }<br \/>\n\t}<\/p>\n<p>\t\/\/ create a shorthand function for language translation<br \/>\n\t_ = lang.translate;<\/p>\n<p>\t<\/code><\/p>\n<p>I&#39;ve employed this technique in a very basic <a href=\"http:\/\/www.funsumer.com\/apps\/timer\/\" target=\"_blank\">timer application<\/a> I created a long time ago, but just recently decided to make it global.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Every computer language out there, including JavaScript, has built-in internationalization capabilities, that is, the ability to translate language in order to produce a multilingual application.<\/p>\n","protected":false},"author":1,"featured_media":1497,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"amp_status":""},"categories":[238,5],"tags":[247],"_links":{"self":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/1487"}],"collection":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/comments?post=1487"}],"version-history":[{"count":12,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/1487\/revisions"}],"predecessor-version":[{"id":1500,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/1487\/revisions\/1500"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/media\/1497"}],"wp:attachment":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/media?parent=1487"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/categories?post=1487"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/tags?post=1487"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}