Last active
December 20, 2015 01:49
-
-
Save kaneel/6052331 to your computer and use it in GitHub Desktop.
Simple i18n requireJS module for your simple architectures™
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| You "should" define dict in requireJS path config so you're able, at load, to get the | |
| right lang from wherever you want (lang attribute on <html> tag for example?) | |
| Also, you'll need both text and json plugins for requires. | |
| var config = { | |
| paths: { | |
| dict: "ur/path/to/dictionnary", | |
| i18n: "ur/path/to/i18n" | |
| text: "ur/path/to/plugins/text", | |
| json: "ur/path/to/plugins/json" | |
| } | |
| }); | |
| */ | |
| // usage | |
| define["i18n"], function(i18n) { | |
| /* | |
| i18n has been made for using the same dictionnary that is used by the backend. | |
| Hence, we have some strings containing variables (declared with $1, $2) so we | |
| can generate the strings passing values (as numbers). | |
| Calling i18n will return either a variable or a function. | |
| The function has a toString method that will simply return the translated string at his | |
| actual state (idea from Stefan Grinsted, hi there :) | |
| Let say that "that/stuff/inside/json" => "$1 and $2" | |
| */ | |
| var test = i18n("that/stuff/inside/json"); // "$1 and $2" | |
| test([10,12]); // "10 and 12" | |
| // the i18n method has been curried so... | |
| test = i18n("that/stuff/inside/json", 10); // "10 and $2" | |
| test(12); // "10 and 12" | |
| // Or | |
| test = i18n("that/stuff/inside/json", [null, 12]); // "$1 and 12" | |
| test(10); // "10 and 12" | |
| // Or, just because all the things you can see up there are not so useful | |
| i18n("that/stuff/inside/json", [10, 12]); // "10 and 12" | |
| }) | |
| // The module in itself, depends on your dictionnary. | |
| define(["json!dict"], function(dict) { | |
| var regexp = /\$\d/g; // regexp for search $ variables in a string | |
| /* | |
| Function for currying the translating method | |
| Will take: | |
| match => Array for matched elements | |
| replaced => String (that may have already been modified) | |
| Will return: | |
| Returns of the execution of replacer. (l.48) | |
| */ | |
| function curry(match, replaced) { | |
| function stringer(/* arguments */) { | |
| var replacing = arguments, | |
| toReplace = replaced; | |
| if (replacing.length == 1 && replacing[0] instanceof Array) { | |
| replacing = replacing[0]; | |
| } | |
| return replacer(toReplace, replacing, match); | |
| } | |
| stringer.toString = function() { | |
| return replaced; | |
| } | |
| return stringer; | |
| } | |
| /* | |
| Replacing function. | |
| Will loop on match (Array) and | |
| Takes: | |
| toReplace: Array | |
| replacing: Array | |
| match: Array | |
| Return: | |
| Function if there's still some variables to replace | |
| String if there's no more variables to replace | |
| */ | |
| function replacer(toReplace, replacing, match) { | |
| var toRemove = []; | |
| // loop on matches | |
| for (var i = 0, max = match.length; i < max; i++) { | |
| // if there's a replacement for it | |
| if(replacing[i]) { | |
| // replace | |
| toReplace = toReplace.replace(match[i], replacing[i]); | |
| // push to array for later removal | |
| toRemove.push(i); | |
| } | |
| } | |
| // remove used matches | |
| for (var i = 0, max = toRemove.length; i < max; i++) { | |
| match.splice(toRemove[i], 1); | |
| } | |
| // if there's still matches | |
| if (match.length) { | |
| return curry(match, toReplace); | |
| } else { | |
| return toReplace; | |
| } | |
| } | |
| /* | |
| Main method. | |
| Takes: | |
| string: A string to translate | |
| replacing: Array/String/Number for replacing $ variables. | |
| Return: | |
| If no need for "replacing", a String. | |
| If all replacing arguments given, a String. | |
| If partial arguments, a Function. | |
| */ | |
| function translate(string, replacing) { | |
| var words = string.split("/"), | |
| seq = dict, | |
| replaced = "", | |
| match = ""; | |
| // loop on splitted sequence | |
| for (var i = 0, max = words.length; i < max; i++) { | |
| // if not a string, go deeper | |
| if (seq[words[i]] && typeof seq[words[i]] != "string") { | |
| seq = dict[words[i]]; | |
| } | |
| // if string, translate! | |
| if (typeof seq[words[i]] == "string") { | |
| replaced = seq[words[i]]; | |
| match = replaced.match(regexp); | |
| // check if there's matches for variables | |
| if (match) { | |
| // if replacing array/number/string provided | |
| if (replacing) { | |
| // this will format a string or a number into an array. | |
| // not perf savy but avoid condition-hell for dealing with many possible inputs | |
| if(typeof replacing == "string" || typeof replacing == "number") { | |
| replacing = [].concat(replacing); | |
| } | |
| // return what replace returns | |
| // it's either a String or a Function | |
| return replacer(replaced, replacing, match) | |
| } else if (!replacing) { | |
| // instantly return a curry | |
| return curry(match, seq[words[i]]); | |
| } | |
| } | |
| // not matches, simple translation | |
| return seq[words[i]]; | |
| } | |
| } | |
| return words[words.length - 1] | |
| } | |
| return translate | |
| }) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment