diff --git a/packages/ckeditor5-dev-translations/lib/utils/addtranslation.js b/packages/ckeditor5-dev-translations/lib/utils/addtranslation.js new file mode 100644 index 000000000..f235ac7a0 --- /dev/null +++ b/packages/ckeditor5-dev-translations/lib/utils/addtranslation.js @@ -0,0 +1,33 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +/** + * @param {object} options + * @param {string} options.languageCode + * @param {number} options.numberOfPluralForms + * @param {TranslatableEntry} options.message + * @returns {Array.} + */ +export default function addTranslation( { languageCode, numberOfPluralForms, message } ) { + // English is the source (base) language, so set the translation value to the text collected from source code. + if ( languageCode === 'en' ) { + const msgstr = [ message.string ]; + + if ( message.plural ) { + msgstr.push( message.plural ); + } + + return msgstr; + } + + // For other languages, pre-fill the translation value with an empty string which means that it requires translation. + const msgstr = [ '' ]; + + if ( message.plural ) { + msgstr.push( ...Array( numberOfPluralForms - 1 ).fill( '' ) ); + } + + return msgstr; +} diff --git a/packages/ckeditor5-dev-translations/lib/utils/synchronizetranslationsbasedoncontext.js b/packages/ckeditor5-dev-translations/lib/utils/synchronizetranslationsbasedoncontext.js index 972f5d007..59e46a605 100644 --- a/packages/ckeditor5-dev-translations/lib/utils/synchronizetranslationsbasedoncontext.js +++ b/packages/ckeditor5-dev-translations/lib/utils/synchronizetranslationsbasedoncontext.js @@ -12,6 +12,7 @@ import { TRANSLATION_FILES_PATH } from './constants.js'; import cleanTranslationFileContent from './cleantranslationfilecontent.js'; import getHeaders from './getheaders.js'; import getLanguages from './getlanguages.js'; +import addTranslation from './addtranslation.js'; /** * @param {object} options @@ -66,13 +67,13 @@ export default function synchronizeTranslationsBasedOnContext( { packageContexts item.msgctxt = contextContent[ message.id ]; item.msgid = message.id; - item.msgstr.push( '' ); if ( message.plural ) { item.msgid_plural = message.plural; - item.msgstr.push( ...Array( numberOfPluralForms - 1 ).fill( '' ) ); } + item.msgstr = addTranslation( { languageCode, numberOfPluralForms, message } ); + return item; } ) ); diff --git a/packages/ckeditor5-dev-translations/tests/utils/addtranslation.js b/packages/ckeditor5-dev-translations/tests/utils/addtranslation.js new file mode 100644 index 000000000..57b34e4e5 --- /dev/null +++ b/packages/ckeditor5-dev-translations/tests/utils/addtranslation.js @@ -0,0 +1,50 @@ +/** + * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import { beforeEach, describe, expect, it } from 'vitest'; +import addTranslation from '../../lib/utils/addtranslation.js'; + +describe( 'addTranslation()', () => { + let singularMessage, pluralMessage; + + beforeEach( () => { + singularMessage = { + string: 'Example message 1' + }; + + pluralMessage = { + string: 'Example message 2', + plural: 'Example message 2 - plural form' + }; + } ); + + it( 'should be a function', () => { + expect( addTranslation ).toBeInstanceOf( Function ); + } ); + + it( 'should return translation (English, non-plural message)', () => { + const result = addTranslation( { languageCode: 'en', numberOfPluralForms: 2, message: singularMessage } ); + + expect( result ).toEqual( [ 'Example message 1' ] ); + } ); + + it( 'should return translation (English, plural message)', () => { + const result = addTranslation( { languageCode: 'en', numberOfPluralForms: 2, message: pluralMessage } ); + + expect( result ).toEqual( [ 'Example message 2', 'Example message 2 - plural form' ] ); + } ); + + it( 'should return translation (non-English, non-plural message)', () => { + const result = addTranslation( { languageCode: 'pl', numberOfPluralForms: 4, message: singularMessage } ); + + expect( result ).toEqual( [ '' ] ); + } ); + + it( 'should return translation (non-English, plural message)', () => { + const result = addTranslation( { languageCode: 'pl', numberOfPluralForms: 4, message: pluralMessage } ); + + expect( result ).toEqual( [ '', '', '', '' ] ); + } ); +} ); diff --git a/packages/ckeditor5-dev-translations/tests/utils/synchronizetranslationsbasedoncontext.js b/packages/ckeditor5-dev-translations/tests/utils/synchronizetranslationsbasedoncontext.js index 53854f464..a98fefe6b 100644 --- a/packages/ckeditor5-dev-translations/tests/utils/synchronizetranslationsbasedoncontext.js +++ b/packages/ckeditor5-dev-translations/tests/utils/synchronizetranslationsbasedoncontext.js @@ -11,6 +11,7 @@ import cleanTranslationFileContent from '../../lib/utils/cleantranslationfilecon import createMissingPackageTranslations from '../../lib/utils/createmissingpackagetranslations.js'; import getLanguages from '../../lib/utils/getlanguages.js'; import getHeaders from '../../lib/utils/getheaders.js'; +import addTranslation from '../../lib/utils/addtranslation.js'; import synchronizeTranslationsBasedOnContext from '../../lib/utils/synchronizetranslationsbasedoncontext.js'; vi.mock( 'fs-extra' ); @@ -20,6 +21,7 @@ vi.mock( '../../lib/utils/createmissingpackagetranslations.js' ); vi.mock( '../../lib/utils/cleantranslationfilecontent.js' ); vi.mock( '../../lib/utils/getlanguages.js' ); vi.mock( '../../lib/utils/getheaders.js' ); +vi.mock( '../../lib/utils/addtranslation.js' ); describe( 'synchronizeTranslationsBasedOnContext()', () => { let defaultOptions, translations, stubs; @@ -77,6 +79,8 @@ describe( 'synchronizeTranslationsBasedOnContext()', () => { }; } ); + vi.mocked( addTranslation ).mockReturnValue( [] ); + vi.mocked( PO.parse ).mockReturnValue( translations ); vi.mocked( PO.parsePluralForms ).mockReturnValue( { nplurals: 4 } ); @@ -185,22 +189,44 @@ describe( 'synchronizeTranslationsBasedOnContext()', () => { } ); it( 'should add missing translations', () => { + vi.mocked( addTranslation ).mockReturnValue( [ 'added missing translation' ] ); translations.items = []; synchronizeTranslationsBasedOnContext( defaultOptions ); + expect( addTranslation ).toHaveBeenCalledTimes( 2 ); + + expect( addTranslation ).toHaveBeenCalledWith( { + languageCode: 'en', + message: { + id: 'id1', + string: 'Example message 1' + }, + numberOfPluralForms: 4 + } ); + + expect( addTranslation ).toHaveBeenCalledWith( { + languageCode: 'en', + message: { + id: 'id2', + plural: 'Example message 2 - plural form', + string: 'Example message 2' + }, + numberOfPluralForms: 4 + } ); + expect( translations.items ).toEqual( [ { msgid: 'id1', msgctxt: 'Context for example message 1', msgid_plural: '', - msgstr: [ '' ] + msgstr: expect.arrayContaining( [ 'added missing translation' ] ) }, { msgid: 'id2', msgctxt: 'Context for example message 2', msgid_plural: 'Example message 2 - plural form', - msgstr: [ '', '', '', '' ] + msgstr: expect.arrayContaining( [ 'added missing translation' ] ) } ] ); } );