opral / inlang-paraglide-js

Tree-shakable i18n library build on the inlang ecosystem.
https://inlang.com/m/gerre34r/library-inlang-paraglideJs
54 stars 1 forks source link

Using inlang translations in server side and client side components #132

Closed willhama closed 6 months ago

willhama commented 6 months ago

I have an object with some properties that should be used in a client-side and server-side component with next-js.

{
price: 50,
description: m.chair_description()
}

Whats the recommended way for handling that situation? it seems it can't be both. Either client-side or server-side both not both at the same time.

LorisSigrist commented 6 months ago

Is this object in a separate file that's being imported by both a client and a server component? That's supposed to work. Are you getting any errors?

I would love some more detail on your setup & what you're trying to do.

willhama commented 6 months ago

Yes, this object sits in a separate file.

Once I have a server action that consumes the object and once I have the a client component that consumes it.

The usecase is just that they need to refer to the same object as a matter of organization and not the need for duplication.

I am using the latest NextJS version. This is the error what I get when I build it:

Creating an optimized production build ...
 ✓ Compiled successfully
 ✓ Linting and checking validity of types    
   Collecting page data  ..Error: `headers` was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context
......

  type: 'Error'
}
   Collecting page data  . ELIFECYCLE  Command failed with exit code 1.

Running it locally works but as soon as I try to build it breaks. As well from the error messages I can not really conclude what the issue is or where it occurs but its related to the import from m. But in general error messages is an huge issue with NextJS.

LorisSigrist commented 6 months ago

Thanks, I'll try to reproduce!

LorisSigrist commented 6 months ago

Can reproduce. It seems like it is incorrectly using the language-tag getter function for server-components when server-side-rendering client components. I'll see how I can fix this

willhama commented 6 months ago

Thanks a lot @LorisSigrist ! I appreciate it a lot!

LorisSigrist commented 6 months ago

I figured out what's happening.

Let's say you have a shared object like this:

import * as m from "@/lib/paraglide"

export const shared = {
   text: m.my_message()
}

And then you use it in a server-component like so:

import { shared } from "./shared"

export default function Page() {
  return <h1>{shared.text}</h1>
} 

You will get a build error because the m.my_message function gets executed immediately when the module loads, not when the Page gets rendered in response to a request.

This causes an error during building since the message tries to get language from the request, but there is no request.

The solution is to make the "shared" object a function that's called from the component.

import * as m from "@/lib/paraglide"

export const shared = () => ({
   text: m.my_message()
})

There is no way to work around this since its technically expected behavior, even though it's unintuitive.

However, I can detect this happening & add a better error-message for it that tells you how to fix it.

willhama commented 6 months ago

@LorisSigrist I have tried it in my setup and it worked as you suggested. Thanks a lot!