Text Translator: Translating Text Messages using Google Translate API & Twilio

Every time I have dinner or spend time with my in-laws, I’m always wishing that I was able to understand Korean — I dream of a day when I can get subtitles while they are talking. Alas, we only see them a few times of the year, but the subtitles got me thinking about how can I communicate with them more regularly? So I wrote a script that my in-laws can text a phone number in Korean and my app will translate it and send me the message in English!

parents-to-me

Whenever I text that number in English, it’ll translate my message into Korean and send it to either my mother-in-law or father-in-law.

me-to-them

I’m using Webapp2 as my web framework and I made a route to handle Twilio text messages (don’t know how to use Twilio? Check out Twilio 2 Ways of Sending Text Messages). I started this project by creating a Request Handler that accepts only POST request because that is what Twilio web hooks provide and accept.

class ProcessText(webapp2.RequestHandler):
    """A POST Request Handler"""

    def post(self):
        """Receives a POST request"""

        from_phone_number = self.request.get("From")[1:]
        message = self.request.get("Body").lower()

        to_phone_number, response = process_message(from_phone_number, message)

        send_text_message(to_phone_number, response)

On lines 7 & 8,  I am getting the data from Twilio’s post request and setting them to from_phone_number and message. I am not getting the first index of the phone number because that would include a “+” which I do not need. Then on line 10, I process the message and get back the phone number in which this app should send the text message to and what the message is after the translation. Finally, I called the send_text_message function giving it the to_phone_number and the translated message so Twilio can send it. Let’s process the message!

def process_message(from_phone_number, message):
"""Processes message, returns from who and translated message"""
    to_phone_number = MY_PHONE_NUMBER

    if from_phone_number == MY_PHONE_NUMBER:
        to_who = message[:3]
        to_phone_number = PARENTS[to_who]
        message = message[3:]

I bring in my actual phone number and set that to the to_phone_number.

If the from_phone_number is from me, I need to pull off the first 3 characters from my message and use that to rebind to_phone_number to either mom or dad’s number (by using the PARENTS dictionary) and rebind message to be without the 3 first characters. At this point I now know who the message is for and I have the correct message to actually process:

translated_message = translation(to_phone_number, message)

I call the translation function:

def translation(to_phone_number, message):
    """Makes an API call to translate the message."""
    translation = translate_client.translate(
        message,
        target_language=PHONE_DIRECTORY[to_phone_number]['language'])
    return translation[u'translatedText'].encode('utf-8')

The translate_client is an instance of Google Translate and I pass my message and the targeted language by using my PHONE_DIRECTORy using the phone number as a key and getting that person’s preferred language (ie. My mother-in-law’s phone will give ‘ko’ for Korean and my phone number will give ‘en’ for English). I return the actual translations and since Python 2.7 doesn’t support Korean characters, I need to use .encode(‘uft-8’) so python can process these special characters.

Then I return to my process_message function, where I check to see if the original text was sent from my in-laws again.

    if from_phone_number != MY_PHONE_NUMBER:
        translated_message = "{}: {}".format(FROM_PARENTS[from_phone_number].upper(), translated_message.encode('utf-8'))

    return (to_phone_number, translated_message)

I do this because I am using the same Twilio phone number for both parents, and I need to know who actually sent me the text when I receive it on my phone — I add either “MOM:” or “DAD:” to the message.

Now I can return the to_phone_number and my translated_message to the original post function where the send_text_message function gets called.

def send_text_message(phone, message):
"""sends a text message to the phone number""""

    try:
        twilio_client = TwilioRestClient(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)

        message = twilio_client.messages.create(
            body=message,
            to="+"+phone,
            from_ = TWILIO_NUMBER
        )
    except twilio.TwilioRestException as e:
        print e

In this function I do a try/except so I can handle any errors from Twilio. On line 5, I create a Twilio instance  and then I create a message, passing in my translated message and to_phone_number. Then tada! It sends the text!

In order to make this work you’ll need a Twilio account (guide) and Google Translate API account (docs) as well as a config.py file where you source your actual phone numbers for the terminal environment and set up the relationships (who to send it to and in what language). Since I am using one phone number for two people, its a little complicated, but if you are only using this for a one-to-one relationship it’ll be simpler.

Check out the full code here

Finally, to actually get it working in development, I used Google App Engine to deploy and that’s why there is app.yaml and appengine_config.py files. Checkout Google App Engine docs to learn how to deploy your web application.

2 comments

  1. Hey Jessica! I don’t know anything about Webapp2. Why did you choose it over Flask? Both seem pretty lightweight but I’m wondering if there’s less set up time or if it has anything to do with Google Translate and it being a Google App Engine.

    Like

    1. Hey Ally! They are both light weight and are not too different — there was a time where webapp2 was a better option for Google App Engine because Flask wasn’t support, but now they are both supported. I just felt like doing something different 🙂

      Like

Leave a Reply