inlang Paraglide-JS for SvelteKit (i18n)

After 6 months of research and development for SvelteKit, inlang Paraglide-JS for SvelteKit is finally ready.

Paraglide-JS comes with two main innovations that make Paraglide JS the simplest, most efficient, and typesafe i18n library for SvelteKit.

1. A compiler (sounds familiar?) emits message functions instead of key-value runtime lookup logic.

2. The message functions are tree-shakable, leading to auto optimization by the bundler.

Transcript

(upbeat music)
(upbeat music)
(upbeat music)
(upbeat music)
- Hello everyone, I'm Samuel from the Inlang team.
And today we're going to announce what we believe
will become the best i18n library for SvelteKit,
other frameworks and the web platform in general.
This is over two years of research and development.
And if you can't tell,
I'm so excited to finally show what we got.
Before I do so,
huge thanks to the Svelte community.
Over the last couple of months,
early adopters gave us a lot of feedback
on how to make things right and how to get where we got.
Now for everyone who doesn't know
what an i18n library does,
in short, if you want to adapt your application
or website to different markets,
for example, you want to show you the Uber application
in English, Spanish, German, French, Chinese,
and so on and so forth,
you need a lot of technical infrastructure
that loads the right translations,
determines the user language,
doesn't blow the bundle size.
You don't want to ship all translations to the user,
only the ones that the user actually needs.
You want to server-side render those translations
so that they appear on Google and so on and so forth.
It's a lot of technical infrastructure.
It's not about creating the translation,
it's about making it possible
that your application can be showcased
for different user groups.
Now, what will make Paraglide.js
the best i18n library for SvelteKit
and the web platform in general?
Two things.
Again, the result of over two years of R&D,
and I'm so excited to finally show it.
A breakthrough innovation when it comes down
to an i18n library,
and a plug-and-play ecosystem
that takes care of all the other things
that you need to do when you adapt your app
to different markets.
Let's start with the breakthrough innovation.
Wow!
We call it tree-shakeable message functions.
Paraglide.js leverages a compiler similar to Svelte
that takes your translation files
and contained messages
and compiles them to pure JavaScript functions.
Pure JavaScript functions mean that your bundler,
Vite, Rollup, Webpack, TurboPack,
can automatically tree-shake them and optimize them.
Your bundlers can't optimize your translation files,
but your bundlers can optimize your JavaScript files.
That's what they're built for,
and this is the innovation.
Now, if you do that, for example,
if you only use the message login button
in a particular component or page,
your bundler will automatically get rid of
hello and login header, stuff like that.
Now, why is this so amazing?
As I mentioned,
you don't have to care about async loading anymore.
Like, how do you load this translation file
and how do you split it
so that you don't send everything to the user?
You don't have to think about it anymore,
and usually with async loading
comes a lot of bottlenecks
for server-side rendering and everything.
For Paraglide.js, this is not a problem.
You're gonna import your JavaScript files.
You don't need to async load stuff.
Your bundler automatically imports,
synchronously imports your stuff
and gets rid of all the unused messages
and optimizing everything.
This means that with Paraglide.js,
and it seems, all right, this seems easy,
but wow, it took us so long to get here and nail it.
Server-side rendering works.
Client-side rendering works.
Static site generation just works.
Everything just works because it's plain JavaScript.
Now, manual message splitting.
If you take your translation file
and then usually, you know,
if you have, let's say you have 10,000 translations, right?
10,000 messages for English.
You don't want to send 10,000 messages
for the login page, which only uses 10 messages.
And traditionally, a lot of, you know,
a lot of manual optimization comes in
where you need to split those files.
This is not the case with Paraglide.js.
Your bundler automatically bundles
only the messages that you're using.
This means that Paraglide.js is the most efficient,
type-safe, and after all,
simplest E1N library that is out there.
It took us so long to get here.
It's so obvious in hindsight.
We believe everyone will copy
what we did here with Paraglide.js.
It is just so good.
But yeah, the innovation comes down
to three shakable message functions.
Instead of trying to resolve your translations
during the runtime,
it means that your bundlers can automatically optimize them.
This is the innovation in a nutshell.
And I said, there's more to it.
There's an entire ecosystem.
Let me show you Paraglide.js in action.
I'm going to show a SvelteKit example now.
Mind you, this is a pre-release.
So some things you see might change
by the time you try Paraglide.js.
I recommend following the guide
that we're going to link in the comments or description.
Generally, I hope that you see
just how simple Paraglide.js is
and how the inline ecosystem comes into play.
This is the page I built.
Hello Samuel.
Let's do it in English.
Hello, welcome Samuel.
You have five messages.
The current language tag is EN.
And I can switch the language to German, back to English.
And in German, I have a missing translation.
Okay, this is the code behind that page.
I'm saying here, greeting.
This is the welcome Samuel, current language tag.
Your current language tag is.
And two buttons to change the language tag.
You already see Paraglide.js in action here.
We're importing our message functions as plain JavaScript,
except that we're using a namespace import.
The namespace import enables the bundler.
If I'm not using greeting on this page,
it's not going to be bundled automatically.
This is the simplicity of Paraglide.js.
Now I want to use both messages.
Let's look how those messages work under the hood.
As I mentioned, Paraglide.js uses a compiler
that takes your translation files or message files,
or sometimes called resources.
In my case, it's this messages.json.
Warning, this is optimized for machine readability.
You can use any format that you'd like.
Classical JSON key value pairs also work.
Now this is the messages file, again, machine readable.
Paraglide.js takes those.
Here, this file, again, unopinioned.
You can use any format,
and compiles it into the Paraglide.js directory.
You can name it however you'd like.
It's get ignored.
It won't bother you.
In that Paraglide.js directory,
we have that messages.js, which serves as an index file.
This is exactly where we're importing our messages from.
If I go in here, for example, greeting,
this index file serves as a,
all right, your language tag is en,
so I'm returning the en message function.
Let's go in here.
This is it.
We're now in the en.js file.
The de file looks similar,
except that turn language tag is undefined.
But this is it.
Those are tree-shakeable message functions
because they're pure JavaScript functions.
Your Bundler can automatically optimize them
however it needs.
And this is Paraglide.js.
There's one second side to it.
So you have the messages file,
and you have a runtime file
where you define what is the current language tag,
and you can set the language tag,
which is exactly what we're doing here.
We're saying set the language tag to de and en.
Then I have a tiny adapter,
which depends on your app.
We're gonna provide that in the library,
which has, in this case, another 10 lines of code,
and it defines what should happen
if the language tag is set.
And in this case,
it also sets the context for service side rendering.
Overall, the entire runtime,
if we go into the compiled output,
this is unminified,
is 38 lines of code.
38 lines of code.
It comes down to around about 500 bytes.
And with the adapter code,
it's maybe 10 more lines.
So you're well beneath 100 lines of code.
This is the beauty of Paraglide.js.
I mentioned the ecosystem.
So we have a missing translation on the side here.
And if I run the CLI as part of the inline ecosystem,
I can say, hey, Lind, my code,
you can run it as part of CI/CD.
And I see here, for example,
hey, the message ID current language tag
has a missing variant for the language tag de.
So it's missing.
We get a warning here.
I'm lazy, so I'm gonna say,
you know what, mpx inline machine translate that.
And the moment it machine translates this,
we can go into de,
and what we see here, boom,
it machine translated that.
And I can save this.
And if we go into the app, there we go.
It's now machine translated in my application,
and I'm good to go.
I'm gonna set my translator a link
to the web editor in the ecosystem
that opens the repository.
We're running, no joke,
we're running Git here in the browser,
our own version of it.
And your translator can now directly contribute
towards your repository without any setup.
Here, I'm gonna add the language French.
Let's add that.
Unfortunately, I really don't speak French,
so let me machine translate that and push.
And you're gonna see here now
that we're gonna see French translations coming in.
Again, this is optimized for machine readability,
this format.
You can use a human readable format as well.
Let me pull, there we go.
There's French, and it's now in my application.
There was no handoff.
It all just works.
Let me lint it.
Lint it.
Are we good to go?
We're good to go.
Linting is successful.
The example is successful,
and I hope to get across how simple Paraglide.js is.
Thank you very much for listening in.
Two years of R&D.
Here was the presentation.
We're really excited for you to try it out.
If you have feedback, let us know.
We're gonna link a guide in the description
on how to get started.
And yeah, thank you.
(upbeat music)
you

Svelte Summit is a conference made possible by Svelte School AB and Svelte Society.