Run a basic "Google Translate" app locally on Flask

1. Overview

This series of codelabs (self-paced, hands-on tutorials) aims to help developers understand the various options they have when deploying their applications. In this codelab, you will learn how to use the Google Cloud Translation API with Python and either run locally or deploy to a Cloud serverless compute platform (App Engine, Cloud Functions, or Cloud Run). The sample app found in this tutorial's repo can be deployed (at least) eight different ways with only minor configuration changes:

  1. Local Flask server (Python 2)
  2. Local Flask server (Python 3)
  3. App Engine (Python 2)
  4. App Engine (Python 3)
  5. Cloud Functions (Python 3)
  6. Cloud Run (Python 2 via Docker)
  7. Cloud Run (Python 3 via Docker)
  8. Cloud Run (Python 3 via Cloud Buildpacks)

This codelab focuses on deploying this app to the bolded platform(s) above.

You'll learn how to

What you'll need

Survey

How will you use this tutorial?

Read it and complete the exercises Read it only

How would you rate your experience with Python?

Novice Intermediate Proficient

How would you rate your experience with using Google Cloud services?

Novice Intermediate Proficient

2. Setup and requirements

Self-paced environment setup

  1. Sign-in to the Google Cloud Console and create a new project or reuse an existing one. If you don't already have a Gmail or Google Workspace account, you must create one.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • The Project name is the display name for this project's participants. It is a character string not used by Google APIs, and you can update it at any time.
  • The Project ID must be unique across all Google Cloud projects and is immutable (cannot be changed after it has been set). The Cloud Console auto-generates a unique string; usually you don't care what it is. In most codelabs, you'll need to reference the Project ID (and it is typically identified as PROJECT_ID), so if you don't like it, generate another random one, or, you can try your own and see if it's available. Then it's "frozen" after the project is created.
  • There is a third value, a Project Number which some APIs use. Learn more about all three of these values in the documentation.
  1. Next, you'll need to enable billing in the Cloud Console in order to use Cloud resources/APIs. Running through this codelab shouldn't cost much, if anything at all. To shut down resources so you don't incur billing beyond this tutorial, follow any "clean-up" instructions found at the end of the codelab. New users of Google Cloud are eligible for the $300 USD Free Trial program.

3. Confirm Python environment

This codelab requires you to use the Python language (although many languages are supported by the Google APIs client libraries, so feel free to build something equivalent in your favorite development tool and simply use the Python as pseudocode). In particular, this codelab supports Python 2 and 3, but we recommend moving to 3.x as soon as possible.

The Cloud Shell is a convenient tool available for users directly from the Cloud Console and doesn't require a local development environment, so this tutorial can be done completely in the cloud with a web browser. More specifically for this codelab, the Cloud Shell has already pre-installed both versions of Python.

The Cloud Shell also has IPython installed: it is a higher-level interactive Python interpreter which we recommend, especially if you are part of the data science or machine learning community. If you are, IPython is the default interpreter for Jupyter Notebooks as well as Colab, Jupyter Notebooks hosted by Google Research.

IPython favors a Python 3 interpreter first but falls back to Python 2 if 3.x isn't available. IPython can be accessed from the Cloud Shell but can also be installed in a local development environment. Exit with ^D (Ctrl-d) and accept the offer to exit. Example output of starting ipython will look like this:

$ ipython
Python 3.7.3 (default, Mar  4 2020, 23:11:43)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.13.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]:

If IPython isn't your preference, use of a standard Python interactive interpreter (either the Cloud Shell or your local development environment) is perfectly acceptable (also exit with ^D):

$ python
Python 2.7.13 (default, Sep 26 2018, 18:42:22)
[GCC 6.3.0 20170516] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 
$ python3
Python 3.7.3 (default, Mar 10 2020, 02:33:39)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

The codelab also assumes you have the pip installation tool (Python package manager and dependency resolver). It comes bundled with versions 2.7.9+ or 3.4+. If you have an older Python version, see this guide for installation instructions. Depending on your permissions, you may need to have sudo or superuser access, but generally this isn't the case. You can also explicitly use pip2 or pip3 to execute pip for specific Python versions.

The remainder of the codelab assumes you're using Python 3—specific instructions will be provided for Python 2 if they differ significantly from 3.x.

[optional] Create and use virtual environments

This section is optional and only really required for those who must use a virtual environment for this codelab (per the warning sidebar above). If you only have Python 3 on your computer, you can simply issue this command to create a virtualenv called my_env (you can choose another name if desired):

virtualenv my_env

However, if you have both Python 2 & 3 on your computer, we recommend you install a Python 3 virtualenv which you can do with the -p flag like this:

virtualenv -p python3 my_env

Enter your newly created virtualenv by "activating" it like this:

source my_env/bin/activate

Confirm you're in the environment by observing your shell prompt is now preceded with your environment name, i.e.,

(my_env) $ 

Now you should be able to pip install any required packages, execute code within this eivonment, etc. Another benefit is that if you completely mess it up, get into a situation where your Python installation is corrupted, etc., you can blow away this entire environment without affecting the rest of your system.

4. Enable Translation API

In this section, you'll learn how to enable Google APIs in general. For our sample app, you'll enable the Cloud Translation API.

Introduction

Regardless of which Google API you want to use in your application, they must be enabled. The following example shows two ways to enable the Cloud Vision API. After you learn how to enable one Cloud API, you'll be able to enable other APIs because the process is similar.

Option 1: From Cloud Shell or your command-line interface

While enabling APIs from the Cloud Console is more common, some developers prefer doing everything from the command line. To do so, you need to look up an API's "service name." It looks like a URL: SERVICE_NAME.googleapis.com. You can find these in the Supported products chart, or you can programmatically query for them with the Google Discovery API.

Armed with this information, using Cloud Shell (or your local development environment with the gcloud command-line tool installed), you can enable an API, as follows:

gcloud services enable SERVICE_NAME.googleapis.com

For example, this command enables the Cloud Vision API:

gcloud services enable vision.googleapis.com

This command enables App Engine:

gcloud services enable appengine.googleapis.com

You can also enable multiple APIs with one request. For example, this command line enables Cloud Run, Cloud Artifact Registry, and the Cloud Translation API:

gcloud services enable artifactregistry.googleapis.com run.googleapis.com translate.googleapis.com

Option 2: From the Cloud Console

You can also enable the Vision API in the API Manager. From the Cloud Console, go to API Manager and select Library.

fb0f1d315f122d4a.png

If you wanted to enable the Cloud Vision API, start entering "vision" in the search bar, and anything that matches what you've entered so far will appear:

2275786a24f8f204.png

Select the API you're seeking to enable and click Enable:

2556f923b628e31.png

Cost

While many Google APIs can be used without fees, use of Google Cloud products & APIs is not free. When enabling Cloud APIs, you may be asked for an active billing account. It is, however, important to note that some Google Cloud products feature an "Always Free" tier (daily/monthly), which you have to exceed in order to incur billing charges; otherwise, your credit card (or specified billing instrument) won't be charged.

Users should reference the pricing information for any API before enabling, especially noting whether it has a free tier, and if so, what it is. If you were enabling the Cloud Vision API, you would check its pricing information page. Cloud Vision does have a free quota, and so long as you stay within its limits in aggregate (within each month), you should not incur any charges.

Pricing and free tiers vary between Google APIs. Examples:

Different Google products are billed differently, so be sure to reference your API's documentation for that information.

Summary

Now that you know how to enable Google APIs in general, please go to the API Manager and enable the Cloud Translation API (if you haven't already), the former because our application will use it, the middle because that is where our container images will be stored before deployed to start your Cloud Run service, and the latter because you're deploying to Cloud Run. If you prefer to do it from the command-line, issue this command instead:

gcloud services enable translate.googleapis.com

While its monthly quota isn't listed in the overall "Always Free" tier summary page, the Translation API's pricing page states all users get a fixed amount of translated characters monthly. You shouldn't incur any charges from the API if you stay below that threshold. If there are any other Google Cloud related charges, they will be discussed at the end in the "Clean up" section.

5. Authorize API requests (service acct authorization)

Introduction

In this section, you'll learn how to create a service account and a service account key (public/private key-pair actually) and download the credentials JSON file. The following passage shows you an example of creating a service account and key for the Cloud Vision API with View access. For this tutorial, you'll select the Cloud Translation API instead with either User, Editor, or Admin roles. Do not select the Viewer role as that will not give you enough permission to request a translation with the API. See the Cloud Translation API IAM roles documentation for more information.

API authorization

In order to make requests to the APIs, your application needs to have the proper authorization. Authentication, a similar word, describes login credentials—you authenticate yourself when logging into your Google account with a login & password. Once authenticated, the next step is whether you are—or rather, your code, is—authorized to access data, such as blob files on Cloud Storage or a user's personal files on Google Drive.

Google APIs support several types of authorization, but the one most common for GCP API users is service account authorization since applications like the one in this codelab run in the cloud as a "robot user." While the Vision API supports API key authorization as well, it's strongly recommended that users employ a more secure form of authorization.

A service account is an account that belongs to your project or application (rather than a user) that is used by the client library to make Vision API requests. Like a user account, a service account is represented by an email address. You can create service account credentials from either the command line (via gcloud) or in the Cloud Console. Let's take a look at both below.

Option 1: Using gcloud (in Cloud Shell or your dev environment)

In this section, you will use the gcloud tool to create a service account then create the credentials needed to access the API. First you will set an environment variable with your PROJECT_ID which you will use throughout this codelab:

export PROJECT_ID=$(gcloud config get-value core/project)

For example, if this tutorial requires you to create a new service account to access the Cloud Vision API, you would do so with a command like this:

gcloud iam service-accounts create my-vision-sa \
  --display-name "my vision service account"

Next, you will create the private key credentials that your Python code will use to log in as your new service account. Create these credentials and save it as JSON file ~/key.json by using the following command:

gcloud iam service-accounts keys create ~/key.json \
  --iam-account my-vision-sa@${PROJECT_ID}.iam.gserviceaccount.com

Option 2: From the Cloud Console

To get OAuth2 credentials for user authorization, go back to the API manager (shortcut link: console.developers.google.com) and select the Credentials tab on the left-nav:

4c50e84bc5570d85.png

From the Credentials page, click on the "+ Create Credentials" button at the top, which then gives you a pull-down dialog where you'd choose "Service account:"

201b754357f2a31b.png

On the "Create service account" screen (similar to the below), you must enter a Service account name. Choose something short but explanatory like "svc acct vision" or the one we used with gcloud above, "my vision sa". A Service account ID is also required, and the form will create a valid ID string similar to the name you chose. The Service account description field is optional, but you can specify something related to what you're trying to do, for example: "Service account for Vision API demo". Click the "Create" button when complete.

fc1257f371d71a3.png

The next step is to grant service account access to this project. Having a service account is great, but if it doesn't have permissions to access project resources, it's kind-of useless... it's like creating a new user who doesn't have any access.

d603451226724dfd.png

Here, click on the "Select a role" pull-down menu. You'll see a variety of options (see below), some more granular than others. For some codelabs, choosing Project → Viewer will suffice, but not all. Check what this tutorial requires, select the right option, then click Continue.

3bfeeb77e36927fc.png

On this 3rd screen (see below), we will skip granting specific users access to this service account, but we do need to make a private key our application script can use to access the Vision API with. To that end, click the "+ Create Key" button.

8532fc287d50fa5a.png

Creating a key is straightforward on the next screen. Take the default of a JSON key structure. Note that P12 is only used for backwards-compatibility, so it is not recommended for new projects. Click the Create button and save the private key file when prompted. The default filename will be long and possibly confusing, i.e., PROJECT_ID-HASH.json, so we recommend renaming it to something more digestible such as key.json or svc_acct.json.

3462676a7a13d653.png

Once the file is saved, you'll get the following confirmation message:

624e60cd383fe9d0.png

Click the Close button to complete this task from the console.

Summary

One last step whether you created your service account from the command-line or in the Cloud console: direct your cloud project to use this as the default service account private key to use for your application by assigning this file to the GOOGLE_APPLICATION_CREDENTIALS environment variable:

export GOOGLE_APPLICATION_CREDENTIALS=~/key.json

The environment variable should be set to the full path of the credentials JSON file you saved. It's not necessary to do so, but if you don't, you can only use that key file from the current working directory.

You can read more about authenticating the Google APIs, including the other forms of authorization, i.e., API key, user authorization OAuth2 client ID, etc.

6. Get the sample app code and add credentials

Clone the code in the repo locally or in Cloud Shell (using the git clone command), or download the ZIP file from its green Code button as shown in the following screenshot:

5cd6110c4414cf65.png

Now that you have everything, create a full copy of the folder to do this specific tutorial, because it will likely involve deleting or changing the files. If you want to do a different deployment, you can start over by copying the original so you don't have to clone or download it again.

Also move the credentials.json file you saved earlier into the same folder. Now you have to tell the Cloud SDK to use those credentials: set the GOOGLE_APPLICATION_CREDENTIALS environment variable to point to that file.

Read more about creating the service account, the service account key (public/private key-pair), downloading the credentials file, and pointing your application to it from this documentation page.

7. Install local packages/dependencies

As already mentioned, the sample app uses the Flask micro web framework and the Google Cloud Translation API client library for Python, so install/update pip plus this pair of packages with this pip (or pip3) command:

$ pip install -U pip -r requirements.txt
. . . (installation output) . . .
$

Confirm both are installed correctly with the following command and ensure your Python interpreter can import both without errors or any output:

$ python -c "import google.cloud.translate, flask"
$

This command should work regardless of whether you're using Python 2 or 3. If you have both installed, you may need to explicitly call specific versions, e.g., python3. In either case, there's no output other than the next shell prompt.

8. Tour of sample app

The sample app is a simple Google Translate derivative that prompts users to enter text in English and receive the equivalent translation of that text in Spanish. Now open the main.py file so we can see how it works. Omitting the commented lines about licensing, it looks like this at the top and bottom:

from flask import Flask, render_template, request
import google.auth
from google.cloud import translate

app = Flask(__name__)
_, PROJECT_ID = google.auth.default()
TRANSLATE = translate.TranslationServiceClient()
PARENT = 'projects/{}'.format(PROJECT_ID)
SOURCE, TARGET = ('en', 'English'), ('es', 'Spanish')

# . . . [translate() function definition] . . .

if __name__ == '__main__':
    import os
    app.run(debug=True, threaded=True, host='0.0.0.0',
            port=int(os.environ.get('PORT', 8080)))
  1. The imports bring in Flask functionality, the google.auth module, and the Cloud Translation API client library.
  2. The global variables represent the Flask app, the Cloud project ID, the Translation API client, the parent "location path" for Translation API calls, and the source and target languages. In this case, it's English (en) and Spanish (es), but feel free to change these values to other language codes supported by the Cloud Translation API.
  3. The large if block at the bottom is used in the tutorial for running this app locally—it utilizes the Flask development server to serve our app. This section is also here for the Cloud Run deployment tutorials in case the web server isn't bundled into the container. You are asked to enable bundling the server in the container, but in case you overlook this, the app code falls back to using the Flask development server. (It is not an issue with App Engine or Cloud Functions because those are sourced-based platforms, meaning Google Cloud provides and runs a default web server.)

Finally, in the middle of main.py is the heart of the application, the translate() function:

@app.route('/', methods=['GET', 'POST'])
def translate(gcf_request=None):
    """
    main handler - show form and possibly previous translation
    """

    # Flask Request object passed in for Cloud Functions
    # (use gcf_request for GCF but flask.request otherwise)
    local_request = gcf_request if gcf_request else request

    # reset all variables (GET)
    text = translated = None

    # if there is data to process (POST)
    if local_request.method == 'POST':
        text = local_request.form['text']
        data = {
            'contents': [text],
            'parent': PARENT,
            'target_language_code': TARGET[0],
        }
        # handle older call for backwards-compatibility
        try:
            rsp = TRANSLATE.translate_text(request=data)
        except TypeError:
            rsp = TRANSLATE.translate_text(**data)
        translated = rsp.translations[0].translated_text

    # create context & render template
    context = {
        'orig':  {'text': text, 'lc': SOURCE},
        'trans': {'text': translated, 'lc': TARGET},
    }
    return render_template('index.html', **context)

The primary function does the work of taking the user input, and calling the Translation API to do the heavy-lifting. Let's break it down:

  1. Check to see if requests are coming from Cloud Functions using the local_request variable. Cloud Functions sends in its own Flask Request object whereas all others (running locally or deploying to App Engine or Cloud Run) will get the request object directly from Flask.
  2. Reset the basic variables for the form. This is primarily for GET requests as POST requests will have data that replace these.
  3. If it's a POST, grab the text to translate, and create a JSON structure representing the API metadata requirement. Then call the API, falling back to a previous version of the API if the user is employing an older library.
  4. Regardless, format the actual results (POST) or no data (GET) into the template context and render.

The visual part of the application is in the template index.html file. It shows any previously translated results (blank otherwise) followed by the form asking for something to translate:

<!doctype html>
<html><head><title>My Google Translate 1990s</title><body>
<h2>My Google Translate (1990s edition)</h2>

{% if trans['text'] %}
    <h4>Previous translation</h4>
    <li><b>Original</b>:   {{ orig['text'] }}  (<i>{{ orig['lc'][0] }}</i>)</li>
    <li><b>Translated</b>: {{ trans['text'] }} (<i>{{ trans['lc'][0] }}</i>)</li>
{% endif %}

<h4>Enter <i>{{ orig['lc'][1] }}</i> text to translate to <i>{{ trans['lc'][1] }}</i>:</h4>
<form method="POST"><input name="text"><input type="submit"></form>
</body></html>

9. Start the service

Now you're ready to start your translation service! Launch Flask's development server locally with the following command (or python3 if both Python 2 and Python 3 are installed on your system):

$ python main.py
 * Serving Flask app "main" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
 * Restarting with fsevents reloader
 * Debugger is active!
 * Debugger PIN: 314-455-037

Hit it at localhost:8080, and you should see the following:

adc6665b7ae13c40.png

Translate something to see it work!

fc154326080bf14f.png

10. Conclusion

Congratulations! You learned how to enable the Cloud Translation API, get the necessary credentials, and deploy a simple web app to Flask, whether in Python 2, Python 3, or both! The instructions are the same, and the application code and configuration files are Python 2 & 3-compatible.

Clean up

The Cloud Translation API lets you perform a fixed amount of translated characters per month for free. Because you only incur charges each time you call the Translation API, there's no need to shut anything down nor must you disable/delete your project. More information on billing for the Translation API can be found on its pricing page.

11. Additional resources

In the following sections, you can find additional reading material as well as recommended exercises to augment your knowledge gained from completing this tutorial.

Additional study

Now that you have some experience with the Translation API under your belt, let's do some additional exercises to further develop your skills. To continue your learning path, modify our sample app to do the following:

  1. Complete all the other editions of this codelab for running locally or deploying to Google Cloud serverless compute platforms (see repo README).
  2. Complete this tutorial using another programming language.
  3. Change this application to support different source or target languages.
  4. Upgrade this application to be able to translate text into more than one language; change the template file to have a pulldown of supported target languages.

Learn more

Google App Engine

Google Cloud Functions

Google Cloud Run

Google Cloud Buildpacks, Container Registry, Artifact Registry

Google Cloud Translation and Google ML Kit

Other Google Cloud products/pages

Python and Flask

License

This tutorial is licensed under a Creative Commons Attribution 2.0 Generic License while the source code in the repo is licensed under Apache 2.