1 | var fs = require("fs");
|
2 | var path = require("path");
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | function regExpText(text) {
|
8 | return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
9 | }
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 | function findFilesCommon(folder, filePostfix, callback, readdir, stat) {
|
20 |
|
21 | var regExp = new RegExp("^(?:(.+)\\.)"+regExpText(filePostfix)+"$")
|
22 |
|
23 | readdir(folder, function(err, files) {
|
24 | if(err) return callback(err);
|
25 |
|
26 |
|
27 |
|
28 | var result = [];
|
29 | var errors = [];
|
30 | var count = files.length;
|
31 | files.forEach(function(file) {
|
32 | stat(path.join(folder, file), function(err, stat) {
|
33 | if(err || !stat) return endOne(err);
|
34 | if(stat.isDirectory()) {
|
35 | endOne();
|
36 | } else {
|
37 | if(regExp.test(file)) {
|
38 | var match = regExp.exec(file);
|
39 | var name = match[1];
|
40 | result.push(name);
|
41 | }
|
42 | endOne();
|
43 | }
|
44 | });
|
45 | });
|
46 | function endOne(err) {
|
47 | if(err) errors.push(err);
|
48 | count--;
|
49 | if(count == 0) {
|
50 | if(errors.length > 0)
|
51 | callback(new Error("cannot find files: " + errors.join("\n")));
|
52 | else
|
53 | callback(null, result);
|
54 | }
|
55 | }
|
56 | });
|
57 | }
|
58 |
|
59 |
|
60 | function findFiles(folder, filePostfix, callback) {
|
61 | findFilesCommon(folder, filePostfix, callback, fs.readdir, fs.stat);
|
62 | }
|
63 |
|
64 |
|
65 | function findFilesSync(folder, filePostfix, callback) {
|
66 | findFilesCommon(folder, filePostfix, callback, function(folder, cb) {
|
67 | try {
|
68 | cb(null, fs.readdirSync(folder));
|
69 | } catch(e) { cb(e); }
|
70 | }, function(path, cb) {
|
71 | try {
|
72 | cb(null, fs.statSync(path));
|
73 | } catch(e) { cb(e); }
|
74 | });
|
75 | }
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 | module.exports = function(rootLoader, localeLoader, requireAsync, chuckPrefix) {
|
86 | chuckPrefix = chuckPrefix || "i18n";
|
87 | var loader = function(content) {
|
88 |
|
89 | var loaderSign = this.request.indexOf("!");
|
90 | var remReq = this.request.substr(loaderSign);
|
91 | var fileMatch = /^(.*!)([^!]+?)$/.exec(remReq);
|
92 | remReq = fileMatch[1];
|
93 | var file = fileMatch[2];
|
94 | var filedir = path.dirname(file);
|
95 | var filebase = path.basename(file);
|
96 | var cb = this.async();
|
97 |
|
98 | var configuredLocales = this.options && this.options.i18n && this.options.i18n.locales;
|
99 |
|
100 | var dontBundleTogether = this.options && this.options.i18n && (this.options.i18n.bundleTogether === false);
|
101 | var sync = !cb;
|
102 | cb = cb || this.callback;
|
103 | (sync ? findFilesSync : findFiles)
|
104 | (filedir, filebase, function(err, files) {
|
105 | if(err) return cb(err);
|
106 | var buf = [];
|
107 |
|
108 | if(requireAsync) {
|
109 | buf.push("var cbs = [];\n");
|
110 | buf.push("exports = module.exports = function(cb) {\n");
|
111 | buf.push(" if(cbs) cbs.push(cb);\n");
|
112 | buf.push(" else cb(exports);\n");
|
113 | buf.push("}\n");
|
114 | buf.push("\n");
|
115 | }
|
116 |
|
117 | buf.push("var map = {\n");
|
118 | function addLocale(locale, file) {
|
119 | buf.push(JSON.stringify(locale));
|
120 | buf.push(": function() {\n");
|
121 | requireAsync && buf.push(" require.ensure([], function(require) {\n");
|
122 | buf.push(" use(require(");
|
123 |
|
124 | if(file)
|
125 | buf.push(JSON.stringify(localeLoader + remReq + filedir + "/" + file + "." + filebase));
|
126 | else
|
127 | buf.push(JSON.stringify(rootLoader + remReq + filedir + "/" + filebase));
|
128 | buf.push("));\n");
|
129 | if(requireAsync) {
|
130 | buf.push(" }");
|
131 | if(!dontBundleTogether) {
|
132 | buf.push(", ");
|
133 | buf.push(JSON.stringify(chuckPrefix + (locale ? "-" + locale : "")));
|
134 | }
|
135 | buf.push(");\n");
|
136 | }
|
137 | buf.push("},\n");
|
138 | }
|
139 | addLocale("", "");
|
140 | var locales = files.slice(0);
|
141 | if(configuredLocales) configuredLocales.forEach(function(locale) {
|
142 | if(locales.indexOf(locale) == -1)
|
143 | locales.push(locale);
|
144 | });
|
145 | locales.forEach(function(locale) {
|
146 | file = locale;
|
147 | if(files.indexOf(file) == -1) {
|
148 | file = file.split("-");
|
149 | for(var i = file.length; i >= 0; i--)
|
150 | if(files.indexOf(file.join("-")) != -1) {
|
151 | file = file.join("-");
|
152 | break;
|
153 | }
|
154 | if(i == -1) file = "";
|
155 | }
|
156 | addLocale(locale, file);
|
157 | });
|
158 | buf.push("};\n");
|
159 | buf.push("\n");
|
160 |
|
161 |
|
162 | buf.push("var nav = window.navigator, lang = nav.userLanguage || nav.language;\n");
|
163 | buf.push("lang = lang && lang.split('-') || [];\n");
|
164 | buf.push("(function() {\n");
|
165 | buf.push(" for(var i = lang.length; i >= 0; i--) {\n");
|
166 | buf.push(" var l = lang.slice(0, i).join('-');\n");
|
167 | buf.push(" if(map[l]) return map[l]();\n");
|
168 | buf.push(" }\n");
|
169 | buf.push(" map['']();\n");
|
170 | buf.push("}())\n");
|
171 | buf.push("\n");
|
172 |
|
173 | buf.push("function use(locale) {\n");
|
174 | if(requireAsync) {
|
175 |
|
176 |
|
177 | buf.push(" if(typeof locale === 'function') {\n");
|
178 | buf.push(" exports.call = function() {\n");
|
179 | buf.push(" return locale.call.apply(locale, arguments);\n");
|
180 | buf.push(" }\n");
|
181 | buf.push(" exports.apply = function() {\n");
|
182 | buf.push(" return locale.apply.apply(locale, arguments);\n");
|
183 | buf.push(" }\n");
|
184 | buf.push(" }\n");
|
185 | buf.push(" for(var p in locale) exports[p] = locale[p];\n");
|
186 | buf.push(" var c = cbs; cbs = null;\n");
|
187 | buf.push(" for(var i = 0; i < c.length; i++) c[i](exports);\n");
|
188 | } else {
|
189 |
|
190 | buf.push(" module.exports = locale;\n");
|
191 | }
|
192 | buf.push("}\n");
|
193 | cb(null, buf.join(""));
|
194 | });
|
195 | }
|
196 | loader.seperable = true;
|
197 | return loader;
|
198 | } |
\ | No newline at end of file |