Yeah, the weirdest thing is that HTTP Accept-Language has been around for decades and is usually configured correctly (to the OS system language). No idea why people use geolocation for language at all, on the web.
i18nstrings = {'My string':<?= _('My string') ?>, 'Second string':<?= _('Second string') ?>};
then you can just do stuff like elem.innerHTML = i18nstrings['My string'];
Of course, you process the language header in the backend.
I reviewed a couple of i18n libraries for javascript but ended up liking this approach more. It was simple and effective.