Skip to content

Instantly share code, notes, and snippets.

@jokamjohn
Forked from CodingDoug/README.md
Created January 16, 2018 20:37
Show Gist options
  • Save jokamjohn/7fa51e2d4bd5e4b683dda74bcfce72bf to your computer and use it in GitHub Desktop.
Save jokamjohn/7fa51e2d4bd5e4b683dda74bcfce72bf to your computer and use it in GitHub Desktop.
Building an assistant (chatbot) that translates languages, integrated with Slack

Building an assistant (chatbot) that translates languages, integrated with Slack

If you're trying to do this, you came to the right place!

See this code in action here: https://twitter.com/CodingDoug/status/953031540811825152

Setup

  1. Create a Firebase project at the Firebase Console

  2. Create a Dialogflow agent the Dialogflow console that uses the Firebase project that was just created (select it from the dropdown).

  3. Import the prebuilt agent called "Translate" by selecting "Prebuilt Agents" on the left and scrolling down to find "Translate". This will create some intents automatically - you don't have to create any intents or entities. Take a look at them to see how conversation works.

  4. Using the Firebase CLI, initialize a new project space with Functions, and select the Firebase project you created earlier.

  5. Install the Actions on Google and Cloud Translate API libraries for node:

    cd functions
    npm install actions-on-google @google-cloud/translate
    
  6. Edit functions/src/index.ts and copy the code from index.ts in this gist into it, replacing its contents.

  7. Deploy the function with firebase deploy

  8. In the deployment output, copy the function URL. It will look something like this:

    https://us-central1-your-project.cloudfunctions.net/fulfill

  9. In the Dialogflow console, select "Fulfillment" on the left,enable the webhook with the switch, then paste the function URL into the URL field.

  10. Select "Intents" on the left. For every intent that was imported, select it, scroll to the very bottom, check the "Use webhook" checkbox under "Fulfillment", and click "Save" at the top.

  11. In the Google Cloud console for your Firebase project, enable the Cloud Translate API. This requires billing to be enabled on your project.

    (If you don't enable this API, then first time the translate API is called by your function, it will leave an error in the Functions log with a URL to follow to enable the Google Cloud Translate API. Copy that URL and load it into your browser to enable the API.)

  12. At this point, you should be able to type translation requests using the Dialogflow test panel on the right in the Dialogflow console.

Enabling Slack integration

  1. Create a workspace in Slack, or use an existing workspace.

  2. To enable Slack integration with Dialogflow, choose "Integrations" on the left, then enable Slack. Follow the instructions and give permission to Dialogflow to operate a bot on your workspace.

  3. When you enable the test bot, it should appear as an app in your Slack workspace with the name "Dialogflow Bot". You can direct message this bot to get translations.

Helpful documentation

// Copyright 2018 Google LLC.
//
// 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
//
// https://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.
import * as functions from 'firebase-functions'
import { DialogflowApp } from 'actions-on-google'
import * as Translate from '@google-cloud/translate'
const translate = new Translate({
projectId: functions.config().firebase.projectId,
})
const actionMap = new Map()
actionMap.set('translate.text', translateText)
const languages = {
'French': 'fr',
'Russian': 'ru',
'Spanish': 'es',
'Japanese': 'ja',
'Chinese': 'zh',
'Dutch': 'nl',
'English': 'en',
'German': 'de',
'Italian': 'it',
'Korean': 'ko'
}
export const fulfill = functions.https.onRequest((request, response) => {
const app = new DialogflowApp({request, response})
app.handleRequest(actionMap)
})
function translateText(app) {
let text = app.getArgument('text')
let langTo = app.getArgument('lang-to')
let langFrom = app.getArgument('lang-from')
console.log(app.getContext('translate-text'))
if (!text) {
const arg = app.getContextArgument('translate-text', 'lastText')
if (arg) { text = arg.value }
}
if (!langTo) {
const arg = app.getContextArgument('translate-text', 'lastLangTo')
if (arg) { langTo = arg.value }
}
if (!langFrom) {
const arg = app.getContextArgument('translate-text', 'lastLangFrom')
if (arg) { langFrom = arg.value }
if (!langFrom) { langFrom = 'English' }
}
app.setContext('translate-text', 2, {
lastText: text,
lastLangTo: langTo,
lastLangFrom: langFrom
})
console.log(`text: ${text}`)
console.log(`lang-to: ${langTo}`)
console.log(`lang-from: ${langFrom}`)
if (!text) {
ask(app, "What would you like to translate?")
}
else if (!langTo) {
ask(app, "What language would you like to translate to?")
}
else {
const options = { to: languages[langTo] }
if (langFrom) {
options['from'] = languages[langFrom]
}
translate.translate(text, options)
.then(results => {
const translation = results[0]
console.log(`translation: ${translation}`)
tell(app, translation)
})
.catch(error => {
console.error(error)
const message = "Sorry, I couldn't translate that."
tell(app, message)
})
}
}
// Warning! I'm using private APIs below to gain access to the data field
// in the Dialogflow response.
function tell(app, speech) {
const res = app.buildResponse_(speech, false)
res.data.slack = { text: speech }
app.doResponse_(res, 200)
}
function ask(app, question) {
const res = app.buildResponse_(question, true)
res.data.slack = { text: question }
app.doResponse_(res, 200)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment