Skip to content

Commit c54293f

Browse files
committed
add i18n plugin
1 parent 467e8a8 commit c54293f

File tree

6 files changed

+151
-2
lines changed

6 files changed

+151
-2
lines changed

Gruntfile.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ module.exports = function (grunt) {
77
jshint: {
88
all: [
99
"Gruntfile.js",
10-
"plugins/*.js"
10+
"plugins/**/*.js"
1111
],
1212
options: {
1313
jshintrc: ".jshintrc",
1414
},
1515
},
1616

1717
jsbeautifier: {
18-
files: ["Gruntfile.js", "plugins/*.js"],
18+
files: ["Gruntfile.js", "plugins/**/*.js"],
1919
options: {
2020
config: ".jshintrc",
2121
js: {

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
This plugin purpose is to load a file if it exists, while not blocking the loader if it does not. If the module was not found, it will be falsy.
88
This plugin should work with RequireJS and Dojo.
99

10+
## i18n.js
11+
12+
This plugin is based on requirejs i18n.
13+
* see: http://github.com/requirejs/i18n for details
14+
1015
## Licensing
1116

1217
This project is distributed by the Dojo Foundation and licensed under the ["New" BSD License](https://github.com/dojo/dojo/blob/master/LICENSE#L13-L41).

plugins/i18n.js

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/**
2+
* Plugin based on requirejs i18n
3+
* see: http://github.com/requirejs/i18n for details
4+
*/
5+
(function () {
6+
'use strict';
7+
8+
//regexp for reconstructing the master bundle name from parts of the regexp match
9+
//nlsRegExp.exec("foo/bar/baz/nls/en-ca/foo") gives:
10+
//["foo/bar/baz/nls/en-ca/foo", "foo/bar/baz/nls/", "/", "/", "en-ca", "foo"]
11+
//nlsRegExp.exec("foo/bar/baz/nls/foo") gives:
12+
//["foo/bar/baz/nls/foo", "foo/bar/baz/nls/", "/", "/", "foo", ""]
13+
//so, if match[5] is blank, it means this is the top bundle definition.
14+
var nlsRegExp = /(^.*(^|\/)nls(\/|$))([^\/]*)\/?([^\/]*)/;
15+
16+
/**
17+
* Simple function to mix in properties from source into target,
18+
* but only if target does not already have a property of the same name.
19+
* This is not robust in IE for transferring methods that match
20+
* Object.prototype names, but the uses of mixin here seem unlikely to
21+
* trigger a problem related to that.
22+
*/
23+
function mixin(target, source, force) {
24+
var prop;
25+
for (prop in source) {
26+
if (source.hasOwnProperty(prop) && (!target.hasOwnProperty(prop) || force)) {
27+
target[prop] = source[prop];
28+
} else if (typeof source[prop] === 'object') {
29+
if (!target[prop] && source[prop]) {
30+
target[prop] = {};
31+
}
32+
mixin(target[prop], source[prop], force);
33+
}
34+
}
35+
}
36+
37+
define(['./i18n/common' /*, './i18n/preload!myapp/nls/src*["fr","ROOT"]'*/ ], function (common) {
38+
39+
return {
40+
load: function (name, req, onLoad, config) {
41+
config = config || {};
42+
43+
var masterName,
44+
match = nlsRegExp.exec(name),
45+
prefix = match[1],
46+
locale = match[4],
47+
suffix = match[5];
48+
49+
//If match[5] is blank, it means this is the top bundle definition,
50+
//so it does not have to be handled. Locale-specific requests
51+
//will have a match[4] value but no match[5]
52+
if (match[5]) {
53+
//locale-specific bundle
54+
prefix = match[1];
55+
masterName = prefix + suffix;
56+
} else {
57+
//Top-level bundle.
58+
masterName = name;
59+
suffix = match[4];
60+
locale = common.getLocale(config);
61+
}
62+
63+
//First, fetch the master bundle, it knows what locales are available.
64+
req([masterName], function (master) {
65+
var getBundleAndMixin = function (prefix, suffix, locale, value) {
66+
var mixBundle = function (bundle) {
67+
mixin(value, bundle);
68+
locale = common.getParentLocale(locale);
69+
if (!bundle._flattened && locale) {
70+
getBundleAndMixin(prefix, suffix, locale, value);
71+
} else {
72+
value._flattened = true;
73+
onLoad(value);
74+
return;
75+
}
76+
};
77+
if (master[locale] === true || master[locale] === 1) {
78+
req([prefix + locale + '/' + suffix], mixBundle);
79+
} else {
80+
// root is on the master bundle or locale is unexisting
81+
mixBundle(master[locale] || {});
82+
}
83+
};
84+
85+
getBundleAndMixin(prefix, suffix, locale, {});
86+
});
87+
}
88+
};
89+
});
90+
}());

plugins/i18n/common.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
define(["../maybe!./parentLocales"], function (parentLocales) {
2+
parentLocales = parentLocales || {};
3+
4+
return {
5+
getLocale: function (config) {
6+
var locale = config.locale;
7+
if (!locale) {
8+
locale = typeof navigator === "undefined" ? "root" :
9+
(navigator.language ||
10+
navigator.userLanguage || "root");
11+
}
12+
// just to be extra-sure
13+
return locale.toLowerCase();
14+
},
15+
16+
getParentLocale: function (loc) {
17+
if (!loc || loc === "root") {
18+
return undefined;
19+
}
20+
if (parentLocales[loc]) {
21+
return parentLocales[loc];
22+
}
23+
24+
var parts = loc.split("-");
25+
parts.pop();
26+
return (parts.length > 0) ? parts.join("-") : "root";
27+
}
28+
};
29+
});

plugins/i18n/parentLocales.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
define({
2+
"en": "es"
3+
});

plugins/i18n/preload.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
define(["./common"], function (common) {
2+
return {
3+
load: function (name, req, onLoad, config) {
4+
config = config || {};
5+
6+
var locale = common.getLocale(config),
7+
parts = name.split("*"),
8+
flattenedLocales = JSON.parse(parts[1]);
9+
10+
name = parts[0];
11+
while (locale) {
12+
if (flattenedLocales.indexOf(locale) >= 0) {
13+
require([name + "_" + locale], function (bundle) {
14+
onLoad(bundle);
15+
return;
16+
});
17+
}
18+
locale = common.getParentLocale(locale);
19+
}
20+
}
21+
};
22+
});

0 commit comments

Comments
 (0)