Skip to content

Commit

Permalink
one more function
Browse files Browse the repository at this point in the history
  • Loading branch information
ematipico committed Feb 22, 2024
1 parent 0a2f112 commit 659a6c0
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 36 deletions.
2 changes: 1 addition & 1 deletion packages/astro/src/core/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ export const AstroConfigSchema = z.object({
.optional()
.superRefine((i18n, ctx) => {
if (i18n) {
const { defaultLocale, locales: _locales, fallback, domains, strategy } = i18n;
const { defaultLocale, locales: _locales, fallback, domains } = i18n;
const locales = _locales.map((locale) => {
if (typeof locale === 'string') {
return locale;
Expand Down
10 changes: 8 additions & 2 deletions packages/astro/src/i18n/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ import { MissingLocale } from '../core/errors/errors-data.js';
import { AstroError } from '../core/errors/index.js';
import type { RoutingStrategies } from './utils.js';

export function requestHasLocale(locales: Locales) {
return function (context: APIContext) {
return pathHasLocale(context.url.pathname, locales);
};
}

// Checks if the pathname has any locale
export function pathHasLocale(pathname: string, locales: Locales): boolean {
const segments = pathname.split('/');
export function pathHasLocale(path: string, locales: Locales): boolean {
const segments = path.split('/');
for (const segment of segments) {
for (const locale of locales) {
if (typeof locale === 'string') {
Expand Down
54 changes: 27 additions & 27 deletions packages/astro/src/i18n/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { appendForwardSlash, joinPaths } from '@astrojs/internal-helpers/path';
import type { APIContext, Locales, MiddlewareHandler, SSRManifest } from '../@types/astro.js';
import { getPathByLocale, normalizeTheLocale } from './index.js';
import { shouldAppendForwardSlash } from '../core/build/util.js';
import type { APIContext, MiddlewareHandler, SSRManifest } from '../@types/astro.js';
import {
getPathByLocale,
type MiddlewarePayload,
noFoundForNonLocaleRoute,
normalizeTheLocale,
requestHasLocale,
redirectToDefaultLocale,
} from './index.js';
import type { SSRManifestI18n } from '../core/app/types.js';
import { ROUTE_TYPE_HEADER } from '../core/constants.js';

Expand All @@ -22,18 +27,16 @@ export function createI18nMiddleware(

const _redirectToDefaultLocale = redirectToDefaultLocale(payload);
const _noFoundForNonLocaleRoute = noFoundForNonLocaleRoute(payload);
const _requestHasLocale = requestHasLocale(payload.locales);

const prefixAlways = (
url: URL,
response: Response,
context: APIContext
): Response | undefined => {
const prefixAlways = (response: Response, context: APIContext): Response | undefined => {
const url = context.url;
if (url.pathname === base + '/' || url.pathname === base) {
return _redirectToDefaultLocale(context);
}

// Astro can't know where the default locale is supposed to be, so it returns a 404 with no content.
else if (!pathHasLocale(url.pathname, i18n.locales)) {
else if (!_requestHasLocale(context)) {
return new Response(null, {
status: 404,
headers: response.headers,
Expand Down Expand Up @@ -111,15 +114,15 @@ export function createI18nMiddleware(
}

case 'pathname-prefix-always': {
const result = prefixAlways(url, response, context);
const result = prefixAlways(response, context);
if (result) {
return result;
}
break;
}
case 'domains-prefix-always': {
if (localeHasntDomain(i18n, currentLocale)) {
const result = prefixAlways(url, response, context);
const result = prefixAlways(response, context);
if (result) {
return result;
}
Expand All @@ -146,21 +149,18 @@ export function createI18nMiddleware(
return false;
});

if (urlLocale && fallbackKeys.includes(urlLocale)) {
const fallbackLocale = fallback[urlLocale];
// the user might have configured the locale using the granular locales, so we want to retrieve its corresponding path instead
const pathFallbackLocale = getPathByLocale(fallbackLocale, locales);
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 &&
strategy === 'pathname-prefix-other-locales'
) {
newPathname = url.pathname.replace(`/${urlLocale}`, ``);
} else {
newPathname = url.pathname.replace(`/${urlLocale}`, `/${pathFallbackLocale}`);
}
if (urlLocale && fallbackKeys.includes(urlLocale)) {
const fallbackLocale = fallback[urlLocale];
// the user might have configured the locale using the granular locales, so we want to retrieve its corresponding path instead
const pathFallbackLocale = getPathByLocale(fallbackLocale, locales);
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 && strategy === 'pathname-prefix-other-locales') {
newPathname = url.pathname.replace(`/${urlLocale}`, ``);
} else {
newPathname = url.pathname.replace(`/${urlLocale}`, `/${pathFallbackLocale}`);
}

return context.redirect(newPathname);
}
Expand Down
24 changes: 18 additions & 6 deletions packages/astro/src/virtual-modules/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ export { normalizeTheLocale, toCodes, toPaths } from '../i18n/index.js';
const { trailingSlash, format, site, i18n, isBuild } =
// @ts-expect-error
__ASTRO_INTERNAL_I18N_CONFIG__ as I18nInternalConfig;
const { defaultLocale, locales, strategy, domains, fallback } = i18n!;
const { defaultLocale, locales, domains, fallback } = i18n!;
const base = import.meta.env.BASE_URL;

const routing = toRoutingStrategy(i18n!);
const strategy = toRoutingStrategy(i18n!);

export type GetLocaleOptions = I18nInternals.GetLocaleOptions;

Expand Down Expand Up @@ -51,7 +51,7 @@ export const getRelativeLocaleUrl = (locale: string, path?: string, options?: Ge
format,
defaultLocale,
locales,
strategy: routing: strategy,
strategy,
domains,
...options,
});
Expand Down Expand Up @@ -91,7 +91,7 @@ export const getAbsoluteLocaleUrl = (locale: string, path?: string, options?: Ge
site,
defaultLocale,
locales,
strategy: routing: strategy,
strategy,
domains,
isBuild,
...options,
Expand All @@ -111,7 +111,7 @@ export const getRelativeLocaleUrlList = (path?: string, options?: GetLocaleOptio
format,
defaultLocale,
locales,
strategy: routing: strategy,
strategy,
domains,
...options,
});
Expand All @@ -131,7 +131,7 @@ export const getAbsoluteLocaleUrlList = (path?: string, options?: GetLocaleOptio
format,
defaultLocale,
locales,
strategy: routing: strategy,
strategy,
domains,
isBuild,
...options,
Expand Down Expand Up @@ -281,6 +281,18 @@ export const noFoundForNonLocaleRoute =
})
: noop('noFoundForNonLocaleRoute');

/**
* Checks whether the current URL contains a configured locale. Internally, this function will use `APIContext#url.pathname`
*
* @param {APIContext} context The context passed to the middleware
*
*
*/
export const requestHasLocale =
i18n?.routing?.strategy === 'manual'
? I18nInternals.requestHasLocale(locales)
: noop('requestHasLocale');

export const useFallback: UseFallback =
i18n?.routing?.strategy === 'manual'
? I18nInternals.useFallback({
Expand Down

0 comments on commit 659a6c0

Please sign in to comment.