svelte-i18n
svelte-i18n copied to clipboard
[Question] A way to initialize svelte-i18n for Storybook
Hello, thank you for making this awesome library! I just have a question related to the usage of this library with Storybook.
I am using svelte with storybook, and it turns out that I need to properly initialize svelte-i18n somehow by using something like addDecorator
in Storybook, but I just don't know how. I've already struggled a lot with this, but I haven't found a workaround for this.
Both Storybook for Svelte and svelte-i18n are at their early stages, so I could not really find much information on the web. So I would be really glad if anybody would knows about this issue could help.
Thank you very much in advance!
Hey @9oelM, would you be able to provide a simple repro with a minimal storybook setup? It'd help a lot.
@kaisermann thank you for following up. I will give you an example soon.
Hey guys,
Any update on it ?
I am facing the same problematic.
Thanks in advance 🙌
@9oelM you're right, using addDecorator
is the correct way. I suggest to use it globally in order to initialize svelte-i18n
for all stories.
Creation of global decorators can be done in .storybook/preview.js
. The tricky part here is that you need to create a wrapper component which will initialize i18n
for your story component.
Create your wrapper component for example in .storybook/Wrapper.svelte
// Wrapper.svelte
<script>
import { addMessages, init, getLocaleFromNavigator } from 'svelte-i18n';
import { addMessages } from 'svelte-i18n';
import en from './en.json';
import enUS from './en-US.json';
addMessages('en', en);
addMessages('en-US', enUS);
init({
fallbackLocale: 'en',
initialLocale: getLocaleFromNavigator(),
});
</script>
<slot /> // Here where your story component's content will be projected
Next step it's telling to Storybook to use the global decorator.
// preview.js
import { addDecorator } from '@storybook/svelte';
import Wrapper from './Wrapper.svelte;
addDecorator(storyFn => {
const { Component, props, on, WrapperData } = storyFn();
return {
Component,
props,
on,
Wrapper,
WrapperData,
};
});
Thanks @smoglica , this works for me, but I still have a problem if I reload the page while checking a component that uses translations, it shows the error [svelte-i18n] Cannot format a message without first setting the initial locale.
but it works fine if I navigate to another component and then back, can you reproduce such issue also?
@igarcez, No I don't. I have the problem that you mentioned only when I include translations asynchronously, in that case you should probably wrap <slot />
in a if condition block and waiting for the translation, so:
// Wrapper.svelte
<script>
import { isLoading } from 'svelte-i18n'
...
</script>
{#if $isLoading}
Please wait...
{:else}
<slot />
{/if}
Anyone here have a working repo for this combination.
The approach with the global wrapper didn't work for me either. Did the syntax for addDecorator
change in any way?
Works fine when using a decorator in the *.stories.svelte
file, like described here: https://storybook.js.org/docs/svelte/writing-stories/decorators
@bummzack I think it changed yeah. The following works for me:
Change this:
// preview.js
import { addDecorator } from '@storybook/svelte';
import Wrapper from './Wrapper.svelte;
addDecorator(storyFn => {
const { Component, props, on, WrapperData } = storyFn();
return {
Component,
props,
on,
Wrapper,
WrapperData,
};
});
To this:
// preview.js
import Wrapper from './Wrapper.svelte;
export const decorators = [
() => Wrapper,
// optionally_add_your_other_decorators
];