-
Notifications
You must be signed in to change notification settings - Fork 80
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
Allow to initialize a non-singleton i18n client. #179
base: main
Are you sure you want to change the base?
Conversation
Hey @Tal500 👋thanks for this! I'll give it a good read soon and review it |
This option tells whether the client document language should be changed to the locale, every time it is set.
In the second commit I did (842c558), I let the user cancel automatic setting of document I also would like to share a possible code of Svelte component(not included in the PR), making life easier for nested i18n clients: <script lang="ts">
import { onDestroy } from 'svelte';
import type { Readable, Subscriber } from 'svelte/store';
import { setupI18nClientInComponentInit } from "svelte-i18n";
export function componentInitializationSubscribe<T>(store: Readable<T>, run: Subscriber<T>) {
const unsubscribe = store.subscribe(run);
onDestroy(() => { unsubscribe(); });
}
export let locale: string = undefined;
const client = setupI18nClientInComponentInit({
fallbackLocale: locale,// Must be the same locale, otherwise the messages may not be loaded yet.
initialLocale: locale,
loadingDelay: 0,
autoLangAttribute: false,
});
const { _, t, json, date, time, number, format, isLoading } = client;
const localeStore = client.locale;
componentInitializationSubscribe(localeStore, () => {
if (locale !== $localeStore) {
locale = $localeStore;
}
});
$: $localeStore = locale;
</script>
<div lang={locale}><slot client={client} locale={$localeStore} _={$_} t={$t} json={$json} date={$date} time={$time}
number={$number} format={$format} isLoading={$isLoading}></slot></div> An example to a user code using it: <I18nContainer locale="fr" let:_={_}>
{_('test_str')}
<SomeComponent1 />
<SomeComponent2 />
</I18nContainer> |
Hey @Tal500! Thanks again for your PR! After giving it a read and some consideration, I think I would implement it a little bit differently. I will probably do it in the coming weeks, but I will make sure to add you as a co-author 🙏 |
Great! I used this PR as a fork for few months, will glad to see a good official implementation eventually. |
Additionally, I would like to share an idea about how to detect the correct locales to be loaded on the client-side, after SSR, which are the ones who are being loaded in In the preloading, I'm awaiting to the needed locales to be loaded on SSR. function htmlToAdd() {
return `<script id=${jsonId} type="application/json">${
JSON.stringify(Array.from(this.loaded))
}</script>`
} So on the client loading, we can get do: function waitOnClientLoad() {
const localeList: string[] = JSON.parse(document.getElementById(jsonId).textContent);
console.log(`Waiting for locales ${JSON.stringify(localeList)}`);
return Promise.all(localeList.map((locale) => waitLocale(locale)));
} If you'd be more sophisticated a little bit, with the help of Svelte Context API, you can also add a locale to be loaded not only on the main layout. This is the way for dealing with Sapper. SvelteKit is similar, except that you should do ES6 top-level await, since you don't have the client initialization script there. A disadvantage I didn't solve: |
BTW, I'd like to here about the sketch of your plans for the change in the library. I might have suggestions |
a77b7aa
to
d1d0306
Compare
Intro
Solves #165.
One of the reasons this issue was critical is because of serving SSR on two different languages in the same time, but we gain much more by solving this issue.
It was a hard and tough work, but I have managed to do it finally.
I have carefully redesign the code to be able (internally) to create new formatters and locales given some options (not necessarily the global ones from
getOption()
!).Using the above, I could finally implement the function
createI18nClient()
.Additionally, as I mentioned in the issue, the user may&should use the context based API (calling
setupI18nClientInComponentInit()
), so any component designer could get the i18n stores viagetI18nClientInComponentInit()
, see the next example.Seketch for a Sapper User
client.ts
i18n.ts (notice to the unresolved problem in fallbackLocale)
src/_layout.svelte
A generic component now will do: (can get more stores if they wish, not just
_
)Using
getI18nClientInComponentInit()
is great, because the designer can use svelte-i18n without knowing i18n setup details.This allow the main website developer to choose one of the following, and the component will just work:
init()
.src/_layout.svelte
.src/_layout.svelte
also the sub layout/page/component (for the component case, one needs to be careful and make sure the the locale were already loaded before the component initialization, since there is nopreload()
function.All this use cases was verified by me on my private website project.
Tests
Because of lint problems on base commits I just ignored it.
But Jest tests works very well, and I enhance them for checking the newly added code of mine.
I was also testing this in my own private svelte website project, as said above.