diff --git a/core/js/l10n.js b/core/js/l10n.js
index fb93d7b789e166ccc490ef406a407358ecaf99a1..43cfc7e820fa3b2482eb6d00a0334d8edfcce67c 100644
--- a/core/js/l10n.js
+++ b/core/js/l10n.js
@@ -66,13 +66,19 @@ OC.L10N = {
 	 * @param {Function|String} [pluralForm] optional plural function or plural string
 	 */
 	register: function(appName, bundle, pluralForm) {
-		this._bundles[appName] = bundle || {};
-
-		if (_.isFunction(pluralForm)) {
-			this._pluralFunctions[appName] = pluralForm;
+		var self = this;
+		if (_.isUndefined(this._bundles[appName])) {
+			this._bundles[appName] = bundle || {};
+
+			if (_.isFunction(pluralForm)) {
+				this._pluralFunctions[appName] = pluralForm;
+			} else {
+				// generate plural function based on form
+				this._pluralFunctions[appName] = this._generatePluralFunction(pluralForm);
+			}
 		} else {
-			// generate plural function based on form
-			this._pluralFunctions[appName] = this._generatePluralFunction(pluralForm);
+			// Theme overwriting the default language
+			_.extend(self._bundles[appName], bundle);
 		}
 	},
 
diff --git a/core/js/tests/specs/l10nSpec.js b/core/js/tests/specs/l10nSpec.js
index bafc7746d6c851f34c3ae8f7c3b872bce3134f97..2ceb2f4a916b076d07f3deedd2e4a6ffaf252400 100644
--- a/core/js/tests/specs/l10nSpec.js
+++ b/core/js/tests/specs/l10nSpec.js
@@ -52,6 +52,14 @@ describe('OC.L10N tests', function() {
 				t(TEST_APP, 'Hello {name}', {name: '<strong>Steve</strong>'}, null, {escape: false})
 			).toEqual('Hello <strong>Steve</strong>');
 		});
+		it('keeps old texts when registering existing bundle', function() {
+			OC.L10N.register(TEST_APP, {
+				'sunny': 'sonnig',
+				'new': 'neu'
+			});
+			expect(t(TEST_APP, 'sunny')).toEqual('sonnig');
+			expect(t(TEST_APP, 'new')).toEqual('neu');
+		});
 	});
 	describe('plurals', function() {
 		function checkPlurals() {
diff --git a/lib/private/template/jsresourcelocator.php b/lib/private/template/jsresourcelocator.php
index 4df1ac8c7f01ec833f1bc192aa91ec58c6854321..6ea7b6291c0ac3afc1a86e896aba8d740be94b9b 100644
--- a/lib/private/template/jsresourcelocator.php
+++ b/lib/private/template/jsresourcelocator.php
@@ -31,8 +31,24 @@ class JSResourceLocator extends ResourceLocator {
 	public function doFind($script) {
 		$theme_dir = 'themes/'.$this->theme.'/';
 		if (strpos($script, '3rdparty') === 0
-			&& $this->appendIfExist($this->thirdpartyroot, $script.'.js')
-			|| $this->appendIfExist($this->serverroot, $theme_dir.'apps/'.$script.'.js')
+			&& $this->appendIfExist($this->thirdpartyroot, $script.'.js')) {
+			return;
+		}
+
+		if (strpos($script, '/l10n/') !== false) {
+			// For language files we try to load them all, so themes can overwrite
+			// single l10n strings without having to translate all of them.
+			$found = 0;
+			$found += $this->appendIfExist($this->serverroot, 'core/'.$script.'.js');
+			$found += $this->appendIfExist($this->serverroot, $theme_dir.'core/'.$script.'.js');
+			$found += $this->appendIfExist($this->serverroot, $script.'.js');
+			$found += $this->appendIfExist($this->serverroot, $theme_dir.$script.'.js');
+			$found += $this->appendIfExist($this->serverroot, $theme_dir.'apps/'.$script.'.js');
+
+			if ($found) {
+				return;
+			}
+		} else if ($this->appendIfExist($this->serverroot, $theme_dir.'apps/'.$script.'.js')
 			|| $this->appendIfExist($this->serverroot, $theme_dir.$script.'.js')
 			|| $this->appendIfExist($this->serverroot, $script.'.js')
 			|| $this->appendIfExist($this->serverroot, $theme_dir.'core/'.$script.'.js')
@@ -40,6 +56,7 @@ class JSResourceLocator extends ResourceLocator {
 		) {
 			return;
 		}
+
 		$app = substr($script, 0, strpos($script, '/'));
 		$script = substr($script, strpos($script, '/')+1);
 		$app_path = \OC_App::getAppPath($app);