浏览代码

Merge pull request #124 from ckeditor/t/116

Added translation service.
Piotrek Koszuliński 8 年之前
父节点
当前提交
111c125edc

+ 8 - 2
packages/ckeditor5-utils/src/locale.js

@@ -7,6 +7,8 @@
  * @module utils/locale
  */
 
+import { translate } from './translation-service';
+
 /**
  * Represents the localization services.
  */
@@ -53,10 +55,14 @@ export default class Locale {
 	 * @private
 	 */
 	_t( str, values ) {
+		let translatedString = translate( this.lang, str );
+
 		if ( values ) {
-			str = str.replace( /\%(\d+)/g, ( match, index ) => ( index < values.length ) ? values[ index ] : match );
+			translatedString = translatedString.replace( /\%(\d+)/g, ( match, index ) => {
+				return ( index < values.length ) ? values[ index ] : match;
+			} );
 		}
 
-		return str;
+		return translatedString;
 	}
 }

+ 69 - 0
packages/ckeditor5-utils/src/translation-service.js

@@ -0,0 +1,69 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * @module utils/translation-service
+ */
+
+let dictionaries = {};
+
+/**
+ * Adds package translations to existing ones.
+ * These translations will later be available for {@link module:utils/translations-service~translate translate}.
+ *
+ *		add( 'pl', {
+ *			'OK': 'OK',
+ *			'Cancel [context: reject]': 'Anuluj'
+ *		} );
+ *
+ * @param {String} lang Target language.
+ * @param {Object.<String, String>} translations Translations which will be added to the dictionary.
+ */
+export function add( lang, translations ) {
+	dictionaries[ lang ] = dictionaries[ lang ] || {};
+
+	Object.assign( dictionaries[ lang ], translations );
+}
+
+/**
+ * Translates string if the translation of the string was previously {@link module:utils/translations-service~add added}
+ * to the dictionary. This happens in a multi-language mode were translation modules are created by the bundler.
+ *
+ * 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
+ * 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.
+ * @returns {String} Translated sentence.
+ */
+export function translate( lang, translationKey ) {
+	if ( !hasTranslation( lang, translationKey ) ) {
+		return translationKey.replace( / \[context: [^\]]+\]$/, '' ) ;
+	}
+
+	return dictionaries[ lang ][ translationKey ];
+}
+
+// Checks whether the dictionary exists and translaiton in that dictionary exists.
+function hasTranslation( lang, translationKey ) {
+	return (
+		( lang in dictionaries ) &&
+		( translationKey in dictionaries[ lang ] )
+	);
+}
+
+/**
+ * Clears dictionaries for test purposes.
+ *
+ * @protected
+ */
+export function _clear() {
+	dictionaries = {};
+}

+ 64 - 0
packages/ckeditor5-utils/tests/translation-service.js

@@ -0,0 +1,64 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+import { translate, add, _clear } from '../src/translation-service';
+
+describe( 'translation-service', () => {
+	beforeEach( () => {
+		_clear();
+	} );
+
+	it( 'should return english string if no translation exists', () => {
+		const translation = translate( 'pl', 'Bold' );
+
+		expect( translation ).to.be.equal( 'Bold' );
+	} );
+
+	it( 'should return english string without context if no translation exists', () => {
+		const translation = translate( 'pl', 'Bold [context: bold]' );
+
+		expect( translation ).to.be.equal( 'Bold' );
+	} );
+
+	it( 'should return translation if the translation for the concrete language is defined', () => {
+		add( 'pl', {
+			'OK': 'OK',
+			'Cancel [context: reject]': 'Anuluj'
+		} );
+
+		const translation = translate( 'pl', 'Cancel [context: reject]' );
+
+		expect( translation ).to.be.equal( 'Anuluj' );
+	} );
+
+	it( 'should return english string without context if the translations for the concrete language exist, but translation doesn\'t', () => {
+		add( 'pl', {
+			'OK': 'OK',
+			'Cancel [context: reject]': 'Anuluj'
+		} );
+
+		const translation = translate( 'pl', 'Bold [context: bold]' );
+
+		expect( translation ).to.be.equal( 'Bold' );
+	} );
+
+	it( 'should be able to merge translations', () => {
+		add( 'pl', {
+			'OK': 'OK',
+			'Cancel [context: reject]': 'Anuluj'
+		} );
+
+		add( 'en_US', {
+			'OK': 'OK',
+			'Cancel [context: reject]': 'Cancel'
+		} );
+
+		const translationPL = translate( 'pl', 'Cancel [context: reject]' );
+		const translationEN = translate( 'en', 'Cancel [context: reject]' );
+
+		expect( translationPL ).to.be.equal( 'Anuluj' );
+		expect( translationEN ).to.be.equal( 'Cancel' );
+	} );
+} );