Skip to content

Instantly share code, notes, and snippets.

@littlelazer
Forked from dryan/demo.html
Created April 24, 2012 17:14
Show Gist options
  • Save littlelazer/2481611 to your computer and use it in GitHub Desktop.
Save littlelazer/2481611 to your computer and use it in GitHub Desktop.
Utility function for translatable strings in JavaScript. See demo.html for usage examples.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Translation Demo</title>
<meta charset="utf-8">
</head>
<body>
<p id="hello"></p>
<h1>Usage</h1>
<p>Create an object called <code>translations</code> attached to the <code>window</code> object. That object should have a key for each language you want to support that points to an object containing key/value pairs for all of your strings.</p>
<p>The language to use is determined first by the <code>lang</code> parameter of the <code>&lt;html&gt;</code> element then the <code>navigator.language</code> property. A fallback language can be specified by setting a <code>fallbackLang</code> variable on the <code>window</code> object.</p>
<p>The function is called via <code>translate(key)</code>; additionally, if no variable named <code>_</code> is found on the window object, you may use <code>_(key)</code> as a shortcut.</p>
<script charset="utf-8">
(function(a,b,c){var d="undefined",e='"{{ key }}" is not defined for language "{{ lang }}"',f="{{ key }}",g="{{ lang }}",h="",i="-",j=(b.getElementsByTagName("html")[0].getAttribute("lang")||c.language||h).toLowerCase(),k="en",l=a.console||{warn:function(a){}},m={},n=function(b){m=a.translations||m;if(typeof n.lang===d){k=a.fallbackLang||k;n.lang=typeof m[j]!==d?j:typeof m[j.split(i).pop(0)]!==d?j.split(i).pop(0):k}if(typeof m[n.lang]===d){n=function(a){l.warn("window.translations is not properly set up.");return h};return n(b)}if(typeof m[n.lang][b]!==d)return m[n.lang][b];l.warn(e.replace(f,b).replace(g,n.lang));return h};typeof a._===d&&(a._=n);a.translate=n})(window,document,navigator);
var
hello = document.getElementById('hello'),
translations = translations || { // make sure we don't overwrite translations provided by other scripts
'en': {
},
'es': {
}
};
if(typeof translations.en === "undefined") {
translations.en = {};
}
if(typeof translations.es === "undefined") {
translations.es = {};
}
translations.en.hello = "Hello!";
translations.es.hello = "¡Hola!";
hello.innerHTML = translate('hello');
</script>
</body>
</html>
(function(win, doc, nav) {
var
UNDEFINED = "undefined",
WARNING = "\"{{ key }}\" is not defined for language \"{{ lang }}\"",
KEY = "{{ key }}",
LANG = "{{ lang }}",
EMPTY = "",
HYPHEN = "-",
lang = ( doc.getElementsByTagName('html')[0].getAttribute('lang') || nav.language || EMPTY ).toLowerCase(),
fallbackLang = "en",
console = win.console || {"warn": function(message) {}},
translations = {},
_ = function(key) {
translations = win.translations || translations; // grab the translations object if it is set, otherwise fall back to an empty object
if(typeof _.lang === UNDEFINED) {
fallbackLang = win.fallbackLang || fallbackLang; // grab the fallbackLang variable if its been set, otherwise fallback to English
_.lang = ( typeof translations[lang] !== UNDEFINED ? lang : (typeof translations[lang.split(HYPHEN).pop(0)] !== UNDEFINED ? lang.split(HYPHEN).pop(0) : fallbackLang ) ); // first try the language key directly, then try the language key's root language ('en' for 'en-US'), then the fallbackLang setting
}
if(typeof translations[_.lang] === UNDEFINED) { // if the translations object does not have strings for the language, replace this function with a console.warn statement
_ = function(key) {
console.warn("window.translations is not properly set up.");
return EMPTY;
};
return _(key);
}
if(typeof translations[_.lang][key] !== UNDEFINED) { // if the key exists, return it
return translations[_.lang][key];
} else { // if the key does not exist, send a console.warn and return an empty string
console.warn(WARNING.replace(KEY, key).replace(LANG, _.lang));
return EMPTY;
}
};
if(typeof win._ === UNDEFINED) { // make sure we don't overwrite underscore.js with our shortcut
win._ = _; // make the function available outside of the anonymous function by attaching it to the window
}
win.translate = _; // make the function available outside of the anonymous function by attaching it to the window
})(window, document, navigator);
(function(a,b,c){var d="undefined",e='"{{ key }}" is not defined for language "{{ lang }}"',f="{{ key }}",g="{{ lang }}",h="",i="-",j=(b.getElementsByTagName("html")[0].getAttribute("lang")||c.language||h).toLowerCase(),k="en",l=a.console||{warn:function(a){}},m={},n=function(b){m=a.translations||m;if(typeof n.lang===d){k=a.fallbackLang||k;n.lang=typeof m[j]!==d?j:typeof m[j.split(i).pop(0)]!==d?j.split(i).pop(0):k}if(typeof m[n.lang]===d){n=function(a){l.warn("window.translations is not properly set up.");return h};return n(b)}if(typeof m[n.lang][b]!==d)return m[n.lang][b];l.warn(e.replace(f,b).replace(g,n.lang));return h};typeof a._===d&&(a._=n);a.translate=n})(window,document,navigator);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment