GoLocal!
Open dashboard
Bubble developer guideFree runtime 4.1.23

Safe multilingual search with GoLocal Query

A beginner-friendly guide to the main GoLocal element, the optional GoLocal Query element, Bubble's automatic search controls, and the safest way to keep translated interfaces separate from database logic.

The core concept

A Bubble app normally has one canonical language in which its database labels, Option Set display values, and hard-coded text conditions were created. GoLocal may show those values in another language, but Bubble logic can still expect the canonical value.

Project source

English

Stored category: News

Visitor sees

French

Visible label: Actualités

Bubble searches

News

Normalized source value

Safety rule: the visible Input remains the user-facing and save-facing value. A separate normalized_query is used only where Bubble explicitly needs source-language text.

Which GoLocal element should I use?

The plugin contains two different non-visual Bubble elements. They solve different problems. Most pages need the main GoLocal! element; only pages with a specific text-search problem need GoLocal Query.

Plugin availability: the separate GoLocal Query element is included in the Free/API-key Bubble plugin and works with an active GoLocal SaaS project.

Required translator

GoLocal!

This is the main translation engine. It loads your project, translates page content, displays the language widget, and publishes the current language and translation events.

  • Usually place one instance in a reusable header or another element shared by the page.
  • Use its fields for the API key, widget, excluded IDs/selectors, and source/target behavior.
  • Use its states and events when Bubble must know the selected language or translation status.

Optional logic helper

GoLocal Query

This does not translate the page and it does not display a widget. It converts one visitor-entered search phrase into your app's canonical source-language phrase for Bubble logic.

  • Add it only when a normal Input must search or compare text stored in the project's source language.
  • Use one Query element per independent search Input.
  • Never use normalized_query to save user-created names, titles, descriptions, or messages.
Bubble element or taskWhat to use
Text, Button, Group, reusable UIGoLocal! only
Input that saves user dataOriginal Input value
Plain Input filtering an English text fieldOne GoLocal Query
Bubble SearchBox or DropdownAutomatic
Legacy or Select2 MultiDropdownAutomatic
Multiline Input, Quill, contenteditableOriginal editor value
Repeating Group constraintThing/Option Set/ID first
Email, phone, password, number, date, ID, fileOriginal value
Simple decision: if the value is being displayed, use the main translator. If the value is being saved, use the original Bubble value. If a translated phrase must be matched against source-language text, use a supported automatic control or one dedicated GoLocal Query element.

Preferred Bubble architecture

Whenever possible, build conditions around Bubble Things, Option Set options, unique IDs, or stable codes—not translated display text. Translation should change what a person sees, not the identity of the record.

Best: compare the object

Current cell's Article's Category
is Category News

The visitor may see “Actualités”, but Bubble compares the Category Thing or Option Set option itself.

Use Query only for text matching

Category name contains
GoLocal Query Categories's normalized_query

This is appropriate when the database or an existing condition genuinely searches canonical English text.

Example category set

Canonical EnglishFrench display
NewsActualités
OpinionOpinion
TutorialTutoriel
GuideGuide
ReviewAvis
HistoryHistoire
OtherAutre

Automatic reverse lookup

Free runtime 4.1.23 automatically applies reverse lookup only to Bubble controls whose purpose is selecting or searching an existing value:

Bubble SearchBox
Bubble Dropdown
Legacy Bubble MultiDropdown
Current Select2 MultiDropdown

Visitor types: Actualités

Control matches: News

Visitor continues to see: Actualités

Each supported control has isolated reverse state, including multiple controls on the same page. Do not add a GoLocal Query element just to duplicate this built-in behavior.

Bubble SearchBox

Use it when the visitor searches and selects an existing Bubble Thing. GoLocal helps the translated phrase match the canonical text used by the SearchBox.

Bubble Dropdown

Use it for a single selection from an existing static or dynamic list. The selected option remains the real Bubble value.

Legacy Bubble MultiDropdown

Use it for selecting several existing options in older Bubble apps. Each control is normalized independently.

Select2 MultiDropdown

Use it for current searchable multi-select controls. Typed search text can match source-language option labels without changing ordinary Inputs.

A plain Bubble Input is deliberately not automatic. The plugin cannot safely guess whether an Input is a search box, a person's name, a database title, a conditional value, or text that will be saved. Add GoLocal Query only for the particular Input whose downstream logic requires canonical text.

Using GoLocal Query

Use the non-visual GoLocal Query element when an ordinary Bubble Input intentionally drives a text search, source-language conditional, or backend/API filter.

1

Add one query element for this input

Place it once on the page or in the reusable element that owns the Input. Do not place it in every repeating-group cell.

Element name: GoLocal Query Categories
2

Bind its Query field

Query = Input Category Search's value
Enabled = yes
Debounce (ms) = 180

Bubble automatically updates the element when the dynamic Input value changes. No Input-changed workflow is required.

3

Use normalized_query only in source-language logic

GoLocal Query Categories's normalized_query

Use this value in a repeating-group constraint, advanced filter, text conditional, or API parameter that expects English.

4

Keep saves and validation connected to the Input

Save Category Name = Input Category Search's value

Never replace a normal save value, email check, number calculation, or required-field check with normalized_query.

What happens while the visitor types?

  1. 1The Input changes: Bubble passes the exact current Input value into the Query field.
  2. 2Debounce waits briefly: The default 180 ms prevents a request for every single keystroke.
  3. 3The newest phrase is normalized: For example, “Actualités” is resolved to “News”. Older unfinished requests cannot overwrite the newest result.
  4. 4Bubble receives the states: normalized_query becomes “News”, is_normalizing becomes no, and the normalized event fires.
  5. 5Only the intended logic consumes it: The repeating group, conditional, or API filter uses normalized_query; saves still use the original Input.

Practical Bubble examples

Repeating group

Search English article categories from a French Input

The visitor types Actualités. The database stores News. Set the repeating group's category-name constraint to:

GoLocal Query Categories's normalized_query

Prefer a Category Thing/Option Set selection when available; use text normalization only when the filter really is text-based.

Bubble conditional

Compare with a hard-coded source-language value

When GoLocal Query Status's is_normalizing is no
and GoLocal Query Status's normalized_query is "Archived"

If the condition controls a critical workflow, wait until normalization finishes. For display-only filtering, the raw fallback may be sufficient.

Backend or API

Send a canonical-language query to an endpoint

API parameter q = GoLocal Query Products's normalized_query
Run only when is_normalizing is no

IDs, UUIDs, emails, tokens, dates, and numeric values should bypass GoLocal Query and be sent unchanged.

Complete beginner walkthrough

Filter articles by a translated category name

Assume the app was built in English. The database field Category name contains News, but a French visitor types Actualités into a normal Input.

1. Name the Bubble Input clearly
Input Category Search
2. Add and name one non-visual helper
GoLocal Query Categories
3. Bind the helper field
GoLocal Query Categories → Query
= Input Category Search's value
4. Set the repeating group's text constraint
Search for Articles
Category name = GoLocal Query Categories's normalized_query
5. Keep create/edit workflows unchanged
Create a new Article's title
= Input Article Title's value

Result: the visitor searches in French, Bubble finds the English database value, and no user-entered text is rewritten or saved in another form.

Pages with multiple inputs

Create one GoLocal Query instance for each independent search context. Each instance has its own value, debounce timer, sequence guard, states, and events, so one input cannot overwrite another.

Input Article SearchGoLocal Query ArticlesArticles repeating group
Input Customer SearchGoLocal Query CustomersCustomer API filter
Input Tag FilterGoLocal Query TagsTag condition
Do not reuse one query element for unrelated inputs. If a value must cross a reusable-element boundary, copy that specific element's normalized_query into a dedicated Bubble custom state when its normalized event fires.

What must stay untouched

Use GoLocal Query for

  • Free-form text used to search canonical-language database fields
  • Text conditions that expect an English constant
  • API query parameters whose backend expects English
  • Third-party search controls that expose their typed query to Bubble

Do not use it for

  • Names, titles, comments, descriptions, or user-created tags being saved
  • Quill, rich-text, contenteditable, or Multiline Input content
  • Emails, passwords, phones, IDs, dates, numbers, files, or validation
  • Bubble Things or Option Set objects that can be compared directly

Saved user content displayed later

A protected Input can still be rendered later inside a normal Bubble Text element. Mark the display container with a reusable class such as .gl-user-content and add it to the main GoLocal element's do_not_translate_selectors. For repeating groups, use a class/selector instead of duplicating the same HTML ID across rows.

Fields, states, and events

Fields

Querytext

Bind to one visible Bubble Input's value.

Enabledyes/no

Default yes. When disabled, trimmed text passes through unchanged.

Debounce (ms)number

Default 180. Recommended range for search is 150–250 ms.

States

original_querytext

Exact value received from Bubble before normalization.

normalized_querytext

Canonical source-language value for search or comparison logic.

is_normalizingyes/no

Yes while the newest non-empty query is being resolved.

normalization_foundyes/no

Yes when a source-language mapping was found.

last_errortext

Technical failure message; empty during normal operation.

normalized

Fires after the latest query finishes. Use it when a workflow must wait or copy the result into a custom state.

normalization_failed

Fires for a technical failure. The raw query remains as a usable fallback and details appear in last_error.

Troubleshooting common Bubble setups

normalized_query always equals the raw Input

Confirm that the main GoLocal! element is present and ready, the project source language is configured correctly, and the Query field is bound to the intended Input. An unknown phrase may intentionally use the raw text as a safe fallback.

The repeating group briefly shows the previous result

For strict filtering, show a loading state or run the final search only when the matching Query element’s is_normalizing state is no. The sequence guard prevents an older request from replacing a newer result.

A saved title or description changed

The save workflow is referencing normalized_query or translated display text. Change it back to the original Input, Multiline Input, or rich-text editor value. GoLocal Query is for matching logic only.

Two inputs interfere with one another

Give each independent search Input its own GoLocal Query element. Do not dynamically switch one helper between unrelated Inputs.

A third-party selector does not reverse-match

Automatic support is limited to Bubble SearchBox, Bubble Dropdown, legacy MultiDropdown, and Select2 MultiDropdown. If the third-party control exposes typed text to Bubble, connect that text to a dedicated GoLocal Query element.

Saved user content is translated when displayed later

Add a reusable class such as .gl-user-content to its display container and include that selector in do_not_translate_selectors on the main GoLocal! element.

The Input is inside a repeating group

Do not place one Query element in every cell and do not duplicate HTML IDs. Prefer filtering the repeating group before rendering it; otherwise keep the Query helper outside the repeating group and pass a single selected/search value into it.

Acceptance checklist

  1. 1Search for the same record in English and French.
  2. 2Type quickly and confirm an older result never replaces a newer one.
  3. 3Clear the Input and confirm the repeating group resets.
  4. 4Switch language while the Input is not empty.
  5. 5Test two independent search Inputs on the same page.
  6. 6Save a French title with accents and confirm the exact text is stored.
  7. 7Type and paste into Quill; neither path should be rewritten.
  8. 8Test an unknown query and confirm the raw fallback keeps the page usable.
  9. 9Confirm every save workflow uses the original Input value.
  10. 10Confirm critical source-language workflows wait for is_normalizing = no.

Quick decision rule

Display and saving use the Input. Canonical text matching uses GoLocal Query.

If Bubble can compare a Thing, Option Set option, ID, or stable code, use that object directly. Add GoLocal Query only when a translated free-form text value must be matched against canonical source-language text.