Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rfc: i18n routing domain support #798

Merged
merged 5 commits into from
May 21, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions proposals/0046-i18n-domain-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
- Start Date: 2023/12/21
- Reference Issues:
- Implementation PR: https://github.com/withastro/astro/pull/9143


# Summary

First-class support for domain support in i18n routing.


# Background & Motivation

Websites that support internationalisation have different requirements. Among these requirements, there's the need to
have localised content under different subdomains or domains.

# Goals

- Support different domains, all driven by the same Astro project;
- Mix locales that require a different domain, with locales that don't require a different domain;

# Non-Goals

- Force a redirect to users
ematipico marked this conversation as resolved.
Show resolved Hide resolved
- Change website/domain based on the language of the user's browser


# Detailed Design


A feature that allows to support different domains for certain locales.

Using the configuration `domains`, a user can specify which locales should benefit from a domain. This feature changes the behaviour of some of the APIs exported by the virtual module `astro:i18n`.

```js
// astro.config.mjs
import {defineConfig} from "astro/config"
export default defineConfig({
i18n: {
defaultLocaLe: 'en',
locales: ['en', 'es', 'pt_BR', 'pt', 'fr'],
domains: {
fr: "https://fr.example.com",
pt: "https://example.pt"
},
routingStrategy: "domain"
ematipico marked this conversation as resolved.
Show resolved Hide resolved
}
})
```

The following APIs will behave as follows:
- [`getRelativeLocaleUrl`](#getrelativelocaleurllocale-string-string): it won't prefix the locale to the URL. From `/en` to `/`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering if this should even be an error or something in this case? Seems like kind of a footgun if you use getRelativeLocaleUrl() hoping to navigate to a different locale, but get a same-domain random path instead.

Also to make sure I follow this. With the example config above, would you get the following behaviour?

getRelativeLocaleUrl('en', '') // => '/en'
getRelativeLocaleUrl('es', '') // => '/es'
getRelativeLocaleUrl('fr', '') // => '/'

And is that consistent across domains? i.e. for a page on fr.example.com, does getRelativeLocaleUrl('en', '') still return '/en'? That would resolve to fr.example.com/en, which seems kind of useless.

Should sites using multiple domains perhaps always use getAbsoluteLocaleUrl()? At the most extreme end, we could even change the type of astro:i18n and remove getRelativeLocaleUrl() entirely in these cases.

Copy link
Member Author

@ematipico ematipico Jan 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And is that consistent across domains? i.e. for a page on fr.example.com, does getRelativeLocaleUrl('en', '') still return '/en'? That would resolve to fr.example.com/en, which seems kind of useless.

No, it's not consistent and it's impossible to make it consistent.

Should sites using multiple domains perhaps always use getAbsoluteLocaleUrl()? At the most extreme end, we could even change the type of astro:i18n and remove getRelativeLocaleUrl() entirely in these cases.

Is it something that we can do? 😮 If so, I think we should go this way, although it should make the transition from a non-domain website to a domain website a horrible experience, because a user would have to change all APIs in one go in order to make it work.

Maybe we should do something in the middle; if the user uses a getRelativeLocale* function, we should fall back to use getAbsoluteLocale* instead. And we could add a warning.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I realised that getRelativeLocaleUrl should not change its behaviour. I removed that line

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should do something in the middle; if the user uses a getRelativeLocale* function, we should fall back to use getAbsoluteLocale* instead. And we could add a warning.

Yes, that would be a nice compromise I think and wouldn’t need the type to change (I assume? The two functions have the same signature right?) while still giving feedback that the function used is not intended for this context.

- [`getAbsoluteLocaleUrl`](#getabsolutelocaleurllocale-string-string): it won't have the locale in the URL: From `example.com/fr` to `fr.example.com/`;
delucis marked this conversation as resolved.
Show resolved Hide resolved

Adapters must have the capabilities to redirect a user from one domain to another based on the domains configured.
ematipico marked this conversation as resolved.
Show resolved Hide resolved

An adapter can signal Astro the feature support using the relative configuration:
ematipico marked this conversation as resolved.
Show resolved Hide resolved

In order to support this feature, Astro needs to know the origin of the server (the domain where the server is hosted). To achieve this, Astro will rely on the following headers:
- [`X-Forwarded-Host`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host) and [`Host`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host). Astro will use the former, and if not present will try the latter.
- [`X-Forwarded-Proto`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto) and [`URL#protocol`](https://developer.mozilla.org/en-US/docs/Web/API/URL/protocol) of the server request.

If any of this information is missing, Astro won't be able to map the route. This will result in a 404.