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

paraglide-astro: middleware incorrectly detects the locale #101

Closed W1M0R closed 4 days ago

W1M0R commented 2 months ago

I am not using the built-in Astro i18n feature: https://docs.astro.build/en/guides/internationalization/#configure-i18n-routing

I am using the astro-i18n-aut integration: https://github.com/jlarmstrongiv/astro-i18n-aut?tab=readme-ov-file#configure

My astro.config.mjs sets the Astro base to '/app'.

With this setup, the paraglide languageTag() and Astro.locals.paraglide.lang values always evaluate to en in Astro frontmatter, regardless of whether I am viewing /app/en/bla or /app/bla or /app/de/bla. It looks like the paraglide-astro middleware may not be incorporating the Astro base url in its calculation.

Thankfully paraglide-astro configures its Astro middleware to run before the user's middleware:

  1. https://github.com/opral/monorepo/blob/6cc91c3d0d0fb198b10044612b35e7edce82079b/inlang/source-code/paraglide/paraglide-astro/src/integration.ts#L23

This means I am able to provide my own middleware to override the paraglide settings:

  1. https://github.com/opral/monorepo/blob/6cc91c3d0d0fb198b10044612b35e7edce82079b/inlang/source-code/paraglide/paraglide-astro/src/middleware.ts#L12
  2. https://github.com/opral/monorepo/blob/6cc91c3d0d0fb198b10044612b35e7edce82079b/inlang/source-code/paraglide/paraglide-astro/src/middleware.ts#L14
import { defineMiddleware } from "astro:middleware";

import {
    setLanguageTag
} from "virtual:paraglide-astro:runtime"

import { getLocale, getLocaleUrl } from "astro-i18n-aut";

export const onRequest = defineMiddleware(async (context, next) => {
    const { locals, url } = context

    // currentLocale is provided by the built-in i18n functionality of Astro,
    // but since we don't use that, let's override the value using the result provided by astro-i18n-aut.
    const currentLocale = context.currentLocale ?? getLocale(url.pathname)

    const dir = guessTextDirection(currentLocale)
    setLanguageTag(currentLocale)
    locals.paraglide = {
        lang: currentLocale,
    dir,
    }
    return next();
});

This workaround does seem to solve the issue for me.

I suspect the getLangFromPath function struggles with my config: https://github.com/opral/monorepo/blob/6cc91c3d0d0fb198b10044612b35e7edce82079b/inlang/source-code/paraglide/paraglide-astro/src/middleware.ts#L22

The astro-i18n-aut integration specifically checks for the base url: https://github.com/jlarmstrongiv/astro-i18n-aut/blob/8078ea6935f89c1228b0ef5754b791ea7c296aa9/src/edge-runtime/middleware.ts#L25

Here is how the astro-i18n-aut integration calculates the locale: https://github.com/jlarmstrongiv/astro-i18n-aut/blob/8078ea6935f89c1228b0ef5754b791ea7c296aa9/src/edge-runtime/getLocale.ts#L21

Upon searching for a solution, I wondered whether it may be best to allow users to manually call the astro middleware. This will give users the opportunity to call the middleware wherever it makes sense to them, and also to provide other relevant parameters according to their project configuration.

Since my Astro config has no built-in i18n configuration, the supported locales are also not set there, so I'm currently not sure whether paraglide will be good for my use case.

@LorisSigrist Am I trying to use paraglide-astro outside its intended design, or have I stumbled on a bug?

Related links:

  1. https://github.com/jlarmstrongiv/astro-i18n-aut/issues/21
LorisSigrist commented 2 months ago

You're right that the basePath is currently not being considered. We should certainly fix that.

While we haven't really considered mixing Paraglide & other i18n integrations, the use-case you described seems reasonable.

We will need to update the getLocaleFromPathname function to include the pathname.

Since my Astro config has no built-in i18n configuration, the supported locales are also not set there

If they aren't set there the locales from project.inlang/settings.json will be used directly. That shouldn't be an issue