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

feat: make i18n domains stable #11022

Merged
merged 4 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
23 changes: 23 additions & 0 deletions .changeset/five-crabs-rhyme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
"astro": minor
---

The `i18nDomains` routing feature introduced behind a flag in [v3.4.0](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md#430) is no longer experimental and is available for general use.

This routing option allows you to configure different domains for individual locales in entirely server-rendered projects using the [@astrojs/node](https://docs.astro.build/en/guides/integrations-guide/node/) or [@astrojs/vercel](https://docs.astro.build/en/guides/integrations-guide/vercel/) adapter with a `site` configured.

If you were using this feature, please remove the experimental flag from your Astro config:

```diff
import { defineConfig } from 'astro'

export default defineConfig({
- experimental: {
- i18nDomains: true,
- }
})
```

If you have been waiting for stabilization before using this routing option, you can now do so.

Please see [the internationalization docs](https://docs.astro.build/en/guides/internationalization/#domains) for more about this feature.
45 changes: 1 addition & 44 deletions packages/astro/src/@types/astro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1953,50 +1953,7 @@ export interface AstroUserConfig {
* In the event of route collisions, where two routes of equal route priority attempt to build the same URL, Astro will log a warning identifying the conflicting routes.
*/
globalRoutePriority?: boolean;

/**
* @docs
* @name experimental.i18nDomains
* @type {boolean}
* @default `false`
* @version 4.3.0
* @description
*
* Enables domain support for the [experimental `domains` routing strategy](https://docs.astro.build/en/guides/internationalization/#domains-experimental) which allows you to configure the URL pattern of one or more supported languages to use a custom domain (or sub-domain).
*
* When a locale is mapped to a domain, a `/[locale]/` path prefix will not be used. However, localized folders within `src/pages/` are still required, including for your configured `defaultLocale`.
*
* Any other locale not configured will default to a localized path-based URL according to your `prefixDefaultLocale` strategy (e.g. `https://example.com/[locale]/blog`).
*
* ```js
* //astro.config.mjs
* export default defineConfig({
* site: "https://example.com",
* output: "server", // required, with no prerendered pages
* adapter: node({
* mode: 'standalone',
* }),
* i18n: {
* defaultLocale: "en",
* locales: ["en", "fr", "pt-br", "es"],
* prefixDefaultLocale: false,
* domains: {
* fr: "https://fr.example.com",
* es: "https://example.es",
* },
* },
* experimental: {
* i18nDomains: true,
* },
* });
* ```
*
* Both page routes built and URLs returned by the `astro:i18n` helper functions [`getAbsoluteLocaleUrl()`](https://docs.astro.build/en/reference/api-reference/#getabsolutelocaleurl) and [`getAbsoluteLocaleUrlList()`](https://docs.astro.build/en/reference/api-reference/#getabsolutelocaleurllist) will use the options set in `i18n.domains`.
*
* See the [Internationalization Guide](https://docs.astro.build/en/guides/internationalization/#domains-experimental) for more details, including the limitations of this experimental feature.
*/
i18nDomains?: boolean;


/**
* @docs
* @name experimental.security
Expand Down
6 changes: 3 additions & 3 deletions packages/astro/src/core/build/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ export async function generatePages(options: StaticBuildOptions, internals: Buil
if (ssr) {
for (const [pageData, filePath] of pagesToGenerate) {
if (pageData.route.prerender) {
// i18n domains won't work with pre rendered routes at the moment, so we need to to throw an error
if (config.experimental.i18nDomains) {
// i18n domains won't work with pre rendered routes at the moment, so we need to throw an error
if (config.i18n?.domains && Object.keys(config.i18n.domains).length > 0) {
throw new AstroError({
...NoPrerenderedRoutesWithDomains,
message: NoPrerenderedRoutesWithDomains.message(pageData.component),
Expand Down Expand Up @@ -284,7 +284,7 @@ async function getPathsForRoute(
const label = staticPaths.length === 1 ? 'page' : 'pages';
logger.debug(
'build',
`├── ${bold(green(''))} ${route.component} → ${magenta(`[${staticPaths.length} ${label}]`)}`
`├── ${bold(green(''))} ${route.component} → ${magenta(`[${staticPaths.length} ${label}]`)}`
);

paths = staticPaths
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/build/plugins/plugin-manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ function buildManifest(
* logic meant for i18n domain support, where we fill the lookup table
*/
const i18n = settings.config.i18n;
if (settings.config.experimental.i18nDomains && i18n && i18n.domains) {
if (i18n && i18n.domains) {
for (const [locale, domainValue] of Object.entries(i18n.domains)) {
domainLookupTable[domainValue] = normalizeTheLocale(locale);
}
Expand Down
32 changes: 14 additions & 18 deletions packages/astro/src/core/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ const ASTRO_CONFIG_DEFAULTS = {
contentCollectionJsonSchema: false,
clientPrerender: false,
globalRoutePriority: false,
i18nDomains: false,
security: {},
rewriting: false,
},
Expand Down Expand Up @@ -527,7 +526,6 @@ export const AstroConfigSchema = z.object({
})
.optional()
.default(ASTRO_CONFIG_DEFAULTS.experimental.security),
i18nDomains: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.i18nDomains),
rewriting: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.rewriting),
})
.strict(
Expand Down Expand Up @@ -668,22 +666,20 @@ export function createRelativeSchema(cmd: string, fileProtocolRoot: string) {
})
.superRefine((configuration, ctx) => {
const { site, experimental, i18n, output } = configuration;
if (experimental.i18nDomains) {
const hasDomains = i18n?.domains ? Object.keys(i18n.domains).length > 0 : false;
if (hasDomains) {
if (!site) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message:
"The option `site` isn't set. When using the 'domains' strategy for `i18n`, `site` is required to create absolute URLs for locales that aren't mapped to a domain.",
});
}
if (output !== 'server') {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'Domain support is only available when `output` is `"server"`.',
});
}
const hasDomains = i18n?.domains ? Object.keys(i18n.domains).length > 0 : false;
if (hasDomains) {
if (!site) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message:
"The option `site` isn't set. When using the 'domains' strategy for `i18n`, `site` is required to create absolute URLs for locales that aren't mapped to a domain.",
});
}
if (output !== 'server') {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'Domain support is only available when `output` is `"server"`.',
});
}
}
});
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/integrations/features-validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export function validateSupportedFeatures(
);
validationResult.assets = validateAssetsFeature(assets, adapterName, config, logger);

if (i18nDomains && config?.experimental?.i18nDomains === true && !config.i18n?.domains) {
if (!config.i18n?.domains) {
validationResult.i18nDomains = validateSupportKind(
i18nDomains,
adapterName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,5 @@ export default defineConfig({
redirectToDefaultLocale: false
}
},
experimental: {
i18nDomains: true
},
site: "https://example.com",
})
6 changes: 0 additions & 6 deletions packages/astro/test/units/config/config-validate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,6 @@ describe('Config Validation', () => {
en: 'https://www.example.com/',
},
},
experimental: {
i18nDomains: true,
},
},
process.cwd()
).catch((err) => err);
Expand All @@ -343,9 +340,6 @@ describe('Config Validation', () => {
en: 'https://www.example.com/',
},
},
experimental: {
i18nDomains: true,
},
site: 'https://foo.org',
},
process.cwd()
Expand Down
5 changes: 2 additions & 3 deletions packages/astro/test/units/i18n/astro_i18n.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1548,6 +1548,7 @@ describe('getLocaleAbsoluteUrlList', () => {
const config = await validateConfig(
{
format: 'directory',
output: "server",
site: 'https://example.com/',
trailingSlash: 'always',
i18n: {
Expand Down Expand Up @@ -1587,7 +1588,6 @@ describe('getLocaleAbsoluteUrlList', () => {
* @type {import("../../../dist/@types").AstroUserConfig}
*/
const config = {
experimental: {
i18n: {
defaultLocale: 'en',
locales: [
Expand All @@ -1599,15 +1599,14 @@ describe('getLocaleAbsoluteUrlList', () => {
codes: ['it', 'it-VA'],
},
],
},
},
};
// directory format
assert.deepEqual(
getLocaleAbsoluteUrlList({
locale: 'en',
base: '/blog/',
...config.experimental.i18n,
...config.i18n,
trailingSlash: 'always',
format: 'file',
site: 'https://example.com',
Expand Down
Loading