8
0
Pārlūkot izejas kodu

Merge branch 'master' into t/196

Kamil Piechaczek 8 gadi atpakaļ
vecāks
revīzija
13223d8493

+ 6 - 0
packages/ckeditor5-utils/src/observablemixin.js

@@ -216,6 +216,12 @@ const ObservableMixin = {
 
 			unbindAttrs.forEach( attrName => {
 				const binding = boundAttributes.get( attrName );
+
+				// Nothing to do if the binding is not defined
+				if ( !binding ) {
+					return;
+				}
+
 				let toObservable, toAttr, toAttrs, toAttrBindings;
 
 				binding.to.forEach( to => {

+ 31 - 5
packages/ckeditor5-utils/src/translation-service.js

@@ -3,6 +3,8 @@
  * For licensing, see LICENSE.md.
  */
 
+/* globals window */
+
 /**
  * @module utils/translation-service
  */
@@ -18,6 +20,12 @@ let dictionaries = {};
  *			'Cancel [context: reject]': 'Anuluj'
  *		} );
  *
+ * That function is accessible globally via `window.CKEDITOR_TRANSLATIONS.add()`. So it's possible to add translation from
+ * the other script, just after that one.
+ *
+ * 		<script src="./path/to/ckeditor.js"></script>
+ * 		<script src="./path/to/translations/en.js"></script>
+ *
  * @param {String} lang Target language.
  * @param {Object.<String, String>} translations Translations which will be added to the dictionary.
  */
@@ -34,24 +42,33 @@ export function add( lang, translations ) {
  * When no translation is defined in the dictionary or the dictionary doesn't exist this function returns
  * the original string without the `'[context: ]'` (happens in development and single-language modes).
  *
- * In a single-language mode (when values passed to `t()` were replaced with target languange strings) the dictionary
+ * In a single-language mode (when values passed to `t()` were replaced with target language strings) the dictionary
  * is left empty, so this function will return the original strings always.
  *
  *		translate( 'pl', 'Cancel [context: reject]' );
  *
  * @param {String} lang Target language.
- * @param {String} translationKey String which is going to be translated.
+ * @param {String} translationKey String that will be translated.
  * @returns {String} Translated sentence.
  */
 export function translate( lang, translationKey ) {
-	if ( !hasTranslation( lang, translationKey ) ) {
+	const numberOfLanguages = getNumberOfLanguages();
+
+	if ( numberOfLanguages === 1 ) {
+		// Override the language to the only supported one.
+		// This can't be done in the `Locale` class, because the translations comes after the `Locale` class initialization.
+		lang = Object.keys( dictionaries )[ 0 ];
+	}
+
+	if ( numberOfLanguages === 0 || !hasTranslation( lang, translationKey ) ) {
 		return translationKey.replace( / \[context: [^\]]+\]$/, '' );
 	}
 
-	return dictionaries[ lang ][ translationKey ];
+	// In case of missing translations we still need to cut off the `[context: ]` parts.
+	return dictionaries[ lang ][ translationKey ].replace( / \[context: [^\]]+\]$/, '' );
 }
 
-// Checks whether the dictionary exists and translaiton in that dictionary exists.
+// Checks whether the dictionary exists and translation in that dictionary exists.
 function hasTranslation( lang, translationKey ) {
 	return (
 		( lang in dictionaries ) &&
@@ -67,3 +84,12 @@ function hasTranslation( lang, translationKey ) {
 export function _clear() {
 	dictionaries = {};
 }
+
+function getNumberOfLanguages() {
+	return Object.keys( dictionaries ).length;
+}
+
+// Export globally add function to enable adding later translations.
+// See https://github.com/ckeditor/ckeditor5/issues/624
+window.CKEDITOR_TRANSLATIONS = window.CKEDITOR_TRANSLATIONS || {};
+window.CKEDITOR_TRANSLATIONS.add = add;

+ 8 - 0
packages/ckeditor5-utils/tests/observablemixin.js

@@ -739,6 +739,14 @@ describe( 'Observable', () => {
 			observable.unbind();
 		} );
 
+		it( 'should not fail when unbinding attribute that is not bound', () => {
+			const observable = new Observable();
+
+			observable.bind( 'foo' ).to( car, 'color' );
+
+			expect( () => observable.unbind( 'bar' ) ).to.not.throw();
+		} );
+
 		it( 'should throw when non-string attribute is passed', () => {
 			expect( () => {
 				car.unbind( new Date() );

+ 19 - 1
packages/ckeditor5-utils/tests/translation-service.js

@@ -3,10 +3,12 @@
  * For licensing, see LICENSE.md.
  */
 
+/* globals window */
+
 import { translate, add, _clear } from '../src/translation-service';
 
 describe( 'translation-service', () => {
-	beforeEach( () => {
+	afterEach( () => {
 		_clear();
 	} );
 
@@ -45,6 +47,17 @@ describe( 'translation-service', () => {
 		expect( translation ).to.be.equal( 'Bold' );
 	} );
 
+	it( 'should use provided language if only one is provided', () => {
+		add( 'pl', {
+			'OK': 'OK',
+			'Cancel [context: reject]': 'Anuluj'
+		} );
+
+		const translation = translate( 'de', 'Cancel [context: reject]' );
+
+		expect( translation ).to.be.equal( 'Anuluj' );
+	} );
+
 	it( 'should be able to merge translations', () => {
 		add( 'pl', {
 			'OK': 'OK',
@@ -62,4 +75,9 @@ describe( 'translation-service', () => {
 		expect( translationPL ).to.be.equal( 'Anuluj' );
 		expect( translationEN ).to.be.equal( 'Cancel' );
 	} );
+
+	it( 'should expose `add` function globally', () => {
+		expect( window.CKEDITOR_TRANSLATIONS ).to.be.an( 'object' );
+		expect( window.CKEDITOR_TRANSLATIONS.add ).to.be.a( 'function' );
+	} );
 } );