Open nosovk opened 4 months ago
It seems that i18next namespaces should cover that case
Hi đŸ™‹
The usage like you outlined unfortunately can't work. Any form of dynamic key, like m[prefix + ".promotion"]
, on the client will break treeshaking. Bundlers won't be able to determine the possible values at build-time.
This would cause all messages to be loaded, regardless of if they are used.
If you want to only load the messages for the current i18nContext you need to render the messages on the server & pass them to the client.
// src/routes/+page.server.ts
import * as m from "$lib/paraglide/messages"
export const load({ locals }) {
return {
promotion: m[locals.i18nContext + "_promotion"](),
title: m[locals.i18nContext + "_title"](),
}
}
<script>
export let data;
</script>
<h1>{data.title}</h1>
<p>{data.promotion}</p>
As for nesting: Paraglide does not support nesting, even if a plugin that does support it is used to load the messages.
We recommend to do one of the following:
variation_promotion
Hm, but there is no dynamic key. The key is actually static. Like https://webpack.js.org/plugins/define-plugin/ long time before. And it's actually processed by vite as static string. In my example we use context, which is actually rendered on ssr for example.
I mean that there is no need to make dynamic key load, it should be statically parametrized :)
I was thinking about that namespace thing from https://inlang.com/m/3i8bor92/plugin-inlang-i18next Could it be used to add prefix to all language strings in a context scope?
Ok, after bit more testing I now understand that even if I use i18next source files with nesting, there is no way to use it in paraglide, because its converted to simple kv. And : which is used to create divider does not supported as literal in function names, which causes paraglide to fail.
I just tested the keys with static parameterization & vite does not statically parameterize the keys, even if they are computed only from build-time constants.
It seems that any sort of computation for the key used to index into a namespace will break treeshaking in the current generation of bundlers. Only hard-coded constants work.
You're not the only one with this requirement. A while back Eric Burel from the State of JS/HTML survey approached us with a similar use-case. They needed to use the year + the topic of the survey as a namespace, similar to what you're doing here.
Clearly this is something people expect to work. We should open a feature request in Rollup
https://vitejs.dev/config/build-options#build-minify vite supports terser, which is does those modifications.
it seems that there is a reason to use it for prodcutin builds
Yep, we also need that feature, would be nice to have it
+1, we are using sveltekit, and we're investigating an opportunity of using paraglide as i18n backbone in our application. Unfortunately, this feature is a dealbreaker in comparison with https://github.com/kaisermann/svelte-i18n
This is absolutely something we want to see, but it's fundamentally a bundler limitation. As bundlers get better this will automatically start to work with no change on paraglide's side.
I did try the following approaches but could not get vite to treeshake reliably:
Using terser
unfortunately doesn't solve this today. The following code doesn't get treeshaken properly.
import * as m from "../paraglide/messages.js"
const year = "2024"
console.log(m[`msg_${year}`])
This is also unlikely to work soon. Consider the situation where the year
is imported from another file. In this case you would need to resolve it from a different file before you can optimize this one. You would have to do the bundling step twice. This would require major changes to how our bundlers currently work.
define
to replace valuesIn vite.config.js
you can provide a define
option which allows you to replace certain values at build time.
define: {
__YEAR__: "'2024"
}
Unfortunately this doesn't work either:
import * as m from "../paraglide/messages.js"
console.log(m[`msg_${__YEAR__}`])
However, this approach is the most likely to work soon, since there aren't really any major changes needed to the bundler internals. I'll open some issues.
Update: I've tried the define
approach with just EsBuild (instead of vite) & that seems to work. If rollup were to support the same define
feature then this would be the way to go
I've opened an issue in vite about this: https://github.com/vitejs/vite/issues/17898
wow, I've spent 3 hours trying to do that, because its certainly unclear from docs that its not working. There is https://inlang.com/m/3i8bor92/plugin-inlang-i18next in a docs, which clearly supports namespaces, but its actually not working with paraglide :(
We're using paraglide at the current project, and can't move out. But we also stuck with that problem, when we tried to implement user customizations to bundles. I see some workarounds in Vite, but it does not look like it works with paraglide.
Any updates on it? We are now evaluating different options
@nosovk @NataliiaSe Do I understand the requirement correctly?
I want to start using paraglide in sveltekit, but I have a bit strange use case.
My translation file:
Then in my component: component.svelte
inside router in svelte I create files like: /src/routes/custom_client/+page.svelte
In case above we use some prefix constant, that modifies scope of translations, inside some route. Actually we have one landing, but we have dozens of variations with different promotions. Currently we use selfmade translation service, but we have to send full {lang}.json to clients, with all variations. Currently its size is pretty big, and we tried to move to paraglide, because treeshakable translations is what we need.
I've found that there are two different approaches in paraglide -
t
andm
plugins, but wasn't able to make composable key in none of them. Also I found mention that you're not going to support nested messages, that we highly dependant from (https://github.com/opral/inlang-paraglide-js/issues/159). But I see that you use some other message formats, that support nested messages. Probably we can achieve the same with custom source plugin?