Skip to main content
RapidDev - Software Development Agency
bubble-tutorial

How to build a language translation system in Bubble.io: Step-by-Step Guide

Build a complete translation management system in Bubble with an input interface for source text, a workflow that triggers API-based translation, a database structure to store translations per language, and a user-facing language selector. This lets non-technical founders create multilingual apps where content is translated on demand and stored for instant retrieval.

What you'll learn

  • How to design a data structure for storing multilingual content
  • How to build a translation input interface in the Bubble editor
  • How to trigger API translations and store the results
  • How to add a user-facing language selector that switches displayed content
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner8 min read20-25 minAll Bubble plans (translation API required)March 2026RapidDev Engineering Team
TL;DR

Build a complete translation management system in Bubble with an input interface for source text, a workflow that triggers API-based translation, a database structure to store translations per language, and a user-facing language selector. This lets non-technical founders create multilingual apps where content is translated on demand and stored for instant retrieval.

Overview: Building a Translation System in Bubble

This tutorial walks you through building a translation management system in Bubble. You will create data types to store content in multiple languages, build an admin interface for inputting source text and triggering translations, store translation results in the database, and add a front-end language selector that dynamically switches displayed content. This guide is for non-technical founders building apps that need multilingual support.

Prerequisites

  • A Bubble account with an existing app
  • The API Connector plugin installed with a translation API configured (e.g., Google Translate)
  • Basic understanding of Bubble data types and workflows
  • Familiarity with Repeating Groups and dynamic data display

Step-by-step guide

1

Create the translation data structure

Go to the Data tab and click New type. Create a data type called Content with fields: key (text, a unique identifier like homepage_hero_title), default_text (text, the original language content). Then create a second data type called Translation with fields: content (type: Content), language_code (text, e.g., es, fr, de), translated_text (text), and is_approved (yes/no). This separates your source content from its translations and supports unlimited languages.

Pro tip: Use descriptive keys like page_section_element (e.g., pricing_hero_subtitle) so translators can understand context without seeing the page.

Expected result: Two data types exist: Content (with key and default_text) and Translation (with content, language_code, translated_text, and is_approved).

2

Create the admin translation interface

Go to the Design tab and create a new page called admin-translations. Add a Repeating Group with data source Do a search for Contents. In each cell, display the Content's key and default_text. Add a Dropdown for target language populated with an Option Set called Languages (with options like en, es, fr, de, ja). Add a Translate button in each cell. Below the default text, add a Text element to show the existing translation if one exists: Search for Translations (content = Current cell's Content, language_code = Dropdown's value):first item's translated_text.

Expected result: An admin page displays all content entries with their source text, a language selector, and a translate button per entry.

3

Build the translation workflow

Go to the Workflow tab. Create a workflow: When Button Translate is clicked. First, check for an existing translation: Do a search for Translations (content = Current cell's Content, language_code = Dropdown Language's value). Add the API call action with Only when the search count is 0: call your translation API with q = Current cell's Content's default_text and target = Dropdown Language's value. Then Create a new Translation with content = Current cell's Content, language_code = Dropdown's value, translated_text = Result of API step's translatedText, and is_approved = no.

Expected result: Clicking Translate calls the API only if no cached translation exists, and saves the result to the database.

4

Add a manual edit and approval flow

In the Repeating Group cell on the admin page, add a Multiline Input pre-filled with the existing translation text. Add an Approve button next to it. Create a workflow: When Button Approve is clicked — Make changes to the Translation (search for the matching Translation record), set translated_text = Multiline Input's value and is_approved = yes. This lets translators review and correct machine translations before they go live.

Pro tip: Add a conditional on the Approve button background: When this Translation's is_approved is yes, change the color to green to give visual feedback.

Expected result: Admins can edit machine-translated text and mark translations as approved.

5

Build the user-facing language selector

On your public-facing pages, add a Dropdown or set of flag icons in the header. When the user selects a language, set a Custom State on the page called current_language (type: text) to the selected language code. Alternatively, use a URL parameter called lang so the language persists across page navigation. For each text element that needs translation, set its content to: Search for Translations (content = [the Content entry for this element], language_code = Page's current_language, is_approved = yes):first item's translated_text. Add a fallback: if empty, show the Content's default_text.

Expected result: Users can select a language and all translated content on the page updates to the chosen language.

6

Add a bulk translation workflow for new languages

Go to the Workflow tab and access Backend workflows from the Pages dropdown. Create a backend workflow called bulk_translate with parameters content_id (text) and target_lang (text). In it, look up the Content by ID, call the translation API, and save the result. Then create a frontend workflow that loops through all Content records: use Schedule API workflow on a list with the list of Content IDs and the target language. This lets you translate all content to a new language in one click.

Pro tip: Add a pause of 200ms between API calls in the recursive workflow to avoid hitting rate limits on the translation API.

Expected result: A single button click translates all content entries to a new language via a scheduled backend workflow.

Complete working example

Workflow summary
1TRANSLATION SYSTEM WORKFLOW SUMMARY
2======================================
3
4DATA TYPES:
5 Content
6 - key (text) unique identifier e.g. homepage_hero_title
7 - default_text (text) original language content
8
9 Translation
10 - content (Content) linked source content
11 - language_code (text) ISO code e.g. es, fr, de
12 - translated_text (text) the translated string
13 - is_approved (yes/no) human review status
14
15 Option Set: Languages
16 - English (en)
17 - Spanish (es)
18 - French (fr)
19 - German (de)
20 - Japanese (ja)
21
22ADMIN PAGE (admin-translations):
23 Repeating Group: Do a search for Contents
24 Cell contents:
25 - Text: Current cell's Content's key
26 - Text: Current cell's Content's default_text
27 - Dropdown: Languages Option Set
28 - Button: Translate
29 - Multiline Input: existing translation
30 - Button: Approve
31
32WORKFLOW 1: Translate single entry
33 Event: Button Translate is clicked
34 Step 1: Search for existing Translation
35 content = Current cell's Content
36 language_code = Dropdown's value
37 Step 2: Call Translation API
38 Only when: Step 1's count is 0
39 q = Current cell's Content's default_text
40 target = Dropdown's value
41 Step 3: Create new Translation
42 Only when: Step 1's count is 0
43 content = Current cell's Content
44 language_code = Dropdown's value
45 translated_text = Result of Step 2's translatedText
46 is_approved = no
47
48WORKFLOW 2: Approve translation
49 Event: Button Approve is clicked
50 Step 1: Make changes to Translation
51 translated_text = Multiline Input's value
52 is_approved = yes
53
54WORKFLOW 3: Bulk translate (Backend)
55 Name: bulk_translate
56 Parameters: content_id (text), target_lang (text)
57 Step 1: Look up Content by unique ID
58 Step 2: Call Translation API
59 Step 3: Create Translation record
60
61USER-FACING LANGUAGE SELECTOR:
62 Custom State on page: current_language (text)
63 Each text element:
64 Search for Translations
65 (content = matching Content, language_code = current_language,
66 is_approved = yes):first item's translated_text
67 Fallback: Content's default_text

Common mistakes when building a language translation system in Bubble.io: Step-by-Step Guide

Why it's a problem: Storing translations as fields on the Content data type instead of separate records

How to avoid: Use a separate Translation data type linked to Content with a language_code field so you can add unlimited languages without schema changes.

Why it's a problem: Showing unapproved machine translations to end users

How to avoid: Filter user-facing translation searches by is_approved = yes and fall back to the default language when no approved translation exists.

Why it's a problem: Not caching translations and calling the API on every page load

How to avoid: Store translations in the database and only call the API when a translation does not yet exist for that content and language combination.

Best practices

  • Use a Content data type with unique keys to decouple translations from page structure
  • Store translations as separate records with language codes for unlimited language scalability
  • Add an approval workflow so human reviewers can verify machine translations before they go live
  • Cache all translations in the database to avoid repeated API calls
  • Use URL parameters for language selection so the chosen language persists across page navigation
  • Fall back to the default language when a translation is not available or not yet approved
  • Create an Option Set for supported languages to keep codes consistent across the app

Still stuck?

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

ChatGPT Prompt

I am building a Bubble.io app that needs multilingual support. I want an admin interface where I can manage source text and trigger translations via API, store translations per language in the database, and let users switch languages on the frontend. How should I structure the data types and workflows?

Bubble Prompt

Build a translation management system for my app. Create Content and Translation data types, an admin page to manage and translate entries, and a user-facing language selector that dynamically switches displayed text based on the selected language.

Frequently asked questions

How many languages can this system support?

There is no hard limit. Each language is a record in the Translation data type, so you can add as many as your translation API supports — typically 100+ for Google Translate.

Can I use a free translation API instead of Google?

Yes. LibreTranslate is a free open-source option you can self-host or use via their public API. Configure it in the API Connector the same way as Google Translate.

How do I handle right-to-left languages like Arabic or Hebrew?

Add a direction attribute to your text elements. Use a conditional: When current_language is ar or he, set the text alignment to right and add dir=rtl via an HTML element wrapping the text.

Will translated content appear in search engine results?

For SEO, you need to create separate pages or use URL parameters per language and add hreflang tags. Bubble's SEO settings support dynamic meta titles and descriptions that can pull from your Translation data type.

Can RapidDev help build a multilingual app?

Yes. RapidDev specializes in Bubble development and can help you build production-ready multilingual apps with automatic translation, human review workflows, and SEO-optimized language routing.

How do I translate dynamic user-generated content?

For user content like reviews or messages, trigger the translation API in a backend workflow when new content is created. Store the translation as a related record and display it based on the viewer's language preference.

What happens if a translation is missing for a content entry?

The system falls back to showing the default_text from the Content data type. This ensures users always see something meaningful even if a translation has not been created yet.

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.