opral / inlang-paraglide-js

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

languageTag() does not seem to get the correct language in SvelteKit #69

Closed pago93 closed 2 months ago

pago93 commented 2 months ago

Calling languageTag() from $lib/paraglide/runtime.js with @inlang/paraglide-js-adapter-sveltekit does always return the default language for me.

In my SvelteKit app with @sveltejs/adapter-static (don't know if relevant) I can't get the correct language via the built in functionality. A workaround I found is calling 'getLanguageFromUrl(url)' with the current url. The example below gets me the following output for route https://my-site/de/x:

de
en

Code for reference (+page.ts for https://my-site/de/x):

import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
import { i18n } from '$lib/i18n.js'
import { languageTag } from "$lib/paraglide/runtime.js"

export const ssr = false;

export const load: PageLoad = ({ url }) => {
    let currentLangUrl = i18n.getLanguageFromUrl(url);
    console.log(currentLangUrl);
    let currentLangTag = languageTag();
    console.log(currentLangTag);

    redirect(302, i18n.resolveRoute('/x', currentLangUrl));
};

i18n.resolveRoute also doesn't get the correct route without the language tag.

I get the same beviour for example in onMount().

LorisSigrist commented 2 months ago

As mentioned in the docs, the languageTag isn't set on the server before rendering starts. This is to avoid cross-talk between different concurrent requests.

To use the language on the server (outside of .svelte files or code called from .svelte files) you need to get it from the locals. You can access the current language on event.locals.paraglide.lang.

Calling languageTag() on the server should probably throw an error with an explanation. I'll see if I can do that.

You can get a message in a specific message by passing it into the message options m.my_message({}, { languageTag: "en"})

pago93 commented 2 months ago

The load function runs on the Browser (see ssr = false). The log output is from the browser. Maybe not the best example for this... I see if I can get a repro up later.

pago93 commented 2 months ago

Repro is here: https://github.com/pago93/ParagildeJSLanguageTag I created a new SvelteKit app, added paraglide as per documentation and modified the root page to demonstrate it.

For http://localhost:5173/de/ I get the following: image

Code for reference: https://github.com/pago93/ParagildeJSLanguageTag/blob/8def2fe07ee453b020019a1e6d5a87aa5aa689eb/src/routes/%2Bpage.svelte#L13

Browser console: image

Maybe I am doing something wrong here, but I expected languageTag() to give me the correct language because the code is executed in the browser and not on the server.

LorisSigrist commented 2 months ago

Thanks! Will be working on this today.

I expected languageTag() to give me the correct language because the code is executed in the browser

That's how it's supposed to work, you aren't doing anything wrong here

LorisSigrist commented 2 months ago

I have a working version that eagerly sets the language as the first thing when running reroute on the client.

This will still not set the language in module-scope

languageTag() //won't work

export function load() {
  if(client) languageTag() //will work
}

That being said, using the language in module scope is a bad idea anyway since it won't be possible to react to language changes.

LorisSigrist commented 2 months ago

Actually, scratch everything I've said. We can't use the languageTag in load functions on the client either.

The reason is SvelteKit's preloading behavior. load functions, including the ones on the client, are run if a link is hovered. This causes an obvious issue when hovering a link to a page in a different language.

Let's say the current languages is en and you hover a link to /de/ueber-uns. This is going to run the load function for /de/ueber-uns. This leaves us in the following Catch 22:

Unfortunately the restriction on not using languageTag() in load functions needs to stay.