diff --git a/.travis.yml b/.travis.yml
index 058c012624..d59119159f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -75,6 +75,7 @@ cache:
- speech/node_modules/
- storage/node_modules/
- trace/node_modules/
+ - translate/node_modules/
- vision/node_modules/
env:
@@ -85,6 +86,7 @@ env:
before_install:
- openssl aes-256-cbc -K $encrypted_fda0b707c7d5_key -iv $encrypted_fda0b707c7d5_iv -in key.json.enc -out key.json -d
+ - npm install -g npm
- npm set progress=false
before_script:
diff --git a/README.md b/README.md
index a4b321a4d7..610a5ee71a 100644
--- a/README.md
+++ b/README.md
@@ -37,6 +37,7 @@ on Google Cloud Platform.
* [Google Cloud Pub/Sub](#google-cloud-pubsub)
* [Google Cloud Speech API (Beta)](#google-cloud-speech-api-beta)
* [Google Cloud Storage](#google-cloud-storage)
+ * [Google Translate API](#google-translate-api)
* [Google Cloud Vision API](#google-cloud-vision-api)
* [Stackdriver Debugger (Beta)](#stackdriver-debugger-beta)
* [Stackdriver Logging (Beta)](#stackdriver-logging-beta)
@@ -321,6 +322,16 @@ View the [Cloud Storage Node.js samples][storage_samples].
[storage_docs]: https://cloud.google.com/storage/docs/
[storage_samples]: storage
+### Google Translate API
+
+With the [Google Translate API][translate_docs], you can dynamically translate
+text between thousands of language pairs.
+
+View the [Translate API Node.js samples][translate_samples].
+
+[translate_docs]: https://cloud.google.com/translate/docs/
+[translate_samples]: translate
+
### Google Cloud Vision API
The [Cloud Vision API][vision_docs] allows developers to easily integrate vision
diff --git a/circle.yml b/circle.yml
index 042ae5ca1e..adaa7b57ad 100644
--- a/circle.yml
+++ b/circle.yml
@@ -62,4 +62,5 @@ dependencies:
- speech/node_modules/
- storage/node_modules/
- trace/node_modules/
+ - translate/node_modules/
- vision/node_modules/
diff --git a/scripts/install b/scripts/install
index c03a19d12f..ab110f922d 100755
--- a/scripts/install
+++ b/scripts/install
@@ -38,6 +38,7 @@ queue.push('pubsub');
queue.push('speech');
queue.push('storage');
queue.push('trace');
+queue.push('translate');
queue.push('vision');
/**
diff --git a/scripts/uninstall b/scripts/uninstall
index 2fa9c45eae..413c814c15 100755
--- a/scripts/uninstall
+++ b/scripts/uninstall
@@ -38,6 +38,7 @@ queue.push('pubsub');
queue.push('speech');
queue.push('storage');
queue.push('trace');
+queue.push('translate');
queue.push('vision');
/**
diff --git a/translate/README.md b/translate/README.md
new file mode 100644
index 0000000000..173ff49046
--- /dev/null
+++ b/translate/README.md
@@ -0,0 +1,57 @@
+
+
+# Google Translate API Node.js Samples
+
+With the [Google Translate API][translate_docs], you can dynamically translate
+text between thousands of language pairs.
+
+[translate_docs]: https://cloud.google.com/translate/docs/
+
+## Table of Contents
+
+* [Setup](#setup)
+* [Samples](#samples)
+ * [Translate](#translate)
+
+## Setup
+
+1. Read [Prerequisites][prereq] and [How to run a sample][run] first.
+1. Install dependencies:
+
+ npm install
+
+[prereq]: ../README.md#prerequisities
+[run]: ../README.md#how-to-run-a-sample
+
+## Samples
+
+### Translate
+
+View the [documentation][translate_docs] or the [source code][translate_code].
+
+__Usage:__ `node translate --help`
+
+```
+Commands:
+ detect Detect the language of the provided text
+ list List available translation languages.
+ translate Translate the provided text to the target language.
+
+Options:
+ --apiKey, -k Your Translate API key. Defaults to the value of the TRANSLATE_API_KEY environment
+ variable. [string]
+ --help Show help [boolean]
+
+Examples:
+ node translate detect -k your-key "Hello world!" Detect the language of "Hello world!".
+ node translate list -k your-key List available translation languages.
+ node translate translate -k your-key --to ru "Good Translate "Good morning!" to Russian,
+ morning!" auto-detecting English.
+ node translate translate -k your-key --to ru Translate "Good morning!" to Russian from
+ --from en "Good morning!" English.
+
+For more information, see https://cloud.google.com/translate/docs
+```
+
+[translate_docs]: https://cloud.google.com/translate/docs
+[translate_code]: translate.js
diff --git a/translate/package.json b/translate/package.json
new file mode 100644
index 0000000000..79251cdc1e
--- /dev/null
+++ b/translate/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "nodejs-docs-samples-translate",
+ "version": "0.0.1",
+ "private": true,
+ "license": "Apache Version 2.0",
+ "author": "Google Inc.",
+ "scripts": {
+ "test": "mocha -R spec -t 120000 --require intelli-espower-loader ../test/_setup.js test/*.test.js",
+ "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",
+ "iso-639-1": "^1.2.1",
+ "yargs": "^5.0.0"
+ },
+ "devDependencies": {
+ "mocha": "^3.0.2"
+ }
+}
diff --git a/translate/system-test/translate.test.js b/translate/system-test/translate.test.js
new file mode 100644
index 0000000000..4fa7d6ae7d
--- /dev/null
+++ b/translate/system-test/translate.test.js
@@ -0,0 +1,66 @@
+// Copyright 2015-2016, Google, Inc.
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+'use strict';
+
+var program = require('../translate');
+var apiKey = process.env.TRANSLATE_API_KEY;
+var text = 'Hello world!';
+
+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');
+ assert.equal(result.language, 'en', 'should have detected english');
+ assert(console.log.calledWith('Detected %s with confidence %d', 'English', result.confidence));
+ done();
+ });
+ });
+ });
+
+ 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));
+ done();
+ });
+ });
+ });
+
+ 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);
+ assert.equal(translation, expected);
+ assert(console.log.calledWith('Translated text to %s', 'Russian'));
+ done();
+ });
+ });
+ });
+});
diff --git a/translate/test/translate.test.js b/translate/test/translate.test.js
new file mode 100644
index 0000000000..e7226d84bd
--- /dev/null
+++ b/translate/test/translate.test.js
@@ -0,0 +1,188 @@
+// Copyright 2016, Google, Inc.
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+'use strict';
+
+var proxyquire = require('proxyquire').noCallThru();
+var text = 'Hello world!';
+var apiKey = 'key';
+
+function getSample () {
+ var languagesMock = [
+ 'en',
+ 'ru'
+ ];
+ var resultMock = {
+ language: 'en',
+ confidence: 0.75,
+ input: text
+ };
+ 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)
+ };
+ var TranslateMock = sinon.stub().returns(translateMock);
+
+ return {
+ program: proxyquire('../translate', {
+ '@google-cloud/translate': TranslateMock,
+ yargs: proxyquire('yargs', {})
+ }),
+ mocks: {
+ Translate: TranslateMock,
+ translate: translateMock,
+ languages: languagesMock,
+ result: resultMock,
+ translation: translationMock
+ }
+ };
+}
+
+describe('translate:translate', function () {
+ describe('detectLanguage', function () {
+ it('should detect language', function () {
+ var sample = getSample();
+ var callback = sinon.stub();
+
+ sample.program.detectLanguage(text, apiKey, 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 with confidence %d', 'English', sample.mocks.result.confidence));
+ });
+
+ it('should handle error', function () {
+ var error = 'error';
+ var sample = getSample();
+ var callback = sinon.stub();
+ sample.mocks.translate.detect = sinon.stub().callsArgWith(1, error);
+
+ sample.program.detectLanguage(text, apiKey, 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');
+ });
+ });
+
+ describe('listLanguages', function () {
+ it('should list languages', function () {
+ var sample = getSample();
+ var callback = sinon.stub();
+
+ sample.program.listLanguages(apiKey, 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));
+ });
+
+ it('should handle error', function () {
+ var error = 'error';
+ var sample = getSample();
+ var callback = sinon.stub();
+ sample.mocks.translate.getLanguages = sinon.stub().callsArgWith(0, error);
+
+ sample.program.listLanguages(apiKey, 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');
+ });
+ });
+
+ describe('translateText', 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'));
+ });
+
+ it('should handle error', function () {
+ var 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');
+ });
+ });
+
+ describe('main', function () {
+ it('should call detectLanguage', function () {
+ var program = getSample().program;
+
+ sinon.stub(program, 'detectLanguage');
+ program.main(['detect', text, '-k', apiKey]);
+ assert(program.detectLanguage.calledOnce);
+ });
+
+ it('should call listLanguages', function () {
+ var program = getSample().program;
+
+ sinon.stub(program, 'listLanguages');
+ program.main(['list', '-k', apiKey]);
+ assert(program.listLanguages.calledOnce);
+ });
+
+ it('should call translateText', function () {
+ var program = getSample().program;
+
+ sinon.stub(program, 'translateText');
+ program.main(['translate', text, '-k', apiKey, '-t', 'ru']);
+ assert(program.translateText.calledOnce);
+ });
+ });
+});
diff --git a/translate/translate.js b/translate/translate.js
new file mode 100644
index 0000000000..d2be6ec0f8
--- /dev/null
+++ b/translate/translate.js
@@ -0,0 +1,170 @@
+// Copyright 2016, Google, Inc.
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+'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
+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
+ var translate = Translate({
+ key: apiKey
+ });
+
+ // See https://googlecloudplatform.github.io/gcloud-node/#/docs/translate/latest/translate
+ translate.detect(text, function (err, result) {
+ if (err) {
+ return callback(err);
+ }
+
+ console.log('Detected %s with confidence %d', ISO6391.getName(result.language), result.confidence);
+ return callback(null, result);
+ });
+}
+// [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
+ var translate = Translate({
+ key: apiKey
+ });
+
+ // See https://googlecloudplatform.github.io/gcloud-node/#/docs/translate/latest/translate
+ translate.getLanguages(function (err, languages) {
+ if (err) {
+ return callback(err);
+ }
+
+ console.log('Found %d language(s)!', languages.length);
+ return callback(null, languages);
+ });
+}
+// [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
+ var translate = Translate({
+ key: options.apiKey
+ });
+
+ var config = {
+ from: options.from,
+ to: options.to
+ };
+
+ // See https://googlecloudplatform.github.io/gcloud-node/#/docs/translate/latest/translate
+ translate.translate(options.text, config, function (err, translation) {
+ if (err) {
+ return callback(err);
+ }
+
+ console.log('Translated text to %s', ISO6391.getName(options.to));
+ return callback(null, translation);
+ });
+}
+// [END translate_text]
+// [END all]
+
+// The command-line program
+var cli = require('yargs');
+
+var program = module.exports = {
+ detectLanguage: detectLanguage,
+ listLanguages: listLanguages,
+ translateText: translateText,
+ main: function (args) {
+ // Run the command-line program
+ cli.help().strict().parse(args).argv;
+ }
+};
+
+cli
+ .demand(1)
+ .command('detect ', 'Detect the language of the provided text', {}, function (options) {
+ program.detectLanguage(options.text, options.apiKey, console.log);
+ })
+ .command('list', 'List available translation languages.', {}, function (options) {
+ program.listLanguages(options.apiKey, console.log);
+ })
+ .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: {
+ alias: 'f',
+ requiresArg: true,
+ type: 'string',
+ description: 'The language of the source text.'
+ }
+ }, function (options) {
+ program.translateText(options, console.log);
+ })
+ .option('apiKey', {
+ alias: 'k',
+ global: true,
+ requiresArg: true,
+ default: process.env.TRANSLATE_API_KEY,
+ 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)
+ .recommendCommands()
+ .epilogue('For more information, see https://cloud.google.com/translate/docs');
+
+if (module === require.main) {
+ program.main(process.argv.slice(2));
+}