svelte-i18n icon indicating copy to clipboard operation
svelte-i18n copied to clipboard

[Question] A way to initialize svelte-i18n for Storybook

Open 9oelM opened this issue 5 years ago • 9 comments

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!

9oelM avatar Jan 26 '20 09:01 9oelM

Hey @9oelM, would you be able to provide a simple repro with a minimal storybook setup? It'd help a lot.

kaisermann avatar Feb 03 '20 16:02 kaisermann

@kaisermann thank you for following up. I will give you an example soon.

9oelM avatar Feb 06 '20 10:02 9oelM

Hey guys,

Any update on it ?

I am facing the same problematic.

Thanks in advance 🙌

Doltario avatar Jun 01 '20 14:06 Doltario

@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,
  };
});

smoglica avatar Jun 25 '20 17:06 smoglica

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 avatar Jul 20 '20 12:07 igarcez

@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}

smoglica avatar Jul 20 '20 14:07 smoglica

Anyone here have a working repo for this combination.

jerriclynsjohn avatar Dec 19 '20 07:12 jerriclynsjohn

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 avatar Aug 19 '21 14:08 bummzack

@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
];

thenbe avatar Dec 01 '21 10:12 thenbe