diff --git a/translate/package.json b/translate/package.json index 79251cdc1e7..53120d7e1c5 100644 --- a/translate/package.json +++ b/translate/package.json @@ -9,7 +9,7 @@ "system-test": "mocha -R spec -t 120000 --require intelli-espower-loader ../system-test/_setup.js system-test/*.test.js" }, "dependencies": { - "@google-cloud/translate": "^0.1.1", + "@google-cloud/translate": "^0.2.0", "iso-639-1": "^1.2.1", "yargs": "^5.0.0" }, diff --git a/translate/system-test/translate.test.js b/translate/system-test/translate.test.js index d5d8369b27d..b076569a6e5 100644 --- a/translate/system-test/translate.test.js +++ b/translate/system-test/translate.test.js @@ -13,22 +13,27 @@ 'use strict'; +var ISO6391 = require('iso-639-1'); var program = require('../translate'); -var apiKey = process.env.TRANSLATE_API_KEY; + var text = 'Hello world!'; +var toLang = 'ru'; describe('translate:translate', function () { if (!process.env.TRANSLATE_API_KEY) { process.stdout.write('Skipping Translate API tests...\n'); return; } + describe('detectLanguage', function () { it('should detect language', function (done) { - program.detectLanguage(text, apiKey, function (err, result) { - assert.ifError(err); - assert(result, 'should have received a result'); + program.detectLanguage(text, function (err, result, apiResponse) { + assert.equal(err, null); + assert.notEqual(result, undefined); assert.equal(result.language, 'en', 'should have detected english'); - assert(console.log.calledWith('Detected %s (%s) with confidence %d', 'English', 'en', result.confidence)); + assert.equal(console.log.calledOnce, true); + assert.deepEqual(console.log.firstCall.args, ['Detected language(s):', result]); + assert.notEqual(apiResponse, undefined); done(); }); }); @@ -36,11 +41,35 @@ describe('translate:translate', function () { describe('listLanguages', function () { it('should list languages', function (done) { - program.listLanguages(apiKey, function (err, languages) { - assert.ifError(err); - assert(Array.isArray(languages)); - assert(languages.length > 0); - assert(console.log.calledWith('Found %d language(s)!', languages.length)); + program.listLanguages(function (err, languages, apiResponse) { + assert.equal(err, null); + assert.equal(Array.isArray(languages), true); + assert.equal(languages.length > 0, true); + var matchingLanguages = languages.filter(function (language) { + return language.code === 'af' && language.name === 'Afrikaans'; + }); + assert.equal(matchingLanguages.length, 1, 'found language with name in English'); + assert.equal(console.log.calledOnce, true); + assert.deepEqual(console.log.firstCall.args, ['Found %d language(s)!', languages.length]); + assert.notEqual(apiResponse, undefined); + done(); + }); + }); + }); + + describe('listLanguagesWithTarget', function () { + it('should list languages with a target', function (done) { + program.listLanguagesWithTarget('es', function (err, languages, apiResponse) { + assert.equal(err, null); + assert.equal(Array.isArray(languages), true); + assert.equal(languages.length > 0, true); + var matchingLanguages = languages.filter(function (language) { + return language.code === 'af' && language.name === 'afrikáans'; + }); + assert.equal(matchingLanguages.length, 1, 'found language with name in Spanish'); + assert.equal(console.log.calledOnce, true); + assert.deepEqual(console.log.firstCall.args, ['Found %d language(s)!', languages.length]); + assert.notEqual(apiResponse, undefined); done(); }); }); @@ -48,17 +77,14 @@ describe('translate:translate', function () { describe('translateText', function () { it('should translate text', function (done) { - var options = { - text: text, - apiKey: apiKey, - to: 'ru' - }; var expected = 'Привет мир!'; - program.translateText(options, function (err, translation) { - assert.ifError(err); + program.translateText(text, toLang, undefined, function (err, translation, apiResponse) { + assert.equal(err, null); assert.equal(translation, expected); - assert(console.log.calledWith('Translated text to %s:', 'Russian')); + assert.equal(console.log.calledOnce, true); + assert.deepEqual(console.log.firstCall.args, ['Translated to %s:', ISO6391.getName(toLang)]); + assert.notEqual(apiResponse, undefined); done(); }); }); diff --git a/translate/test/translate.test.js b/translate/test/translate.test.js index bff3027bf1f..dbbf2b6c844 100644 --- a/translate/test/translate.test.js +++ b/translate/test/translate.test.js @@ -13,14 +13,19 @@ 'use strict'; +var ISO6391 = require('iso-639-1'); var proxyquire = require('proxyquire').noCallThru(); + var text = 'Hello world!'; var apiKey = 'key'; +var target = 'es'; +var toLang = 'ru'; function getSample () { + var apiResponseMock = {}; var languagesMock = [ 'en', - 'ru' + toLang ]; var resultMock = { language: 'en', @@ -29,9 +34,9 @@ function getSample () { }; var translationMock = 'Привет мир!'; var translateMock = { - getLanguages: sinon.stub().callsArgWith(0, null, languagesMock), - detect: sinon.stub().callsArgWith(1, null, resultMock), - translate: sinon.stub().callsArgWith(2, null, translationMock) + getLanguages: sinon.stub().yields(null, languagesMock, apiResponseMock), + detect: sinon.stub().yields(null, resultMock, apiResponseMock), + translate: sinon.stub().yields(null, translationMock, apiResponseMock) }; var TranslateMock = sinon.stub().returns(translateMock); @@ -45,7 +50,8 @@ function getSample () { translate: translateMock, languages: languagesMock, result: resultMock, - translation: translationMock + translation: translationMock, + apiResponse: apiResponseMock } }; } @@ -56,30 +62,26 @@ describe('translate:translate', function () { var sample = getSample(); var callback = sinon.stub(); - sample.program.detectLanguage(text, apiKey, callback); + sample.program.detectLanguage(text, callback); - assert(sample.mocks.translate.detect.calledOnce, 'method called once'); - assert.equal(sample.mocks.translate.detect.firstCall.args.length, 2, 'method received 2 arguments'); - assert.equal(sample.mocks.translate.detect.firstCall.args[0], text, 'method received correct argument'); - assert(callback.calledOnce, 'callback called once'); - assert.equal(callback.firstCall.args.length, 2, 'callback received 2 arguments'); - assert.ifError(callback.firstCall.args[0], 'callback did not receive error'); - assert.strictEqual(callback.firstCall.args[1], sample.mocks.result, 'callback received result'); - assert(console.log.calledWith('Detected %s (%s) with confidence %d', 'English', 'en', sample.mocks.result.confidence)); + assert.equal(sample.mocks.translate.detect.calledOnce, true); + assert.deepEqual(sample.mocks.translate.detect.firstCall.args.slice(0, -1), [text]); + assert.equal(callback.calledOnce, true); + assert.deepEqual(callback.firstCall.args, [null, sample.mocks.result, sample.mocks.apiResponse]); + assert.equal(console.log.calledOnce, true); + assert.deepEqual(console.log.firstCall.args, ['Detected language(s):', sample.mocks.result]); }); it('should handle error', function () { var error = new Error('error'); var sample = getSample(); var callback = sinon.stub(); - sample.mocks.translate.detect = sinon.stub().callsArgWith(1, error); + sample.mocks.translate.detect.yields(error); - sample.program.detectLanguage(text, apiKey, callback); + sample.program.detectLanguage(text, callback); - assert(callback.calledOnce, 'callback called once'); - assert.equal(callback.firstCall.args.length, 1, 'callback received 1 argument'); - assert(callback.firstCall.args[0], 'callback received error'); - assert.equal(callback.firstCall.args[0].message, error.message, 'error has correct message'); + assert.equal(callback.calledOnce, true); + assert.deepEqual(callback.firstCall.args, [error]); }); }); @@ -88,29 +90,54 @@ describe('translate:translate', function () { var sample = getSample(); var callback = sinon.stub(); - sample.program.listLanguages(apiKey, callback); + sample.program.listLanguages(callback); + + assert.equal(sample.mocks.translate.getLanguages.calledOnce, true); + assert.deepEqual(sample.mocks.translate.getLanguages.firstCall.args.slice(0, -1), []); + assert.equal(callback.calledOnce, true); + assert.deepEqual(callback.firstCall.args, [null, sample.mocks.languages, sample.mocks.apiResponse]); + assert.equal(console.log.calledOnce, true); + assert.deepEqual(console.log.firstCall.args, ['Found %d language(s)!', sample.mocks.languages.length]); + }); + + it('should handle error', function () { + var error = new Error('error'); + var sample = getSample(); + var callback = sinon.stub(); + sample.mocks.translate.getLanguages.yields(error); + + sample.program.listLanguages(callback); + + assert.equal(callback.calledOnce, true); + assert.deepEqual(callback.firstCall.args, [error]); + }); + }); + + describe('listLanguagesWithTarget', function () { + it('should list languages', function () { + var sample = getSample(); + var callback = sinon.stub(); + + sample.program.listLanguagesWithTarget(target, callback); - assert(sample.mocks.translate.getLanguages.calledOnce, 'method called once'); - assert.equal(sample.mocks.translate.getLanguages.firstCall.args.length, 1, 'method received 1 argument'); - assert(callback.calledOnce, 'callback called once'); - assert.equal(callback.firstCall.args.length, 2, 'callback received 2 arguments'); - assert.ifError(callback.firstCall.args[0], 'callback did not receive error'); - assert.strictEqual(callback.firstCall.args[1], sample.mocks.languages, 'callback received result'); - assert(console.log.calledWith('Found %d language(s)!', sample.mocks.languages.length)); + assert.equal(sample.mocks.translate.getLanguages.calledOnce, true); + assert.deepEqual(sample.mocks.translate.getLanguages.firstCall.args.slice(0, -1), [target]); + assert.equal(callback.calledOnce, true); + assert.deepEqual(callback.firstCall.args, [null, sample.mocks.languages, sample.mocks.apiResponse]); + assert.equal(console.log.calledOnce, true); + assert.deepEqual(console.log.firstCall.args, ['Found %d language(s)!', sample.mocks.languages.length]); }); it('should handle error', function () { var error = new Error('error'); var sample = getSample(); var callback = sinon.stub(); - sample.mocks.translate.getLanguages = sinon.stub().callsArgWith(0, error); + sample.mocks.translate.getLanguages.yields(error); - sample.program.listLanguages(apiKey, callback); + sample.program.listLanguagesWithTarget(target, callback); - assert(callback.calledOnce, 'callback called once'); - assert.equal(callback.firstCall.args.length, 1, 'callback received 1 argument'); - assert(callback.firstCall.args[0], 'callback received error'); - assert.equal(callback.firstCall.args[0].message, error.message, 'error has correct message'); + assert.equal(callback.calledOnce, true); + assert.deepEqual(callback.firstCall.args, [error]); }); }); @@ -118,45 +145,27 @@ describe('translate:translate', function () { it('should translate text', function () { var sample = getSample(); var callback = sinon.stub(); - var options = { - text: text, - to: 'ru', - apiKey: apiKey - }; - - sample.program.translateText(options, callback); - - assert(sample.mocks.translate.translate.calledOnce, 'method called once'); - assert.equal(sample.mocks.translate.translate.firstCall.args.length, 3, 'method received 3 arguments'); - assert.equal(sample.mocks.translate.translate.firstCall.args[0], text, 'method received correct first argument'); - assert.deepEqual(sample.mocks.translate.translate.firstCall.args[1], { - to: 'ru', - from: undefined - }, 'method received correct second argument'); - assert(callback.calledOnce, 'callback called once'); - assert.equal(callback.firstCall.args.length, 2, 'callback received 2 arguments'); - assert.ifError(callback.firstCall.args[0], 'callback did not receive error'); - assert.strictEqual(callback.firstCall.args[1], sample.mocks.translation, 'callback received result'); - assert(console.log.calledWith('Translated text to %s:', 'Russian')); + + sample.program.translateText(text, toLang, undefined, callback); + + assert.equal(sample.mocks.translate.translate.calledOnce, true); + assert.deepEqual(sample.mocks.translate.translate.firstCall.args.slice(0, -1), [text, { to: toLang, from: undefined }]); + assert.equal(callback.calledOnce, true); + assert.deepEqual(callback.firstCall.args, [null, sample.mocks.translation, sample.mocks.apiResponse]); + assert.equal(console.log.calledOnce, true); + assert.deepEqual(console.log.firstCall.args, ['Translated to %s:', ISO6391.getName(toLang)]); }); it('should handle error', function () { var error = new Error('error'); var sample = getSample(); var callback = sinon.stub(); - var options = { - text: text, - to: 'ru', - apiKey: apiKey - }; - sample.mocks.translate.translate = sinon.stub().callsArgWith(2, error); - - sample.program.translateText(options, callback); - - assert(callback.calledOnce, 'callback called once'); - assert.equal(callback.firstCall.args.length, 1, 'callback received 1 argument'); - assert(callback.firstCall.args[0], 'callback received error'); - assert.equal(callback.firstCall.args[0].message, error.message, 'error has correct message'); + sample.mocks.translate.translate.yields(error); + + sample.program.translateText(text, toLang, undefined, callback); + + assert.equal(callback.calledOnce, true); + assert.deepEqual(callback.firstCall.args, [error]); }); }); @@ -165,32 +174,108 @@ describe('translate:translate', function () { var program = getSample().program; sinon.stub(program, 'detectLanguage'); - program.main(['detect', text, '-k', apiKey]); + program.main(['detect', text]); assert.equal(program.detectLanguage.calledOnce, true); - assert.deepEqual(program.detectLanguage.firstCall.args.slice(0, -1), [text, apiKey]); + assert.deepEqual(program.detectLanguage.firstCall.args.slice(0, -1), [[text]]); + }); + + describe('detectLanguage with inline API key', function () { + var originalApiKey; + + before(function () { + originalApiKey = process.env.TRANSLATE_API_KEY; + delete process.env.TRANSLATE_API_KEY; + }); + + after(function () { + process.env.TRANSLATE_API_KEY = originalApiKey; + }); + + it('should set env var from option', function () { + var program = getSample().program; + + sinon.stub(program, 'detectLanguage'); + assert.equal(process.env.TRANSLATE_API_KEY, undefined); + program.main(['detect', text, '-k', apiKey]); + assert.equal(process.env.TRANSLATE_API_KEY, apiKey); + assert.equal(program.detectLanguage.calledOnce, true); + assert.deepEqual(program.detectLanguage.firstCall.args.slice(0, -1), [[text]]); + }); }); it('should call listLanguages', function () { var program = getSample().program; sinon.stub(program, 'listLanguages'); - program.main(['list', '-k', apiKey]); + program.main(['list']); assert.equal(program.listLanguages.calledOnce, true); - assert.deepEqual(program.listLanguages.firstCall.args.slice(0, -1), [apiKey]); + assert.deepEqual(program.listLanguages.firstCall.args.slice(0, -1), []); + }); + + it('should call listLanguagesWithTarget', function () { + var program = getSample().program; + + sinon.stub(program, 'listLanguagesWithTarget'); + program.main(['list', target]); + assert.equal(program.listLanguagesWithTarget.calledOnce, true); + assert.deepEqual(program.listLanguagesWithTarget.firstCall.args.slice(0, -1), [target]); + }); + + describe('listLanguagesWithTarget with inline API key', function () { + var originalApiKey; + + before(function () { + originalApiKey = process.env.TRANSLATE_API_KEY; + delete process.env.TRANSLATE_API_KEY; + }); + + after(function () { + process.env.TRANSLATE_API_KEY = originalApiKey; + }); + + it('should set env var from option', function () { + var program = getSample().program; + + sinon.stub(program, 'listLanguagesWithTarget'); + assert.equal(process.env.TRANSLATE_API_KEY, undefined); + program.main(['list', target, '-k', apiKey]); + assert.equal(process.env.TRANSLATE_API_KEY, apiKey); + assert.equal(program.listLanguagesWithTarget.calledOnce, true); + assert.deepEqual(program.listLanguagesWithTarget.firstCall.args.slice(0, -1), [target]); + }); }); it('should call translateText', function () { var program = getSample().program; sinon.stub(program, 'translateText'); - program.main(['translate', text, '-k', apiKey, '-t', 'ru']); + program.main(['translate', toLang, text]); assert.equal(program.translateText.calledOnce, true); - assert.deepEqual(program.translateText.firstCall.args.slice(0, -1), [{ - text: text, - to: 'ru', - from: undefined, - apiKey: apiKey - }]); + assert.deepEqual(program.translateText.firstCall.args.slice(0, -1), [[text], toLang, undefined]); + }); + + describe('translateText with inline API key', function () { + var originalApiKey; + + before(function () { + originalApiKey = process.env.TRANSLATE_API_KEY; + delete process.env.TRANSLATE_API_KEY; + }); + + after(function () { + process.env.TRANSLATE_API_KEY = originalApiKey; + }); + + it('should set env var from option', function () { + var program = getSample().program; + + sinon.stub(program, 'translateText'); + assert.equal(process.env.TRANSLATE_API_KEY, undefined); + program.main(['translate', toLang, text, '-k', apiKey]); + assert.equal(process.env.TRANSLATE_API_KEY, apiKey); + assert.equal(program.translateText.calledOnce, true); + assert.deepEqual(program.translateText.firstCall.args.slice(0, -1), [[text], toLang, undefined]); + }); }); }); }); diff --git a/translate/translate.js b/translate/translate.js index 8f24c680c75..da6072cf999 100644 --- a/translate/translate.js +++ b/translate/translate.js @@ -13,108 +13,98 @@ 'use strict'; -// [START all] // [START setup] -// By default, the client will authenticate using the service account file -// specified by the GOOGLE_APPLICATION_CREDENTIALS environment variable and use -// the project specified by the GCLOUD_PROJECT environment variable. See -// https://googlecloudplatform.github.io/gcloud-node/#/docs/google-cloud/latest/guides/authentication +// By default, the client will use the project specified by the GCLOUD_PROJECT +// environment variable. The Translate API uses an API key for authentication. +// See https://googlecloudplatform.github.io/gcloud-node/#/docs/google-cloud/latest/guides/authentication var Translate = require('@google-cloud/translate'); - -// Helper library for language codes -var ISO6391 = require('iso-639-1'); // [END setup] -// [START detect_language] -/** - * Detect the language of the provided text. - * - * @param {string} text The text for which to detect the language. - * @param {string} apiKey Your Translate API key. - * @param {function} cb The callback function. - */ -function detectLanguage (text, apiKey, callback) { - // Instantiate a translate client +function detectLanguage (input, callback) { var translate = Translate({ - key: apiKey + // The Translate API uses an API key for authentication. This sample looks + // at an environment variable for the key. + key: process.env.TRANSLATE_API_KEY }); - // See https://googlecloudplatform.github.io/gcloud-node/#/docs/translate/latest/translate - translate.detect(text, function (err, result) { + // "input" can be a string for detecting the language of a single piece of + // text, or an array of strings for detecting the languages of multiple texts. + // See https://googlecloudplatform.github.io/gcloud-node/#/docs/translate/latest/translate?method=detect + translate.detect(input, function (err, result, apiResponse) { if (err) { return callback(err); } - console.log( - 'Detected %s (%s) with confidence %d', - ISO6391.getName(result.language), - result.language, - result.confidence - ); - return callback(null, result); + console.log('Detected language(s):', result); + return callback(null, result, apiResponse); }); } -// [END detect_language] - -// [START list_languages] -/** - * List all of the authenticated project's buckets. - * - * @param {string} apiKey Your Translate API key. - * @param {function} cb The callback function. - */ -function listLanguages (apiKey, callback) { - // Instantiate a translate client + +function listLanguages (callback) { var translate = Translate({ - key: apiKey + // The Translate API uses an API key for authentication. This sample looks + // at an environment variable for the key. + key: process.env.TRANSLATE_API_KEY }); - // See https://googlecloudplatform.github.io/gcloud-node/#/docs/translate/latest/translate - translate.getLanguages(function (err, languages) { + // List available translation language with their names in English (the default). + // See https://googlecloudplatform.github.io/gcloud-node/#/docs/translate/latest/translate?method=getLanguages + translate.getLanguages(function (err, languages, apiResponse) { if (err) { return callback(err); } console.log('Found %d language(s)!', languages.length); - return callback(null, languages); + return callback(null, languages, apiResponse); }); } -// [END list_languages] -// [START translate_text] -/** - * Translate the provided text. - * - * @param {object} options Configuration options. - * @param {string} options.text The text to translate. - * @param {string} options.from The language of the source text. - * @param {string} options.to The language to which to translate the text. - * @param {string} options.apiKey Your Translate API key. - * @param {function} cb The callback function. - */ -function translateText (options, callback) { - // Instantiate a translate client +function listLanguagesWithTarget (target, callback) { var translate = Translate({ - key: options.apiKey + // The Translate API uses an API key for authentication. This sample looks + // at an environment variable for the key. + key: process.env.TRANSLATE_API_KEY }); - var config = { - from: options.from, - to: options.to - }; + // List available translation language with their names in the target language. + // See https://googlecloudplatform.github.io/gcloud-node/#/docs/translate/latest/translate?method=getLanguages + translate.getLanguages(target, function (err, languages, apiResponse) { + if (err) { + return callback(err); + } + + console.log('Found %d language(s)!', languages.length); + return callback(null, languages, apiResponse); + }); +} - // See https://googlecloudplatform.github.io/gcloud-node/#/docs/translate/latest/translate - translate.translate(options.text, config, function (err, translation) { +// [START translate_text] +// Helper library for language codes +var ISO6391 = require('iso-639-1'); + +function translateText (input, toLang, fromLang, callback) { + var translate = Translate({ + // The Translate API uses an API key for authentication. This sample looks + // at an environment variable for the key. + key: process.env.TRANSLATE_API_KEY + }); + + // "input" can be a string for translating a single piece of text, or an array + // of strings for translating multiple texts. + // See https://googlecloudplatform.github.io/gcloud-node/#/docs/translate/latest/translate?method=translate + translate.translate(input, { + from: fromLang, + to: toLang + }, function (err, translation, apiResponse) { if (err) { return callback(err); } - console.log('Translated text to %s:', ISO6391.getName(options.to)); - return callback(null, translation); + console.log('Translated to %s:', ISO6391.getName(toLang)); + return callback(null, translation, apiResponse); }); } // [END translate_text] -// [END all] // The command-line program var cli = require('yargs'); @@ -123,6 +113,7 @@ var utils = require('../utils'); var program = module.exports = { detectLanguage: detectLanguage, listLanguages: listLanguages, + listLanguagesWithTarget: listLanguagesWithTarget, translateText: translateText, main: function (args) { // Run the command-line program @@ -132,28 +123,34 @@ var program = module.exports = { cli .demand(1) - .command('detect ', 'Detect the language of the provided text', {}, function (options) { - program.detectLanguage(options.text, options.apiKey, utils.makeHandler(false)); + .command('detect ', 'Detect the language of the provided text or texts', {}, function (options) { + if (!process.env.TRANSLATE_API_KEY) { + process.env.TRANSLATE_API_KEY = options.apiKey; + } + program.detectLanguage(options.input, utils.makeHandler(false)); }) - .command('list', 'List available translation languages.', {}, function (options) { - program.listLanguages(options.apiKey, utils.makeHandler()); + .command('list [target]', 'List available translation languages. To return language names in a language other than English, specify a target language.', {}, function (options) { + if (!process.env.TRANSLATE_API_KEY) { + process.env.TRANSLATE_API_KEY = options.apiKey; + } + if (options.target) { + program.listLanguagesWithTarget(options.target, utils.makeHandler()); + } else { + program.listLanguages(utils.makeHandler()); + } }) - .command('translate ', 'Translate the provided text to the target language.', { - to: { - alias: 't', - demand: true, - requiresArg: true, - type: 'string', - description: 'The language to which to translate the text.' - }, - from: { + .command('translate ', 'Translate the provided text or texts to the target language, optionally specifying the source language.', { + fromLang: { alias: 'f', requiresArg: true, type: 'string', description: 'The language of the source text.' } }, function (options) { - program.translateText(utils.pick(options, ['text', 'to', 'from', 'apiKey']), utils.makeHandler()); + if (!process.env.TRANSLATE_API_KEY) { + process.env.TRANSLATE_API_KEY = options.apiKey; + } + program.translateText(options.input, options.toLang, options.fromLang, utils.makeHandler()); }) .option('apiKey', { alias: 'k', @@ -163,11 +160,13 @@ cli type: 'string', description: 'Your Translate API key. Defaults to the value of the TRANSLATE_API_KEY environment variable.' }) - .example('node $0 detect -k your-key "Hello world!"', 'Detect the language of "Hello world!".') - .example('node $0 list -k your-key', 'List available translation languages.') - .example('node $0 translate -k your-key --to ru "Good morning!"', 'Translate "Good morning!" to Russian, auto-detecting English.') - .example('node $0 translate -k your-key --to ru --from en "Good morning!"', 'Translate "Good morning!" to Russian from English.') - .wrap(100) + .example('node $0 detect "Hello world!"', 'Detect the language of "Hello world!".') + .example('node $0 detect -k your-api-key "Hello world!" "Goodbye"', 'Detect the language of "Hello world!" and "Goodbye", supplying the API key inline..') + .example('node $0 list -k your-api-key', 'List available translation languages with names in English, supplying the API key inline..') + .example('node $0 list es', 'List available translation languages with names in Spanish.') + .example('node $0 translate ru "Good morning!"', 'Translate "Good morning!" to Russian, auto-detecting the source language.') + .example('node $0 translate ru "Good morning!" -f en -k your-api-key', 'Translate "Good morning!" to Russian from English, supplying the API key inline.') + .wrap(120) .recommendCommands() .epilogue('For more information, see https://cloud.google.com/translate/docs');