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

Precompile translations

Open cibernox opened this issue 5 years ago • 5 comments
trafficstars

I open this PR for visibility on the spike to precompile translations at built time.

In this branch I basically comment everything I could to reduce the public API of the library to only addMessages and $t("key"), and attempt to implement the logic that is not svelte specific (mostly stores really) there. That way this approach can be reused by non-svelte projects.

However, my broccoli-fu is not very strong, I'm not sure how to make the app that consumes this branch bundle icu-helpers.

I created a sample app to play with this like installing the packaged locally with "svelte-i18n": "file:~/path/to/package"

The sample app: https://github.com/cibernox/svelte-translations-app runtime helpers: https://github.com/cibernox/precompile-intl-runtime babel-plugin: https://github.com/cibernox/babel-plugin-precompile-intl

I'm sure there is some combination of external + resolve that can make it work, but I haven't found it yet.

cibernox avatar Jan 16 '20 16:01 cibernox

Ok, I have it working.

Now the size of an very simple app without svelte-i18n and with no messages is 2.1kb, and the same app including svelte-i18n (this crippled version) and with these 10 messages:

  "plain": "Some text without interpolations",
  "interpolated": "A text with I interpolate {count} times",
  "time": "Now is {now, time}",
  "time-custom-format": "The hour is {now, time, hour}",
  "date": "Today is {today, date}",
  "date-custom-format": "Today is {today, date, abbr-full}",
  "number": "My favorite number is {n, number}",
  "percent": "My favorite number is {n, number, percent}",
  "pluralized": "I have {count, plural,=0 {no cats} =1 {one cat} other {{count} cats}}",
  "selected": "{gender, select, male {He is a good boy} female {She is a good girl} other {They are good fellas}}"

is 4.14kb, barely 2 extra kb.

And three-shaking works, I don't format dates or numbers, the functions for doing that are removed from the bundle. I think we're on the good track.

cibernox avatar Jan 17 '20 00:01 cibernox

Screen Shot 2020-01-17 at 18 10 19

I have the demo app working 🎉 Translations are very compact. This is how the compiled and uglified output looks in the app if you pretty-print it:

{
  plain: "Some text without interpolations",
  interpolated: t=>`A text where I interpolate ${B(t)} times`,
  time: t=>`Now is ${P(t)}`,
  "time-custom-format": t=>`The hour is ${P(t, "hour")}`,
  date: t=>`Today is ${G(t)}`,
  "date-custom-format": t=>`Today is ${G(t, "abbr-full")}`,
  number: t=>`My favorite number is ${q(t)}`,
  percent: t=>`My favorite number is ${q(t, "percent")}`,
  pluralized: t=>`I have ${V(t,{0: "no cats",1: "one cat",other: `${B(t)} cats`})}`,
  selected: t=>Z(t, {male: "He is a good boy",female: "She is a good girl",other: "They are good fellas"})
}

It's ~5% smaller than the ICU syntax. I haven't measured performance but I also suspect they are faster to invoke as you don't have to parse or instantiate anything (except formatters if they contain dates/numbers). And if you don't format dates, or times, or numbers, the code is treeshaken completely. Probably the typical app will gain 3/4 kb by internationalizing, translations included.

For that, i've implemented some subset of this library in the the icu-helpers repository.

I think. good plan could be to make icu-helpers library-agnostic, so it can be used by React and Vue users and more people can contribute to it. svelte-i18n v3 would contain only the svelte-specific bits if there's any, because I've implemented locale, locales and dictionary in icu-helpers as stores/observables (without importing svelte/store. I think that having them as observables is a) convenient for this svelte implementation, as this library only reexports them. b) Even if you're not using svelte, being able to subscribe to changes in the locales or the dictionaries is framework-agnostic enough to build your own utilities around them.

However my implementation in ICU helpers is very naive. I'm not caching formatters for instance.

Here is where I think I could use your expertise, since you wrote the code to begin with. And I'm not too familiar with typecript, and I do think that using typescript would be a good idea.

cibernox avatar Jan 17 '20 17:01 cibernox

I believe this could be ready. I moved to babel the flattening of the translations, so we don't ship any code for it, and also I'm using svelte/store to avoid duplicating code.

I believe that I've only made one API change. To detect the locale the library exports a function on the code for detecting the best locale:

import { init } from "****";
init({
  fallbackLocale: "en",
  initialLocale: {navigator: true},
})

is now

import { init, getClientLocale } from "****";

init({
  fallbackLocale: "en",
  initialLocale: getClientLocale({navigator: true}),
})

This allows to treeshake that function if it's not used. And in fact independent functions for each detection strategy are exported, so the above example could be just

import { init, navigatorLocale } from "****";

init({
  fallbackLocale: "en",
  initialLocale: navigatorLocale(),
})

Those seem like reasonable changes?

On a very simple app, but one that uses almost the features that the library has to offer except registering loaders for locales, the size after gzip goes from 3.37kb to 5.7kb, that is 2.3kb including some translations. If you happen to not use all the feature it can be less.

cibernox avatar Jan 22 '20 22:01 cibernox

How is the current state of this PR? Is it planned to follow its development? 🙃

albertms10 avatar Nov 08 '20 22:11 albertms10

@albertms10 I don't think i will be merged into this project anytime soon, but I have independent repositories for all the pieces with some instructions to make it work.

https://github.com/cibernox/precompile-intl-runtime https://github.com/cibernox/babel-plugin-precompile-intl https://github.com/cibernox/rollup-plugin-precompile-intl

The instructions are in the last repo.

Parenthood is not leaving me much spare time to work on side projects, but hopefully after xmas I'll be starting my first svelte app for a client, so I should have an excuse then.

cibernox avatar Nov 09 '20 08:11 cibernox

Realistically, this won't me merged and I don't plan on adding a compilation step to the package in the short-to-medium future.

kaisermann avatar Sep 11 '22 14:09 kaisermann