-
-
Notifications
You must be signed in to change notification settings - Fork 84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Concurrent requests can cause LL store to change locale mid-flight during SSR (SvelteKit, adapter-node) #159
Comments
Oh, right 🙈 I actually thought that SvelteKit handles concurrent users. |
@aloker I now have tried a few things and the following solution works for me.
import { getI18nSvelteStore } from 'typesafe-i18n/adapters/adapter-svelte';
import type { Locales, Translation, TranslationFunctions, Formatters } from './i18n-types'
import { baseLocale, getTranslationForLocale } from './i18n-util'
import { initFormatters } from './formatters'
import { derived, get, writable } from 'svelte/store';
const { initI18n: init, setLocale, isLoadingLocale, locale: _locale, LL: _LL } = getI18nSvelteStore<Locales, Translation, TranslationFunctions, Formatters>()
const cache = {} as Record<Locales, { LL: TranslationFunctions, locale: Locales }>
const initI18n = async (locale: Locales = baseLocale) => {
await init(locale, getTranslationForLocale, initFormatters)
cache[locale] = { LL: get(_LL), locale: get(_locale) }
}
export const restoreI18n = (l: Locales) => {
const x = cache[l]
__LL.set(x.LL)
__locale.set(x.locale)
}
const __LL = writable(get(_LL))
_LL.subscribe(v => __LL.set(v))
const __locale = writable(get(_locale))
_locale.subscribe(v => __locale.set(v))
const LL = derived([__LL], (v) => v)
const locale = derived([__locale], (v) => v)
export { initI18n, setLocale, isLoadingLocale, locale, LL }
export default LL
This should block the correct store until everthing is rendered for that request. If you are accessing translations inside the load function, you would need to make sure that you also call Let me know if this works for you or you need some help. |
I will refactor how |
@aloker I now have refactored how You can check the latest commit I have made to the Please visit the release post for more information. |
Thanks for your fast response! I didn't have the opportunity to test it, but I'll check it out ASAP. Keep up the great work! |
Version
2.60.1
Describe the bug
In SvelteKit with adapter-node, currently typesafe-i18n creates only a single LL store in memory that is used for all requests. Multiple concurrent requests may change the current locale of that store. This can cause locales to switch within one requests if another request with another locale runs concurrently, leading to completely or partially wrong translations.
Reproduction
The code I used is based on the sveltekit example, including the hook, the __layout.svelte and the [lang] dir.
Consider this load function of a route:
Let's say we have to visistors, one at http://localhost:3000/en, the other at http://localhost:3000/de
When request come in sequentially, the server side output would be something like:
But if http://localhost:3000/de is visisted before "someExpensiveRequest" resolves, we'd see this:
That is, request 4 changes the locale and that's the locale that is then used by the older request 3 (which started in English).
Logs
Config
Additional information
The issue is obviously caused by the fact that there's a single store in memory that can be changed concurrently by multiple in-flight requests. It would probably an idea to have one store in memory for each locale and somehow "attach" the correct one to each request.
I've done something in the past using i18next where the correct store is selected in the root __layout and then passed to the components via context (https://svelte.dev/docs#run-time-svelte-setcontext) and to other load functions via "stuff" (https://kit.svelte.dev/docs#loading-output-stuff). It wasn't very beautiful tbh, but it worked. Maybe you can come up with something more elegant.
The text was updated successfully, but these errors were encountered: