Skip to content

ADR 0002: Translate in place by driving Google's hidden language selector ​

  • Status: Accepted
  • Date: 2026-11-02 (released in 1.1.0)

Context ​

1.0 reloaded the page on every language change. Its code tried to switch in place by setting Google's select.goog-te-combo, but it created Google's widget with InlineLayout.SIMPLE. Probing the real widget in a browser showed that the SIMPLE layout renders a link menu inside an iframe and no <select> at all, so the in-place path never ran and every change fell through to the reload.

The same probe showed the default layout renders a <select> with every language, that setting it and dispatching change translates the page in place (about 1.2 seconds warm; up to about 13 seconds for the first translation of a visit), and that Google's "Show original" button, in a same-origin iframe, restores the original without a reload.

Decision ​

Create Google's widget with the default layout, inside a hidden host element (its appearance doesn't matter), and switch languages by setting its <select>. Restore by clicking "Show original", falling back to a reload if it can't be found. Keep reload as an opt-in mode: 'reload'.

Alternatives considered ​

  • Keep reloading. Simple and robust, but it loses form state, scroll position and anything else in memory, and it makes every change feel slow.
  • Calling Google's internal JavaScript API. Undocumented and obfuscated; it would break without warning.

Consequences ​

Changes no longer reload the page. The package depends on Google's goog-te-combo class name and the "Show original" button's ID pattern; a weekly CI job loads the live widget and the fake used in tests mirrors the observed behaviour, so a change on Google's side is noticed.

Released under the MIT License.