# How to Integrate Real-Time Translation Features in FlutterFlow

- Tool: FlutterFlow
- Difficulty: Beginner
- Time required: 30-45 min
- Compatibility: FlutterFlow Free+ (Google Cloud Translation API and Cloud Functions required)
- Last updated: March 2026

## TL;DR

Add real-time translation by calling Google Cloud Translation API v3 (translate.googleapis.com/v3/projects/{projectId}:translateText) from a Cloud Function with the target language and source text. Display a language selector DropDown, trigger translation on button tap or language change, and cache translations in a Firestore map field {en: 'Hello', es: 'Hola'} to avoid re-translating identical content.

## Translate user-generated content and dynamic text in real time within your FlutterFlow app

FlutterFlow's built-in multi-language support handles pre-translated static UI strings — but it cannot translate user-generated content like chat messages, product reviews, or support tickets that you do not know in advance. This tutorial covers real-time dynamic translation: calling Google Cloud Translation API from a Cloud Function, building a language picker, displaying original and translated text, and caching translations in Firestore to keep costs manageable. You will also learn when on-device translation (no internet required) is the better choice.

## Before you start

- A FlutterFlow project with Firebase connected and Cloud Functions enabled (Blaze plan)
- Google Cloud Translation API enabled in your Google Cloud Console (APIs & Services → Enable APIs → Cloud Translation API)
- A Google Cloud API key or service account with Translation API access (Cloud Console → APIs & Services → Credentials)
- A use case with user-generated or dynamic text content to translate (chat messages, product descriptions, reviews)

## Step-by-step guide

### 1. Create the Cloud Function that calls Google Cloud Translation API v3

In your Firebase Cloud Functions, create a function named translateText. It receives a POST request from FlutterFlow with: sourceText (the text to translate), targetLanguage (a BCP-47 language code like 'es', 'fr', 'ja', 'zh'), and optionally sourceLanguage (if not provided, the API auto-detects). The function calls the Translation API v3 endpoint using your service account credentials. Using Cloud Functions keeps your API key server-side — never put a Translation API key in FlutterFlow's API Manager headers where it can be extracted from the compiled app. The endpoint is https://translation.googleapis.com/v3/projects/{projectId}:translateText with a POST body containing the text and target language. Return the translated text in the response.

```
// functions/index.js — Google Cloud Translation proxy
// Install: cd functions && npm install axios
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const axios = require('axios');

admin.initializeApp();

exports.translateText = functions.https.onRequest(async (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');
  if (req.method === 'OPTIONS') { res.status(204).send(''); return; }

  const { sourceText, targetLanguage, sourceLanguage, contentId } = req.body;

  if (!sourceText || !targetLanguage) {
    res.status(400).json({ error: 'sourceText and targetLanguage required' });
    return;
  }

  // Check Firestore translation cache first
  const db = admin.firestore();
  if (contentId) {
    const cacheDoc = await db
      .collection('translation_cache')
      .doc(`${contentId}_${targetLanguage}`)
      .get();
    if (cacheDoc.exists) {
      res.json({ translatedText: cacheDoc.data().text, fromCache: true });
      return;
    }
  }

  // Call Google Cloud Translation API v3
  const projectId = process.env.GCLOUD_PROJECT;
  const apiKey = functions.config().translation.api_key;

  try {
    const response = await axios.post(
      `https://translation.googleapis.com/v3/projects/${projectId}:translateText`,
      {
        contents: [sourceText],
        targetLanguageCode: targetLanguage,
        sourceLanguageCode: sourceLanguage || null,
        mimeType: 'text/plain',
      },
      { params: { key: apiKey } }
    );

    const translatedText =
      response.data.translations[0].translatedText;
    const detectedLanguage =
      response.data.translations[0].detectedLanguageCode;

    // Cache the translation in Firestore
    if (contentId) {
      await db
        .collection('translation_cache')
        .doc(`${contentId}_${targetLanguage}`)
        .set({
          text: translatedText,
          sourceLanguage: detectedLanguage || sourceLanguage,
          targetLanguage,
          contentId,
          cachedAt: admin.firestore.FieldValue.serverTimestamp(),
        });
    }

    res.json({ translatedText, detectedLanguage });
  } catch (err) {
    console.error('Translation API error:', err.response?.data || err.message);
    res.status(500).json({ error: 'Translation failed', details: err.message });
  }
});

// Set config: firebase functions:config:set translation.api_key='YOUR_KEY'
// Deploy: firebase deploy --only functions
```

**Expected result:** Cloud Function is deployed. A test POST to translateText with {sourceText: 'Hello', targetLanguage: 'es'} returns {translatedText: 'Hola'}.

### 2. Configure the FlutterFlow API call and build the language selector

In FlutterFlow, go to API Manager → Add API Group → name it TranslationService. Set the Base URL to your Cloud Function URL. Add an API Call named translate with Method: POST and request body: {"sourceText": "[sourceText]", "targetLanguage": "[targetLanguage]", "contentId": "[contentId]"}. The [variableName] syntax creates dynamic variables you bind to widget values. Click Test and verify the response. For the language selector, add a DropDown widget to your page. Populate it with the most common target languages as static options — label/value pairs: English/en, Spanish/es, French/fr, German/de, Japanese/ja, Portuguese/pt, Chinese Simplified/zh-CN, Arabic/ar, Hindi/hi, Russian/ru. Bind the DropDown's initial value to a Page State variable named selectedLanguage (initial value: your app's default language, e.g., 'en'). On DropDown change, update the selectedLanguage Page State variable to the newly selected language code.

**Expected result:** API Manager shows the TranslationService group with a working translate API call. A DropDown on the page shows language options and updates Page State on selection.

### 3. Add translate button and display original and translated text

Create a UI layout for a translatable content item — for example, a chat message bubble or a product review. Add a Column widget containing: a Text widget (originalText) displaying the source content from your Backend Query, a Divider, a Text widget (translatedText) initially hidden, a Row with a translate icon button and a language label. Create two Page State variables: translatedText (String, initial: ''), showTranslation (Boolean, initial: false). The translatedText Text widget uses Conditional Value for visibility: show if showTranslation == true. Bind its text to the translatedText Page State variable. On the translate icon button, add an Action Flow: (1) Update Page State showTranslation = true, (2) call translate API with sourceText = the content text, targetLanguage = selectedLanguage Page State, contentId = the document ID, (3) Update Page State translatedText = API response translatedText field. Add a small 'Show original' toggle below the translated text that sets showTranslation = false. This gives users control — translation is on-demand, not automatic.

**Expected result:** Tapping the translate icon calls the API and displays the translated text below the original. Tapping 'Show original' hides the translation.

### 4. Cache translations in Firestore to control costs

Google Cloud Translation API charges $20 per million characters. A chat app with 1,000 messages of 100 characters each translated to 5 languages = 500,000 characters = $10 every time your full message history is translated. Cache translations to eliminate this cost for repeated translations. The Cloud Function already implements a translation_cache Firestore collection (from Step 1). For content stored in Firestore (blog posts, product descriptions), add a translations map field to the document: {en: 'original text', es: 'texto traducido', fr: 'texte traduit'}. When the user requests a translation: check if the translations map already has the target language → if yes, display cached translation → if no, call the Cloud Function, then update the document's translations map. In FlutterFlow: modify the translate Action Flow: first check the Backend Query result's translations map for the selected language key. Use a Custom Function translateFromCache(Map translations, String lang) that returns the cached translation if it exists, or an empty String if not. If the result is empty, call the API and update the translations map using Firestore Update Document Action.

**Expected result:** Second and subsequent translation requests for the same content and language return instantly from Firestore cache with no API call, reducing Translation API costs by 80-95%.

### 5. Add on-device offline translation with google_mlkit_translation

For use cases where users might be offline (traveling, poor connectivity) or where privacy matters (translating sensitive content without sending to Google servers), use on-device translation via the google_mlkit_translation Flutter package. In FlutterFlow: Custom Code → Pubspec Dependencies → add google_mlkit_translation with the current version. Create a Custom Action named translateOnDevice with parameters: sourceText (String), targetLanguageCode (String). The action downloads the language model if not already downloaded (one-time download per language, about 20-30MB), then translates locally without an internet connection. Add a Toggle widget to your translation UI: 'Use offline translation'. Bind a Page State useOfflineTranslation: Boolean to the toggle. In the translate Action Flow, use a Conditional Action: if useOfflineTranslation == true → call translateOnDevice Custom Action, else → call the TranslationService API Call. Language model downloads happen on first use — show a CircularProgressIndicator with text 'Downloading language model...' during the first offline translation for a new language.

```
// Custom Action: translateOnDevice
// Add to Pubspec: google_mlkit_translation: ^0.9.0
// Parameters:
//   sourceText (String)
//   targetLanguageCode (String)  e.g. 'es', 'fr', 'de'
// Returns: String (translated text)

import 'package:google_mlkit_translation/google_mlkit_translation.dart';

Future<String> translateOnDevice(
  String sourceText,
  String targetLanguageCode,
) async {
  // Map BCP-47 code to MLKit TranslateLanguage
  final languageMap = {
    'es': TranslateLanguage.spanish,
    'fr': TranslateLanguage.french,
    'de': TranslateLanguage.german,
    'ja': TranslateLanguage.japanese,
    'zh': TranslateLanguage.chinese,
    'pt': TranslateLanguage.portuguese,
    'ar': TranslateLanguage.arabic,
    'hi': TranslateLanguage.hindi,
    'ru': TranslateLanguage.russian,
    'ko': TranslateLanguage.korean,
  };

  final targetLanguage =
      languageMap[targetLanguageCode] ?? TranslateLanguage.spanish;

  // Download model if needed (first time per language)
  final modelManager = OnDeviceTranslatorModelManager();
  final isDownloaded = await modelManager.isModelDownloaded(
    targetLanguage.bcpCode,
  );
  if (!isDownloaded) {
    await modelManager.downloadModel(
      targetLanguage.bcpCode,
      isWifiRequired: false,
    );
  }

  final translator = OnDeviceTranslator(
    sourceLanguage: TranslateLanguage.english,
    targetLanguage: targetLanguage,
  );

  final result = await translator.translateText(sourceText);
  translator.close();
  return result;
}
```

**Expected result:** Toggle between cloud and on-device translation. On-device translation works without an internet connection after the first download and produces results in under 200ms.

## Complete code example

File: `Real-Time Translation Architecture`

```text
Cloud Function: translateText (HTTPS onRequest)
================================================
Input:  sourceText, targetLanguage, contentId (optional)
Output: translatedText, detectedLanguage, fromCache

Flow:
  1. Check Firestore translation_cache/{contentId}_{lang}
  2. If cached → return cached text immediately
  3. Call Translation API v3:
     POST https://translation.googleapis.com/v3/projects/{id}:translateText
     Body: { contents: [text], targetLanguageCode: lang }
     Auth: API key via query param (server-side only)
  4. Cache result in Firestore
  5. Return translatedText

Firestore Schema
=================
Message / review / post document:
  content: String (original text)
  authorId: String
  createdAt: Timestamp
  translations: Map
    en: 'Original English text'
    es: 'Texto traducido en español'
    fr: 'Texte traduit en français'

translation_cache/{contentId}_{lang}
  text: String
  sourceLanguage: String
  targetLanguage: String
  cachedAt: Timestamp

FlutterFlow UI Layout
======================
Column (Backend Query: messages)
  ├── Text (content — original)
  ├── Row (translate controls)
  │   ├── DropDown (language selector → Page State: selectedLanguage)
  │   └── IconButton (translate icon)
  │       Action Flow:
  │         1. Update Page State isTranslating = true
  │         2. Check translations[selectedLanguage] (Custom Fn)
  │         3. If empty → Call translateText API
  │            → Update Page State translatedText = response
  │            → Update Firestore translations map
  │         4. Update Page State isTranslating = false
  └── ConditionalColumn (visible when showTranslation)
      ├── Text (translatedText Page State)
      └── TextButton ('Show original' → showTranslation = false)

Page State Variables
=====================
selectedLanguage: String    initial: 'en'
translatedText: String      initial: ''
showTranslation: Boolean    initial: false
isTranslating: Boolean      initial: false
useOfflineTranslation: Boolean  initial: false
```

## Common mistakes

- **Translating every text widget on every page load automatically without caching, resulting in hundreds of API calls per user session** — The Translation API charges $20 per million characters. An app with a 100-item product catalog where each description is 200 characters, auto-translated to 5 languages on every app open, costs $20 × (100 items × 200 chars × 5 languages = 100,000 chars / 1,000,000) = $2 per user per app open. With 100 daily active users, that is $200/day just for translation. Fix: Only translate on explicit user request (tap a translate button or change the language selector). Cache all translations in the Firestore document's translations map field after the first translation — subsequent reads of the same content in the same language come from Firestore with zero API cost.
- **Putting the Google Cloud Translation API key directly in FlutterFlow's API Manager headers to call the Translation API from the client** — The API key in FlutterFlow's API Manager is embedded in the compiled app binary and can be extracted with standard APK decompilation tools. An exposed Translation API key allows anyone to run unlimited translation calls billed to your Google Cloud account — a single abuse incident can result in thousands of dollars in charges before you notice. Fix: All Translation API calls must go through a Cloud Function. The Cloud Function uses an API key stored in Firebase Functions config (server-side, never in the client app). Use firebase functions:config:set translation.api_key='YOUR_KEY' to store it securely.
- **Assuming the Translation API auto-detects the source language correctly for short texts like single words or product titles** — Language detection accuracy drops significantly for texts under 20 characters. A single word like 'bank' could be English, German (bench/edge), or a proper noun — the API may detect the wrong language and produce a nonsensical translation. Single-character inputs return errors. Fix: Store the source language when content is created: when a user submits a form, detect their device locale (Global Properties → Device Info → locale) and store it as the sourceLanguage field on the document. Pass this stored sourceLanguage value to the Translation API rather than relying on auto-detection for content creation.

## Best practices

- Always route Translation API calls through a Cloud Function — never put the API key in FlutterFlow's client-side API Manager headers
- Cache every translation in Firestore immediately after it is generated — use a Map field on the content document with language codes as keys
- Make translation on-demand (user taps a button) rather than automatic on page load — this gives users control and prevents surprise API costs
- Store the original content language on each document (sourceLanguage field) to avoid language auto-detection errors on short texts
- Use ML Kit on-device translation for use cases requiring offline access or privacy-sensitive content — downloaded language models are free to use unlimited times
- Show the detected source language to users so they can correct it if the auto-detection is wrong — a wrong source language produces poor translations
- Set up Google Cloud budget alerts at $10, $50, and $100 for the Translation API — it is easy to accidentally over-use if caching is not working correctly

## Frequently asked questions

### How much does Google Cloud Translation API cost?

Cloud Translation Basic (v2) and Advanced (v3) both charge $20 per million characters after the first 500,000 characters per month (which are free). For a typical chat app with 1,000 users sending 10 messages/day of 50 characters each: 1,000 × 10 × 50 = 500,000 characters/day. If all messages are translated once, that is the free tier daily. With caching, only new unique messages are translated, dramatically reducing usage. Set up a Google Cloud budget alert at $10 to catch unexpected usage early.

### What languages does Google Cloud Translation API support?

Over 100 languages. Most common: es (Spanish), fr (French), de (German), it (Italian), pt (Portuguese), ru (Russian), ja (Japanese), ko (Korean), zh-CN (Chinese Simplified), zh-TW (Chinese Traditional), ar (Arabic), hi (Hindi), nl (Dutch), tr (Turkish), pl (Polish), sv (Swedish). Get the full list by calling GET https://translation.googleapis.com/v3/projects/{projectId}/supportedLanguages in your Cloud Function and caching the result in Firestore.

### Can I translate rich text with HTML formatting?

Yes — set mimeType: 'text/html' in the Translation API request body instead of 'text/plain'. The API translates the text content while preserving HTML tags (bold, italic, links). The translated text returned will have the HTML tags intact. In FlutterFlow, use a flutter_html Custom Widget to render HTML text with formatting in your app. For plain text chat messages, always use 'text/plain' — sending plain text as HTML can corrupt special characters.

### How do I handle translation in a real-time chat app where messages arrive via Firestore listener?

Use a Firestore Cloud Function trigger instead of client-side translation. Create a Cloud Function triggered by new document creation in your messages collection: functions.firestore.document('chats/{chatId}/messages/{messageId}').onCreate(). This function auto-translates the message to all active languages in that chat room and stores them in the message's translations map before any client reads it. The FlutterFlow real-time listener then picks up the message WITH translations already populated — no client-side translation call needed.

### Does FlutterFlow's built-in multi-language support work for this?

No — FlutterFlow's built-in localization (Settings → Localizations → Add Language) handles static UI strings you define in advance, like button labels, navigation titles, and fixed messages. It does not handle dynamic content from your database that users write at runtime. For user-generated content (chat messages, reviews, posts), you must use the Translation API approach described in this tutorial.

### Can RapidDev add multilingual support to my existing FlutterFlow app?

Yes. A full multilingual implementation includes static UI localization via FlutterFlow's built-in system, dynamic content translation via Cloud Translation API with Firestore caching, user language preference stored in the user's Firestore profile, on-device fallback for offline users, and auto-detection of the user's preferred language on first launch. RapidDev can implement the full stack across any FlutterFlow app.

---

Source: https://www.rapidevelopers.com/flutterflow-tutorials/how-to-integrate-real-time-translation-features-in-flutterflow
© RapidDev — https://www.rapidevelopers.com/flutterflow-tutorials/how-to-integrate-real-time-translation-features-in-flutterflow
