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
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.
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.
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 NewsThe 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_queryThis is appropriate when the database or an existing condition genuinely searches canonical English text.
Example category set
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:
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.
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.
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 CategoriesBind its Query field
Query = Input Category Search's value
Enabled = yes
Debounce (ms) = 180Bubble automatically updates the element when the dynamic Input value changes. No Input-changed workflow is required.
Use normalized_query only in source-language logic
GoLocal Query Categories's normalized_queryUse this value in a repeating-group constraint, advanced filter, text conditional, or API parameter that expects English.
Keep saves and validation connected to the Input
Save Category Name = Input Category Search's valueNever replace a normal save value, email check, number calculation, or required-field check with normalized_query.
What happens while the visitor types?
- 1The Input changes: Bubble passes the exact current Input value into the Query field.
- 2Debounce waits briefly: The default 180 ms prevents a request for every single keystroke.
- 3The newest phrase is normalized: For example, “Actualités” is resolved to “News”. Older unfinished requests cannot overwrite the newest result.
- 4Bubble receives the states: normalized_query becomes “News”, is_normalizing becomes no, and the normalized event fires.
- 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_queryPrefer 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 noIDs, 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.
Input Category SearchGoLocal Query CategoriesGoLocal Query Categories → Query
= Input Category Search's valueSearch for Articles
Category name = GoLocal Query Categories's normalized_queryCreate a new Article's title
= Input Article Title's valueResult: 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 groupInput Customer SearchGoLocal Query CustomersCustomer API filterInput Tag FilterGoLocal Query TagsTag conditionnormalized 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
QuerytextBind to one visible Bubble Input's value.
Enabledyes/noDefault yes. When disabled, trimmed text passes through unchanged.
Debounce (ms)numberDefault 180. Recommended range for search is 150–250 ms.
States
original_querytextExact value received from Bubble before normalization.
normalized_querytextCanonical source-language value for search or comparison logic.
is_normalizingyes/noYes while the newest non-empty query is being resolved.
normalization_foundyes/noYes when a source-language mapping was found.
last_errortextTechnical 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
- 1Search for the same record in English and French.
- 2Type quickly and confirm an older result never replaces a newer one.
- 3Clear the Input and confirm the repeating group resets.
- 4Switch language while the Input is not empty.
- 5Test two independent search Inputs on the same page.
- 6Save a French title with accents and confirm the exact text is stored.
- 7Type and paste into Quill; neither path should be rewritten.
- 8Test an unknown query and confirm the raw fallback keeps the page usable.
- 9Confirm every save workflow uses the original Input value.
- 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.