From ee929dda06b07714da2c4158661af77abdcecb12 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 3 Apr 2024 14:05:45 +0100 Subject: [PATCH 01/13] feat(i18n): manual routing --- .../docs/en/guides/internationalization.mdx | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/content/docs/en/guides/internationalization.mdx b/src/content/docs/en/guides/internationalization.mdx index 3bd0898f12003..3d16af8fc22e9 100644 --- a/src/content/docs/en/guides/internationalization.mdx +++ b/src/content/docs/en/guides/internationalization.mdx @@ -224,6 +224,66 @@ Astro uses a [middleware](/en/guides/middleware/) to implement its routing logic This means that operations (e.g. redirects) from your own middleware and your page logic are run first, your routes are rendered, and then the i18n middleware performs its own actions such as verifying that a localized URL corresponds to a valid route. +#### Manual routing + +

+ +The `routing` option can be changed to `"manual"`. When this option is enabled, Astro will **disable** its i18n middleware, so a user can implement their custom logic. When this option is enabled, new utility functions become available, which can be used in the user middleware. + +```js title="astro.config.mjs" del={6-8} ins={9} +import { defineConfig } from "astro/config" +export default defineConfig({ + i18n: { + defaultLocale: "en", + locales: ["es", "en", "fr"], + routing: { + prefixDefaultLocale: true + }, + routing: "manual" + } +}) +``` + +```js title="src/middleware.js" +import {defineMiddleware} from "astro:middleware"; +import { redirectToDefaultLocale } from "astro:i18n"; // new function provided by the manual routing +export const onRequest = defineMiddleware(async (ctx, next) => { + if (ctx.url.startsWith("/about")) { + return next(); + } else { + return redirectToDefaultLocale(302); + } +}) +``` + +Sometimes, you want to take advantage of the Astro i18n routing, but you'd want to have some exceptions. Now this is possible via manual routing. When manual routing is enabled, Astro will export a function tha allows to *manually* create the Astro i18n middleware, and you can decide where to place it in combination with the `sequence` utility: + +```js title="src/middleware.js" +import {defineMiddleware, sequence} from "astro:middleware"; +import { middleware } from "astro:i18n"; // new function provided by the manual routing +export const userMiddleware = defineMiddleware(async (ctx, next) => { + // this response might come from the i18n middleware, and it might return a 404 + const response = await next(); + // the /about page is an exception and we want to render it + if (ctx.url.startsWith("/about")) { + return new Response("About page", { + status: 200 + }); + } else { + return response; + } +}); + + +export const onRequest = sequence( + userMiddleware, + middleware({ + redirectToDefaultLocale: false, + prefixDefaultLocale: true + }) +) +``` + ### `defaultLocale` and `locales` Both a default language ([`defaultLocale`](/en/reference/configuration-reference/#i18ndefaultlocale)) and a list of all supported languages ([`locales`](/en/reference/configuration-reference/#i18nlocales)) must be specified in your `i18n` routing configuration. From 8ffe5ffac5d575bf0f65051587d6faa43e22e7aa Mon Sep 17 00:00:00 2001 From: Sarah Rainsberger Date: Fri, 5 Apr 2024 19:40:33 +0000 Subject: [PATCH 02/13] sarah edit to streamline/reorg --- .../docs/en/guides/internationalization.mdx | 344 ++++++++++-------- 1 file changed, 186 insertions(+), 158 deletions(-) diff --git a/src/content/docs/en/guides/internationalization.mdx b/src/content/docs/en/guides/internationalization.mdx index 3d16af8fc22e9..4a82863e4c1b1 100644 --- a/src/content/docs/en/guides/internationalization.mdx +++ b/src/content/docs/en/guides/internationalization.mdx @@ -1,5 +1,5 @@ --- -title: Internationalization +title: Internationalization (i18n) Routing description: Learn how to use i18n routing in Astro. i18nReady: false --- @@ -7,92 +7,95 @@ i18nReady: false import { FileTree } from '@astrojs/starlight/components'; import Since from '~/components/Since.astro' -Astro's internationalization (i18n) features allow you to adapt your project for an international audience. +Astro’s internationalization (i18n) features allow you to adapt your project for an international audience. This routing API helps you generate, use, and verify the URLs that your multi-language site produces. +Astro's i18n routing allows you to bring your multilingual content with support for configuring a default language, computing relative page URLs, and accepting preferred languages provided by your visitor's browser. You can also specify fallback languages on a per-language basis so that your visitors can always be directed to existing content on your site. -## i18n Routing +## Routing Logic -

+Astro uses a [middleware](/en/guides/middleware/) to implement its routing logic. This middleware function is placed in the [first position](/en/guides/middleware/#chaining-middleware) where it awaits every `Response` coming from any additional middleware and each page route before finally executing its own logic. -Astro's i18n routing allows you to add your multilingual content with support for configuring a default language, computing relative page URLs, and accepting preferred languages provided by your visitor's browser. You can also specify fallback languages on a per-language basis so that your visitors can always be directed to existing content on your site. +This means that operations (e.g. redirects) from your own middleware and your page logic are run first, your routes are rendered, and then the i18n middleware performs its own actions such as verifying that a localized URL corresponds to a valid route. -This routing API helps you generate, use, and verify the URLs that your multi-language site produces. Check back and update regularly for the latest new features as this API continues to develop! +You can also choose to [add your own i18n logic in addition to or instead of Astro's i18n middleware](#manual), giving you even more control over your routes while still having access to the `astro:i18n` helper functions. -### Configure i18n routing +## Configure i18n routing -1. Enable the routing option by adding an `i18n` object to your Astro configuration with a [default location (`defaultLocale`) and a list of all languages to support (`locales`)](#defaultlocale-and-locales): +Both a default language ([`defaultLocale`](/en/reference/configuration-reference/#i18ndefaultlocale)) and a list of all supported languages ([`locales`](/en/reference/configuration-reference/#i18nlocales)) must be specified in an `i18n` configuration object. Additionally, you can configure more specific routing and fallback behavior to match your desired URLs. - ```js title="astro.config.mjs" - import { defineConfig } from "astro/config" - export default defineConfig({ - i18n: { - defaultLocale: "en", - locales: ["en", "es", "pt-br"] - } - }) - ``` - -2. Choose and configure a [`routing`](#routing) based on the desired URL path for your `defaultLocale`: +```js title="astro.config.mjs" +import { defineConfig } from "astro/config" +export default defineConfig({ + i18n: { + defaultLocale: "en", + locales: ["es", "en", "pt-br"], + } +}) +``` - - `"prefixDefaultLocale: false"` (default): URLs in your default language will **not** have a `/[locale]/` prefix. All other locales will. +### Create localized folders - - `"prefixDefaultLocale: true"`: All URLs, including your default language, will have a `/[locale]/` prefix. +Organize your content folders with localized content by language. Create individual `/[locale]/` folders anywhere within `src/pages/` and Astro's [file-based routing](/en/guides/routing/) will create your pages at corresponding URL paths. - ```js title="astro.config.mjs" ins={7} - import { defineConfig } from "astro/config" - export default defineConfig({ - i18n: { - defaultLocale: "en", - locales: ["es", "en", "fr"], - routing: { - prefixDefaultLocale: false - } - } - }) - ``` +Your folder names must match the items in `locales` exactly. Include a localized folder for your `defaultLocale` only if you configure `prefixDefaultLocale: true` to show a localized URL path for your default language (e.g. /en/about/). -3. Organize your content folders with localized content by language. Your folder names must match the items in `locales` exactly, and your folder organization must match the URL paths chosen for your [`routing`](#routing). + +- src + - pages + - about.astro + - index.astro + - es + - about.astro + - index.astro + - pt-br + - about.astro + - index.astro + - Include a localized folder for your `defaultLocale` only if you configure `prefixDefaultLocale: true` to show a localized URL path. +:::note +The localized folders do not need to be at the root of the `/pages/` folder. +::: - - - src - - pages - - about.astro - - index.astro - - es - - about.astro - - index.astro - - pt-br - - about.astro - - index.astro - - :::note - The localized folders do not need to be at the root of the `/pages/` folder. - - Create individual `/[locale]/` folders anywhere within `src/pages/` and Astro's [file-based routing](/en/guides/routing/) will create your pages at corresponding URL paths. - ::: - -4. With i18n routing configured, you can now compute links to pages within your site using the [`getRelativeLocaleURL()`](#getrelativelocaleurl) helper available from the [`astro:i18n` module](#virtual-module-astroi18n). This will always provide the correct, localized route and can help you correctly use, or check, URLs on your site. You can also still write the links manually. +### Create links - ```astro title="src/pages/es/index.astro" - --- - import { getRelativeLocaleUrl } from 'astro:i18n'; +With i18n routing configured, you can now compute links to pages within your site using the helper functions such as [`getRelativeLocaleURL()`](#getrelativelocaleurl) available from the [`astro:i18n` module](#virtual-module-astroi18n). These generated links will always provide the correct, localized route and can help you correctly use, or check, URLs on your site. - // defaultLocale is "es" - const aboutURL=getRelativeLocaleUrl("es", "about"); - --- +You can also still write the links manually. - ¡Vamos! - Blog - Acerca - ``` +```astro title="src/pages/es/index.astro" +--- +import { getRelativeLocaleUrl } from 'astro:i18n'; + +// defaultLocale is "es" +const aboutURL=getRelativeLocaleUrl("es", "about"); +--- + +¡Vamos! +Blog +Acerca +``` + +## Routing options + +

+ +Astro's built-in file-based routing automatically creates URL routes for you based on your file structure within `src/pages/`. When you configure i18n routing, the `routing` value now allows you to specify your file structure (and corresponding URL paths generated) in order to use helper functions to generate, use, and verify the routes in your project. Many of these options can be used together for even more customization and per-language flexibility. + +You can even choose to [implement your own routing logic manually](#manual-routing) for even greater control. + +### `prefixDefaultLocale` + +This routing strategy defines whether or not your default language's URLs should use a language prefix (e.g. `/en/about/`). -### `routing` +All non-default supported languages **will** use a localized prefix (e.g. `/fr/` or `/french/`) and content files must be located in appropriate folders. This configuration option allows you to specify whether your default launguage should also follow a localized URL structure. -Astro's built-in file-based routing automatically creates URL routes for you based on your file structure within `src/pages/`. When you configure i18n routing, the `routing` value now allows you to specify your file structure (and corresponding URL paths generated) in order to use helper functions to generate, use, and verify the routes in your project. +This setting also determines where the page files for your default language must exist (e.g. `src/pages/about/` or `src/pages/en/about`) as the file structure and URL structure must match for all languages. + +- `"prefixDefaultLocale: false"` (default): URLs in your default language will **not** have a `/[locale]/` prefix. All other locales will. + +- `"prefixDefaultLocale: true"`: All URLs, including your default language, will have a `/[locale]/` prefix. #### `prefixDefaultLocale: false` @@ -110,11 +113,23 @@ export default defineConfig({ }) ``` -This is the **default** value. Set this option when URLs in your default language will **not** have a `/[locale]/` prefix and files in your default language exist at the root of `src/pages/`. +This is the **default** value. Set this option when URLs in your default language will **not** have a `/[locale]/` prefix and files in your default language exist at the root of `src/pages/`: -- `src/pages/blog.astro` will produce the route `example.com/blog/` -- `src/pages/fr/blog.astro` will produce the route `example.com/fr/blog/` -- If there is no file at `src/pages/es/blog.astro`, then the route `example.com/es/blog/` will 404 unless you specify a [fallback strategy](#fallback). + + - src + - pages + - about.astro + - index.astro + - es + - about.astro + - index.astro + - fr + - about.astro + - index.astro + + +- `src/pages/about.astro` will produce the route `example.com/about/` +- `src/pages/fr/about.astro` will produce the route `example.com/fr/about/` #### `prefixDefaultLocale: true` @@ -149,9 +164,9 @@ Set this option when all routes will have their `/locale/` prefix in their URL a - index.astro -- URLs without a locale prefix, (e.g. `example.com/blog/`) will return a 404 (not found) status code. +- URLs without a locale prefix, (e.g. `example.com/about/`) will return a 404 (not found) status code unless you specify a [fallback strategy](#fallback). -#### `redirectToDefaultLocale` +### `redirectToDefaultLocale`

@@ -161,92 +176,32 @@ Setting `prefixDefaultLocale: true` will also automatically set `redirectToDefau You can opt out of this behavior by [setting `redirectToDefaultLocale: false`](/en/reference/configuration-reference/#i18nroutingredirecttodefaultlocale). This allows you to have a site home page that exists outside of your configured locale folder structure. -#### `domains` (experimental) - -

- -This routing option allows you to customize your domains on a per-language basis for `server` rendered projects using the [`@astrojs/node`](/en/guides/integrations-guide/node/) or [`@astrojs/vercel`](/en/guides/integrations-guide/vercel/) adapter with a `site` configured. - -To enable this in your project, [configure i18n routing](#configure-i18n-routing) with your preferences if you have not already done so. Then, set the `experimental.i18nDomains` flag to `true` and add `i18n.domains` to map any of your supported `locales` to custom URLs: - -```js title="astro.config.mjs" {3-7} ins={14-21} -import { defineConfig } from "astro/config" -export default defineConfig({ - site: "https://example.com", - output: "server", // required, with no prerendered pages - adapter: node({ - mode: 'standalone', - }), - i18n: { - defaultLocale: "en", - locales: ["es", "en", "fr", "ja"], - routing: { - prefixDefaultLocale: false - }, - domains: { - fr: "https://fr.example.com", - es: "https://example.es" - } - }, - experimental: { - i18nDomains: true - } -}) -``` -All non-mapped `locales` will follow your `prefixDefaultLocales` configuration. However, even if this value is `false`, page files for your `defaultLocale` must also exist within a localized folder. For the configuration above, an `/en/` folder is required. - -With the above configuration: - -- The file `/fr/about.astro` will create the URL `https://fr.example.com/about`. -- The file `/es/about.astro` will create the URL `https://example.es/about`. -- The file `/ja/about/astro` will create the URL `https://example.com/ja/about`. -- The file `/en/about.astro` will create the URL `https://example.com/about`. - -The above URLs will also be returned by the `getAbsoluteLocaleUrl()` and `getAbsoluteLocaleUrlList()` functions. - -##### Limitations - -This feature has some restrictions: -- The `site` option is mandatory. -- The `output` option must be set to `"server"`. -- There cannot be any individual prerendered pages. -- The adapter feature [`functionPerRoute`](/en/reference/adapter-reference/#functionperroute) is not supported. - -Astro relies on the following headers in order to support the feature: -- [`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. - -Make sure that your server proxy/hosting platform is able to provide this information. Failing to retrieve these headers will result in a 404 (status code) page. - -#### Routing logic - -Astro uses a [middleware](/en/guides/middleware/) to implement its routing logic. This middleware function is placed in the [first position](/en/guides/middleware/#chaining-middleware) where it awaits every `Response` coming from any additional middleware and each page route before finally executing its own logic. - -This means that operations (e.g. redirects) from your own middleware and your page logic are run first, your routes are rendered, and then the i18n middleware performs its own actions such as verifying that a localized URL corresponds to a valid route. -#### Manual routing +### `manual`

-The `routing` option can be changed to `"manual"`. When this option is enabled, Astro will **disable** its i18n middleware, so a user can implement their custom logic. When this option is enabled, new utility functions become available, which can be used in the user middleware. +When this option is enabled, Astro will **disable** its i18n middleware so that you can implement your own custom logic. No other `routing` options (e.g. `prefixDefaultLocale`) may be configured with `routing: "manual"`. + +You will be responsible for writing your own routing logic, or [executing Astro's i18n middleware manually](#middleware-function) alongside your own. -```js title="astro.config.mjs" del={6-8} ins={9} +```js title="astro.config.mjs" import { defineConfig } from "astro/config" export default defineConfig({ i18n: { defaultLocale: "en", locales: ["es", "en", "fr"], - routing: { - prefixDefaultLocale: true - }, routing: "manual" } }) ``` +Astro provides helper functions for your middleware so you can control your own default routing, exceptions, fallback behavior, error catching, etc: [`redirectToDefaultLocale`](#redirecttodefaultlocale), [`notFound`](#notfound), and [`useFallback`](#usefallback): + + ```js title="src/middleware.js" -import {defineMiddleware} from "astro:middleware"; -import { redirectToDefaultLocale } from "astro:i18n"; // new function provided by the manual routing +import { defineMiddleware } from "astro:middleware"; +import { redirectToDefaultLocale } from "astro:i18n"; // function available with `manual` routing export const onRequest = defineMiddleware(async (ctx, next) => { if (ctx.url.startsWith("/about")) { return next(); @@ -256,13 +211,18 @@ export const onRequest = defineMiddleware(async (ctx, next) => { }) ``` -Sometimes, you want to take advantage of the Astro i18n routing, but you'd want to have some exceptions. Now this is possible via manual routing. When manual routing is enabled, Astro will export a function tha allows to *manually* create the Astro i18n middleware, and you can decide where to place it in combination with the `sequence` utility: +#### middleware function + +The [`middleware`](#middleware) function manually creates Astro's i18n middleware. This allows you to extend Astro's i18n routing instead of completely replacing it. + +You can run `middleware` with [routing options](#routing-options) in combination with your own middleware, using the [`sequence`](#sequence) utility to determine the order: ```js title="src/middleware.js" import {defineMiddleware, sequence} from "astro:middleware"; -import { middleware } from "astro:i18n"; // new function provided by the manual routing +import { middleware } from "astro:i18n"; // Astro's own i18n routing config + export const userMiddleware = defineMiddleware(async (ctx, next) => { - // this response might come from the i18n middleware, and it might return a 404 + // this response might come from Astro's i18n middleware, and it might return a 404 const response = await next(); // the /about page is an exception and we want to render it if (ctx.url.startsWith("/about")) { @@ -284,17 +244,7 @@ export const onRequest = sequence( ) ``` -### `defaultLocale` and `locales` - -Both a default language ([`defaultLocale`](/en/reference/configuration-reference/#i18ndefaultlocale)) and a list of all supported languages ([`locales`](/en/reference/configuration-reference/#i18nlocales)) must be specified in your `i18n` routing configuration. - -Each entry in the `locales` configuration array must be either a string (e.g. `"fr"`, `"pt-br"`) or a [custom locale path](#custom-locale-paths). `locales` may contain a combination of strings and custom paths. - -Your `/[locale]/` folder names must match exactly the `locale`s in the list (either the string or the `path` value), and your [routing](#routing) configuration must correspond to whether or not you have a localized folder for your default language. Every other supported language must have its own localized folder. - -Depending on your deploy host, you may discover transformations in URL paths, so check your deployed site to determine the best syntax for your `locale` values. - -### Custom locale paths +## Custom locale paths In addition to defining your site's supported `locales` as strings (e.g. "en", "pt-br"), Astro also allows you to map an arbitrary number of [browser-recognized language `codes`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language#syntax) to a custom URL `path`. While locales can be strings of any format as long as they correspond to your project folder structure, `codes` must follow the browser's accepted syntax. @@ -321,7 +271,7 @@ export default defineConfig({ When using functions from the [`astro:i18n` virtual module](#virtual-module-astroi18n) to compute valid URL paths based on your configuration (e.g. `getRelativeLocaleUrl()`), [use the `path` as the value for `locale`](#generating-urls-from-custom-paths). -### Browser language detection +## Browser language detection Astro’s i18n routing allows you to access two properties for browser language detection in pages rendered on demand: `Astro.preferredLocale` and `Astro.preferredLocaleList`. All pages, including static prerendered pages, have access to `Astro.currentLocale`. @@ -335,7 +285,7 @@ These combine the browser's `Accept-Language` header, and your `locales` (string In order to successfully match your visitors' preferences, provide your `codes` using the same pattern [used by the browser](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language#syntax). -### Fallback +## Fallback Astro's i18n routing allows you to configure a **fallback routing strategy**. When a page in one language doesn't exist (e.g. a page that is not yet translated), instead of displaying a 404 page, you can redirect a user from one locale to another on a per-language basis. This is useful when you do not yet have a page for every route, but you want to still provide some content to your visitors. @@ -356,10 +306,81 @@ export default defineConfig({ Astro will ensure that a page is built in `src/pages/fr` for every page that exists in `src/pages/es/`. If the page does not already exist, then a page with a redirect to the corresponding `es` route will be created. +## `domains` (experimental) + +

+ +This routing option allows you to customize your domains on a per-language basis for `server` rendered projects using the [`@astrojs/node`](/en/guides/integrations-guide/node/) or [`@astrojs/vercel`](/en/guides/integrations-guide/vercel/) adapter with a `site` configured. + +To enable this in your project, [configure i18n routing](#configure-i18n-routing) with your preferences if you have not already done so. Then, set the `experimental.i18nDomains` flag to `true` and add `i18n.domains` to map any of your supported `locales` to custom URLs: + +```js title="astro.config.mjs" {3-7} ins={14-21} +import { defineConfig } from "astro/config" +export default defineConfig({ + site: "https://example.com", + output: "server", // required, with no prerendered pages + adapter: node({ + mode: 'standalone', + }), + i18n: { + defaultLocale: "en", + locales: ["es", "en", "fr", "ja"], + routing: { + prefixDefaultLocale: false + }, + domains: { + fr: "https://fr.example.com", + es: "https://example.es" + } + }, + experimental: { + i18nDomains: true + } +}) +``` + +All non-mapped `locales` will follow your `prefixDefaultLocales` configuration. However, even if this value is `false`, page files for your `defaultLocale` must also exist within a localized folder. For the configuration above, an `/en/` folder is required. + +With the above configuration: + +- The file `/fr/about.astro` will create the URL `https://fr.example.com/about`. +- The file `/es/about.astro` will create the URL `https://example.es/about`. +- The file `/ja/about/astro` will create the URL `https://example.com/ja/about`. +- The file `/en/about.astro` will create the URL `https://example.com/about`. + +The above URLs will also be returned by the `getAbsoluteLocaleUrl()` and `getAbsoluteLocaleUrlList()` functions. + +#### Limitations + +This feature has some restrictions: +- The `site` option is mandatory. +- The `output` option must be set to `"server"`. +- There cannot be any individual prerendered pages. +- The adapter feature [`functionPerRoute`](/en/reference/adapter-reference/#functionperroute) is not supported. + +Astro relies on the following headers in order to support the feature: +- [`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. + +Make sure that your server proxy/hosting platform is able to provide this information. Failing to retrieve these headers will result in a 404 (status code) page. + ## Virtual module `astro:i18n` This module provides functions that can help you create URLs using your project's configured locales. +```astro title="src/pages/es/index.astro" +--- +import { getRelativeLocaleUrl } from 'astro:i18n'; + +// defaultLocale is "es" +const aboutURL=getRelativeLocaleUrl("es", "about"); +--- + +¡Vamos! +Blog +Acerca +``` + Creating routes for your project with the i18n router will depend on certain configuration values you have set that affect your page routes. When creating routes with these functions, be sure to take into account your individual settings for: - [`base`](/en/reference/configuration-reference/#base) @@ -516,3 +537,10 @@ console.log(getLocaleByPath("portugues")) // will log "pt-AO" [`site`]: /en/reference/configuration-reference/#site [`i18n.locales`]: /en/reference/configuration-reference/#i18nlocales + + +### `redirectToDefaultLocale` +### `notFound` +### `useFallback` +### `middleware` +### `sequence` From 95a02f1afe4603dcbb8af32499571413e2c56dde Mon Sep 17 00:00:00 2001 From: Sarah Rainsberger Date: Fri, 5 Apr 2024 19:52:38 +0000 Subject: [PATCH 03/13] link fixes --- src/content/docs/en/guides/internationalization.mdx | 2 +- .../reference/errors/missing-index-for-internationalization.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/docs/en/guides/internationalization.mdx b/src/content/docs/en/guides/internationalization.mdx index 4a82863e4c1b1..00f520e326989 100644 --- a/src/content/docs/en/guides/internationalization.mdx +++ b/src/content/docs/en/guides/internationalization.mdx @@ -83,7 +83,7 @@ const aboutURL=getRelativeLocaleUrl("es", "about"); Astro's built-in file-based routing automatically creates URL routes for you based on your file structure within `src/pages/`. When you configure i18n routing, the `routing` value now allows you to specify your file structure (and corresponding URL paths generated) in order to use helper functions to generate, use, and verify the routes in your project. Many of these options can be used together for even more customization and per-language flexibility. -You can even choose to [implement your own routing logic manually](#manual-routing) for even greater control. +You can even choose to [implement your own routing logic manually](#manual) for even greater control. ### `prefixDefaultLocale` diff --git a/src/content/docs/en/reference/errors/missing-index-for-internationalization.mdx b/src/content/docs/en/reference/errors/missing-index-for-internationalization.mdx index 1d3e5b56e3408..5acd2a73212e2 100644 --- a/src/content/docs/en/reference/errors/missing-index-for-internationalization.mdx +++ b/src/content/docs/en/reference/errors/missing-index-for-internationalization.mdx @@ -19,7 +19,7 @@ import DontEditWarning from '~/components/DontEditWarning.astro' Astro could not find the index URL of your website. An index page is required so that Astro can create a redirect from the main index page to the localized index page of the default locale when using [`i18n.routing.prefixDefaultLocale`](/en/reference/configuration-reference/#i18nroutingprefixdefaultlocale). **See Also:** -- [Internationalization](/en/guides/internationalization/#routing) +- [Internationalization](/en/guides/internationalization/#routing-options) - [`i18n.routing` Configuration Reference](/en/reference/configuration-reference/#i18nrouting) From 779debf6d194590496ad3af034265adb9da0ee46 Mon Sep 17 00:00:00 2001 From: Sarah Rainsberger Date: Sat, 6 Apr 2024 12:35:44 +0000 Subject: [PATCH 04/13] change heading back to avoid broken links --- src/content/docs/en/guides/internationalization.mdx | 4 ++-- .../errors/missing-index-for-internationalization.mdx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/docs/en/guides/internationalization.mdx b/src/content/docs/en/guides/internationalization.mdx index 00f520e326989..0e14229c99190 100644 --- a/src/content/docs/en/guides/internationalization.mdx +++ b/src/content/docs/en/guides/internationalization.mdx @@ -77,7 +77,7 @@ const aboutURL=getRelativeLocaleUrl("es", "about"); Acerca ``` -## Routing options +## `routing`

@@ -215,7 +215,7 @@ export const onRequest = defineMiddleware(async (ctx, next) => { The [`middleware`](#middleware) function manually creates Astro's i18n middleware. This allows you to extend Astro's i18n routing instead of completely replacing it. -You can run `middleware` with [routing options](#routing-options) in combination with your own middleware, using the [`sequence`](#sequence) utility to determine the order: +You can run `middleware` with [routing options](#routing) in combination with your own middleware, using the [`sequence`](#sequence) utility to determine the order: ```js title="src/middleware.js" import {defineMiddleware, sequence} from "astro:middleware"; diff --git a/src/content/docs/en/reference/errors/missing-index-for-internationalization.mdx b/src/content/docs/en/reference/errors/missing-index-for-internationalization.mdx index 5acd2a73212e2..1d3e5b56e3408 100644 --- a/src/content/docs/en/reference/errors/missing-index-for-internationalization.mdx +++ b/src/content/docs/en/reference/errors/missing-index-for-internationalization.mdx @@ -19,7 +19,7 @@ import DontEditWarning from '~/components/DontEditWarning.astro' Astro could not find the index URL of your website. An index page is required so that Astro can create a redirect from the main index page to the localized index page of the default locale when using [`i18n.routing.prefixDefaultLocale`](/en/reference/configuration-reference/#i18nroutingprefixdefaultlocale). **See Also:** -- [Internationalization](/en/guides/internationalization/#routing-options) +- [Internationalization](/en/guides/internationalization/#routing) - [`i18n.routing` Configuration Reference](/en/reference/configuration-reference/#i18nrouting) From c175618053c757298bf4532fccd7c08695dc2894 Mon Sep 17 00:00:00 2001 From: Sarah Rainsberger Date: Mon, 8 Apr 2024 14:18:15 -0300 Subject: [PATCH 05/13] typo --- src/content/docs/en/guides/internationalization.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/en/guides/internationalization.mdx b/src/content/docs/en/guides/internationalization.mdx index 0e14229c99190..1e29b1945b1ca 100644 --- a/src/content/docs/en/guides/internationalization.mdx +++ b/src/content/docs/en/guides/internationalization.mdx @@ -345,7 +345,7 @@ With the above configuration: - The file `/fr/about.astro` will create the URL `https://fr.example.com/about`. - The file `/es/about.astro` will create the URL `https://example.es/about`. -- The file `/ja/about/astro` will create the URL `https://example.com/ja/about`. +- The file `/ja/about.astro` will create the URL `https://example.com/ja/about`. - The file `/en/about.astro` will create the URL `https://example.com/about`. The above URLs will also be returned by the `getAbsoluteLocaleUrl()` and `getAbsoluteLocaleUrlList()` functions. From 5a204ba3373b7518e8e6d008d4d276548ac1e0be Mon Sep 17 00:00:00 2001 From: Sarah Rainsberger Date: Tue, 9 Apr 2024 09:39:34 -0300 Subject: [PATCH 06/13] fix typo Co-authored-by: Yan <61414485+yanthomasdev@users.noreply.github.com> --- src/content/docs/en/guides/internationalization.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/en/guides/internationalization.mdx b/src/content/docs/en/guides/internationalization.mdx index 1e29b1945b1ca..46e3b65cb8461 100644 --- a/src/content/docs/en/guides/internationalization.mdx +++ b/src/content/docs/en/guides/internationalization.mdx @@ -89,7 +89,7 @@ You can even choose to [implement your own routing logic manually](#manual) for This routing strategy defines whether or not your default language's URLs should use a language prefix (e.g. `/en/about/`). -All non-default supported languages **will** use a localized prefix (e.g. `/fr/` or `/french/`) and content files must be located in appropriate folders. This configuration option allows you to specify whether your default launguage should also follow a localized URL structure. +All non-default supported languages **will** use a localized prefix (e.g. `/fr/` or `/french/`) and content files must be located in appropriate folders. This configuration option allows you to specify whether your default language should also follow a localized URL structure. This setting also determines where the page files for your default language must exist (e.g. `src/pages/about/` or `src/pages/en/about`) as the file structure and URL structure must match for all languages. From 17bad1a30ec9b0e54e954743faadadd62f1679bd Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 10 Apr 2024 11:39:58 +0100 Subject: [PATCH 07/13] chore: move APIs to api-reference.mdx --- .../docs/en/guides/internationalization.mdx | 178 --------------- .../docs/en/reference/api-reference.mdx | 215 ++++++++++++++++++ 2 files changed, 215 insertions(+), 178 deletions(-) diff --git a/src/content/docs/en/guides/internationalization.mdx b/src/content/docs/en/guides/internationalization.mdx index 46e3b65cb8461..eace19136673c 100644 --- a/src/content/docs/en/guides/internationalization.mdx +++ b/src/content/docs/en/guides/internationalization.mdx @@ -364,183 +364,5 @@ Astro relies on the following headers in order to support the feature: Make sure that your server proxy/hosting platform is able to provide this information. Failing to retrieve these headers will result in a 404 (status code) page. -## Virtual module `astro:i18n` - -This module provides functions that can help you create URLs using your project's configured locales. - -```astro title="src/pages/es/index.astro" ---- -import { getRelativeLocaleUrl } from 'astro:i18n'; - -// defaultLocale is "es" -const aboutURL=getRelativeLocaleUrl("es", "about"); ---- - -¡Vamos! -Blog -Acerca -``` - -Creating routes for your project with the i18n router will depend on certain configuration values you have set that affect your page routes. When creating routes with these functions, be sure to take into account your individual settings for: - -- [`base`](/en/reference/configuration-reference/#base) -- [`trailingSlash`](/en/reference/configuration-reference/#trailingslash) -- [`build.format`](/en/reference/configuration-reference/#buildformat) -- [`site`](/en/reference/configuration-reference/#site) - -Also, note that the returned URLs created by these functions for your `defaultLocale` will reflect your `i18n.routing` configuration. - -URLs created when `prefixDefaultLocale: true` is configured will include a `/lang/` path in the URL. URLs created with `prefixDefaultLocale: false` will not include a language prefix. - -### `getRelativeLocaleUrl()` - -`getRelativeLocaleUrl(locale: string, path: string, options?: GetLocaleOptions): string` - -Use this function to retrieve a relative path for a locale. If the locale doesn't exist, Astro throws an error. - -```astro ---- -getRelativeLocaleUrl("fr"); -// returns /fr - -getRelativeLocaleUrl("fr", ""); -// returns /fr - -getRelativeLocaleUrl("fr", "getting-started"); -// returns /fr/getting-started - -getRelativeLocaleUrl("fr_CA", "getting-started", { - prependWith: "blog" -}); -// returns /blog/fr-ca/getting-started - -getRelativeLocaleUrl("fr_CA", "getting-started", { - prependWith: "blog", - normalizeLocale: false -}); -// returns /blog/fr_CA/getting-started ---- -``` - -### `getAbsoluteLocaleUrl()` - -`getAbsoluteLocaleUrl(locale: string, path: string, options?: GetLocaleOptions): string` - - -Use this function to retrieve an absolute path for a locale when [`site`] has a value. If [`site`] isn't configured, the function returns a relative URL. If the locale doesn't exist, Astro throws an error. - - -```astro title="src/pages/index.astro" ---- -// If `site` is set to be `https://example.com` - -getAbsoluteLocaleUrl("fr"); -// returns https://example.com/fr - -getAbsoluteLocaleUrl("fr", ""); -// returns https://example.com/fr - -getAbsoluteLocaleUrl("fr", "getting-started"); -// returns https://example.com/fr/getting-started - -getAbsoluteLocaleUrl("fr_CA", "getting-started", { - prependWith: "blog" -}); -// returns https://example.com/blog/fr-ca/getting-started - -getAbsoluteLocaleUrl("fr_CA", "getting-started", { - prependWith: "blog", - normalizeLocale: false -}); -// returns https://example.com/blog/fr_CA/getting-started ---- -``` - -### `getRelativeLocaleUrlList()` - -Use this like [`getRelativeLocaleUrl`](#getrelativelocaleurl) to return a list of relative paths for all the locales. - - -`getRelativeLocaleUrlList(path?: string, options?: GetLocaleOptions): string[]` - -### `getAbsoluteLocaleUrlList()` - -`getAbsoluteLocaleUrlList(path?: string, options?: GetLocaleOptions): string[]` - -Use this like [`getAbsoluteLocaleUrl`](#getabsolutelocaleurl) to return a list of absolute paths for all the locales. - -### `getPathByLocale(locale: string): string` - -A function that returns the `path` associated to one or more `codes` when [custom locale paths](#custom-locale-paths) are configured. - -### Generating URLs from custom paths - -When a `locale` is a custom path, use the `path` as the value for `locale`. - -For example, use `french` in the i18n helper functions for the `locales` configuration below: - -```js -locales: ["es", "en", { - path: "french", - codes: ["fr", "fr-BR", "fr-CA"] -}], -``` - -```astro title="src/pages/index.astro" ---- -import { getPathByLocale, getRelativeLocaleUrl, getLocaleByPath } from "astro:i18n"; - -getRelativeLocaleUrl("french", "blog"); // returns /french/blog ---- -``` -Note that other `astro:i18n` functions will return the following results for the same configuration: - -```astro title="src/pages/index.astro" ---- -getPathByLocale("fr"); // returns "french" -getPathByLocale("fr-CA"); // returns "french" -getLocaleByPath("french"); // returns "fr" because that's the first code configured ---- -``` - -### `getLocaleByPath(path: string): string` - -A function that returns the `code` associated to a locale `path`. - -### Retrieve the locale for a custom path - -Given a custom path configured with multiple `codes`, the function will return the **first** code configured: - -```js -// astro.config.mjs -import {defineConfig} from "astro/config" -export default defineConfig({ - i18n: { - defaultLocale: "en", - locales: ["en", "es", "fr", { - path: "portugues", - codes: ["pt-AO", "pt", "pt-BR"] - }] - } -}) -``` - -```astro ---- -// src/pages/index.astro -import { getLocaleByPath } from "astro:i18n"; -console.log(getLocaleByPath("en")) // will log "en" -console.log(getLocaleByPath("fr")) // will log "fr" -console.log(getLocaleByPath("portugues")) // will log "pt-AO" ---- -``` - [`site`]: /en/reference/configuration-reference/#site [`i18n.locales`]: /en/reference/configuration-reference/#i18nlocales - - -### `redirectToDefaultLocale` -### `notFound` -### `useFallback` -### `middleware` -### `sequence` diff --git a/src/content/docs/en/reference/api-reference.mdx b/src/content/docs/en/reference/api-reference.mdx index 97acde8510a40..f69f4793c8e5d 100644 --- a/src/content/docs/en/reference/api-reference.mdx +++ b/src/content/docs/en/reference/api-reference.mdx @@ -1395,6 +1395,221 @@ This function can be used by integrations/adapters to programmatically execute t A low-level API that takes in any value and tries to return a serialized version (a string) of it. If the value cannot be serialized, the function will throw a runtime error. +## Internationalization (`astro:i18n`) + +### `getRelativeLocaleUrl(locale: string, path?: string, options?: GetLocaleOptions): string` + +Use this function to retrieve a relative path for a locale. If the locale doesn't exist, Astro throws an error. + +```astro +--- +getRelativeLocaleUrl("fr"); +// returns /fr + +getRelativeLocaleUrl("fr", ""); +// returns /fr + +getRelativeLocaleUrl("fr", "getting-started"); +// returns /fr/getting-started + +getRelativeLocaleUrl("fr_CA", "getting-started", { + prependWith: "blog" +}); +// returns /blog/fr-ca/getting-started + +getRelativeLocaleUrl("fr_CA", "getting-started", { + prependWith: "blog", + normalizeLocale: false +}); +// returns /blog/fr_CA/getting-started +--- +``` + +### `getAbsoluteLocaleUrl(locale: string, path: string, options?: GetLocaleOptions): string` + +Use this function to retrieve an absolute path for a locale when [`site`] has a value. If [`site`] isn't configured, the function returns a relative URL. If the locale doesn't exist, Astro throws an error. + + +```astro title="src/pages/index.astro" +--- +// If `site` is set to be `https://example.com` + +getAbsoluteLocaleUrl("fr"); +// returns https://example.com/fr + +getAbsoluteLocaleUrl("fr", ""); +// returns https://example.com/fr + +getAbsoluteLocaleUrl("fr", "getting-started"); +// returns https://example.com/fr/getting-started + +getAbsoluteLocaleUrl("fr_CA", "getting-started", { + prependWith: "blog" +}); +// returns https://example.com/blog/fr-ca/getting-started + +getAbsoluteLocaleUrl("fr_CA", "getting-started", { + prependWith: "blog", + normalizeLocale: false +}); +// returns https://example.com/blog/fr_CA/getting-started +--- +``` + +### `getRelativeLocaleUrlList(path?: string, options?: GetLocaleOptions): string[]` + + +Use this like [`getRelativeLocaleUrl`](#getrelativelocaleurl) to return a list of relative paths for all the locales. + + +### `getAbsoluteLocaleUrlList(path?: string, options?: GetLocaleOptions): string[]` + +Use this like [`getAbsoluteLocaleUrl`](#getabsolutelocaleurl) to return a list of absolute paths for all the locales. + +### `getPathByLocale(locale: string): string` + +A function that returns the `path` associated to one or more `codes` when [custom locale paths](#custom-locale-paths) are configured. + +```js title="astro.config.mjs" +export default defineConfig({ + i18n: { + locales: ["es", "en", { + path: "french", + codes: ["fr", "fr-BR", "fr-CA"] + }] + } +}) +``` + +```astro title="src/pages/index.astro" +--- +getPathByLocale("fr"); // returns "french" +getPathByLocale("fr-CA"); // returns "french" +--- +``` + +### `getLocaleByPath(path: string): string` + +A function that returns the `code` associated to a locale `path`. + +```js title="astro.config.mjs" +export default defineConfig({ + i18n: { + locales: ["es", "en", { + path: "french", + codes: ["fr", "fr-BR", "fr-CA"] + }] + } +}) +``` + +```astro title="src/pages/index.astro" +--- +getLocaleByPath("french"); // returns "fr" because that's the first code configured +--- +``` + +### `redirectToDefaultLocale(context: APIContext, statusCode?: ValidRedirectStatus): Promise` + +:::note +Available only when `i18n.routing` is set to `"manual"` +::: + +It returns a `Response` that redirects to the `defaultLocale` configured. It accepts an optional valid redirect status code. + +```js title="middleware.js" +import { defineMiddleware } from "astro:middleware"; +import { redirectToDefaultLocale } from "astro:i18n"; + +export const onRequest = defineMiddleware((context, next) => { + if (context.url.pathname.startsWith("/about") { + return next(); + } else { + return redirectToDefaultLocale(context, 302); + } +}) +``` + +### `redirectToFallback(context: APIContext, response: Response): Promise` + +Allows to use the build-in fallback system of Astro. + +```js title="middleware.js" +import { defineMiddleware } from "astro:middleware"; +import { redirectToFallback } from "astro:i18n"; + +export const onRequest = defineMiddleware(async (context, next) => { + const response = await next(); + if (response.status >= 300) { + return redirectToFallback(context, response) + } + return response; +}) +``` + +### `notFound(context: APIContext, response: Response): Promise` + +Use this function to return a 404 when: +- the current path isn't a root. e.g. / or / +- the URL doesn't contain a locale + +When a `Response` is passed, the new `Response` emitted by this function will contain the same headers of the original response. + +```js title="middleware.js" +import { defineMiddleware } from "astro:middleware"; +import { notFound } from "astro:i18n"; + +export const onRequest = defineMiddleware(async (context, next) => { + const pathNotFound = notFound(context); + if (pathNotFound) { + return pathNotFound; + } + return next(); +}) +``` + +### `middleware(options: { prefixDefaultLocale: boolean, redirectToDefaultLocale: boolean })` + +A function that allows to programmatically create the Astro i18n middleware. + +This is use useful when you still want to use the default i18n logic, but add only few exceptions to your website. + +## Examples + +```js title="middleware.js" +import { middleware } from "astro:i18n"; +import { sequence, defineMiddleware } from "astro:middleware"; + +const customLogic = defineMiddleware(async (context, next) => { + const response = await next(); + + // Custom logic after resolving the response. + // It's possible to catch the response coming from Astro i18n middleware. + + return response; +}); + +export const onRequest = sequence(customLogic, middleware({ + prefixDefaultLocale: true, + redirectToDefaultLocale: false +})) +``` + +### `requestHasLocale(context: APIContext): boolean` + +Checks whether the current URL contains a configured locale. Internally, this function will use `APIContext#url.pathname` + +```js title="middleware.js" +import { defineMiddleware } from "astro:middleware"; +import { requestHasLocale } from "astro:i18n"; + +export const onRequest = defineMiddleware(async (context, next) => { + if (requestHasLocale(context)) { + return next(); + } + return new Response("Not found", { status: 404 }); +}) +``` ## Built-in Components From 50e6ad36a3fc287747ebbc425267e4e466a8ab4c Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 10 Apr 2024 11:53:05 +0100 Subject: [PATCH 08/13] chore: fix links and better headers --- .../docs/en/guides/internationalization.mdx | 2 +- .../docs/en/reference/api-reference.mdx | 64 ++++++++++++++----- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/content/docs/en/guides/internationalization.mdx b/src/content/docs/en/guides/internationalization.mdx index eace19136673c..cf03fb1c8a402 100644 --- a/src/content/docs/en/guides/internationalization.mdx +++ b/src/content/docs/en/guides/internationalization.mdx @@ -60,7 +60,7 @@ The localized folders do not need to be at the root of the `/pages/` folder. ### Create links -With i18n routing configured, you can now compute links to pages within your site using the helper functions such as [`getRelativeLocaleURL()`](#getrelativelocaleurl) available from the [`astro:i18n` module](#virtual-module-astroi18n). These generated links will always provide the correct, localized route and can help you correctly use, or check, URLs on your site. +With i18n routing configured, you can now compute links to pages within your site using the helper functions such as [`getRelativeLocaleURL()`](/en/reference/api-reference/#getrelativelocaleurl) available from the [`astro:i18n` module](#virtual-module-astroi18n). These generated links will always provide the correct, localized route and can help you correctly use, or check, URLs on your site. You can also still write the links manually. diff --git a/src/content/docs/en/reference/api-reference.mdx b/src/content/docs/en/reference/api-reference.mdx index f69f4793c8e5d..c91dd157719f0 100644 --- a/src/content/docs/en/reference/api-reference.mdx +++ b/src/content/docs/en/reference/api-reference.mdx @@ -1397,7 +1397,9 @@ A low-level API that takes in any value and tries to return a serialized version ## Internationalization (`astro:i18n`) -### `getRelativeLocaleUrl(locale: string, path?: string, options?: GetLocaleOptions): string` +### `getRelativeLocaleUrl()` + +`getRelativeLocaleUrl(locale: string, path?: string, options?: GetLocaleOptions): string` Use this function to retrieve a relative path for a locale. If the locale doesn't exist, Astro throws an error. @@ -1425,7 +1427,9 @@ getRelativeLocaleUrl("fr_CA", "getting-started", { --- ``` -### `getAbsoluteLocaleUrl(locale: string, path: string, options?: GetLocaleOptions): string` +### `getAbsoluteLocaleUrl()` + +`getAbsoluteLocaleUrl(locale: string, path: string, options?: GetLocaleOptions): string` Use this function to retrieve an absolute path for a locale when [`site`] has a value. If [`site`] isn't configured, the function returns a relative URL. If the locale doesn't exist, Astro throws an error. @@ -1456,17 +1460,23 @@ getAbsoluteLocaleUrl("fr_CA", "getting-started", { --- ``` -### `getRelativeLocaleUrlList(path?: string, options?: GetLocaleOptions): string[]` +### `getRelativeLocaleUrlList()` + +`getRelativeLocaleUrlList(path?: string, options?: GetLocaleOptions): string[]` Use this like [`getRelativeLocaleUrl`](#getrelativelocaleurl) to return a list of relative paths for all the locales. -### `getAbsoluteLocaleUrlList(path?: string, options?: GetLocaleOptions): string[]` +### `getAbsoluteLocaleUrlList()` + +`getAbsoluteLocaleUrlList(path?: string, options?: GetLocaleOptions): string[]` Use this like [`getAbsoluteLocaleUrl`](#getabsolutelocaleurl) to return a list of absolute paths for all the locales. -### `getPathByLocale(locale: string): string` +### `getPathByLocale()` + +`getPathByLocale(locale: string): string` A function that returns the `path` associated to one or more `codes` when [custom locale paths](#custom-locale-paths) are configured. @@ -1488,7 +1498,9 @@ getPathByLocale("fr-CA"); // returns "french" --- ``` -### `getLocaleByPath(path: string): string` +### `getLocaleByPath` + + `getLocaleByPath(path: string): string` A function that returns the `code` associated to a locale `path`. @@ -1509,7 +1521,9 @@ getLocaleByPath("french"); // returns "fr" because that's the first code configu --- ``` -### `redirectToDefaultLocale(context: APIContext, statusCode?: ValidRedirectStatus): Promise` +### `redirectToDefaultLocale()` + +`redirectToDefaultLocale(context: APIContext, statusCode?: ValidRedirectStatus): Promise` :::note Available only when `i18n.routing` is set to `"manual"` @@ -1522,7 +1536,7 @@ import { defineMiddleware } from "astro:middleware"; import { redirectToDefaultLocale } from "astro:i18n"; export const onRequest = defineMiddleware((context, next) => { - if (context.url.pathname.startsWith("/about") { + if (context.url.pathname.startsWith("/about")) { return next(); } else { return redirectToDefaultLocale(context, 302); @@ -1530,7 +1544,13 @@ export const onRequest = defineMiddleware((context, next) => { }) ``` -### `redirectToFallback(context: APIContext, response: Response): Promise` +### `redirectToFallback()` + +:::note +Available only when `i18n.routing` is set to `"manual"` +::: + +`redirectToFallback(context: APIContext, response: Response): Promise` Allows to use the build-in fallback system of Astro. @@ -1547,10 +1567,16 @@ export const onRequest = defineMiddleware(async (context, next) => { }) ``` -### `notFound(context: APIContext, response: Response): Promise` +### `notFound()` + +:::note +Available only when `i18n.routing` is set to `"manual"` +::: + +`notFound(context: APIContext, response: Response): Promise` Use this function to return a 404 when: -- the current path isn't a root. e.g. / or / +- the current path isn't a root. e.g. `/` or `/` - the URL doesn't contain a locale When a `Response` is passed, the new `Response` emitted by this function will contain the same headers of the original response. @@ -1559,7 +1585,7 @@ When a `Response` is passed, the new `Response` emitted by this function will co import { defineMiddleware } from "astro:middleware"; import { notFound } from "astro:i18n"; -export const onRequest = defineMiddleware(async (context, next) => { +export const onRequest = defineMiddleware((context, next) => { const pathNotFound = notFound(context); if (pathNotFound) { return pathNotFound; @@ -1568,14 +1594,18 @@ export const onRequest = defineMiddleware(async (context, next) => { }) ``` -### `middleware(options: { prefixDefaultLocale: boolean, redirectToDefaultLocale: boolean })` +### `middleware()` + +`middleware(options: { prefixDefaultLocale: boolean, redirectToDefaultLocale: boolean })` + +:::note +Available only when `i18n.routing` is set to `"manual"` +::: A function that allows to programmatically create the Astro i18n middleware. This is use useful when you still want to use the default i18n logic, but add only few exceptions to your website. -## Examples - ```js title="middleware.js" import { middleware } from "astro:i18n"; import { sequence, defineMiddleware } from "astro:middleware"; @@ -1595,7 +1625,9 @@ export const onRequest = sequence(customLogic, middleware({ })) ``` -### `requestHasLocale(context: APIContext): boolean` +### `requestHasLocale()` + +`requestHasLocale(context: APIContext): boolean` Checks whether the current URL contains a configured locale. Internally, this function will use `APIContext#url.pathname` From a05509250fc8fcaca86b24de1017627d1c801060 Mon Sep 17 00:00:00 2001 From: Sarah Rainsberger Date: Wed, 10 Apr 2024 12:05:46 +0000 Subject: [PATCH 09/13] fix some links! --- .../docs/en/guides/internationalization.mdx | 16 +++++++++------- .../docs/ko/guides/internationalization.mdx | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/content/docs/en/guides/internationalization.mdx b/src/content/docs/en/guides/internationalization.mdx index cf03fb1c8a402..ff1bacffeaa7d 100644 --- a/src/content/docs/en/guides/internationalization.mdx +++ b/src/content/docs/en/guides/internationalization.mdx @@ -60,7 +60,7 @@ The localized folders do not need to be at the root of the `/pages/` folder. ### Create links -With i18n routing configured, you can now compute links to pages within your site using the helper functions such as [`getRelativeLocaleURL()`](/en/reference/api-reference/#getrelativelocaleurl) available from the [`astro:i18n` module](#virtual-module-astroi18n). These generated links will always provide the correct, localized route and can help you correctly use, or check, URLs on your site. +With i18n routing configured, you can now compute links to pages within your site using the helper functions such as [`getRelativeLocaleURL()`](/en/reference/api-reference/#getrelativelocaleurl) available from the [`astro:i18n` module](/en/reference/api-reference/#internationalization-astroi18n). These generated links will always provide the correct, localized route and can help you correctly use, or check, URLs on your site. You can also still write the links manually. @@ -79,15 +79,17 @@ const aboutURL=getRelativeLocaleUrl("es", "about"); ## `routing` -

+Astro's built-in file-based routing automatically creates URL routes for you based on your file structure within `src/pages/`. -Astro's built-in file-based routing automatically creates URL routes for you based on your file structure within `src/pages/`. When you configure i18n routing, the `routing` value now allows you to specify your file structure (and corresponding URL paths generated) in order to use helper functions to generate, use, and verify the routes in your project. Many of these options can be used together for even more customization and per-language flexibility. +When you configure i18n routing, information about this file structure (and the corresponding URL paths generated) is available to the i18n helper functions so they can generate, use, and verify the routes in your project. Many of these options can be used together for even more customization and per-language flexibility. You can even choose to [implement your own routing logic manually](#manual) for even greater control. ### `prefixDefaultLocale` -This routing strategy defines whether or not your default language's URLs should use a language prefix (e.g. `/en/about/`). +

+ +This routing option defines whether or not your default language's URLs should use a language prefix (e.g. `/en/about/`). All non-default supported languages **will** use a localized prefix (e.g. `/fr/` or `/french/`) and content files must be located in appropriate folders. This configuration option allows you to specify whether your default language should also follow a localized URL structure. @@ -196,7 +198,7 @@ export default defineConfig({ }) ``` -Astro provides helper functions for your middleware so you can control your own default routing, exceptions, fallback behavior, error catching, etc: [`redirectToDefaultLocale`](#redirecttodefaultlocale), [`notFound`](#notfound), and [`useFallback`](#usefallback): +Astro provides helper functions for your middleware so you can control your own default routing, exceptions, fallback behavior, error catching, etc: [`redirectToDefaultLocale()`](/en/reference/api-reference/#redirecttodefaultlocale), [`notFound()`](/en/reference/api-reference/#notfound), and [`redirectToFallback()`](/en/reference/api-reference/#redirecttofallback): ```js title="src/middleware.js" @@ -215,7 +217,7 @@ export const onRequest = defineMiddleware(async (ctx, next) => { The [`middleware`](#middleware) function manually creates Astro's i18n middleware. This allows you to extend Astro's i18n routing instead of completely replacing it. -You can run `middleware` with [routing options](#routing) in combination with your own middleware, using the [`sequence`](#sequence) utility to determine the order: +You can run `middleware` with [routing options](#routing) in combination with your own middleware, using the [`sequence`](/en/reference/api-reference/#sequence) utility to determine the order: ```js title="src/middleware.js" import {defineMiddleware, sequence} from "astro:middleware"; @@ -269,7 +271,7 @@ export default defineConfig({ }) ``` -When using functions from the [`astro:i18n` virtual module](#virtual-module-astroi18n) to compute valid URL paths based on your configuration (e.g. `getRelativeLocaleUrl()`), [use the `path` as the value for `locale`](#generating-urls-from-custom-paths). +When using functions from the [`astro:i18n` virtual module](/en/reference/api-reference/#internationalization-astroi18n) to compute valid URL paths based on your configuration (e.g. `getRelativeLocaleUrl()`), [use the `path` as the value for `locale`](/en/reference/api-reference/#getlocalebypath). ## Browser language detection diff --git a/src/content/docs/ko/guides/internationalization.mdx b/src/content/docs/ko/guides/internationalization.mdx index dc0c338413239..1654aef5d1fdd 100644 --- a/src/content/docs/ko/guides/internationalization.mdx +++ b/src/content/docs/ko/guides/internationalization.mdx @@ -21,7 +21,7 @@ Astro의 i18n 라우팅을 사용하면 기본 언어 구성, 상대 페이지 U ### i18n 라우팅 구성 -1. [기본 언어 (`defaultLocale`) 및 지원할 모든 언어 목록 (`locales`)](#defaultlocale-및-locales)을 사용하여 Astro 구성에 `i18n` 객체를 추가하여 라우팅 옵션을 활성화합니다. +1. [기본 언어 (`defaultLocale`) 및 지원할 모든 언어 목록 (`locales`)](/ko/reference/configuration-reference/#i18nlocales)을 사용하여 Astro 구성에 `i18n` 객체를 추가하여 라우팅 옵션을 활성화합니다. ```js title="astro.config.mjs" import { defineConfig } from 'astro/config'; From b8f858c33a03c2ed38280ab0632e86c6be13fda6 Mon Sep 17 00:00:00 2001 From: Sarah Rainsberger Date: Wed, 10 Apr 2024 12:23:06 +0000 Subject: [PATCH 10/13] rest of links fixed! --- src/content/docs/en/guides/internationalization.mdx | 2 +- src/content/docs/en/reference/api-reference.mdx | 2 +- src/content/docs/en/reference/configuration-reference.mdx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/docs/en/guides/internationalization.mdx b/src/content/docs/en/guides/internationalization.mdx index ff1bacffeaa7d..3fd7e124c6a34 100644 --- a/src/content/docs/en/guides/internationalization.mdx +++ b/src/content/docs/en/guides/internationalization.mdx @@ -215,7 +215,7 @@ export const onRequest = defineMiddleware(async (ctx, next) => { #### middleware function -The [`middleware`](#middleware) function manually creates Astro's i18n middleware. This allows you to extend Astro's i18n routing instead of completely replacing it. +The [`middleware`](#middleware-function) function manually creates Astro's i18n middleware. This allows you to extend Astro's i18n routing instead of completely replacing it. You can run `middleware` with [routing options](#routing) in combination with your own middleware, using the [`sequence`](/en/reference/api-reference/#sequence) utility to determine the order: diff --git a/src/content/docs/en/reference/api-reference.mdx b/src/content/docs/en/reference/api-reference.mdx index c91dd157719f0..a5bff6e6b4882 100644 --- a/src/content/docs/en/reference/api-reference.mdx +++ b/src/content/docs/en/reference/api-reference.mdx @@ -1472,7 +1472,7 @@ Use this like [`getRelativeLocaleUrl`](#getrelativelocaleurl) to return a list o `getAbsoluteLocaleUrlList(path?: string, options?: GetLocaleOptions): string[]` -Use this like [`getAbsoluteLocaleUrl`](#getabsolutelocaleurl) to return a list of absolute paths for all the locales. +Use this like [`getAbsoluteLocaleUrl`](/en/guides/internationalization/#custom-locale-paths) to return a list of absolute paths for all the locales. ### `getPathByLocale()` diff --git a/src/content/docs/en/reference/configuration-reference.mdx b/src/content/docs/en/reference/configuration-reference.mdx index 27f20b8fe7e83..2e0ed0328a75b 100644 --- a/src/content/docs/en/reference/configuration-reference.mdx +++ b/src/content/docs/en/reference/configuration-reference.mdx @@ -1340,7 +1340,7 @@ export default defineConfig({ }); ``` -Both page routes built and URLs returned by the `astro:i18n` helper functions [`getAbsoluteLocaleUrl()`](/en/guides/internationalization/#getabsolutelocaleurl) and [`getAbsoluteLocaleUrlList()`](/en/guides/internationalization/#getabsolutelocaleurllist) will use the options set in `i18n.domains`. +Both page routes built and URLs returned by the `astro:i18n` helper functions [`getAbsoluteLocaleUrl()`](/en/reference/api-reference/#getabsolutelocaleurl) and [`getAbsoluteLocaleUrlList()`](/en/reference/api-reference/#getabsolutelocaleurllist) will use the options set in `i18n.domains`. See the [Internationalization Guide](/en/guides/internationalization/#domains-experimental) for more details, including the limitations of this experimental feature. From e14c026fd32c8891aabf6c8aba28b20082d6356d Mon Sep 17 00:00:00 2001 From: Sarah Rainsberger Date: Wed, 10 Apr 2024 12:43:34 +0000 Subject: [PATCH 11/13] fix more links! --- src/content/docs/en/reference/api-reference.mdx | 2 +- src/content/docs/es/reference/configuration-reference.mdx | 2 +- src/content/docs/ja/reference/configuration-reference.mdx | 2 +- src/content/docs/zh-cn/reference/configuration-reference.mdx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/content/docs/en/reference/api-reference.mdx b/src/content/docs/en/reference/api-reference.mdx index a5bff6e6b4882..a60fe6a765b14 100644 --- a/src/content/docs/en/reference/api-reference.mdx +++ b/src/content/docs/en/reference/api-reference.mdx @@ -1478,7 +1478,7 @@ Use this like [`getAbsoluteLocaleUrl`](/en/guides/internationalization/#custom-l `getPathByLocale(locale: string): string` -A function that returns the `path` associated to one or more `codes` when [custom locale paths](#custom-locale-paths) are configured. +A function that returns the `path` associated to one or more `codes` when [custom locale paths](/en/guides/internationalization/#custom-locale-paths) are configured. ```js title="astro.config.mjs" export default defineConfig({ diff --git a/src/content/docs/es/reference/configuration-reference.mdx b/src/content/docs/es/reference/configuration-reference.mdx index 92ed0b2444f86..75b4d6fa1223f 100644 --- a/src/content/docs/es/reference/configuration-reference.mdx +++ b/src/content/docs/es/reference/configuration-reference.mdx @@ -1306,5 +1306,5 @@ export default defineConfig({ }, }); ``` -Ambas rutas de página construidas y URLs devueltas por las funciones auxiliares `astro:i18n` [`getAbsoluteLocaleUrl()`](/es/guides/internationalization/#getabsolutelocaleurl) y [`getAbsoluteLocaleUrlList()`](/es/guides/internationalization/#getabsolutelocaleurllist) utilizarán las opciones establecidas en `i18n.domains`. +Ambas rutas de página construidas y URLs devueltas por las funciones auxiliares `astro:i18n` [`getAbsoluteLocaleUrl()`](/es/reference/api-reference/#getabsolutelocaleurl) y [`getAbsoluteLocaleUrlList()`](/es/reference/api-reference/#getabsolutelocaleurllist) utilizarán las opciones establecidas en `i18n.domains`. Ver la [Guía de Internacionalización](/es/guides/internationalization/#domains-experimental) para más detalles, incluyendo las limitaciones de esta característica experimental. diff --git a/src/content/docs/ja/reference/configuration-reference.mdx b/src/content/docs/ja/reference/configuration-reference.mdx index f875eb6b14de6..da22b6961832e 100644 --- a/src/content/docs/ja/reference/configuration-reference.mdx +++ b/src/content/docs/ja/reference/configuration-reference.mdx @@ -1223,6 +1223,6 @@ export default defineConfig({ }); ``` -作成されたページルートと、`astro:i18n`のヘルパー関数[`getAbsoluteLocaleUrl()`](/ja/guides/internationalization/#getabsolutelocaleurl)および[`getAbsoluteLocaleUrlList()`](/ja/guides/internationalization/#getabsolutelocaleurllist)から返されたURLは、ともに`i18n.domains`に設定されたオプションを使用します。 +作成されたページルートと、`astro:i18n`のヘルパー関数[`getAbsoluteLocaleUrl()`](/ja/reference/api-reference/#getabsolutelocaleurl)および[`getAbsoluteLocaleUrlList()`](/ja/reference/api-reference/#getabsolutelocaleurllist)から返されたURLは、ともに`i18n.domains`に設定されたオプションを使用します。 この実験的機能の制限を含む詳しい情報については、[国際化ガイド](/ja/guides/internationalization/#domains-experimental)を参照してください。 diff --git a/src/content/docs/zh-cn/reference/configuration-reference.mdx b/src/content/docs/zh-cn/reference/configuration-reference.mdx index a0ff5803c9533..b9df46228ec74 100644 --- a/src/content/docs/zh-cn/reference/configuration-reference.mdx +++ b/src/content/docs/zh-cn/reference/configuration-reference.mdx @@ -1338,6 +1338,6 @@ export default defineConfig({ }); ``` -`astro:i18n` 辅助函数 [`getAbsoluteLocaleUrl()`](/zh-cn/guides/internationalization/#getabsolutelocaleurl) 和 [`getAbsoluteLocaleUrlList()`](/zh-cn/guides/internationalization/#getabsolutelocaleurllist) 构建的页面路由和 URL 将使用 `i18n.domains` 中设置的选项。 +`astro:i18n` 辅助函数 [`getAbsoluteLocaleUrl()`](/zh-cn/reference/api-reference/#getabsolutelocaleurl) 和 [`getAbsoluteLocaleUrlList()`](/zh-cn/reference/api-reference/#getabsolutelocaleurllist) 构建的页面路由和 URL 将使用 `i18n.domains` 中设置的选项。 查看 [国际化指南](/zh-cn/guides/internationalization/#domains-experimental) 以获取更多细节,包括这个实验性功能的限制。 From 2be6beae3a9d6f5adf69cd3f4ab0916496566666 Mon Sep 17 00:00:00 2001 From: Sarah Rainsberger Date: Wed, 10 Apr 2024 13:16:37 +0000 Subject: [PATCH 12/13] should be last link fix --- src/content/docs/es/reference/configuration-reference.mdx | 2 +- src/content/docs/zh-cn/reference/configuration-reference.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/docs/es/reference/configuration-reference.mdx b/src/content/docs/es/reference/configuration-reference.mdx index 75b4d6fa1223f..7013b4453b2b4 100644 --- a/src/content/docs/es/reference/configuration-reference.mdx +++ b/src/content/docs/es/reference/configuration-reference.mdx @@ -1306,5 +1306,5 @@ export default defineConfig({ }, }); ``` -Ambas rutas de página construidas y URLs devueltas por las funciones auxiliares `astro:i18n` [`getAbsoluteLocaleUrl()`](/es/reference/api-reference/#getabsolutelocaleurl) y [`getAbsoluteLocaleUrlList()`](/es/reference/api-reference/#getabsolutelocaleurllist) utilizarán las opciones establecidas en `i18n.domains`. +Ambas rutas de página construidas y URLs devueltas por las funciones auxiliares `astro:i18n` `getAbsoluteLocaleUrl()` y `getAbsoluteLocaleUrlList()` utilizarán las opciones establecidas en `i18n.domains`. Ver la [Guía de Internacionalización](/es/guides/internationalization/#domains-experimental) para más detalles, incluyendo las limitaciones de esta característica experimental. diff --git a/src/content/docs/zh-cn/reference/configuration-reference.mdx b/src/content/docs/zh-cn/reference/configuration-reference.mdx index b9df46228ec74..0f85c95ff739e 100644 --- a/src/content/docs/zh-cn/reference/configuration-reference.mdx +++ b/src/content/docs/zh-cn/reference/configuration-reference.mdx @@ -1338,6 +1338,6 @@ export default defineConfig({ }); ``` -`astro:i18n` 辅助函数 [`getAbsoluteLocaleUrl()`](/zh-cn/reference/api-reference/#getabsolutelocaleurl) 和 [`getAbsoluteLocaleUrlList()`](/zh-cn/reference/api-reference/#getabsolutelocaleurllist) 构建的页面路由和 URL 将使用 `i18n.domains` 中设置的选项。 +`astro:i18n` 辅助函数 `getAbsoluteLocaleUrl()` 和 `getAbsoluteLocaleUrlList()` 构建的页面路由和 URL 将使用 `i18n.domains` 中设置的选项。 查看 [国际化指南](/zh-cn/guides/internationalization/#domains-experimental) 以获取更多细节,包括这个实验性功能的限制。 From 9920060925c9eeb0d843388c5444c935f27713cc Mon Sep 17 00:00:00 2001 From: Sarah Rainsberger Date: Wed, 10 Apr 2024 13:48:53 +0000 Subject: [PATCH 13/13] api-reference updates --- .../docs/en/reference/api-reference.mdx | 49 +++++++++++++++---- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/content/docs/en/reference/api-reference.mdx b/src/content/docs/en/reference/api-reference.mdx index a60fe6a765b14..273a9eff21689 100644 --- a/src/content/docs/en/reference/api-reference.mdx +++ b/src/content/docs/en/reference/api-reference.mdx @@ -1397,6 +1397,21 @@ A low-level API that takes in any value and tries to return a serialized version ## Internationalization (`astro:i18n`) +

+ +This module provides functions to help you create URLs using your project's configured locales. + +Creating routes for your project with the i18n router will depend on certain configuration values you have set that affect your page routes. When creating routes with these functions, be sure to take into account your individual settings for: + +- [`base`](/en/reference/configuration-reference/#base) +- [`trailingSlash`](/en/reference/configuration-reference/#trailingslash) +- [`build.format`](/en/reference/configuration-reference/#buildformat) +- [`site`](/en/reference/configuration-reference/#site) + +Also, note that the returned URLs created by these functions for your `defaultLocale` will reflect your `i18n.routing` configuration. + +For features and usage examples, [see our i18n routing guide](/en/guides/internationalization/). + ### `getRelativeLocaleUrl()` `getRelativeLocaleUrl(locale: string, path?: string, options?: GetLocaleOptions): string` @@ -1525,11 +1540,13 @@ getLocaleByPath("french"); // returns "fr" because that's the first code configu `redirectToDefaultLocale(context: APIContext, statusCode?: ValidRedirectStatus): Promise` +

+ :::note Available only when `i18n.routing` is set to `"manual"` ::: -It returns a `Response` that redirects to the `defaultLocale` configured. It accepts an optional valid redirect status code. +A function that returns a `Response` that redirects to the `defaultLocale` configured. It accepts an optional valid redirect status code. ```js title="middleware.js" import { defineMiddleware } from "astro:middleware"; @@ -1546,13 +1563,15 @@ export const onRequest = defineMiddleware((context, next) => { ### `redirectToFallback()` +`redirectToFallback(context: APIContext, response: Response): Promise` + +

+ :::note Available only when `i18n.routing` is set to `"manual"` ::: -`redirectToFallback(context: APIContext, response: Response): Promise` - -Allows to use the build-in fallback system of Astro. +A function that allows you to use your [`i18n.fallback` configuration](/en/reference/configuration-reference/#i18nfallback) in your own middleware. ```js title="middleware.js" import { defineMiddleware } from "astro:middleware"; @@ -1569,13 +1588,15 @@ export const onRequest = defineMiddleware(async (context, next) => { ### `notFound()` +`notFound(context: APIContext, response: Response): Promise` + +

+ :::note Available only when `i18n.routing` is set to `"manual"` ::: -`notFound(context: APIContext, response: Response): Promise` - -Use this function to return a 404 when: +Use this function in your routing middleware to return a 404 when: - the current path isn't a root. e.g. `/` or `/` - the URL doesn't contain a locale @@ -1598,13 +1619,15 @@ export const onRequest = defineMiddleware((context, next) => { `middleware(options: { prefixDefaultLocale: boolean, redirectToDefaultLocale: boolean })` +

+ :::note Available only when `i18n.routing` is set to `"manual"` ::: -A function that allows to programmatically create the Astro i18n middleware. +A function that allows you to programmatically create the Astro i18n middleware. -This is use useful when you still want to use the default i18n logic, but add only few exceptions to your website. +This is use useful when you still want to use the default i18n logic, but add only a few exceptions to your website. ```js title="middleware.js" import { middleware } from "astro:i18n"; @@ -1629,7 +1652,13 @@ export const onRequest = sequence(customLogic, middleware({ `requestHasLocale(context: APIContext): boolean` -Checks whether the current URL contains a configured locale. Internally, this function will use `APIContext#url.pathname` +

+ +:::note +Available only when `i18n.routing` is set to `"manual"` +::: + +Checks whether the current URL contains a configured locale. Internally, this function will use `APIContext#url.pathname`. ```js title="middleware.js" import { defineMiddleware } from "astro:middleware";