Building a multilingual app in Bubble involves using Option Sets for static text translations, translating dynamic database content with a Translation Data Type, implementing a language switcher that persists across sessions, and structuring your app so adding new languages requires minimal rework. This tutorial covers the complete multilingual architecture from data design through UI implementation.
Overview: Building a Multilingual App in Bubble
This tutorial shows how to build app-level multilingual support in Bubble. You will create a translation system for both static UI text and dynamic database content, with a language switcher that remembers user preferences.
Prerequisites
- A Bubble app with content to translate
- An understanding of Bubble Option Sets and Data Types
- The translated text for at least two languages
- Basic familiarity with Bubble custom states and conditions
Step-by-step guide
Set up the language infrastructure
Set up the language infrastructure
Create an Option Set called Language with options: English, Spanish, French (or your target languages). Each option has attributes: code (text — 'en', 'es', 'fr'), name (text — 'English', 'Español', 'Français'), flag_emoji (text — optional). Add a preferred_language field (type: Language Option Set) to the User Data Type, defaulting to English. Create a page-level custom state called 'active_language' (type: Language) that loads from Current User's preferred_language on page load.
Expected result: The language infrastructure is in place with Language Option Set and user preference tracking.
Create translations for static UI text using Option Sets
Create translations for static UI text using Option Sets
Create an Option Set called UIText with an option for each static text element in your app (e.g., btn_login, nav_home, label_email, msg_welcome). Add an attribute for each language: en_text, es_text, fr_text. Populate each option with the translated strings. In your UI, instead of typing static text, use expressions: Get an option of UIText where Display = 'btn_login's [active_language code]_text. This approach loads instantly (Option Sets are cached) and costs zero workload units.
Pro tip: Use Bubble's built-in App Text / Translation feature (Settings → Languages tab) as an alternative. It provides a dedicated translation interface that may be simpler for apps with many text strings.
Expected result: All static UI text dynamically switches between languages using Option Set lookups.
Handle dynamic database content translations
Handle dynamic database content translations
For user-generated or admin-managed content that needs translation (product descriptions, blog posts), create a Translation Data Type with fields: content_type (text), content_id (text), language (Language), field_name (text), translated_text (text). When displaying dynamic content, search for a Translation matching the content ID, field name, and active language. If found, show the translated text. If not found, fall back to the original language. For admin content, build a translation editor where admins enter translations for each language.
Expected result: Dynamic database content displays in the user's selected language with fallback to the default.
Build the language switcher
Build the language switcher
Add a Dropdown or clickable flag icons in your header (reusable element). The Dropdown data source is All Languages from the Option Set. When the user selects a language, the workflow: (1) Sets the page's active_language state. (2) If the user is logged in, makes changes to Current User's preferred_language. This persists their choice across sessions. All text elements and content displays on the page update immediately since they reference the active_language state. For non-logged-in users, store the preference in a cookie or local storage via a plugin.
Expected result: Users can switch languages from a header dropdown, with their preference saved for future sessions.
Complete working example
1MULTILINGUAL APP ARCHITECTURE2===============================34LANGUAGE OPTION SET:5 English: code='en', name='English'6 Spanish: code='es', name='Español'7 French: code='fr', name='Français'89STATIC TEXT (Option Set approach):10 UIText Option Set:11 btn_login: en_text='Log In', es_text='Iniciar Sesión', fr_text='Connexion'12 nav_home: en_text='Home', es_text='Inicio', fr_text='Accueil'13 msg_welcome: en_text='Welcome!', es_text='¡Bienvenido!', fr_text='Bienvenue!'1415 Usage in elements:16 Text = UIText btn_login's [active_language's code]_text1718DYNAMIC CONTENT (Data Type approach):19 Translation:20 content_type, content_id, language, field_name, translated_text2122 Usage:23 Search Translations where content_id = item's ID24 AND language = active_language AND field_name = 'description'25 If found: show translated_text26 If not: show original content2728LANGUAGE SWITCHER:29 Header dropdown: All Languages30 On change:31 1. Set page state active_language = selected32 2. If logged in: Update User preferred_language33 3. If not logged in: Save to cookie/local storage3435PAGE LOAD:36 Set active_language = Current User's preferred_language37 Fallback: English (default)Common mistakes when building a multilingual app in Bubble.io: Step-by-Step Guide
Why it's a problem: Hardcoding text in UI elements instead of using a translation system
How to avoid: Use Option Sets for static text or Bubble's built-in Translation feature so all text is managed centrally
Why it's a problem: Creating separate pages for each language
How to avoid: Use a single set of pages with dynamic text that changes based on the active language selection
Why it's a problem: Not providing a fallback when a translation is missing
How to avoid: Always fall back to the default language (English) when a translation is not found
Best practices
- Use Option Sets for static UI text — they load instantly with zero WU cost
- Use a Translation Data Type for dynamic content that needs per-language versions
- Always provide a fallback to the default language for missing translations
- Store language preference on the User record for logged-in users
- Build the language switcher in a reusable header for app-wide access
- Use Bubble's built-in Languages tab for simpler translation management
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to make my Bubble.io app support English, Spanish, and French. How do I set up translations for both static UI text and dynamic database content, with a language switcher that saves the user's preference?
Create a Language Option Set with English, Spanish, and French. Create a UIText Option Set with translated strings for common UI elements. Build a language switcher dropdown in the header that sets a page custom state and saves the preference to the User record. Display text dynamically based on the active language.
Frequently asked questions
Should I use Option Sets or Bubble's built-in Translation feature?
Bubble's Languages tab (Settings → Languages) is simpler for apps with many text strings. Option Sets give you more control and work well for smaller apps. Both approaches are valid.
How do I handle right-to-left (RTL) languages like Arabic?
Add a direction attribute to the Language Option Set (ltr/rtl). Apply a Conditional on the page: when active_language's direction is 'rtl', add an HTML element that sets dir='rtl' on the body.
Can I auto-detect the user's language?
Yes. Use JavaScript to read navigator.language and match it to your supported languages. Set the active_language to the detected language on first visit.
How do I translate content generated by users?
For automatic translation, use the Google Translate API via the API Connector. For curated translations, build a translation editor where admins enter translations for each piece of content.
Can RapidDev help build a multilingual Bubble app?
Yes. RapidDev can implement complete multilingual systems with translation management, language switching, RTL support, and SEO optimization for each language in your Bubble app.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation