Skip to content

Commit 9a1aa9b

Browse files
committed
Adds multiple languages support to build
1 parent 2a9c16a commit 9a1aa9b

File tree

5 files changed

+139
-38
lines changed

5 files changed

+139
-38
lines changed

lib/api.js

+20
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ BT.COMBINE_FWS_WRAPPER = "combineWrapperFrameworks", // combine only wrapper fra
1212
BT.COMBINE_FWS_APPSUPP_SPROUTCORE = "combineAppSproutCore", // combine sproutcore in one, the app and the rest in another
1313
BT.COMBINE_FWS_NONE = "combineNone"; // no combining on app level
1414

15+
BT.LANGUAGE_MAP = {
16+
en: ['english', 'en_US'],
17+
fr: ['french', 'fr_FR'],
18+
de: ['german', 'de_DE'],
19+
ja: ['japanese', 'ja_JA'],
20+
es: ['spanish', 'es_ES'],
21+
it: ['italian', 'it_IT']
22+
};
23+
1524
// very useful as
1625
BT.path2Url = function (path) {
1726
if (BT.PLATFORM === BT.P_WIN32) {
@@ -99,3 +108,14 @@ BT.mkdir = function (dir, baseDir) {
99108
});
100109
return wdir;
101110
};
111+
112+
BT.languageFor = function (lang) {
113+
if (BT.LANGUAGE_MAP[lang]) return lang;
114+
else {
115+
for (var l in BT.LANGUAGE_MAP) {
116+
var langs = BT.LANGUAGE_MAP[l];
117+
if (langs.contains(lang)) return l;
118+
}
119+
}
120+
throw new Error("Could not find the language for '" + lang + "'.");
121+
};

lib/appbuilder.js

+18-3
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ BT.AppBuilder = SC.Object.extend({
5050
framework: this._appfw, // bring it under the apps fw control
5151
relpath: BT.path2Url(combinedName),
5252
});
53-
}.property('combineFrameworks').cacheable(),
53+
}.property(),
5454

5555
combineWrapperFrameworks: function (fileType) {
5656
var files = [];
@@ -81,7 +81,7 @@ BT.AppBuilder = SC.Object.extend({
8181
}
8282
});
8383
return files.flatten().filterProperty('content');
84-
}.property('combineFrameworks').cacheable(),
84+
}.property(),
8585

8686
combineAppSproutCore: function (fileType) { // combine sproutcore in one, the app and the rest in another
8787
var k = fileType === "scripts" ? BT.ScriptFile: BT.CSSFile;
@@ -108,7 +108,7 @@ BT.AppBuilder = SC.Object.extend({
108108
});
109109

110110
return [sc, app];
111-
}.property('combineFrameworks').cacheable(),
111+
}.property(),
112112

113113
/**
114114
Set it to true to automatically generate a cache manifest file.
@@ -149,6 +149,16 @@ BT.AppBuilder = SC.Object.extend({
149149
return this.get('name');
150150
}.property(), // the title of the app
151151

152+
/**
153+
Languages to add to the build. If null, the build tool will look
154+
for lproj folders and add every languages found.
155+
156+
@property
157+
@type Array
158+
@default null
159+
*/
160+
languages: null,
161+
152162
language: 'en', // by default en?
153163

154164
favicon: '', // favicon
@@ -231,6 +241,9 @@ BT.AppBuilder = SC.Object.extend({
231241

232242
bootstrap: function () {
233243
var ret = [];
244+
245+
ret.push('<script>String.preferredLanguage="' + this.get('language') + '";</script>');
246+
234247
this._bootstrap.get('scripts').forEach(function (f) {
235248
if (f.get('path').indexOf('system') > -1) {
236249
// prepend bootstrap/system/bench, browser and loader
@@ -241,6 +254,7 @@ BT.AppBuilder = SC.Object.extend({
241254
// scripts.push([f]); // in array for the moment, because of flatten issues...
242255
// }
243256
});
257+
244258
return ret.join("\n");
245259
}.property(),
246260

@@ -458,6 +472,7 @@ BT.AppBuilder = SC.Object.extend({
458472

459473
buildFiles: function () {
460474
var ret = [];
475+
461476
ret.pushObjects(this.get('scripts'))
462477
.pushObjects(this.get('stylesheets'))
463478
.pushObjects(this.get('moduleScripts'))

lib/file.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ BT.File = SC.Object.extend({
2525

2626
framework: null,
2727

28+
language: 'any',
29+
2830
urlTemplate: function () {
2931
if (BT.runMode === BT.RM_DEBUG) {
3032
return "/%{appName}/%{frameworkName}/%{relativePath}";
@@ -46,7 +48,7 @@ BT.File = SC.Object.extend({
4648
// this.getPath('framework.fullname')));
4749
//var ret = pathlib.join(this.getPath('framework.fullname'), relp);
4850
return BT.path2Url(relp);
49-
}.property('path', 'framework', 'urlPrefix').cacheable(),
51+
}.property('path', 'framework').cacheable(),
5052

5153
// pending the PR request https://github.com/sproutcore/sproutcore/pull/1240 this stays the
5254
// way it is...
@@ -66,7 +68,7 @@ BT.File = SC.Object.extend({
6668
basename: this.get('basename')
6769
};
6870
return urlTemplate.fmt(opts);
69-
}.property('relativePath', 'path', 'urlPrefix').cacheable(),
71+
}.property('relativePath').cacheable(),
7072

7173
extension: null,
7274

lib/framework.js

+57-24
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ BT.Framework = SC.Object.extend({
3131
if (BT.runMode === BT.RM_DEBUG) return true;
3232
else return false;
3333
}.property(),
34-
watchFiles: true,
35-
defaultLanguage: 'english',
34+
watchFiles: function () {
35+
if (BT.runMode === BT.RM_DEBUG) return true;
36+
else return false;
37+
}.property(),
3638
createSprite: false,
3739
scriptExtensions: function () {
3840
return BT.projectManager.get('scriptExtensions');
@@ -125,6 +127,8 @@ BT.Framework = SC.Object.extend({
125127
this.scanFiles({
126128
skipDirs: ['apps']
127129
});
130+
var belongsTo = this.belongsTo;
131+
if (belongsTo) belongsTo.addObserver('language', this, 'setFilesForLanguage');
128132
if (BT.runBenchmarks) SC.Benchmark.end('framework:scanFiles');
129133
},
130134

@@ -166,14 +170,18 @@ BT.Framework = SC.Object.extend({
166170
}.property(),
167171

168172
scanFiles: function (opts) {
169-
var pathlib = require('path');
170-
var fslib = require('fs');
171-
var files = [];
172-
var me = this;
173+
var pathlib = require('path'),
174+
fslib = require('fs'),
175+
files = [],
176+
me = this,
177+
app = this.get('belongsTo'),
178+
language = app ? app.get('language') : null,
179+
languages = SC.Set.create(),
180+
181+
// get all registered extensions first
182+
exts = BT.projectManager.get('extensions'),
183+
skipDirs = opts.skipDirs || [];
173184

174-
// get all registered extensions first
175-
var exts = BT.projectManager.get('extensions');
176-
var skipDirs = opts.skipDirs || [];
177185
if (!this.get('includeFixtures')) skipDirs.push('fixtures');
178186
if (!this.includeTests) skipDirs.push('tests');
179187

@@ -184,34 +192,49 @@ BT.Framework = SC.Object.extend({
184192
files.push(BT.ModuleScriptFile.create({ path: modulePath, framework: me, }));
185193
}
186194

187-
var scanDir = function (dir) {
195+
var scanDir = function (dir, language) {
196+
if (language === 'es') console.log(dir);
188197
var ret = [];
189198
var fileList = fslib.readdirSync(dir);
190199
fileList.forEach(function (fn) {
191200
var p = pathlib.join(dir, fn);
192201
var ext = pathlib.extname(p);
193202
ext = (ext[0] === ".") ? ext.slice(1) : ext;
194203
var stat = fslib.statSync(p);
195-
if (stat.isFile() && exts.contains(ext)) {
196-
var k = BT.projectManager.fileClassFor(ext);
197-
var f = k.create({ path: p,
198-
framework: me,
199-
//watchForChanges: this.watchFiles, // this works differently now
200-
});
201-
files.push(f);
204+
if (stat.isFile()) {
205+
if (exts.contains(ext)) {
206+
var k = BT.projectManager.fileClassFor(ext);
207+
var f = k.create({ path: p,
208+
framework: me,
209+
language: language || 'any'
210+
//watchForChanges: this.get('watchFiles'), // this works differently now
211+
});
212+
files.push(f);
213+
}
202214
}
203-
else if (stat.isDirectory() && !skipDirs.contains(fn)) {
204-
allDirs.push(p); // store full path for dir, for watchers
205-
//ret = ret.concat(scanDir(p));
206-
scanDir(p);
215+
else if (stat.isDirectory()) {
216+
if (!skipDirs.contains(fn)) {
217+
allDirs.push(p); // store full path for dir, for watchers
218+
//ret = ret.concat(scanDir(p));
219+
if (fn.slice(fn.length-6, fn.length) === '.lproj') {
220+
language = BT.languageFor(fn.slice(0, fn.length-6));
221+
languages.add(language);
222+
}
223+
scanDir(p, language);
224+
}
207225
}
226+
language = null;
208227
});
209228
return ret;
210229
};
211230

231+
// set the languages to build for this app only if they are not preset
232+
if (app && !app.get('languages')) app.set('languages', languages);
233+
212234
//var found = scanDir(this.get('path'));
213235
scanDir(this.get('path'));
214-
this.files.set('content', files);
236+
this.allFiles = files;
237+
this.setFilesForLanguage();
215238
// now we set the rawContent of all the files. If we do it earlier
216239
// we get into trouble with slicing. so we start with resources on purpose
217240
// as slicing will need access to the content during css parsing
@@ -227,7 +250,7 @@ BT.Framework = SC.Object.extend({
227250
});
228251

229252
// find folders and add watchers
230-
if (this.watchFiles) {
253+
if (this.get('watchFiles')) {
231254
var os = require('os');
232255
if (os.platform() === "darwin") {
233256
var sysver = os.release().split(".");
@@ -245,6 +268,16 @@ BT.Framework = SC.Object.extend({
245268

246269
},
247270

271+
setFilesForLanguage: function () {
272+
var language = this.getPath('belongsTo.language'),
273+
locFiles = this.allFiles.filter(function (f) {
274+
var l = f.get('language');
275+
return l === 'any' || l === language;
276+
});
277+
this.files.set('content', locFiles);
278+
//this._scripts.notifyPropertyChange('content');
279+
},
280+
248281
setupDirectoryWatchers: function (alldirs) {
249282
// The system of directory watchers is going to be difficult
250283
// it seems there is only one event (on osx?), which is "rename", and doesn't provide any extra information
@@ -474,7 +507,7 @@ BT.Framework = SC.Object.extend({
474507
if (k) { // only create when the file class is known.
475508
if (!this.getPath('files.filenames')[filename]) {
476509
SC.Logger.log("creating new file...");
477-
var f = k.create({ path: filename, framework: this, watchForChanges: this.watchFiles });
510+
var f = k.create({ path: filename, framework: this, watchForChanges: this.get('watchFiles') });
478511
this.get('files').pushObject(f);
479512
f.fileDidChange(); // trigger initial loading of content
480513
SC.Logger.log("should be in files now...");

lib/project.js

+40-9
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,6 @@ BT.projectManager = SC.Object.create({
125125
_buildOpts: null,
126126

127127
_startBuild: function () {
128-
129-
130128
// will save all apps, unless the app specifically indicates not wanting to be saved.
131129
// The main issue with saving is that there will need to be a few ways in which you'd want
132130
// to build, and in special cases even be able to provide your own build specification and / or procedure
@@ -144,6 +142,7 @@ BT.projectManager = SC.Object.create({
144142
else {
145143
apps = Object.keys(this.apps).map(function (appname) { return this.apps[appname]; }, this);
146144
}
145+
this.appsToBuild = apps;
147146

148147
//whatever happens, we should only start after everything is in, so we check the files of the apps
149148
//and if not all files have a rawContent somehow, we are not going to build
@@ -154,9 +153,40 @@ BT.projectManager = SC.Object.create({
154153
return;
155154
}
156155

156+
var allResources = [];
157+
apps.getEach('files').flatten().forEach(function (f) {
158+
allResources.push(f);
159+
});
160+
this.allResources = allResources;
161+
157162
SC.Logger.log("Building apps " + apps.getEach('name'));
158163

159-
var files = [];
164+
this.buildLanguages = SC.Set.create();
165+
apps.forEach(function (app) {
166+
this.buildLanguages.addEach(app.get('languages'));
167+
}, this);
168+
169+
this._startBuildLanguage();
170+
},
171+
172+
_startBuildLanguage: function () {
173+
var language = this.buildLanguages.pop();
174+
if (!language) return this._endBuild();
175+
176+
this.appsToBuild.forEach(function (app) {
177+
if (app.get('languages').contains(language)) {
178+
app.set('language', language);
179+
}
180+
});
181+
182+
this.invokeNext('_doBuildLanguage');
183+
},
184+
185+
_doBuildLanguage: function () {
186+
var apps = this.appsToBuild,
187+
files = [],
188+
allResources = this.allResources;
189+
160190
apps.forEach(function (app) {
161191
files.push(BT.File.create({
162192
framework: app._appfw,
@@ -174,12 +204,8 @@ BT.projectManager = SC.Object.create({
174204
});
175205

176206
apps.getEach('buildFiles').flatten().forEach(function (f) {
177-
files.push(f);
178-
});
179-
180-
var allResources = [];
181-
apps.getEach('files').flatten().forEach(function (f) {
182-
allResources.push(f);
207+
var fLang = f.get('language');
208+
if (fLang === 'any' || fLang === language) files.push(f);
183209
});
184210

185211
SC.Logger.log("Calculating file contents");
@@ -226,6 +252,11 @@ BT.projectManager = SC.Object.create({
226252
SC.Logger.log("saved file %@ of %@".fmt(i, files.length));
227253
//SC.Logger.log("File %@ written to %@".fmt(file.get('url'), p));
228254
}, this);
255+
256+
this._startBuildLanguage();
257+
},
258+
259+
_endBuild: function () {
229260
SC.Logger.log("done...");
230261
// throw new Error("QUIT"); // seems
231262
if (BT.runBenchmarks) {

0 commit comments

Comments
 (0)