opral / inlang-paraglide-js

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

Astro integration - languageTag() is wrong on build #45

Closed dallyh closed 6 months ago

dallyh commented 6 months ago

There seems to be an issue with building for SSG and using languageTag() in the Astro integration. Dev server works fine, however on build the languageTag() always returns the default language tag set in the config.

I have created a simple repository here: https://github.com/dallyh/language-tag-issue-example.

This is the output of the build:

generating static routes 01:05:49 ▶ src/pages/[...lang]/404.astro 01:05:49 
├─ /404.html...Locale from page: cs ...Locale from layout: cs  (+8ms) 01:05:49 
└─ /en/404/index.html...Locale from page: cs ...Locale from layout: cs  (+3ms) 01:05:49 
✓ Completed in 24ms.

The logs in console for locales are from src/layouts/MainLayout.astro and page src/pages/[...lang]/404.astro. getStaticPaths() is used to generate the static routes.

I can reproduce this bug only on my machine which runs Windows, if I open the repository in StackBlitz, run npm install and npm build, the outputs are different. I'm out of ideas of what could be causing this. Please see the screenshot below, where on the left there is a StackBlitz IDE and on the right a simple windows Command Line.

image

dallyh commented 6 months ago

Just to be sure I ran the same on my work laptop, which uses Windows 11, and on my Linux laptop, which runs Debian 12. On the Windows laptop the output is like this:

image

And on Linux it is again different (and correct):

image

Edit: there are also different version of Node installed on both, on the Windows machine there is node 18 and on the Linux machine I have Node 21. I'll be happy to provide more specific versions if required.

Edit 2: Updating to Node 21 on the Windows machine did not make any difference.

LorisSigrist commented 6 months ago

I'm able to reproduce this. Thanks for the repo! I also had to switch to windows, which is very odd

dallyh commented 6 months ago

@LorisSigrist You're fast! I tried it with Astro.currentLocale and it returns the correct locale.

---
const locale = Astro.currentLocale;
console.log("...Locale from layout: " + locale);

---

<!doctype html>
<html lang={locale}>
    <head>
    </head>
    <body>
    </body>
</html>
generating static routes 
10:20:37 ▶ src/pages/[...lang]/404.astro
10:20:37   ├─ /404.html...Locale from page: cs ...Locale from layout: cs (+17ms)
10:20:37   └─ /en/404/index.html...Locale from page: en ...Locale from layout: en(+11ms)
10:20:37 ✓ Completed in 71ms.
LorisSigrist commented 6 months ago

Thanks! I got access to a windows machine via Shadow PC & am getting the same result. I'll need to investigate some more to find out why this is happening. languageTag() is just supposed to be an alias for Astro.currentLocale when called from .astro files.

LorisSigrist commented 6 months ago

More progress, although I'm not sure it's good news.

The adapter correctly identifies the language it's supposed to use, but for some reason the call to setLanguageTag doesn't work on windows. I know its identifying the correct language because Astro.locals.paraglide.lang get's set correctly.

Debugging this online on a Shadow-PC sucks, but it is what it is 😅

dallyh commented 6 months ago

Hey thanks for the effort! In the meantime I've found out that every built page is not localized properly, but that is probably a consequence of setLanguageTag not working.

Fortunately I'm building the site on Cloudflare which uses Linux workers, and I can still spin up my Linux laptop and or develop on Windows under WSL.

Still though, it's an inconvenience and it could potentionaly create some more issues.

There is one workaround which involves doing this on every page and component, but it defeats one of the features of the adapter :(


const locale = Astro.currentLocale;
setLanguageTag(locale);
LorisSigrist commented 6 months ago

New theory

The adapter internal middleware loads the paraglide runtime via a virtual module

import { setLanguageTag, ...} from "paraglide-js-adapter-astro:runtime"

There is a vite plugin that resolves this alias. It does work on windows, but it's possible that vite doesn't recognize the aliased import & the real path imports from the app as the same module & instantiates the module twice. The adapter then calls setLanguageTag in one instance of the module, while the app tries to read it from the other.

The reason it works on mac & linux is that their path-structure isn't such a mess

Hopefully this is it, since that would be fixable relatively easily

LorisSigrist commented 6 months ago

Pretty sure this is it. When logging out all the module-ids that vite loads there is one import for the runtime with backslashes and one with forward slashes. What a silly bug