I'm opening this issue to discuss what would be the suggested pattern to handle translations with svelte. The ideal output of this discussion might be examples for docs, maybe a new feature that makes it simpler, not sure yet. Let's assume that we build a big app that handles few languages. Some ideas:
a)
Import where needed:
// Hello.html
<p>{{translate('hello')}}</p>
<script>
import { translate } from './utilities/translations'
export default {
helpers: { translate }
}
</script>
Pros: simple, works out of the box, available only where needed
Cons: repetition of the import
b)
Pass it to all child components inside of the top component
// Main.html
<Hello/>
<script>
import Hello from './Hello.html'
import { translate } from './utilities/translations'
export default {
// somehow pass the translation method to all child components that it's available in the template (?)
components: { Hello }
}
</script>
// Hello.html
<p>{{translate('hello')}}</p>
Pros: no repetition, saves keystrokes
Cons: global dependency, available everywhere
c)
Pass it to all child components outside of the top component
// main.js
import Main from './Main.html'
import { translate } from './utilities/translations'
new Main({
// somehow pass the translation method to all child components so that it's available in the templates
// maybe:
helpers: { translate }
})
// Hello.html
<p>{{translate('hello')}}</p>
Pros: no repetition, saves keystrokes
Cons: global dependency, available everywhere
I don't have a strong opinion which one is better, any other ideas? Maybe there's an option to do so already and I missed it :) Please let me know what you think.
There is this https://github.com/sveltejs/svelte/pull/1023
But I suppose that's a variation of (a) just moving the repetition to oncreate. Unless you want to sprinkle your templates with {{root.options.translate('hello')}}
This seems like another case for dependency injection.
What about Store?
// main.js
const store = new Store({
translate: str => {
// some logic happens
}
});
const app = new App({ target, store });
<p>{{$translate('hello')}}</p>
translate could even be set lazily (after you've lazy-loaded the translations, for example) or a computed property that depends on a lang property that the user can select — whatever is most suitable for the app in question.
Thanks guys :)
Having the translate method defined as a part of the store works fine. I thought the purpose of the store is to hold the data and not the utility methods. The only concern I have is that it might be unexpected for people to have it there, but maybe it just shouldn't be passed this way. A computed texts property might be a better choice in some scenarios.
Seems like it would not work with Svelte3 ...
Any other ideas? Maybe somebody have tool like i18nliner?
I've written a library using the store approach.
Forked it from the svelte-intl package and just send a PR.
There's also the svelte-i18n, but I didn't use because the bundle is too bloated (about 73kB gz)
Most helpful comment
What about
Store?translatecould even be set lazily (after you've lazy-loaded the translations, for example) or a computed property that depends on alangproperty that the user can select — whatever is most suitable for the app in question.