Skip to content

Commit

Permalink
fix(i18n): move transformation outside the user schema (#10169)
Browse files Browse the repository at this point in the history
* fix(i18n): move transformation outside the user schema

* fix condition

* cleanup

* ops

* fix regression
  • Loading branch information
ematipico committed Feb 21, 2024
1 parent aa5efd1 commit a462491
Show file tree
Hide file tree
Showing 16 changed files with 229 additions and 191 deletions.
5 changes: 5 additions & 0 deletions .changeset/loud-snakes-behave.md
@@ -0,0 +1,5 @@
---
"astro": patch
---

Fixes an issue with the `i18n.routing` types, where an internal transformation was causing the generation of incorrect types for integrations.
6 changes: 3 additions & 3 deletions packages/astro/src/core/app/index.ts
Expand Up @@ -166,9 +166,9 @@ export class App {

if (
this.#manifest.i18n &&
(this.#manifest.i18n.routing === 'domains-prefix-always' ||
this.#manifest.i18n.routing === 'domains-prefix-other-locales' ||
this.#manifest.i18n.routing === 'domains-prefix-always-no-redirect')
(this.#manifest.i18n.strategy === 'domains-prefix-always' ||
this.#manifest.i18n.strategy === 'domains-prefix-other-locales' ||
this.#manifest.i18n.strategy === 'domains-prefix-always-no-redirect')
) {
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host
let host = request.headers.get('X-Forwarded-Host');
Expand Down
4 changes: 2 additions & 2 deletions packages/astro/src/core/app/types.ts
Expand Up @@ -8,7 +8,7 @@ import type {
SSRResult,
} from '../../@types/astro.js';
import type { SinglePageBuiltModule } from '../build/types.js';
import type { RoutingStrategies } from '../config/schema.js';
import type { RoutingStrategies } from '../../i18n/utils.js';

export type ComponentPath = string;

Expand Down Expand Up @@ -60,7 +60,7 @@ export type SSRManifest = {

export type SSRManifestI18n = {
fallback?: Record<string, string>;
routing: RoutingStrategies;
strategy: RoutingStrategies;
locales: Locales;
defaultLocale: string;
domainLookupTable: Record<string, string>;
Expand Down
3 changes: 2 additions & 1 deletion packages/astro/src/core/build/generate.ts
Expand Up @@ -60,6 +60,7 @@ import type {
import { getTimeStat, shouldAppendForwardSlash } from './util.js';
import { NoPrerenderedRoutesWithDomains } from '../errors/errors-data.js';
import { RenderContext } from '../render-context.js';
import { toRoutingStrategy } from '../../i18n/utils.js';

function createEntryURL(filePath: string, outFolder: URL) {
return new URL('./' + filePath + `?time=${Date.now()}`, outFolder);
Expand Down Expand Up @@ -582,7 +583,7 @@ function createBuildManifest(
if (settings.config.i18n) {
i18nManifest = {
fallback: settings.config.i18n.fallback,
routing: settings.config.i18n.routing,
strategy: toRoutingStrategy(settings.config.i18n),
defaultLocale: settings.config.i18n.defaultLocale,
locales: settings.config.i18n.locales,
domainLookupTable: {},
Expand Down
12 changes: 3 additions & 9 deletions packages/astro/src/core/build/plugins/plugin-manifest.ts
Expand Up @@ -17,6 +17,7 @@ import { cssOrder, mergeInlineCss, type BuildInternals } from '../internal.js';
import type { AstroBuildPlugin } from '../plugin.js';
import type { StaticBuildOptions } from '../types.js';
import { normalizeTheLocale } from '../../../i18n/index.js';
import { toRoutingStrategy } from '../../../i18n/utils.js';

const manifestReplace = '@@ASTRO_MANIFEST_REPLACE@@';
const replaceExp = new RegExp(`['"]${manifestReplace}['"]`, 'g');
Expand Down Expand Up @@ -235,14 +236,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 &&
(i18n.routing === 'domains-prefix-always' ||
i18n.routing === 'domains-prefix-other-locales' ||
i18n.routing === 'domains-prefix-always-no-redirect')
) {
if (settings.config.experimental.i18nDomains && i18n && i18n.domains) {
for (const [locale, domainValue] of Object.entries(i18n.domains)) {
domainLookupTable[domainValue] = normalizeTheLocale(locale);
}
Expand All @@ -257,7 +251,7 @@ function buildManifest(
if (settings.config.i18n) {
i18nManifest = {
fallback: settings.config.i18n.fallback,
routing: settings.config.i18n.routing,
strategy: toRoutingStrategy(settings.config.i18n),
locales: settings.config.i18n.locales,
defaultLocale: settings.config.i18n.defaultLocale,
domainLookupTable,
Expand Down
65 changes: 9 additions & 56 deletions packages/astro/src/core/config/schema.ts
Expand Up @@ -66,14 +66,6 @@ const ASTRO_CONFIG_DEFAULTS = {
},
} satisfies AstroUserConfig & { server: { open: boolean } };

export type RoutingStrategies =
| 'pathname-prefix-always'
| 'pathname-prefix-other-locales'
| 'pathname-prefix-always-no-redirect'
| 'domains-prefix-always'
| 'domains-prefix-other-locales'
| 'domains-prefix-always-no-redirect';

export const AstroConfigSchema = z.object({
root: z
.string()
Expand Down Expand Up @@ -363,37 +355,6 @@ export const AstroConfigSchema = z.object({
),
})
.optional()
.transform((i18n) => {
if (i18n) {
let { routing, domains } = i18n;
let strategy: RoutingStrategies;
const hasDomains = domains ? Object.keys(domains).length > 0 : false;
if (!hasDomains) {
if (routing.prefixDefaultLocale === true) {
if (routing.redirectToDefaultLocale) {
strategy = 'pathname-prefix-always';
} else {
strategy = 'pathname-prefix-always-no-redirect';
}
} else {
strategy = 'pathname-prefix-other-locales';
}
} else {
if (routing.prefixDefaultLocale === true) {
if (routing.redirectToDefaultLocale) {
strategy = 'domains-prefix-always';
} else {
strategy = 'domains-prefix-always-no-redirect';
}
} else {
strategy = 'domains-prefix-other-locales';
}
}

return { ...i18n, routing: strategy };
}
return undefined;
})
.superRefine((i18n, ctx) => {
if (i18n) {
const { defaultLocale, locales: _locales, fallback, domains, routing } = i18n;
Expand Down Expand Up @@ -436,20 +397,15 @@ export const AstroConfigSchema = z.object({
}
if (domains) {
const entries = Object.entries(domains);
if (entries.length > 0) {
if (
routing !== 'domains-prefix-other-locales' &&
routing !== 'domains-prefix-always-no-redirect' &&
routing !== 'domains-prefix-always'
) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `When specifying some domains, the property \`i18n.routingStrategy\` must be set to \`"domains"\`.`,
});
}
const hasDomains = domains ? Object.keys(domains).length > 0 : false;
if (entries.length > 0 && !hasDomains) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `When specifying some domains, the property \`i18n.routingStrategy\` must be set to \`"domains"\`.`,
});
}

for (const [domainKey, domainValue] of Object.entries(domains)) {
for (const [domainKey, domainValue] of entries) {
if (!locales.includes(domainKey)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
Expand Down Expand Up @@ -625,11 +581,8 @@ export function createRelativeSchema(cmd: string, fileProtocolRoot: string) {
.superRefine((configuration, ctx) => {
const { site, experimental, i18n, output } = configuration;
if (experimental.i18nDomains) {
if (
i18n?.routing === 'domains-prefix-other-locales' ||
i18n?.routing === 'domains-prefix-always-no-redirect' ||
i18n?.routing === 'domains-prefix-always'
) {
const hasDomains = i18n?.domains ? Object.keys(i18n.domains).length > 0 : false;
if (hasDomains) {
if (!site) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/endpoint/index.ts
Expand Up @@ -6,8 +6,8 @@ import {
computeCurrentLocale,
computePreferredLocale,
computePreferredLocaleList,
type RoutingStrategies,
} from '../../i18n/utils.js';
import type { RoutingStrategies } from '../config/schema.js';

type CreateAPIContext = {
request: Request;
Expand Down
8 changes: 4 additions & 4 deletions packages/astro/src/core/render-context.ts
Expand Up @@ -190,7 +190,7 @@ export class RenderContext {
const { links, scripts, styles } = await pipeline.headElements(routeData);
const componentMetadata =
(await pipeline.componentMetadata(routeData)) ?? manifest.componentMetadata;
const { defaultLocale, locales, routing: routingStrategy } = i18n ?? {};
const { defaultLocale, locales, strategy } = i18n ?? {};
const partial = Boolean(mod.partial);
return createResult({
adapterName,
Expand All @@ -210,7 +210,7 @@ export class RenderContext {
resolve,
request,
route: routeData.route,
routingStrategy,
strategy,
site,
scripts,
ssr: serverLike,
Expand Down Expand Up @@ -238,9 +238,9 @@ export class RenderContext {
preferredLocale: undefined,
preferredLocaleList: undefined,
};
const { defaultLocale, locales, routing } = i18n;
const { defaultLocale, locales, strategy } = i18n;
return (this.#i18nData = {
currentLocale: computeCurrentLocale(routeData.route, locales, routing, defaultLocale),
currentLocale: computeCurrentLocale(routeData.route, locales, strategy, defaultLocale),
preferredLocale: computePreferredLocale(request, locales),
preferredLocaleList: computePreferredLocaleList(request, locales),
});
Expand Down
6 changes: 3 additions & 3 deletions packages/astro/src/core/render/result.ts
Expand Up @@ -17,8 +17,8 @@ import {
computeCurrentLocale,
computePreferredLocale,
computePreferredLocaleList,
type RoutingStrategies,
} from '../../i18n/utils.js';
import type { RoutingStrategies } from '../config/schema.js';
import { clientAddressSymbol, responseSentSymbol } from '../constants.js';

export interface CreateResultArgs {
Expand Down Expand Up @@ -53,7 +53,7 @@ export interface CreateResultArgs {
locales: Locales | undefined;
defaultLocale: string | undefined;
route: string;
routingStrategy: RoutingStrategies | undefined;
strategy: RoutingStrategies | undefined;
}

function getFunctionExpression(slot: any) {
Expand Down Expand Up @@ -234,7 +234,7 @@ export function createResult(args: CreateResultArgs): SSRResult {
currentLocale = computeCurrentLocale(
url.pathname,
args.locales,
args.routingStrategy,
args.strategy,
args.defaultLocale
);
if (currentLocale) {
Expand Down
8 changes: 5 additions & 3 deletions packages/astro/src/core/routing/manifest/create.ts
Expand Up @@ -20,6 +20,7 @@ import { AstroError } from '../../errors/index.js';
import { removeLeadingForwardSlash, slash } from '../../path.js';
import { resolvePages } from '../../util.js';
import { getRouteGenerator } from './generator.js';
import { toRoutingStrategy } from '../../../i18n/utils.js';
const require = createRequire(import.meta.url);

interface Item {
Expand Down Expand Up @@ -686,8 +687,9 @@ export function createRouteManifest(

const i18n = settings.config.i18n;
if (i18n) {
const strategy = toRoutingStrategy(i18n);
// First we check if the user doesn't have an index page.
if (i18n.routing === 'pathname-prefix-always') {
if (strategy === 'pathname-prefix-always') {
let index = routes.find((route) => route.route === '/');
if (!index) {
let relativePath = path.relative(
Expand Down Expand Up @@ -755,7 +757,7 @@ export function createRouteManifest(

// Work done, now we start creating "fallback" routes based on the configuration

if (i18n.routing === 'pathname-prefix-always') {
if (strategy === 'pathname-prefix-always') {
// we attempt to retrieve the index page of the default locale
const defaultLocaleRoutes = routesByLocale.get(i18n.defaultLocale);
if (defaultLocaleRoutes) {
Expand Down Expand Up @@ -830,7 +832,7 @@ export function createRouteManifest(
let route: string;
if (
fallbackToLocale === i18n.defaultLocale &&
i18n.routing === 'pathname-prefix-other-locales'
strategy === 'pathname-prefix-other-locales'
) {
if (fallbackToRoute.pathname) {
pathname = `/${fallbackFromLocale}${fallbackToRoute.pathname}`;
Expand Down
16 changes: 8 additions & 8 deletions packages/astro/src/i18n/index.ts
Expand Up @@ -3,15 +3,15 @@ import type { AstroConfig, Locales } from '../@types/astro.js';
import { shouldAppendForwardSlash } from '../core/build/util.js';
import { MissingLocale } from '../core/errors/errors-data.js';
import { AstroError } from '../core/errors/index.js';
import type { RoutingStrategies } from '../core/config/schema.js';
import type { RoutingStrategies } from './utils.js';

type GetLocaleRelativeUrl = GetLocaleOptions & {
locale: string;
base: string;
locales: Locales;
trailingSlash: AstroConfig['trailingSlash'];
format: AstroConfig['build']['format'];
routing?: RoutingStrategies;
strategy?: RoutingStrategies;
defaultLocale: string;
domains: Record<string, string> | undefined;
path?: string;
Expand Down Expand Up @@ -45,7 +45,7 @@ export function getLocaleRelativeUrl({
path,
prependWith,
normalizeLocale = true,
routing = 'pathname-prefix-other-locales',
strategy = 'pathname-prefix-other-locales',
defaultLocale,
}: GetLocaleRelativeUrl) {
const codeToUse = peekCodePathToUse(_locales, locale);
Expand All @@ -58,10 +58,10 @@ export function getLocaleRelativeUrl({
const pathsToJoin = [base, prependWith];
const normalizedLocale = normalizeLocale ? normalizeTheLocale(codeToUse) : codeToUse;
if (
routing === 'pathname-prefix-always' ||
routing === 'pathname-prefix-always-no-redirect' ||
routing === 'domains-prefix-always' ||
routing === 'domains-prefix-always-no-redirect'
strategy === 'pathname-prefix-always' ||
strategy === 'pathname-prefix-always-no-redirect' ||
strategy === 'domains-prefix-always' ||
strategy === 'domains-prefix-always-no-redirect'
) {
pathsToJoin.push(normalizedLocale);
} else if (locale !== defaultLocale) {
Expand Down Expand Up @@ -107,7 +107,7 @@ interface GetLocalesRelativeUrlList extends GetLocaleOptions {
locales: Locales;
trailingSlash: AstroConfig['trailingSlash'];
format: AstroConfig['build']['format'];
routing?: RoutingStrategies;
strategy?: RoutingStrategies;
defaultLocale: string;
domains: Record<string, string> | undefined;
}
Expand Down
6 changes: 3 additions & 3 deletions packages/astro/src/i18n/middleware.ts
Expand Up @@ -106,9 +106,9 @@ export function createI18nMiddleware(
}

const { url, currentLocale } = context;
const { locales, defaultLocale, fallback, routing } = i18n;
const { locales, defaultLocale, fallback, strategy } = i18n;

switch (i18n.routing) {
switch (i18n.strategy) {
case 'domains-prefix-other-locales': {
if (localeHasntDomain(i18n, currentLocale)) {
const result = prefixOtherLocales(url, response);
Expand Down Expand Up @@ -187,7 +187,7 @@ export function createI18nMiddleware(
let newPathname: string;
// If a locale falls back to the default locale, we want to **remove** the locale because
// the default locale doesn't have a prefix
if (pathFallbackLocale === defaultLocale && routing === 'pathname-prefix-other-locales') {
if (pathFallbackLocale === defaultLocale && strategy === 'pathname-prefix-other-locales') {
newPathname = url.pathname.replace(`/${urlLocale}`, ``);
} else {
newPathname = url.pathname.replace(`/${urlLocale}`, `/${pathFallbackLocale}`);
Expand Down

0 comments on commit a462491

Please sign in to comment.