Add Google Translate integration with language switcher#1909
Add Google Translate integration with language switcher#1909
Conversation
|
Preview is available here: |
There was a problem hiding this comment.
Pull request overview
Adds a cookie-driven language switcher powered by the Google Translate website widget, while protecting technical Stellar values (XDR, hashes, network names) from being machine-translated.
Changes:
- Add Google Translate bootstrap (mount point + scripts) and update CSP/global styles to support the injected widget.
- Add
LanguageSelectorUI and translation helpers (googtranscookie set/reset/read). - Mark technical UI regions as non-translatable and update/extend Playwright e2e coverage.
Reviewed changes
Copilot reviewed 34 out of 34 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/e2e/savedRequests.test.ts | Updates expected empty-state copy for saved RPC methods. |
| tests/e2e/networkSelector.test.ts | Updates expected network switch button text casing. |
| tests/e2e/languageSelector.test.ts | Adds new e2e coverage for language selector behaviors. |
| tests/e2e/fundAccountPage.test.ts | Updates expected network switch button text casing. |
| src/styles/globals.scss | Hides/suppresses Google-injected Translate UI and adjusts sidebar overflow for the dropdown. |
| src/middleware.ts | Expands CSP allowlists for Google Translate resources. |
| src/helpers/translate.ts | Adds helpers to set/reset/read the googtrans cookie and reload. |
| src/constants/networkLimits.ts | Updates Soroban state window values for mainnet/testnet/futurenet. |
| src/components/layout/LayoutSidebarContent.tsx | Adds the LanguageSelector to the sidebar bottom section. |
| src/components/XdrTypeSelect/index.tsx | Prevents translation of XDR type options list. |
| src/components/XdrLink.tsx | Wraps rendered XDR string in NoTranslate. |
| src/components/TxResponse/index.tsx | Wraps response values in NoTranslate. |
| src/components/TxHashLink.tsx | Wraps rendered transaction hash in NoTranslate. |
| src/components/SwitchNetworkButtons.tsx | Wraps network names in NetworkName to prevent translation. |
| src/components/StellarDataRenderer/index.tsx | Prevents translation of rendered Stellar JSON/XDR-derived structures. |
| src/components/PrettyJson/index.tsx | Prevents translation of JSON rendering output. |
| src/components/NoTranslate.tsx | Introduces a reusable non-translation wrapper component. |
| src/components/NetworkSelector/index.tsx | Wraps network names in NetworkName in the submit button label. |
| src/components/NetworkName.tsx | Introduces a network-name-specific non-translation wrapper. |
| src/components/NetworkIndicator/index.tsx | Prevents translation of the network indicator label. |
| src/components/LanguageSelector/styles.scss | Adds sidebar dropdown/drop-up styling for language selection. |
| src/components/LanguageSelector/index.tsx | Adds the language selector UI and cookie-driven selection behavior. |
| src/components/Home/Networks.tsx | Wraps network names in NetworkName in home network switching UI. |
| src/components/GoogleTranslateMountPoint.tsx | Imperatively creates the Google Translate mount node post-hydration. |
| src/components/FloatNotification/index.tsx | Allows notification descriptions to be ReactNode (for embedded NetworkName). |
| src/components/CodeEditor/index.tsx | Prevents translation of code editor contents. |
| src/app/layout.tsx | Adds Google Translate initialization scripts (nonce’d) + mount point, suppresses hydration warnings. |
| src/app/(sidebar)/xdr/diff/page.tsx | Prevents translation of the diff code editor container. |
| src/app/(sidebar)/transaction/saved/page.tsx | Protects network name in empty-state copy from translation. |
| src/app/(sidebar)/smart-contracts/saved/page.tsx | Protects network name in empty-state copy from translation. |
| src/app/(sidebar)/endpoints/components/SavedEndpointsPage.tsx | Fixes empty-state copy and protects network names from translation. |
| src/app/(sidebar)/account/saved/page.tsx | Protects network name in empty-state copy from translation. |
| src/app/(sidebar)/account/fund/page.tsx | Protects network name in headings/notifications from translation. |
| README.md | Documents how to add additional languages to the selector. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Preview is available here: |
5d1c4ba to
2ceabc4
Compare
|
Preview is available here: |
|
Preview is available here: |
|
Preview is available here: |
|
Preview is available here: |
|
Preview is available here: |
|
Preview is available here: |
|
Preview is available here: |
| async | ||
| /> | ||
| </head> | ||
| <body suppressHydrationWarning> |
There was a problem hiding this comment.
body doesn't need suppressHydrationWarning
| return ( | ||
| <html lang="en"> | ||
| <body> | ||
| <html lang="en" suppressHydrationWarning> |
There was a problem hiding this comment.
we really shouldn't enable suppressHydrationWarning.
| <script | ||
| nonce={nonce} | ||
| suppressHydrationWarning | ||
| dangerouslySetInnerHTML={{ |
There was a problem hiding this comment.
we really shouldn't use dangerouslySetInnerHTML - this is also likely to be brought up by HackerOne later
|
We can't use Let's go with your original suggestion - using |


Adds language switching for #1880 via the Google Translate browser engine — no translation files needed. Language is set by writing a
googtranscookie and reloading.Core integration
app/layout.tsxwith nonce-based CSP supportGoogleTranslateMountPointcomponent creates the GT engine mount point imperatively viauseEffect(keeps it outside React's reconciliation tree to avoid hydration errors)src/helpers/translate.ts— helpers for setting/clearing thegoogtranscookie on the root domain so it persistsacross pages
Language selector in sidebar
LanguageSelectorcomponent in the sidebar with 12 languages (English, Español, Français, Português, Deutsch, 中文 (简体), 日本語, 한국어, Русский, العربية, हिन्दी, Türkçe)menu/menuitemradioARIA rolesnotranslateprotection for technical data, network names, and asset names<NoTranslate>— general-purpose wrapper for any technical Stellar data that must never be machine-translated: XDR strings, transaction hashes, public keys, contract IDs, JSON responses. Applied toPrettyJson,StellarDataRenderer,TxHashLink,XdrLink,TxResponse<NetworkName>— wraps Stellar network names (Testnet, Futurenet, Mainnet) so they're never mistranslated. Applied inSwitchNetwork, fund account page, saved keypairs/transactions/endpoints/smart contracts empty states,NetworkSelector,NetworkIndicator,SwitchNetworkButtons,Home/Networks<AssetCode>— wraps Stellar asset codes (USDC, EURC) so they're never altered. Applied in the fund account page and switch-network UI. XLM is excluded — it's already universally understoodPlaywright testing
playwright.config.tsmapstranslate.google.comandtranslate.googleapis.comto127.0.0.1via--host-rulesso GT's async external requests never push page loads pastnavigationTimeoutin CI or restricted environmentslanguageSelector.test.tscovering: default English state, dropdown open/options, active language marker, keyboard close, cookie set on language change, cookie cleared on reset to English