Localization
Deliver flow content in your users' native language with multi-language support.
Localization
Setgreet supports multi-language flows so your in-app experiences reach users in their native language. You create a flow once in your default language, then add translations for any additional languages you need -- without duplicating the flow.
How localization works
Every flow has a base language: the language you write it in. It is English (US) unless you choose another under Written in in the Localization modal. Localizations are stored as translation layers on top of the base content: for each additional language, you provide translated values for the text properties across the flow.
When the SDK requests a flow, it sends the user's language and Setgreet selects the matching translation (see Language detection). If no translation exists for that language, the base content is shown.
Adding a localization
- Open a flow in the flow builder.
- Open the flow menu in the top bar and click Localization.
- In the Localization modal, click Add Language and choose a target language.
- Enter translated content for each text field across all screens in the flow (titles, body text, button labels, input placeholders, option labels).
- Save to apply the translations.
Each language has its own tab, with the flow's text next to the translation, so you can translate every screen's content in one place.
Setgreet supports 100+ languages. The language list uses standard locale codes (e.g., en, es, fr, ja, de,
pt-BR).
Editing the flow's text
The base language's tab edits the flow's own text, not a translation. Your changes appear in the editor straight away, and on a published flow they reach users when you publish, like any other edit.
An option with no value can't be edited there, because its label is also the answer that gets recorded.
Auto-translate with AI
Instead of filling in every field by hand, you can ask Setgreet's AI to translate a flow for you. Open the Build with AI chat in the editor and describe what you want, for example "translate this flow into French, German, and Japanese."
Before anything runs, the assistant shows you exactly what the job covers and what it costs:
- It resolves the target languages (the ones you name, or your flow's current languages if you just say "translate the flow").
- It counts the text it will translate and shows the credit cost in a confirmation card.
- You confirm, and the translation runs. New languages are added automatically and the translated fields appear in the Localization modal, ready for you to review or tweak.
A few things worth knowing:
- Fills the gaps by default. Auto-translate only fills text that is missing in each target language, so your existing or hand-edited translations are left untouched. Ask it to "re-translate everything" if you want to overwrite.
- Keeps your variables intact. Binding expressions like
{{user.firstName}}are preserved exactly in every translation, so personalized sentences keep working in each language. - You stay in control. Auto-translate is a starting point. Every translated field stays fully editable in the Localization modal, so you can refine tone or fix nuance before you publish.
Credit cost scales with the size of the job (the amount of text times the number of languages), and is always shown before you confirm. AI auto-translate is rolling out gradually; if you do not see it in the editor yet, it is not enabled for your workspace.
What gets localized
Localization applies to all text-based component properties:
| Component | Localizable properties |
|---|---|
| Text | Text content |
| Button | Label text |
| TextInput | Label, placeholder and helper text |
| Dropdown, MultiSelect | Label, placeholder and option labels |
| RadioGroup | Label and option labels |
| Quiz | Question, search text and option labels |
| Chip | Option labels |
| SegmentedControl | Option labels, descriptions and badges |
| Carousel | Item titles and descriptions |
| Checkbox, Switch | Label and description |
| NPS | Question and scale labels |
| Rating | Label and description |
Non-text properties like colors, sizes, layout settings, and images are not localized -- they stay the same across all languages.
An option's value is never translated, so the answer you record is the same in every language. Translations follow the option's value, so reordering options keeps each translation on the right option. Options filled from a Data Source come from your API and are not translated.
Built-in text
Text the SDK provides itself, such as default placeholders, date picker buttons, screen reader labels, and paywall period and trial words, appears in the language of the translation shown. If no translation matches, it follows the language chosen under Written in, otherwise the user's own language.
Uppercase and lowercase styling, dates and numbers follow the translation shown or the language chosen under Written in, so Turkish uppercase keeps its dotted İ.
Built-in text is available in 56 locales. Any other language shows it in English. Text you set on a component always wins over the built-in version.
Language detection
Every flow request carries a language, for identified and anonymous users alike. Setgreet uses the first of these that is set:
- The language your app chose with
setLocale(for example from an in-app language picker). - The
localepassed toidentifyUserfor the current user in this session. - The locale saved for the user at an earlier
identifyUser. - The device language (e.g.,
es-MX).
Setgreet looks for that language in the flow's localizations, first as an exact match and then as the closest variant of the same language. If there is none, the flow renders in its base language.
You do not need to write any language-detection code: without setLocale or a locale on identifyUser, users get flows in their device language, including anonymous users who were never identified. identifyUser saves a locale for the user only when you pass one; it never stores the device language. See User Identification for the setLocale and identifyUser code on each platform.
A user on es-MX gets your es or es-ES translation when there is no es-MX. A variant in a different script is
never used, so a zh-Hant user does not get zh-Hans.
Base language and fallback
The base language is the content you build in the flow editor before adding any translations, and it is used when no translation matches the user's language. To change it, pick a language under Written in in the Localization modal. A language that already has a translation can't be chosen until you remove that translation.
Fallback happens in two places:
- Locale not translated -- if there is no translation for the user's locale on a screen, the entire screen renders in the base language.
- Missing translation within a locale -- if a specific text property was not translated for a locale (for example, a button label was skipped), that individual property renders in the base language while the rest of the translated content is shown.
This means partially translated screens still render correctly -- untranslated properties show the original text rather than blank content.
When you edit the base content of a screen after adding translations, the stored translations do not update automatically. Users keep seeing the old translated text until it is updated. The Localization modal marks translations it knows are out of date with "The flow text has changed" on each language's tab. Update the translation, or choose Still correct to clear the mark. Not every translation can be marked (one that came with a template, for example), so review all language versions whenever you change the original.
Variable bindings in localized text
Localization and variable bindings work together. When you translate a screen, include the same binding expressions in your translated text:
English (base):
Welcome back, {{user.firstName}}!Spanish translation:
Bienvenido de nuevo, {{user.firstName}}!Japanese translation:
おかえりなさい、{{user.firstName}}さん!The SDK resolves the binding expressions after selecting the appropriate language, so the user sees their name in the correctly localized sentence.
Best practices
- Start with your primary language. Build and test the entire flow in your default language first. Add translations once the content is stable.
- Use a consistent base language. Pick one base language across all flows (typically English) to keep your workflow predictable.
- Translate all screens in a flow. A flow where some screens are translated and others are not creates a jarring experience.
- Account for text length. Translations often differ in length. German text is typically longer than English; Japanese may be shorter. Preview your screens in each language to check for overflow or awkward spacing.
- Keep binding expressions identical. When translating, copy the
{{source.path}}expressions exactly. A typo in a binding expression means the value will not resolve. - Update translations when base content changes. There is no automatic sync between base content and translations. When you edit the original text, review all language versions.