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

NextJS Adapter - Flexible Detection & Routing API #70

Closed LorisSigrist closed 1 month ago

LorisSigrist commented 2 months ago

Context

The Next Adapter already supports complex language-detection. However, the routing is very opinionated. It does not yet have the necessary Routing APIs to implement non-default routing logic such as domain based routing.

We don't want to add a config setting for every imaginable routing strategy. That would bloat the adapter, be a huge maintenance burden & blow up the bundle size.

Proposal

Define a "Routing Strategy" interface for defining how links should behave. Then pass the routing strategy to createI18n.

From the developers perspective it would look like this:

// src/lib/i18n.js
const routingStrategy = createPrefixRoutingStrategy({ availableLanguageTags, pathnames, exclude })
export const { middleware, Link, redirect , ..., } = createI18n({ routingStrategy })

The "strategy" would need to provide these functions:

type RoutingStrategy = {
   /**
    * Receives the translated pathname of the current page as it is written in the url
    * and returns the pathname that should be rendered 
    * 
    * @example
    * /de/ueber-uns -> /about
    */
   getCanonicalPath(localizedPath: string, language: AvailableLanguageTag) : string,

   /**
    * Receives the current route, a target language, the currentLanguage and NextJS's base-path
    * 
    * It then returns a URL Object for the path that should be rendered
    * It returns an URL Object instead of a pathname to allow for domain-switches and searchParams
    *
    * It receives both the current and the target language, in case the Link needs to be different if the language changes
    *
    * The base path will automatically be added to the `pathname`
    */
   getLocalizedUrl(canonicalPath: string, targetLanguage: AvailableLanguageTag, currentLanguage: AvailableLanguageTag) : import("url").UrlObject
}

With those functions it's possible to implement any imaginable i18n routing strategy.

We then use these functions to localize the Navigation APIs, including the Link component, redirect functions & all the other ones.

To keep the initial setup as simple as possible, we will provide constructor functions to create these strategies for common use-cases. This keeps the config basically the same size, just with another wrapper function.

You would need to pair the routing-strategy with a language-detection middleware that detects the language & sets cookies appropriately. That's not hard, but it's something to keep in mind.

Pros

Cons

rbozan commented 2 months ago

It's the same with Sveltekit. I'd like to have separate domains for each language, but now I seem to be forced to use /en/, /nl/ prefixes just so I can have support for different languages...

LorisSigrist commented 2 months ago

Domain based routing is something we want to support in sveltekit.

We probably can't use the same API as Next since there is no way to access cookies or request headers before rerouteing, but it is a use-case we want to support.

rbozan commented 2 months ago

Domain based routing is something we want to support in sveltekit.

We probably can't use the same API as Next since there is no way to access cookies or request headers before rerouteing, but it is a use-case we want to support.

Do you know when there's going to be work on that feature as I'd otherwise have to move to a different library as it's the only missing feature

LorisSigrist commented 2 months ago

Probably next Month

Right now we're focused on bringing Paraglide-Next to 1.0 and adding Plurals, Formatters and Markup to the message-format.

Sorry if this doesn't work for you.