Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Integrate Real-Time Translation Features in FlutterFlow

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.

What you'll learn

  • How to call Google Cloud Translation API v3 endpoint translateText via a Cloud Function from FlutterFlow
  • How to build a language selector DropDown populated from the Translation API's supported languages list
  • How to cache translations in Firestore map fields to avoid redundant API calls and reduce costs
  • How to support on-device offline translation using the google_mlkit_translation Custom Action
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner13 min read30-45 minFlutterFlow Free+ (Google Cloud Translation API and Cloud Functions required)March 2026RapidDev Engineering Team
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.

Prerequisites

  • 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
1// functions/index.js — Google Cloud Translation proxy
2// Install: cd functions && npm install axios
3const functions = require('firebase-functions');
4const admin = require('firebase-admin');
5const axios = require('axios');
6
7admin.initializeApp();
8
9exports.translateText = functions.https.onRequest(async (req, res) => {
10 res.set('Access-Control-Allow-Origin', '*');
11 if (req.method === 'OPTIONS') { res.status(204).send(''); return; }
12
13 const { sourceText, targetLanguage, sourceLanguage, contentId } = req.body;
14
15 if (!sourceText || !targetLanguage) {
16 res.status(400).json({ error: 'sourceText and targetLanguage required' });
17 return;
18 }
19
20 // Check Firestore translation cache first
21 const db = admin.firestore();
22 if (contentId) {
23 const cacheDoc = await db
24 .collection('translation_cache')
25 .doc(`${contentId}_${targetLanguage}`)
26 .get();
27 if (cacheDoc.exists) {
28 res.json({ translatedText: cacheDoc.data().text, fromCache: true });
29 return;
30 }
31 }
32
33 // Call Google Cloud Translation API v3
34 const projectId = process.env.GCLOUD_PROJECT;
35 const apiKey = functions.config().translation.api_key;
36
37 try {
38 const response = await axios.post(
39 `https://translation.googleapis.com/v3/projects/${projectId}:translateText`,
40 {
41 contents: [sourceText],
42 targetLanguageCode: targetLanguage,
43 sourceLanguageCode: sourceLanguage || null,
44 mimeType: 'text/plain',
45 },
46 { params: { key: apiKey } }
47 );
48
49 const translatedText =
50 response.data.translations[0].translatedText;
51 const detectedLanguage =
52 response.data.translations[0].detectedLanguageCode;
53
54 // Cache the translation in Firestore
55 if (contentId) {
56 await db
57 .collection('translation_cache')
58 .doc(`${contentId}_${targetLanguage}`)
59 .set({
60 text: translatedText,
61 sourceLanguage: detectedLanguage || sourceLanguage,
62 targetLanguage,
63 contentId,
64 cachedAt: admin.firestore.FieldValue.serverTimestamp(),
65 });
66 }
67
68 res.json({ translatedText, detectedLanguage });
69 } catch (err) {
70 console.error('Translation API error:', err.response?.data || err.message);
71 res.status(500).json({ error: 'Translation failed', details: err.message });
72 }
73});
74
75// Set config: firebase functions:config:set translation.api_key='YOUR_KEY'
76// 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.

translate_on_device.dart
1// Custom Action: translateOnDevice
2// Add to Pubspec: google_mlkit_translation: ^0.9.0
3// Parameters:
4// sourceText (String)
5// targetLanguageCode (String) e.g. 'es', 'fr', 'de'
6// Returns: String (translated text)
7
8import 'package:google_mlkit_translation/google_mlkit_translation.dart';
9
10Future<String> translateOnDevice(
11 String sourceText,
12 String targetLanguageCode,
13) async {
14 // Map BCP-47 code to MLKit TranslateLanguage
15 final languageMap = {
16 'es': TranslateLanguage.spanish,
17 'fr': TranslateLanguage.french,
18 'de': TranslateLanguage.german,
19 'ja': TranslateLanguage.japanese,
20 'zh': TranslateLanguage.chinese,
21 'pt': TranslateLanguage.portuguese,
22 'ar': TranslateLanguage.arabic,
23 'hi': TranslateLanguage.hindi,
24 'ru': TranslateLanguage.russian,
25 'ko': TranslateLanguage.korean,
26 };
27
28 final targetLanguage =
29 languageMap[targetLanguageCode] ?? TranslateLanguage.spanish;
30
31 // Download model if needed (first time per language)
32 final modelManager = OnDeviceTranslatorModelManager();
33 final isDownloaded = await modelManager.isModelDownloaded(
34 targetLanguage.bcpCode,
35 );
36 if (!isDownloaded) {
37 await modelManager.downloadModel(
38 targetLanguage.bcpCode,
39 isWifiRequired: false,
40 );
41 }
42
43 final translator = OnDeviceTranslator(
44 sourceLanguage: TranslateLanguage.english,
45 targetLanguage: targetLanguage,
46 );
47
48 final result = await translator.translateText(sourceText);
49 translator.close();
50 return result;
51}

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 working example

Real-Time Translation Architecture
1Cloud Function: translateText (HTTPS onRequest)
2================================================
3Input: sourceText, targetLanguage, contentId (optional)
4Output: translatedText, detectedLanguage, fromCache
5
6Flow:
7 1. Check Firestore translation_cache/{contentId}_{lang}
8 2. If cached return cached text immediately
9 3. Call Translation API v3:
10 POST https://translation.googleapis.com/v3/projects/{id}:translateText
11 Body: { contents: [text], targetLanguageCode: lang }
12 Auth: API key via query param (server-side only)
13 4. Cache result in Firestore
14 5. Return translatedText
15
16Firestore Schema
17=================
18Message / review / post document:
19 content: String (original text)
20 authorId: String
21 createdAt: Timestamp
22 translations: Map
23 en: 'Original English text'
24 es: 'Texto traducido en español'
25 fr: 'Texte traduit en français'
26
27translation_cache/{contentId}_{lang}
28 text: String
29 sourceLanguage: String
30 targetLanguage: String
31 cachedAt: Timestamp
32
33FlutterFlow UI Layout
34======================
35Column (Backend Query: messages)
36 Text (content original)
37 Row (translate controls)
38 DropDown (language selector Page State: selectedLanguage)
39 IconButton (translate icon)
40 Action Flow:
41 1. Update Page State isTranslating = true
42 2. Check translations[selectedLanguage] (Custom Fn)
43 3. If empty Call translateText API
44 Update Page State translatedText = response
45 Update Firestore translations map
46 4. Update Page State isTranslating = false
47 ConditionalColumn (visible when showTranslation)
48 Text (translatedText Page State)
49 TextButton ('Show original' showTranslation = false)
50
51Page State Variables
52=====================
53selectedLanguage: String initial: 'en'
54translatedText: String initial: ''
55showTranslation: Boolean initial: false
56isTranslating: Boolean initial: false
57useOfflineTranslation: Boolean initial: false

Common mistakes

Why it's a problem: Translating every text widget on every page load automatically without caching, resulting in hundreds of API calls per user session

How to avoid: 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.

Why it's a problem: Putting the Google Cloud Translation API key directly in FlutterFlow's API Manager headers to call the Translation API from the client

How to avoid: 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.

Why it's a problem: Assuming the Translation API auto-detects the source language correctly for short texts like single words or product titles

How to avoid: 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

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I am building a FlutterFlow chat app and want to add real-time translation for messages. Write a Firebase Cloud Function in Node.js that accepts sourceText, targetLanguage, and contentId, checks a Firestore translation_cache collection first, and if not cached calls the Google Cloud Translation API v3 endpoint (https://translation.googleapis.com/v3/projects/{projectId}:translateText) and caches the result. Also write a Dart Custom Action using the google_mlkit_translation package for on-device offline translation with model download management.

FlutterFlow Prompt

Add a translate button below each message in the chat ListView. On tap, call the TranslationService API with the message content and the selected language from the DropDown at the top of the page. Display the translated text in a secondary Text widget below the original message, and show a CircularProgressIndicator while the translation is loading.

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.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.