Repository navigation
feat: poll translations (#3917) - #3941
Merged
Merged
Conversation
## 🎯 Goal The backend now auto-translates polls, and `stream-chat` exposes the translations as `name_i18n` on the poll, `text_i18n` on options and `answer_text_i18n` on comments. They're already in our `^9.54.4`, so no bump is needed. Until now the SDK always showed the original text. With this PR, polls show in the user's language, the same way auto-translated message text already does. React counterpart: GetStream/stream-chat-react#3340. Ticket: https://linear.app/stream/issue/REACT-1344/support-automatic-poll-translations-in-the-react-sdk ## 🛠 Implementation details The user's language is `client.user.language`, the same as for messages. Any text without a translation falls back to the original. Translated: - the question in the poll header and in the all-options and results dialogs - option text in the message and in the results, including the vote button's accessibility label - comments in the answers list - the poll previews in the channel list, quoted replies and the thread list ("created: …", "voted: …") There's no "View original" toggle. v9 has none for messages either, so polls always show the translation, like messages do. Editing your own comment still prefills the original text, not the translation. API changes, all additive: - New `usePollTextTranslation()` hook. It returns `translate(original, i18n)`, for custom poll components. - `usePollState()` also returns `nameI18n`. The `<lang>_text` lookup lives in one internal helper, `getTranslatedText`, and `useTranslatedMessage` now uses it too. One edge case changes: a message whose `i18n` has the user's language key set to `undefined` now shows the original text instead of nothing. Offline DB: - The `poll` table gets `name_i18n` and `description_i18n` columns. Option and comment translations were already stored, inside the options and answers JSON. The description isn't displayed anywhere yet; it's stored so the poll round-trips intact. - Both columns are always written, as `null` when the poll has no translation. The upsert skips `undefined` values, so leaving them out would keep a stale translation after the question is edited. - `dbVersion` goes from 16 to 17, so the offline DB is rebuilt once after upgrade, as with earlier schema changes. The cache is fetched again, and offline actions that haven't synced yet are dropped. ## 🎨 UI Changes The layout is unchanged; translated text replaces the original. ## 🧪 Testing Unit tests cover: - translated, partially translated and untranslated polls, in the message and in the dialogs - a translation arriving through `poll.updated` - the channel list and message previews - offline storage: kept, replaced, cleared, and a poll that never had translations On the iOS simulator I checked the poll message, the results and comments dialogs, and the channel preview, including a real vote. The demo app doesn't produce poll translations, so I injected `poll.updated` events with translations into the running client. Not checked on Android, and not checked with offline mode on a device. To try it, you need an app with auto-translation enabled and a user whose `language` differs from the poll's. ## ☑️ Checklist - [ ] I have signed the [Stream CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) (required) - [x] PR targets the `develop` branch - [ ] Documentation is updated - [ ] New code is tested in main example apps, including all possible scenarios - [ ] SampleApp iOS and Android - [ ] Expo iOS and Android
Contributor
SDK Size
|
oliverlaz
approved these changes
Nov 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🎯 Goal
The backend now auto-translates polls, and
stream-chatexposes the translations asname_i18non the poll,text_i18non options andanswer_text_i18non comments. They're already in our^9.54.4, so no bump is needed. Until now the SDK always showed the original text. With this PR, polls show in the user's language, the same way auto-translated message text already does.React counterpart: GetStream/stream-chat-react#3340.
Ticket:
https://linear.app/stream/issue/REACT-1344/support-automatic-poll-translations-in-the-react-sdk
🛠 Implementation details
The user's language is
client.user.language, the same as for messages. Any text without a translation falls back to the original.Translated:
There's no "View original" toggle. v9 has none for messages either, so polls always show the translation, like messages do. Editing your own comment still prefills the original text, not the translation.
API changes, all additive:
usePollTextTranslation()hook. It returnstranslate(original, i18n), for custom poll components.usePollState()also returnsnameI18n.The
<lang>_textlookup lives in one internal helper,getTranslatedText, anduseTranslatedMessagenow uses it too. One edge case changes: a message whosei18nhas the user's language key set toundefinednow shows the original text instead of nothing.Offline DB:
polltable getsname_i18nanddescription_i18ncolumns. Option and comment translations were already stored, inside the options and answers JSON. The description isn't displayed anywhere yet; it's stored so the poll round-trips intact.nullwhen the poll has no translation. The upsert skipsundefinedvalues, so leaving them out would keep a stale translation after the question is edited.dbVersiongoes from 16 to 17, so the offline DB is rebuilt once after upgrade, as with earlier schema changes. The cache is fetched again, and offline actions that haven't synced yet are dropped.🎨 UI Changes
The layout is unchanged; translated text replaces the original.
🧪 Testing
Unit tests cover:
poll.updatedOn the iOS simulator I checked the poll message, the results and comments dialogs, and the channel preview, including a real vote. The demo app doesn't produce poll translations, so I injected
poll.updatedevents with translations into the running client. Not checked on Android, and not checked with offline mode on a device.To try it, you need an app with auto-translation enabled and a user whose
languagediffers from the poll's.☑️ Checklist
developbranch🎯 Goal
🛠 Implementation details
🎨 UI Changes
iOS
Android
🧪 Testing
☑️ Checklist
developbranch