We do actually have per-language code splitting with React/Vite. We essentially just have a map of [language, loader], where the loader utilizes lazy imports. Vite is smart enough to split those all out of the main bundle and they get loaded on demand as expected.
Then we consume it in a component which accepts the language key, lazy-loads the bundle by just calling `LOCALE_MAP[key]()`, and then uses it as the string translation set for a context function which looks up keys in a dict. Super simple.
Yes, it's all the strings per language, for the SPA. We also have services which we can use to request a bundle of strings from the backend, which I guess could in theory be an avenue for JIT translation on the frontend, but so far the per-language bundle splitting has kept things managable for us.