# How to build a multilingual site in Bubble

- Tool: Bubble
- Difficulty: Beginner
- Time required: 25-30 min
- Compatibility: All Bubble plans
- Last updated: March 2026

## TL;DR

Build a multilingual site in Bubble using Option Sets or a translations data type to store text in multiple languages, a language switcher UI, and user language preferences. This tutorial covers static text translation, dynamic content translation, and persisting language selection across sessions.

## Overview: Multilingual Sites in Bubble

A multilingual site serves content in multiple languages based on user preference. Bubble does not have built-in i18n, but you can implement translations using Option Sets for static text and database records for dynamic content. This tutorial covers both approaches.

## Before you start

- A Bubble account with an app
- Translations ready for your target languages
- Basic understanding of Option Sets and conditional expressions

## Step-by-step guide

### 1. Create a Language Option Set

Go to Data → Option sets → Create 'Language' with options: en (English), es (Spanish), fr (French), etc. Add a 'label' attribute for display names. On the User data type, add a 'preferred_language' field (type: Language option set, default: en).

**Expected result:** Language options and user preference field are ready.

### 2. Store static translations in Option Sets

Create a 'Translation' Option Set. Each option represents a text key (e.g., nav_home, nav_about, btn_signup). Add attributes for each language: text_en (text), text_es (text), text_fr (text). Enter translated values for each key. This approach is fast (zero WU) since Option Sets are cached.

> Pro tip: For apps with many translations, use a Translation data type instead of an Option Set for easier management.

**Expected result:** Static text translations stored in an Option Set with one attribute per language.

### 3. Build the language switcher

Add a Dropdown in your header with data source: All Languages. Display the label attribute. When the user changes the selection: Make changes to Current User → preferred_language = Dropdown's value. If the user is not logged in, use a custom state or URL parameter to store the selection.

**Expected result:** Users can switch languages from a dropdown in the header.

### 4. Display translated text throughout the app

For every static text element, replace hardcoded text with a dynamic expression. Example: Get option Translation where Display = nav_home, then use a conditional: When language is en → text_en, When language is es → text_es. A cleaner approach: create a utility expression using the :formatted as text operator to select the right attribute based on the language code.

**Expected result:** All static text displays in the user's selected language.

### 5. Translate dynamic database content

For database content (articles, products), add translation fields directly on the Data Type: title_en, title_es, description_en, description_es. Display using conditionals based on the user's language. Alternatively, create a separate Translation data type linking content ID to language code and translated text for more scalable management.

**Expected result:** Dynamic content displays in the user's selected language.

## Complete code example

File: `Workflow summary`

```text
MULTILINGUAL SITE — ARCHITECTURE
==================================

LANGUAGE OPTION SET:
  en (English), es (Spanish), fr (French)

STATIC TEXT (Option Set approach):
  Translation Option Set:
    nav_home: text_en="Home", text_es="Inicio", text_fr="Accueil"
    btn_signup: text_en="Sign Up", text_es="Registrarse", text_fr="S'inscrire"

DYNAMIC CONTENT (database approach):
  Article type: title_en, title_es, description_en, description_es
  OR ContentTranslation type: content_id, language, field_name, value

LANGUAGE DETECTION:
  1. User's preferred_language (if logged in)
  2. URL parameter ?lang=es (for sharing)
  3. Default: en

DISPLAY LOGIC:
  Text element content:
    When language is en → Translation's text_en
    When language is es → Translation's text_es
    When language is fr → Translation's text_fr
```

## Common mistakes

- **Hardcoding text in elements instead of using translations** — Hardcoded text cannot change based on language selection Fix: Replace all static text with dynamic expressions referencing the Translation Option Set
- **Adding too many languages to an Option Set** — Each new language adds an attribute column — Option Sets with 10+ languages become unwieldy Fix: For more than 3-4 languages, use a database Translation data type instead of Option Set attributes
- **Not persisting language selection for logged-out users** — The language resets on every page load if not saved somewhere Fix: Use a URL parameter (?lang=es) or browser localStorage via JavaScript to persist the selection

## Best practices

- Use Option Sets for static text in apps with 2-3 languages for zero-WU performance
- Use a database Translation type for apps with many languages or dynamic content
- Persist language preference on the User record for logged-in users
- Use URL parameters for language sharing and SEO
- Test all pages in every supported language before launching
- Provide a visible language switcher in the header on every page

## Frequently asked questions

### Does Bubble have built-in translation?

Bubble has a Languages section in Settings that supports basic text translation, but it is limited. Most builders use Option Sets or database records for more control.

### Can I auto-detect the user's browser language?

Yes. Use a JavaScript snippet in an HTML element to read navigator.language and set the default language accordingly.

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

Add dir='rtl' via a conditional on the page's HTML element. Also adjust text alignment and layout direction for RTL languages.

### Will multiple languages affect SEO?

For best SEO, use URL parameters (?lang=es) or separate page slugs (/es/about) so search engines can index each language version.

### Can I translate Bubble system messages?

Yes. Go to Settings → Languages tab to translate built-in messages like error texts and email templates.

### Can RapidDev build a multilingual Bubble app?

Yes. RapidDev implements multilingual solutions with translation management, RTL support, and SEO-optimized language routing.

---

Source: https://www.rapidevelopers.com/bubble-tutorial/build-a-multilingual-site-in-bubble
© RapidDev — https://www.rapidevelopers.com/bubble-tutorial/build-a-multilingual-site-in-bubble
