Solving i18n for React Server Components

Rate this content
Bookmark

How the transition to React Server Components enables better internationalization solutions.

Loris Sigrist
Loris Sigrist
7 min
18 Jun, 2024

Comments

Sign in or register to post your comment.

Video Summary and Transcription

The Talk discusses internationalization for server components and the challenge of loading translations efficiently. It suggests using import statements in JavaScript to optimize message loading and eliminate the need for namespaces. Tree shaking and tools like Paraglide.js can help minimize message delivery and simplify the process. Overall, the Talk emphasizes the importance of efficient internationalization practices in building multilingual apps.

1. Introduction to Internationalization

Short description:

I'm Loris from Inlang, and today I'll talk about internationalization for server components. Our goal is to build a multilingual app while minimizing data sent over the wire. We used to load translations per page into namespaces, but this becomes challenging with server components. On the server, you can load everything, but on the client, it's inefficient to load a namespace for each component.

Hi, I'm Loris. I build internationalization tooling at a company called Inlang, and today I'm going to be talking about internationalization for server components.

So, just that we're all on the same page, I'm going to be talking about string translations, your layouts, your components, not your content. So, when we're doing internationalization, our goal is, of course, to build a multilingual app while sending as few bytes as possible over the wire. We want to be really fine-grained in what we reach messages and translations we load so that we only display what is actually necessary. We respect our users' bandwidth.

Before server components, the unit in which we would load translations is one page at a time. So, it would have a certain set of messages that you would need on one page, certain set of messages that you would need on another page. So, what you would do is you would sort them into namespaces, names groups. Then you would imperatively load these namespaces with some sort of load namespace functions. Each item in a library is going to have some sort of equivalent to that one.

Now, what you would usually end up with is kind of one namespace per page. Then if you have a shared component per page, maybe an auth bar or a component that's used in many pages, you would create a second namespace just for that. It also imperatively loads that one when you load the page. So, you kind of need to keep track of, okay, which messages do I need exactly and which ones do I not need. You also often have some sort of common namespace where you have messages that are used in many different places, generic stuff, forwards, backwards. So, what you can see here is that you do end up with quite a few namespaces usually per page. I'm sure that if you've built a lot of multilingual apps, you're going to be familiar with this.

But there's quite a bit of bookkeeping, but usually it's staged manageable. You end up with between two and five namespaces per page. It's a bit of work, but it's doable. But this pattern works is a lot more difficult to pull off well if you introduce server components into the mix, because the unit in which you load messages is no longer per page. Now you're trying to load exactly the messages that are needed for the client components that you're going to render. With server components, your page is kind of this patchwork of stuff that's rendered on the server and stuff that's on the client, and you need messages in both, you need translations in both. But the requirements on how you actually load these messages is very, very different. On the server, you really don't need to do any fine-grained loading at all. You can just load everything, be gluttonous, and just use what you want, like you like it. Do no bookkeeping at all. That's wonderful. But if we were to stick with the whole namespace and imperative loading approach, on the client, it's going to be very, very painful, because you're going to end up creating a namespace for each client component, then you need to imperative load that one with the page, and it's going to be a lot of work, a lot of overhead.

2. Efficient Loading with Import Statements

Short description:

We want to load only the necessary messages for a page and client components. Namespaces are no longer suitable for server components. Instead, we can use import statements in JavaScript to express dependencies and optimize message loading. By having all messages in one JavaScript file, build tools can analyze and remove unused messages. Tree shaking ensures minimal message delivery. Tools like Paraglide.js can generate the necessary files, eliminating the need for imperative loading. Stop using namespaces and try Paraglide.js.

We really only want to load the messages that are used on a page and used in client components on that page. So kind of these competing scenarios where on the one hand, we really need really, really, really fine-grained loading, and on the server, we don't need fine-grained loading at all. But of course, we can't really do separate APIs for the server and the client, because when we develop our apps, our apps are living documents. Client components become server components, become client components, add components, remove components. So keeping the imperative loading in sync with all of that is going to be way too much work, way too much overhead.

So when it comes to loading translations, namespaces really are no longer the way to go when you introduce server components into the mix, because it just becomes a prohibitive amount of effort that you need to put in to actually load what you need and only what you need. Surely there has to be a better way. Let's take a step back and start thinking about what we're actually trying to do when we do these namespace releases. What we're trying to express is that this component depends on these messages, this code depends on that. And in JavaScript, we have this wonderful tool called an import statement, which expresses that relationship very, very well. And we have tools that can analyze that, at bundlers that can tweak and everything that can really, really take advantage of that.

Let's imagine that instead of sorted namespaces or JSON files, we had kind of one giant JavaScript file where all of our messages that exist in our app are present and exported separately. Now let's not worry where we got that file from. Let's just assume we have it. You can see this on the left here, what we can do in our components, regardless of if they're client components or server components, we can just import from that file and use the messages that we want. And our build tools, or Redpack or TurboPack, is going to be smart enough to see, okay, we're using exactly this message and it's only these messages and we're using them on the client. It's able to do this separately for the server and the client, even though the code is identical. So it's going to be able to see which messages we are using, and it's going to be able to remove all the rest. So we kind of get the minimum set of messages that is used on the client. If you're developing, it's very common for your client component to become a server component or vice versa, usually just by adding or removing the use client bit there. And the tree shaking in our bundlers is clever enough to do this properly. So if I remove the use client there, all the messages would no longer be sent to the client. We're sending as few bytes as possible. This is perfect, fine-grained loading.

Now, of course, you probably don't want to actually write such a messages file yourself. It's pretty straightforward if you're just using strings, but if you have your ICU message formats strings, there's a bunch of plurals, currency formats and all that. It's going to be very, very tedious to maintain. And of course, your translators are not going to be able to work with it. So you're going to want to generate this file somehow. There are a bunch of tools available in order to do this. But I myself, I have been working on one. It's called a Paraglide.js. It does exactly what I just said, just takes an oil translation files, gives you a giant messages file, and then you can just use that use input statements to express all your relationships that you need. And you no longer need to worry about doing any imperative loading at all. That's my elevator pitch. Please stop using namespaces for loading stuff. They're not fit for purpose anymore. And try a library like Paraglide.js. Thank you.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Simplifying Server Components
React Advanced Conference 2023React Advanced Conference 2023
27 min
Simplifying Server Components
Top Content
Server Components are arguably the biggest change to React since its initial release but many of us in the community have struggled to get a handle on them. In this talk we'll try to break down the different moving parts so that you have a good understanding of what's going on under the hood, and explore the line between React and the frameworks that are built upon it.
Exploring React Server Component Fundamentals
React Day Berlin 2023React Day Berlin 2023
21 min
Exploring React Server Component Fundamentals
Top Content
I've been developing a minimalistic framework for React Server Components (RSC). This talk will share my journey to deeply understand RSC from a technical perspective. I'll demonstrate how RSC features operate at a low level and provide insights into what RSC offers at its core. By the end, you should have a stronger mental model of React Server Components fundamentals.
Server Components: The Epic Tale of Rendering UX
React Summit 2023React Summit 2023
26 min
Server Components: The Epic Tale of Rendering UX
Server components, introduced in React v18 end these shortcomings, enabling rendering React components fully on the server, into an intermediate abstraction format without needing to add to the JavaScript bundle. This talk aims to cover the following points:1. A fun story of how we needed CSR and how SSR started to take its place2. What are server components and what benefits did they bring like 0 javascript bundle size3. Demo of a simple app using client-side rendering, SSR, and server components and analyzing the performance gains and understanding when to use what4. My take on how rendering UI will change with this approach
A Practical Guide for Migrating to Server Components
React Advanced Conference 2023React Advanced Conference 2023
28 min
A Practical Guide for Migrating to Server Components
Server Components are the hot new thing, but so far much of the discourse around them has been abstract. Let's change that. This talk will focus on the practical side of things, providing a roadmap to navigate the migration journey. Starting from an app using the older Next.js pages router and React Query, we’ll break this journey down into a set of actionable, incremental steps, stopping only when we have something shippable that’s clearly superior to what we began with. We’ll also discuss next steps and strategies for gradually embracing more aspects of this transformative paradigm.
Batteries Included Reimagined - The Revival of GraphQL Yoga
GraphQL Galaxy 2021GraphQL Galaxy 2021
33 min
Batteries Included Reimagined - The Revival of GraphQL Yoga
The Guild has recently released Envelop - a new, modern GraphQL Server Framework and plugin system. In this talk I’ll share a brief overview of Envelop and why you should probably upgrade your existing GraphQL server to it.
React Server Components
React Day Berlin 2023React Day Berlin 2023
27 min
React Server Components
React Server Components are a newer way of working with React that is widely adopted in frameworks like Next.js. In this talk, we will look under the surface of how they work and are executed on the server side, and how they fit with server rendering and traditional React apps.

Workshops on related topic

Next.js 13: Data Fetching Strategies
React Day Berlin 2022React Day Berlin 2022
53 min
Next.js 13: Data Fetching Strategies
Top Content
WorkshopFree
Alice De Mauro
Alice De Mauro
- Introduction- Prerequisites for the workshop- Fetching strategies: fundamentals- Fetching strategies – hands-on: fetch API, cache (static VS dynamic), revalidate, suspense (parallel data fetching)- Test your build and serve it on Vercel- Future: Server components VS Client components- Workshop easter egg (unrelated to the topic, calling out accessibility)- Wrapping up
React Server Components Unleashed: A Deep Dive into Next-Gen Web Development
React Advanced Conference 2023React Advanced Conference 2023
153 min
React Server Components Unleashed: A Deep Dive into Next-Gen Web Development
Workshop
Maurice de Beijer
Maurice de Beijer
Get ready to supercharge your web development skills with React Server Components! In this immersive, 3-hour workshop, we'll unlock the full potential of this revolutionary technology and explore how it's transforming the way developers build lightning-fast, efficient web applications.
Join us as we delve into the exciting world of React Server Components, which seamlessly blend server-side rendering with client-side interactivity for unparalleled performance and user experience. You'll gain hands-on experience through practical exercises, real-world examples, and expert guidance on how to harness the power of Server Components in your own projects.
Throughout the workshop, we'll cover essential topics, including:
- Understanding the differences between Server and Client Components- Implementing Server Components to optimize data fetching and reduce JavaScript bundle size- Integrating Server and Client Components for a seamless user experience- Strategies for effectively passing data between components and managing state- Tips and best practices for maximizing the performance benefits of React Server Components
Workshop level: 
No matter your current level of React expertise, this workshop will equip you with the knowledge and tools to take your web development game to new heights. Don't miss this opportunity to stay ahead of the curve and master the cutting-edge technology that's changing the face of web development. Sign up now and unleash the full power of React Server Components!
Build a Custom Storefront on Shopify with Hydrogen
React Advanced Conference 2021React Advanced Conference 2021
170 min
Build a Custom Storefront on Shopify with Hydrogen
Workshop
Matt Seccafien
Cathryn Griffiths
2 authors
Hydrogen is an opinionated React framework and SDK for building fast, custom storefronts powered Shopify. Hydrogen embraces React Server Components and makes use of Vite and Tailwind CSS. In this workshop participants will get a first look at Hydrogen, learn how and when to use it, all while building a fully functional custom storefront with the Hydrogen team themselves.
Build a Product Page with Shopify’s Hydrogen Framework
React Advanced Conference 2022React Advanced Conference 2022
81 min
Build a Product Page with Shopify’s Hydrogen Framework
WorkshopFree
David Witt
David Witt
Get hands on with Hydrogen, a React-based framework for building headless storefronts. Hydrogen is built for Shopify commerce with all the features you need for a production-ready storefront. It provides a quick start, build-fast environment so you can focus on the fun stuff - building unique commerce experiences. In this workshop we’ll scaffold a new storefront and rapidly build a product page. We’ll cover how to get started, file-based routing, fetching data from the Storefront API, Hydrogen’s built-in components and how to apply styling with Tailwind.You will know:- Get started with the hello-world template on StackBlitz- File-based routing to create a /products/example route- Dynamic routing /products/:handle- Hit the Storefront API with GraphQL- Move the query into the Hydrogen app- Update the query to fetch a product by handle- Display title, price, image & description.- Tailwind styling- Variant picker and buy now button- Bonus if there’s time: Collections page
Prerequisites: - A Chromium-based browser (StackBlitz)- Ideally experience with React. A general web development background would be fine.