diff --git a/packages/ckeditor5-dev-env/bin/translations.js b/packages/ckeditor5-dev-env/bin/translations.js index 72c898988..aa13a6c7d 100755 --- a/packages/ckeditor5-dev-env/bin/translations.js +++ b/packages/ckeditor5-dev-env/bin/translations.js @@ -32,12 +32,15 @@ const tasks = { * * @returns {Promise} */ - upload() { - const uploadTranslations = require( './../lib/translations/upload' ); + async upload() { + const uploadPotFiles = require( './../lib/translations/upload' ); const getToken = require( './../lib/translations/gettoken' ); - return getToken() - .then( credentials => uploadTranslations( credentials ) ); + const token = await getToken(); + + await uploadPotFiles( { + token + } ); }, /** @@ -45,12 +48,19 @@ const tasks = { * * @returns {Promise} */ - download() { + async download() { const downloadTranslations = require( './../lib/translations/download' ); const getToken = require( './../lib/translations/gettoken' ); + const path = require( 'path' ); + + const token = await getToken(); - return getToken() - .then( credentials => downloadTranslations( credentials ) ); + const packages = new Map( getCKEditor5PackageNames().map( packageName => [ + packageName, + path.join( 'packages', packageName ) + ] ) ); + + await downloadTranslations( { token, packages } ); } }; @@ -62,7 +72,13 @@ if ( !task || !tasks[ task ] ) { process.exit( 1 ); } -tasks[ task ](); +Promise.resolve() + .then( () => tasks[ task ]() ) + .catch( err => { + console.error( err ); + + process.exit( 1 ); + } ); function getCKEditor5SourceFiles() { const glob = require( 'glob' ); @@ -73,9 +89,15 @@ function getCKEditor5SourceFiles() { function getCKEditor5PackagePaths() { const path = require( 'path' ); + + return getCKEditor5PackageNames() + .map( packageName => path.join( 'packages', packageName ) ); +} + +function getCKEditor5PackageNames() { + const path = require( 'path' ); const fs = require( 'fs' ); const ckeditor5PackagesDir = path.join( process.cwd(), 'packages' ); - return fs.readdirSync( ckeditor5PackagesDir ) - .map( packageName => path.join( 'packages', packageName ) ); + return fs.readdirSync( ckeditor5PackagesDir ); } diff --git a/packages/ckeditor5-dev-env/lib/index.js b/packages/ckeditor5-dev-env/lib/index.js index 9b8872942..b549901c5 100644 --- a/packages/ckeditor5-dev-env/lib/index.js +++ b/packages/ckeditor5-dev-env/lib/index.js @@ -36,12 +36,13 @@ const tasks = { * * @returns {Promise} */ - uploadPotFiles() { + async uploadPotFiles() { const uploadPotFiles = require( './translations/upload' ); const getToken = require( './translations/gettoken' ); - return getToken() - .then( credentials => uploadPotFiles( credentials ) ); + const token = await getToken(); + + await uploadPotFiles( { token } ); }, /** @@ -49,12 +50,13 @@ const tasks = { * * @returns {Promise} */ - downloadTranslations() { + async downloadTranslations( { packages } ) { const downloadTranslations = require( './translations/download' ); const getToken = require( './translations/gettoken' ); - return getToken() - .then( credentials => downloadTranslations( credentials ) ); + const token = await getToken(); + + await downloadTranslations( { token, packages } ); } }; diff --git a/packages/ckeditor5-dev-env/lib/translations/download.js b/packages/ckeditor5-dev-env/lib/translations/download.js index 5704ea22f..d4d751b62 100644 --- a/packages/ckeditor5-dev-env/lib/translations/download.js +++ b/packages/ckeditor5-dev-env/lib/translations/download.js @@ -10,92 +10,82 @@ const path = require( 'path' ); const transifexService = require( './transifex-service' ); const logger = require( '@ckeditor/ckeditor5-dev-utils' ).logger(); const { cleanPoFileContent, createDictionaryFromPoFileContent } = require( '@ckeditor/ckeditor5-dev-utils' ).translations; +const languageCodeMap = require( './languagecodemap.json' ); /** - * Downloads translations from the Transifex for each package and language. + * Downloads translations from the Transifex for each CF localizable package. + * It creates PO files out of the translations and replaces old translations with the downloaded ones. * - * @param {Object} loginConfig - * @param {String} loginConfig.token Token to the Transifex API. + * @param {Object} config + * @param {String} config.token Token to the Transifex API. + * @param {Map.} config.packages A resource name -> package path map for which translations should be downloaded. */ -module.exports = function download( loginConfig ) { - return Promise.resolve() - .then( () => getPackageNames( loginConfig ) ) - .then( packageNames => downloadAndReplaceTranslations( loginConfig, packageNames ) ) - .then( () => { - logger.info( 'Saved all translations.' ); - } ) - .catch( err => { - logger.error( err ); - throw err; - } ); -}; - -function getPackageNames( loginConfig ) { - return transifexService.getResources( loginConfig ) - .then( resources => resources.map( resource => resource.slug ) ); -} +module.exports = async function downloadTranslations( config ) { + const localizablePackageNames = await getLocalizablePackages( config ); -function downloadAndReplaceTranslations( loginConfig, packageNames ) { - let promise = Promise.resolve(); + for ( const packageName of localizablePackageNames ) { + const translations = await downloadPoFiles( config, packageName ); - for ( const packageName of packageNames ) { - promise = promise.then( () => downloadAndReplaceTranslationsForPackage( loginConfig, packageName ) ); + removeOldTranslation( config.packages.get( packageName ) ); + saveNewTranslations( packageName, config.packages.get( packageName ), translations ); } - return promise; -} + logger.info( 'Saved all translations.' ); +}; -function downloadAndReplaceTranslationsForPackage( loginConfig, packageName ) { - let translations; +/** + * @param {Object} config + * @param {String} config.token Token to the Transifex API. + */ +async function getLocalizablePackages( config ) { + const packageNames = new Set( config.packages.keys() ); + const resources = await transifexService.getResources( config ); - return downloadPoFilesForPackage( loginConfig, packageName ) - .then( _translations => { translations = _translations; } ) - .then( () => removeOldTranslationForPackage( packageName ) ) - .then( () => { saveTranslations( packageName, translations ); } ); + return resources.map( resource => resource.slug ) + .filter( packageName => packageNames.has( packageName ) ); } -function removeOldTranslationForPackage( packageName ) { - const del = require( 'del' ); - const glob = path.join( process.cwd(), 'packages', packageName, 'lang', 'translations', '**' ); - - return del( glob ); +/** + * @param {String} packagePath Package path. + */ +function removeOldTranslation( packagePath ) { + fs.removeSync( getPathToTranslations( packagePath ) ); } -function downloadPoFilesForPackage( loginConfig, packageName ) { - const resourceDetailsPromise = transifexService.getResourceDetails( Object.assign( {}, loginConfig, { - slug: packageName - } ) ); - let languageCodes; - - const translationsForPackagePromise = resourceDetailsPromise.then( resourceDetails => { - languageCodes = resourceDetails.available_languages.map( languageInfo => languageInfo.code ); - - return Promise.all( - languageCodes.map( lang => downloadPoFile( loginConfig, lang, packageName ) ) - ); - } ); +/** + * Downloads translations for the given package and returns a languageCode -> translations map. + * + * @param {Object} config Configuration. + * @param {String} config.token Token to the Transifex API. + * @param {String} packageName Package name. + * @returns {Promise>} + */ +async function downloadPoFiles( config, packageName ) { + const packageOptions = Object.assign( {}, config, { slug: packageName } ); + const resourceDetails = await transifexService.getResourceDetails( packageOptions ); - return translationsForPackagePromise.then( translationsForPackage => { - const translationMapEntries = translationsForPackage - .map( ( translations, index ) => [ languageCodes[ index ], translations ] ); + const languageCodes = resourceDetails.available_languages.map( languageInfo => languageInfo.code ); + const translations = await Promise.all( languageCodes.map( lang => downloadPoFile( config, lang, packageName ) ) ); - return new Map( translationMapEntries ); - } ); + return new Map( translations.map( ( languageTranslations, index ) => [ + languageCodes[ index ], + languageTranslations + ] ) ); } -function downloadPoFile( loginConfig, lang, packageName ) { - const config = Object.assign( {}, loginConfig, { +async function downloadPoFile( config, lang, packageName ) { + const packageOptions = Object.assign( {}, config, { lang, slug: packageName } ); - return transifexService.getTranslation( config ) - .then( data => data.content ); + const data = await transifexService.getTranslation( packageOptions ); + + return data.content; } -function saveTranslations( packageName, translations ) { - const languageCodeMap = require( './languagecodemap.json' ); - let savedTranslations = 0; +function saveNewTranslations( packageName, packagePath, translations ) { + let savedFiles = 0; for ( let [ lang, poFileContent ] of translations ) { if ( !isPoFileContainingTranslations( poFileContent ) ) { @@ -108,17 +98,22 @@ function saveTranslations( packageName, translations ) { poFileContent = cleanPoFileContent( poFileContent ); - const pathToSave = path.join( process.cwd(), 'packages', packageName, 'lang', 'translations', lang + '.po' ); + const pathToSave = path.join( getPathToTranslations( packagePath ), lang + '.po' ); fs.outputFileSync( pathToSave, poFileContent ); - savedTranslations++; + savedFiles++; } - logger.info( `Saved ${ savedTranslations } PO files for ${ packageName } package.` ); + logger.info( `Saved ${ savedFiles } PO files for ${ packageName } package.` ); +} + +function getPathToTranslations( packagePath ) { + return path.join( process.cwd(), packagePath, 'lang', 'translations' ); } function isPoFileContainingTranslations( poFileContent ) { const translations = createDictionaryFromPoFileContent( poFileContent ); - return Object.keys( translations ).some( key => translations[ key ] !== '' ); + return Object.keys( translations ) + .some( msgId => translations[ msgId ] !== '' ); } diff --git a/packages/ckeditor5-dev-env/lib/translations/gettoken.js b/packages/ckeditor5-dev-env/lib/translations/gettoken.js index 43cfeb864..01a9eaccd 100644 --- a/packages/ckeditor5-dev-env/lib/translations/gettoken.js +++ b/packages/ckeditor5-dev-env/lib/translations/gettoken.js @@ -12,10 +12,12 @@ const inquirer = require( 'inquirer' ); * * @returns {Promise.} */ -module.exports = function getToken() { - return inquirer.prompt( [ { +module.exports = async function getToken() { + const { token } = await inquirer.prompt( [ { type: 'password', message: 'Provide the Transifex token (generate it here: https://www.transifex.com/user/settings/api/):', name: 'token' } ] ); + + return token; }; diff --git a/packages/ckeditor5-dev-env/tests/index.js b/packages/ckeditor5-dev-env/tests/index.js index 27a7e7505..c62a3c8df 100644 --- a/packages/ckeditor5-dev-env/tests/index.js +++ b/packages/ckeditor5-dev-env/tests/index.js @@ -70,7 +70,7 @@ describe( 'dev-env/index', () => { describe( 'releaseSubRepositories()', () => { it( 'creates release for sub repositories', () => { - stubs.release.releaseSubRepositories.returns( Promise.resolve( { result: true } ) ); + stubs.release.releaseSubRepositories.resolves( { result: true } ); return tasks.releaseSubRepositories( 'arg' ) .then( response => { @@ -83,7 +83,7 @@ describe( 'dev-env/index', () => { describe( 'generateChangelogForSinglePackage()', () => { it( 'generates a changelog for package', () => { - stubs.release.generateChangelogForSinglePackage.returns( Promise.resolve( { result: true } ) ); + stubs.release.generateChangelogForSinglePackage.resolves( { result: true } ); return tasks.generateChangelogForSinglePackage( 'arg' ) .then( response => { @@ -96,7 +96,7 @@ describe( 'dev-env/index', () => { describe( 'generateChangelogForMonoRepository()', () => { it( 'generates a changelog for sub repositories', () => { - stubs.release.generateChangelogForMonoRepository.returns( Promise.resolve( { result: true } ) ); + stubs.release.generateChangelogForMonoRepository.resolves( { result: true } ); return tasks.generateChangelogForMonoRepository( 123 ) .then( response => { @@ -109,7 +109,7 @@ describe( 'dev-env/index', () => { describe( 'bumpVersions()', () => { it( 'updates version of dependencies', () => { - stubs.release.bumpVersions.returns( Promise.resolve( { result: true } ) ); + stubs.release.bumpVersions.resolves( { result: true } ); return tasks.bumpVersions( 123 ) .then( response => { @@ -133,27 +133,29 @@ describe( 'dev-env/index', () => { } ); describe( 'uploadPotFiles()', () => { - it( 'should upload translations', () => { - stubs.translations.getToken.returns( Promise.resolve( { token: 'token' } ) ); + it( 'should upload translations', async () => { + stubs.translations.getToken.resolves( 'token' ); - return tasks.uploadPotFiles().then( () => { - sinon.assert.calledOnce( stubs.translations.uploadPotFiles ); - sinon.assert.alwaysCalledWithExactly( stubs.translations.uploadPotFiles, { - token: 'token' - } ); + await tasks.uploadPotFiles(); + + sinon.assert.calledOnce( stubs.translations.uploadPotFiles ); + sinon.assert.alwaysCalledWithExactly( stubs.translations.uploadPotFiles, { + token: 'token' } ); } ); } ); describe( 'downloadTranslations()', () => { - it( 'should download translations', () => { - stubs.translations.getToken.returns( Promise.resolve( { token: 'token' } ) ); + it( 'should download translations', async () => { + stubs.translations.getToken.resolves( 'token' ); + const packages = []; - return tasks.downloadTranslations().then( () => { - sinon.assert.calledOnce( stubs.translations.download ); - sinon.assert.alwaysCalledWithExactly( stubs.translations.download, { - token: 'token' - } ); + await tasks.downloadTranslations( { packages } ); + + sinon.assert.calledOnce( stubs.translations.download ); + sinon.assert.alwaysCalledWithExactly( stubs.translations.download, { + token: 'token', + packages } ); } ); } ); diff --git a/packages/ckeditor5-dev-env/tests/release-tools/utils/executeonpackages.js b/packages/ckeditor5-dev-env/tests/release-tools/utils/executeonpackages.js index 9e6c9aa9e..331e3f484 100644 --- a/packages/ckeditor5-dev-env/tests/release-tools/utils/executeonpackages.js +++ b/packages/ckeditor5-dev-env/tests/release-tools/utils/executeonpackages.js @@ -22,8 +22,8 @@ describe( 'dev-env/release-tools/utils', () => { sandbox.restore(); } ); - it( 'resolves promsie when package list is empty', () => { - const functionToExecute = sandbox.stub().returns( Promise.resolve() ); + it( 'resolves promise when package list is empty', () => { + const functionToExecute = sandbox.stub().resolves(); return executeOnPackages( new Set(), functionToExecute ) .then( () => { @@ -32,7 +32,7 @@ describe( 'dev-env/release-tools/utils', () => { } ); it( 'executes a function for each package found as a dependency in package.json in CWD', () => { - const functionToExecute = sandbox.stub().returns( Promise.resolve() ); + const functionToExecute = sandbox.stub().resolves(); const packages = new Set( [ '/packages/ckeditor5-core', @@ -78,7 +78,7 @@ describe( 'dev-env/release-tools/utils', () => { } ); it( 'works fine with array', () => { - const functionToExecute = sandbox.stub().returns( Promise.resolve() ); + const functionToExecute = sandbox.stub().resolves(); return executeOnPackages( [ 1, 2 ], functionToExecute ) .then( () => { @@ -89,8 +89,9 @@ describe( 'dev-env/release-tools/utils', () => { } ); it( 'works fine with iterator', () => { - const functionToExecute = sandbox.stub().returns( Promise.resolve() ); + const functionToExecute = sandbox.stub().resolves(); const simpleMap = new Map( [ [ 'a', 1 ], [ 'b', 2 ] ] ); + return executeOnPackages( simpleMap.keys(), functionToExecute ) .then( () => { expect( functionToExecute.calledTwice ).to.equal( true ); diff --git a/packages/ckeditor5-dev-env/tests/translations/download.js b/packages/ckeditor5-dev-env/tests/translations/download.js index 45277fd0f..b7d6b2f44 100644 --- a/packages/ckeditor5-dev-env/tests/translations/download.js +++ b/packages/ckeditor5-dev-env/tests/translations/download.js @@ -11,11 +11,9 @@ const mockery = require( 'mockery' ); const { expect } = require( 'chai' ); describe( 'download', () => { - let sandbox, stubs, download, resources, resourcesDetails, translations, fileContents; + let stubs, download, resources, resourcesDetails, translations, fileContents; beforeEach( () => { - sandbox = sinon.createSandbox(); - mockery.enable( { useCleanCache: true, warnOnReplace: false, @@ -23,31 +21,30 @@ describe( 'download', () => { } ); stubs = { - del: sandbox.spy( () => Promise.resolve() ), - logger: { - info: sandbox.stub(), - warning: sandbox.stub(), - error: sandbox.stub() + info: sinon.stub(), + warning: sinon.stub(), + error: sinon.stub() }, fs: { - outputFileSync: sandbox.spy() + outputFileSync: sinon.stub(), + removeSync: sinon.stub() }, translationUtils: { - createDictionaryFromPoFileContent: sandbox.spy( poFileContent => fileContents[ poFileContent ] ), + createDictionaryFromPoFileContent: sinon.stub().callsFake( poFileContent => fileContents[ poFileContent ] ), cleanPoFileContent: x => x }, transifexService: { - getResources: sandbox.spy( () => Promise.resolve( resources ) ), - getResourceDetails: sandbox.spy( ( { slug } ) => Promise.resolve( resourcesDetails[ slug ] ) ), - getTranslation: sandbox.spy( ( { lang, slug } ) => Promise.resolve( translations[ slug ][ lang ] ) ) + getResources: sinon.stub().callsFake( () => Promise.resolve( resources ) ), + getResourceDetails: sinon.stub().callsFake( ( { slug } ) => Promise.resolve( resourcesDetails[ slug ] ) ), + getTranslation: sinon.stub().callsFake( ( { lang, slug } ) => Promise.resolve( translations[ slug ][ lang ] ) ) } }; - sandbox.stub( process, 'cwd' ).returns( 'workspace' ); + sinon.stub( process, 'cwd' ).returns( 'workspace' ); mockery.registerMock( '@ckeditor/ckeditor5-dev-utils', { translations: stubs.translationUtils, @@ -55,19 +52,64 @@ describe( 'download', () => { } ); mockery.registerMock( 'fs-extra', stubs.fs ); - mockery.registerMock( 'del', stubs.del ); mockery.registerMock( './transifex-service', stubs.transifexService ); download = require( '../../lib/translations/download' ); } ); afterEach( () => { - sandbox.restore(); + sinon.restore(); mockery.disable(); } ); - it( 'should download translations', () => { - mockery.registerMock( './languagecodemap.json', { 'en_AU': 'en-au' } ); + it( 'should remove translations before downloading', async () => { + mockery.registerMock( './languagecodemap.json', {} ); + + resources = [ + { slug: 'ckeditor5-core' } + ]; + + resourcesDetails = { + 'ckeditor5-core': { + available_languages: [ { + code: 'pl' + } ] + } + }; + + translations = { + 'ckeditor5-core': { + pl: { content: 'ckeditor5-core-pl-content' } + } + }; + + fileContents = { + 'ckeditor5-core-pl-content': { save: 'save_pl' } + }; + + await download( { + token: 'secretToken', + packages: new Map( [ + [ 'ckeditor5-core', 'foo/ckeditor5-core' ] + ] ) + } ); + + sinon.assert.calledOnce( stubs.fs.removeSync ); + sinon.assert.calledOnce( stubs.fs.outputFileSync ); + + sinon.assert.calledWithExactly( + stubs.fs.removeSync, + path.join( 'workspace', 'foo', 'ckeditor5-core', 'lang', 'translations' ) + ); + + sinon.assert.callOrder( + stubs.fs.removeSync, + stubs.fs.outputFileSync + ); + } ); + + it( 'should download translations for non-empty resources', async () => { + mockery.registerMock( './languagecodemap.json', {} ); resources = [ { slug: 'ckeditor5-core' }, @@ -82,7 +124,7 @@ describe( 'download', () => { }, 'ckeditor5-ui': { available_languages: [ { - code: 'en_AU' + code: 'de' } ] } }; @@ -92,37 +134,70 @@ describe( 'download', () => { pl: { content: 'ckeditor5-core-pl-content' } }, 'ckeditor5-ui': { - en_AU: { content: 'ckeditor5-ui-en-content' } + de: { content: 'ckeditor5-ui-de-content' } } }; fileContents = { - 'ckeditor5-core-pl-content': {}, - 'ckeditor5-ui-en-content': { ui: 'ui' } + 'ckeditor5-core-pl-content': { save: 'save_pl' }, + 'ckeditor5-ui-de-content': { cancel: 'cancel_de' } }; - return download( { token: 'secretToken' } ) - .then( () => { - sinon.assert.calledOnce( stubs.transifexService.getResources ); - sinon.assert.calledTwice( stubs.transifexService.getResourceDetails ); - sinon.assert.calledTwice( stubs.transifexService.getTranslation ); - sinon.assert.calledTwice( stubs.del ); - sinon.assert.calledOnce( stubs.fs.outputFileSync ); - - sinon.assert.calledWithExactly( - stubs.del, - path.join( 'workspace', 'packages', 'ckeditor5-core', 'lang', 'translations', '**' ) - ); - - sinon.assert.calledWithExactly( - stubs.fs.outputFileSync, - path.join( 'workspace', 'packages', 'ckeditor5-ui', 'lang', 'translations', 'en-au.po' ), - 'ckeditor5-ui-en-content' - ); - } ); + await download( { + token: 'secretToken', + packages: new Map( [ + [ 'ckeditor5-core', 'foo/ckeditor5-core' ], + [ 'ckeditor5-ui', 'bar/ckeditor5-ui' ] + ] ) + } ); + + sinon.assert.calledTwice( stubs.fs.outputFileSync ); + + sinon.assert.calledWithExactly( + stubs.fs.outputFileSync, + path.join( 'workspace', 'foo', 'ckeditor5-core', 'lang', 'translations', 'pl.po' ), + 'ckeditor5-core-pl-content' + ); + + sinon.assert.calledWithExactly( + stubs.fs.outputFileSync, + path.join( 'workspace', 'bar', 'ckeditor5-ui', 'lang', 'translations', 'de.po' ), + 'ckeditor5-ui-de-content' + ); + } ); + + it( 'should skip creating a resource with no translations', () => { + mockery.registerMock( './languagecodemap.json', {} ); + + resources = [ + { slug: 'ckeditor5-core' } + ]; + + resourcesDetails = { + 'ckeditor5-core': { + available_languages: [ { + code: 'pl' + } ] + } + }; + + translations = { + 'ckeditor5-core': { + pl: { content: 'ckeditor5-core-pl-content' } + } + }; + + fileContents = { + 'ckeditor5-core-pl-content': { save: 'save_pl' } + }; + + // TODO: Should it be called? It's rather a rare case anyway. + sinon.assert.notCalled( stubs.fs.removeSync ); + + sinon.assert.notCalled( stubs.fs.outputFileSync ); } ); - it( 'should use the default language codes when the codes are missing in the languagecodemap.json file', () => { + it( 'should use the default language codes when the codes are missing in the languagecodemap.json file', async () => { mockery.registerMock( './languagecodemap.json', {} ); resources = [ @@ -158,30 +233,38 @@ describe( 'download', () => { 'ckeditor5-ui-en-content': { ui: 'ui' } }; - // jscs:enable requireCamelCaseOrUpperCaseIdentifiers + await download( { + token: 'secretToken', + packages: new Map( [ + [ 'ckeditor5-core', 'foo/ckeditor5-core' ], + [ 'ckeditor5-ui', 'bar/ckeditor5-ui' ] + ] ) + } ); - return download( { token: 'secretToken' } ) - .then( () => { - sinon.assert.calledWithExactly( - stubs.fs.outputFileSync, - path.join( 'workspace', 'packages', 'ckeditor5-ui', 'lang', 'translations', 'en_AU.po' ), - 'ckeditor5-ui-en-content' - ); - } ); + sinon.assert.calledWithExactly( + stubs.fs.outputFileSync, + path.join( 'workspace', 'bar', 'ckeditor5-ui', 'lang', 'translations', 'en_AU.po' ), + 'ckeditor5-ui-en-content' + ); } ); - it( 'should report an error when something goes wrong', () => { + it( 'should fail with an error when the transifex service responses with an error', async () => { const error = new Error(); - stubs.transifexService.getResources = sandbox.spy( () => Promise.reject( error ) ); + stubs.transifexService.getResources.rejects( error ); - return download( { token: 'secretToken' } ) - .then( () => { - throw new Error( 'It should throws an error' ); - }, err => { - expect( err ).to.equal( error ); - sinon.assert.calledOnce( stubs.logger.error ); - sinon.assert.calledWithExactly( stubs.logger.error, error ); + try { + await download( { + token: 'secretToken', + packages: new Map( [ + [ 'ckeditor5-core', 'foo/ckeditor5-core' ], + [ 'ckeditor5-ui', 'bar/ckeditor5-ui' ] + ] ) } ); + + throw new Error( 'Expected method to throw an error.' ); + } catch ( err ) { + expect( err ).to.equal( error ); + } } ); } ); diff --git a/packages/ckeditor5-dev-utils/lib/translations/multiplelanguagetranslationservice.js b/packages/ckeditor5-dev-utils/lib/translations/multiplelanguagetranslationservice.js index 4faccf88b..20f54b5e9 100644 --- a/packages/ckeditor5-dev-utils/lib/translations/multiplelanguagetranslationservice.js +++ b/packages/ckeditor5-dev-utils/lib/translations/multiplelanguagetranslationservice.js @@ -193,7 +193,11 @@ module.exports = class MultipleLanguageTranslationService extends EventEmitter { compilationAssetNames = compilationAssetNames .filter( name => name.endsWith( '.js' ) ); - let mainLanguage = this._mainLanguage; + let bundledLanguage = this._mainLanguage; + + if ( this._addMainLanguageTranslationsToAllAssets ) { + console.log( true ); + } if ( compilationAssetNames.length == 0 && !this._buildAllTranslationsToSeparateFiles ) { this.emit( 'error', [ @@ -203,9 +207,9 @@ module.exports = class MultipleLanguageTranslationService extends EventEmitter { ].join( '\n' ) ); compilationAssetNames = []; - mainLanguage = null; + bundledLanguage = null; } else if ( this._buildAllTranslationsToSeparateFiles ) { - mainLanguage = null; + bundledLanguage = null; compilationAssetNames = []; } else if ( compilationAssetNames.length > 1 && !this._addMainLanguageTranslationsToAllAssets ) { this.emit( 'error', [ @@ -216,11 +220,11 @@ module.exports = class MultipleLanguageTranslationService extends EventEmitter { ].join( '\n' ) ); compilationAssetNames = []; - mainLanguage = null; + bundledLanguage = null; } - const otherLanguages = Array.from( this._languages ) - .filter( lang => lang !== mainLanguage ); + const assetLanguages = Array.from( this._languages ) + .filter( lang => lang !== bundledLanguage ); return [ // Assets where translations for the main language will be added. @@ -231,7 +235,7 @@ module.exports = class MultipleLanguageTranslationService extends EventEmitter { } ) ), // Translation assets outputted to separate translation files. - ...this._getTranslationAssets( outputDirectory, otherLanguages ) + ...this._getTranslationAssets( outputDirectory, assetLanguages ) ]; }