diff --git a/core/js/js.js b/core/js/js.js index 39e382b544..eb2f10b51f 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -252,6 +252,17 @@ var OC={ } }, + /** + * Loads translations for the given app asynchronously. + * + * @param {String} app app name + * @param {Function} callback callback to call after loading + * @return {Promise} + */ + addTranslations: function(app, callback) { + return OC.L10N.load(app, callback); + }, + /** * Returns the base name of the given path. * For example for "/abc/somefile.txt" it will return "somefile.txt" @@ -475,6 +486,15 @@ var OC={ return window.matchMedia(media); } return false; + }, + + /** + * Returns the user's locale + * + * @return {String} locale string + */ + getLocale: function() { + return $('html').prop('lang'); } }; @@ -869,9 +889,9 @@ function object(o) { function initCore() { /** - * Set users local to moment.js as soon as possible + * Set users locale to moment.js as soon as possible */ - moment.locale($('html').prop('lang')); + moment.locale(OC.getLocale()); /** diff --git a/core/js/l10n.js b/core/js/l10n.js index e375b7eca8..0c66058432 100644 --- a/core/js/l10n.js +++ b/core/js/l10n.js @@ -26,6 +26,38 @@ OC.L10N = { */ _pluralFunctions: {}, + /** + * Load an app's translation bundle if not loaded already. + * + * @param {String} appName name of the app + * @param {Function} callback callback to be called when + * the translations are loaded + * @return {Promise} promise + */ + load: function(appName, callback) { + // already available ? + if (this._bundles[appName] || OC.getLocale() === 'en') { + var deferred = $.Deferred(); + var promise = deferred.promise(); + promise.then(callback); + deferred.resolve(); + return promise; + } + + var self = this; + var url = OC.filePath(appName, 'l10n', OC.getLocale() + '.json'); + + // load JSON translation bundle per AJAX + return $.get(url) + .then( + function(result) { + if (result.translations) { + self.register(appName, result.translations, result.pluralForm); + } + }) + .then(callback); + }, + /** * Register an app's translation bundle. * diff --git a/core/js/tests/specs/l10nSpec.js b/core/js/tests/specs/l10nSpec.js index d5b0363ea3..cf7c8b11b1 100644 --- a/core/js/tests/specs/l10nSpec.js +++ b/core/js/tests/specs/l10nSpec.js @@ -11,8 +11,12 @@ describe('OC.L10N tests', function() { var TEST_APP = 'jsunittestapp'; + beforeEach(function() { + OC.appswebroots[TEST_APP] = OC.webroot + '/apps3/jsunittestapp'; + }); afterEach(function() { delete OC.L10N._bundles[TEST_APP]; + delete OC.appswebroots[TEST_APP]; }); describe('text translation', function() { @@ -98,4 +102,52 @@ describe('OC.L10N tests', function() { checkPlurals(); }); }); + describe('async loading of translations', function() { + it('loads bundle for given app and calls callback', function() { + var localeStub = sinon.stub(OC, 'getLocale').returns('zh_CN'); + var callbackStub = sinon.stub(); + var promiseStub = sinon.stub(); + OC.L10N.load(TEST_APP, callbackStub).then(promiseStub); + expect(callbackStub.notCalled).toEqual(true); + expect(promiseStub.notCalled).toEqual(true); + expect(fakeServer.requests.length).toEqual(1); + var req = fakeServer.requests[0]; + expect(req.url).toEqual( + OC.webroot + '/apps3/' + TEST_APP + '/l10n/zh_CN.json' + ); + req.respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({ + translations: {'Hello world!': '你好世界!'}, + pluralForm: 'nplurals=2; plural=(n != 1);' + }) + ); + + expect(callbackStub.calledOnce).toEqual(true); + expect(promiseStub.calledOnce).toEqual(true); + expect(t(TEST_APP, 'Hello world!')).toEqual('你好世界!'); + localeStub.restore(); + }); + it('calls callback if translation already available', function() { + var promiseStub = sinon.stub(); + var callbackStub = sinon.stub(); + OC.L10N.register(TEST_APP, { + 'Hello world!': 'Hallo Welt!' + }); + OC.L10N.load(TEST_APP, callbackStub).then(promiseStub); + expect(callbackStub.calledOnce).toEqual(true); + expect(promiseStub.calledOnce).toEqual(true); + expect(fakeServer.requests.length).toEqual(0); + }); + it('calls callback if locale is en', function() { + var localeStub = sinon.stub(OC, 'getLocale').returns('en'); + var promiseStub = sinon.stub(); + var callbackStub = sinon.stub(); + OC.L10N.load(TEST_APP, callbackStub).then(promiseStub); + expect(callbackStub.calledOnce).toEqual(true); + expect(promiseStub.calledOnce).toEqual(true); + expect(fakeServer.requests.length).toEqual(0); + }); + }); });