Comments (12)
@hmaesta I recently released a library implementing some of this ideas: https://github.com/cibernox/svelte-intl-precompile
It has an API that I think it's almost 100% compatible with svelte-i18n. The docs say it's for SvelteKit but it will work on any rollup-based svelte app. If shouldn't occupy more than 2/3 kb after minification and compression.
I presented it on a lighting talk in svelte summit a few days ago: https://youtu.be/fnr9XWvjJHw?t=10004
from svelte-i18n.
This page has been open for 26 days in my computer as a pinned tab, just waiting for the time when I could try @cibernox's approach. 😅
After a little struggle with Rollup, I was able to test it and save ~100 KB. 🎉
Thanks for the help. I hope it can be merged to this repository, since the name is more friendly and already have some audience.
from svelte-i18n.
Hey @hmaesta and @cibernox (loved the talk 😁!)
Unfortunately, this is not something that I can invest much time in right now. I'm open to all kinds of contribution 👀
@cibernox if you're (still) interested in "merging" the libraries, we can think about a v4 for svelte-i18n
. It would be great to keep the same API and functionalities if possible though.
from svelte-i18n.
I also did a proof of concept for a babel plugin that takes the translations and converts them into functions: https://github.com/cibernox/babel-plugin-precompile-icu
Check the tests, but the tl;dr; is that it knows how to compile things like:
export default {
nearby: "Find places near your location",
kilometer: "{count} {count, plural, =1 {kilometer} other {kilometers}}"
};
into
import { plural } from "helpers";
export default {
nearby: "Find places near your location",
kilometer: count => `${count} ${plural(count, {1: "kilometer", other: "kilometers"})}`
};
And even things more complex like:
export default {
nearby: "Find places near your location",
kilometer: "This year { gender, select,male {he made {count, plural,=0 {no kilometres} one {one kilometre} other {{count} kilometres}}} female {she made {count, plural,=0 {no kilometres} one {one kilometre} other {{count} kilometres}}} other {they made {count, plural,=0 {no kilometres} one {one kilometre} other {{count} kilometres}}}}"
};
into
import { select, plural } from "helpers";
export default {
nearby: "Find places near your location",
kilometer: (count, gender) => `This year ${select(gender, {
male: `he made ${plural(count, {
0: "no kilometres",
1: "one kilometre",
other: `${count} kilometres`
})}`,
female: `she made ${plural(count, {
0: "no kilometres",
1: "one kilometre",
other: `${count} kilometres`
})}`,
other: `they made ${plural(count, {
0: "no kilometres",
1: "one kilometre",
other: `${count} kilometres`
})}`
})}`
};
As you see the overhead in size is minimal. Infact, after minification, you save space. And the more complex the message is, the more you save:
- "This year { gender, select,male {he made {count, plural,=0 {no kilometres} one {one kilometre} other {{count} kilometres}}} female {she made {count, plural,=0 {no kilometres} one {one kilometre} other {{count} kilometres}}} other {they made {count, plural,=0 {no kilometres} one {one kilometre} other {{count} kilometres}}}}"
+ (c,g)=>`This year ${d(g,{male:`he made ${p(c,{0:"no kilometres",1:"one kilometre",other:`${c} kilometres`})}`,female:`she made ${p(c,{0:"no kilometres",1:"one kilometre",other:`${c} kilometres`})}`,other:`they made ${p(c,{0:"no kilometres",1:"one kilometre",other:`${c} kilometres`})}`})}`
For now I only implemented the transformation of plural
and select
, but it won't be complicated to implement similar compilation for the rest of the syntax.
The next step would be to implement the helpers that I'm importing that don't yet exist, which is where I'd copy-paste from some existing library like intl-message-format, but implement the functionality as functions that rollup/webpack can tree-shake.
from svelte-i18n.
Now I managed to write a rollup plugin that compiles the json files and imports the helpers from https://github.com/cibernox/icu-helpers
Now that the translations are functions that take arguments, the only thing that svelte-i18n would have to do, is exposes methods to register the translations and configure the preferences.
$t("my.key", { values: { count: 3 } })
should basically do
lookupLocation("my.key")({count: 3})
I think we're not too far from that.
from svelte-i18n.
Hey 👋 Thanks for your interest in making the lib better (and smaller, which is always better) 🎉 First of all, I think it's important to notice that we're possibly talking about breaking-changes here.
-
Since I've first built this lib I have thought about those utility methods (
title
,upper
, etc) and never seem to find myself using them and as you said, they're pretty easy to implement. However, I wouldn't say that removing them would reduce that much the size of the library. I'm not against removing them in the future, but would like to hear more feedback about it. It's also possible to add some kind of utility entrypoint, so devs could add them as they please. -
That's actually how it worked on
v1
, albeit with a little more boilerplate to set the locale. My mission withv2
was to make the API smaller and simpler. However, it's nothing that a good documentation change couldn't solve. That may actually simplify the call onserver.js
for sapper builds. -
Yeah, the big one, but very important indeed. Can you give an example of how you imagine that happening? Do you mean transforming the formatter calls to smaller functions which only need to receive the values to be interpolated? That would happen to all locales that you
add
/register
at build-time? About the size issue, as you stated, I think this approach can generate a lot of weight depending on the size of the project. If and after we define what would be the result of that compilation step, we should make a benchmark to check what weight change we'd have.
Anyway, thanks again for the interest in helping the lib 😁
from svelte-i18n.
Example of what I mean:
{
"nearby": "Find places near your location",
"kilometer": "{count} {count, plural, =1 {kilometer} other {kilometers}}",
could be parsed as
import { plural } from 'helpers';
export default {
"nearby": "Find places near your location",
"kilometer": count => `${count} ${plural(count, { 1: "kilometer", other: "kilometers"})}",
}
As you can imagine, after minification that code will be
import { p } from 'helpers';
export default {
"nearby": "Find places near your location",
"kilometer": v => `${v} ${p(v,{1:"kilometer",other:"kilometers"})}"
}
As you see the overhead is typically small. You app has to have a lot of entries with special plurals and stuff for the overhead to surpass the weight of the library.
from svelte-i18n.
I started taking a look into linguijs which is not only much smaller (1.4kb) than intl-messageformatter
, it better supports compiling the messages at build-step. I didn't went to far, since I don't have much free time right now, but will definitely continue to tackle this 😁
If we supposedly switched to lingui, for what I saw we would need/be able to do:
-
remove(done indeepmerge
(800 bytes or so), because it only accepts shallow dictionaries. We can still support deep dictionary definitions and flat them by joining their keys. This would also removedlv
(191 bytes), the object string path parser. We could possibly do this now without being a breaking change anyway 🤔🤔🤔v2.2.3
) -
probably remove all the logic of finding the fallback locale for a certain locale:
en-US
toen
to the defined fallback. (Can be a big breaking change if lingui behaves differently). -
lingui provides ready to use tools to ease the message compilation step. Would be nice to not have to implement them.
Or, if we want to take another route, we can use the intl-message-parser
(6.5kb vs 8.6kb) instead, which is lighter and prevent some of the unused deps and code paths of intl-messageformat
to end up on the lib. Or any other ICU syntax parser which is well maintained and up to date.
One of the things that is important to decide is what kind of responsibility the lib should have. Do we want to only delegate some methods and configurations to the underlying i18n lib? Or do we doing things at a lower level, i.e what I mentioned about using the parser instead of the ready-to-use formatter? I like having more control of what the lib is doing, but I'm open to feedbacks.
from svelte-i18n.
I also discovered that what I suggested is already possible and done in react-intl: https://github.com/formatjs/react-intl/blob/master/docs/Advanced-Usage.md#pre-parsing-messages
It compiles, however, to the AST, which is a bit more verbose than the approach based in functions, and it still requires intl-messageformat (but would spare us from shipping intl-messageformat-parser).
I'm going to play a bit more with the idea of compiling translations to either ASTs or functions.
from svelte-i18n.
Yeah, I know! I found your issue on their repo 😆
I'll play around with the compilation step whenever possible, but for now there is #39 😁. Released as v2.2.3
🎉
Not much, but after removing dlv
and deepmerge
we're down from 38.7kb -> 37.1kb minified and 11.4kb -> 10.9kb.
from svelte-i18n.
@cibernox That's great! I'm going to check both repos soon 😉
I just created the v3
branch to start playing with some of the things mentioned here. The first things I changed were removing the casing utilities and separating the date, time and number formatters from the message one: https://github.com/kaisermann/svelte-i18n/pull/40/files#diff-31df54a9a51bd3da26df362832cc1c9fR28. Not sure if $formatDate
, $formatNumber
, $formatTime
are too verbose... 🤔 could be $date
, $number
, $time
, but maybe that's too generic?
Edit:
Made getClientLocale
tree-shakeable too on the PR above.
from svelte-i18n.
When running rollup-plugin-analyzer
, icu-messageformat-parser
is one of the heaviest parts of my bundle.
A diet would be nice, indeed. Any update here?
from svelte-i18n.
Related Issues (20)
- Allow unit tests with ts-node esm HOT 1
- Sveltekit: Update translation outside of component
- Variable inside html isn't replaced HOT 1
- Inform about unused language keys HOT 1
- When I hover over a <a> the site language changes to the default language. HOT 1
- `intl-getcanocicallocales` is probably not a good idea HOT 2
- CJS / ESM conflict HOT 22
- Change log version comparison links are off
- Production build using svelte-i18n ^3.7.4 throws "Named export 'IntlMessageFormat' not found." HOT 6
- Problems with LIB check in cli extractor HOT 1
- Sapper reference in Getting Started guide
- Allow to restrict some parts of the i18n file to unauthorized users in SvelteKit. HOT 3
- Is it possible when registering several json files to overwrite the previous key contents with latest file?
- Docs on how to use variables in translation strings HOT 1
- How to disable AM/PM in $time formatter
- Leading zeros for day/month when formatting date values
- Add a register store?
- Build error when deploying in vercel
- Provide a Readable<string> instead of pure string
- Svelte 5 support
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from svelte-i18n.