Skip to content

Commit

Permalink
feat(i18n): add Astro.currentLocale (#9101)
Browse files Browse the repository at this point in the history
  • Loading branch information
ematipico authored Nov 16, 2023
1 parent 8366cd7 commit e3dce21
Show file tree
Hide file tree
Showing 17 changed files with 222 additions and 16 deletions.
5 changes: 5 additions & 0 deletions .changeset/quick-toes-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Add a new property `Astro.currentLocale`, available when `i18n` is enabled.
10 changes: 10 additions & 0 deletions packages/astro/src/@types/astro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2112,6 +2112,11 @@ interface AstroSharedContext<
*/

preferredLocaleList: string[] | undefined;

/**
* The current locale computed from the URL of the request. It matches the locales in `i18n.locales`, and returns `undefined` otherwise.
*/
currentLocale: string | undefined;
}

export interface APIContext<
Expand Down Expand Up @@ -2241,6 +2246,11 @@ export interface APIContext<
* [quality value]: https://developer.mozilla.org/en-US/docs/Glossary/Quality_values
*/
preferredLocaleList: string[] | undefined;

/**
* The current locale computed from the URL of the request. It matches the locales in `i18n.locales`, and returns `undefined` otherwise.
*/
currentLocale: string | undefined;
}

export type EndpointOutput =
Expand Down
8 changes: 6 additions & 2 deletions packages/astro/src/core/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,9 @@ export class App {
status,
env: this.#pipeline.env,
mod: handler as any,
locales: this.#manifest.i18n ? this.#manifest.i18n.locales : undefined,
locales: this.#manifest.i18n?.locales,
routingStrategy: this.#manifest.i18n?.routingStrategy,
defaultLocale: this.#manifest.i18n?.defaultLocale,
});
} else {
const pathname = prependForwardSlash(this.removeBase(url.pathname));
Expand Down Expand Up @@ -269,7 +271,9 @@ export class App {
status,
mod,
env: this.#pipeline.env,
locales: this.#manifest.i18n ? this.#manifest.i18n.locales : undefined,
locales: this.#manifest.i18n?.locales,
routingStrategy: this.#manifest.i18n?.routingStrategy,
defaultLocale: this.#manifest.i18n?.defaultLocale,
});
}
}
Expand Down
4 changes: 3 additions & 1 deletion packages/astro/src/core/build/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,9 @@ async function generatePath(pathname: string, gopts: GeneratePathOptions, pipeli
route: pageData.route,
env: pipeline.getEnvironment(),
mod,
locales: i18n ? i18n.locales : undefined,
locales: i18n?.locales,
routingStrategy: i18n?.routingStrategy,
defaultLocale: i18n?.defaultLocale,
});

let body: string | Uint8Array;
Expand Down
28 changes: 24 additions & 4 deletions packages/astro/src/core/endpoint/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import { ASTRO_VERSION } from '../constants.js';
import { AstroCookies, attachCookiesToResponse } from '../cookies/index.js';
import { AstroError, AstroErrorData } from '../errors/index.js';
import { callMiddleware } from '../middleware/callMiddleware.js';
import { computePreferredLocale, computePreferredLocaleList } from '../render/context.js';
import {
computeCurrentLocale,
computePreferredLocale,
computePreferredLocaleList,
} from '../render/context.js';
import { type Environment, type RenderContext } from '../render/index.js';

const encoder = new TextEncoder();
Expand All @@ -27,6 +31,8 @@ type CreateAPIContext = {
props: Record<string, any>;
adapterName?: string;
locales: string[] | undefined;
routingStrategy: 'prefix-always' | 'prefix-other-locales' | undefined;
defaultLocale: string | undefined;
};

/**
Expand All @@ -41,9 +47,12 @@ export function createAPIContext({
props,
adapterName,
locales,
routingStrategy,
defaultLocale,
}: CreateAPIContext): APIContext {
let preferredLocale: string | undefined = undefined;
let preferredLocaleList: string[] | undefined = undefined;
let currentLocale: string | undefined = undefined;

const context = {
cookies: new AstroCookies(request),
Expand Down Expand Up @@ -83,6 +92,16 @@ export function createAPIContext({

return undefined;
},
get currentLocale(): string | undefined {
if (currentLocale) {
return currentLocale;
}
if (locales) {
currentLocale = computeCurrentLocale(request, locales, routingStrategy, defaultLocale);
}

return currentLocale;
},
url: new URL(request.url),
get clientAddress() {
if (clientAddressSymbol in request) {
Expand Down Expand Up @@ -153,16 +172,17 @@ export async function callEndpoint<MiddlewareResult = Response | EndpointOutput>
mod: EndpointHandler,
env: Environment,
ctx: RenderContext,
onRequest: MiddlewareHandler<MiddlewareResult> | undefined,
locales: undefined | string[]
onRequest: MiddlewareHandler<MiddlewareResult> | undefined
): Promise<Response> {
const context = createAPIContext({
request: ctx.request,
params: ctx.params,
props: ctx.props,
site: env.site,
adapterName: env.adapterName,
locales,
routingStrategy: ctx.routingStrategy,
defaultLocale: ctx.defaultLocale,
locales: ctx.locales,
});

let response;
Expand Down
2 changes: 2 additions & 0 deletions packages/astro/src/core/middleware/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ function createContext({ request, params, userDefinedLocales = [] }: CreateConte
props: {},
site: undefined,
locales: userDefinedLocales,
defaultLocale: undefined,
routingStrategy: undefined,
});
}

Expand Down
10 changes: 3 additions & 7 deletions packages/astro/src/core/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ export class Pipeline {
site: env.site,
adapterName: env.adapterName,
locales: renderContext.locales,
routingStrategy: renderContext.routingStrategy,
defaultLocale: renderContext.defaultLocale,
});

switch (renderContext.route.type) {
Expand Down Expand Up @@ -158,13 +160,7 @@ export class Pipeline {
}
}
case 'endpoint': {
return await callEndpoint(
mod as any as EndpointHandler,
env,
renderContext,
onRequest,
renderContext.locales
);
return await callEndpoint(mod as any as EndpointHandler, env, renderContext, onRequest);
}
default:
throw new Error(`Couldn't find route of type [${renderContext.route.type}]`);
Expand Down
24 changes: 24 additions & 0 deletions packages/astro/src/core/render/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export interface RenderContext {
props: Props;
locals?: object;
locales: string[] | undefined;
defaultLocale: string | undefined;
routingStrategy: 'prefix-always' | 'prefix-other-locales' | undefined;
}

export type CreateRenderContextArgs = Partial<
Expand Down Expand Up @@ -60,6 +62,8 @@ export async function createRenderContext(
params,
props,
locales: options.locales,
routingStrategy: options.routingStrategy,
defaultLocale: options.defaultLocale,
};

// We define a custom property, so we can check the value passed to locals
Expand Down Expand Up @@ -208,3 +212,23 @@ export function computePreferredLocaleList(request: Request, locales: string[])

return result;
}

export function computeCurrentLocale(
request: Request,
locales: string[],
routingStrategy: 'prefix-always' | 'prefix-other-locales' | undefined,
defaultLocale: string | undefined
): undefined | string {
const requestUrl = new URL(request.url);
for (const segment of requestUrl.pathname.split('/')) {
for (const locale of locales) {
if (normalizeTheLocale(locale) === normalizeTheLocale(segment)) {
return locale;
}
}
}
if (routingStrategy === 'prefix-other-locales') {
return defaultLocale;
}
return undefined;
}
2 changes: 2 additions & 0 deletions packages/astro/src/core/render/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export async function renderPage({ mod, renderContext, env, cookies }: RenderPag
cookies,
locals: renderContext.locals ?? {},
locales: renderContext.locales,
defaultLocale: renderContext.defaultLocale,
routingStrategy: renderContext.routingStrategy,
});

// TODO: Remove in Astro 4.0
Expand Down
27 changes: 26 additions & 1 deletion packages/astro/src/core/render/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import { chunkToString } from '../../runtime/server/render/index.js';
import { AstroCookies } from '../cookies/index.js';
import { AstroError, AstroErrorData } from '../errors/index.js';
import type { Logger } from '../logger/core.js';
import { computePreferredLocale, computePreferredLocaleList } from './context.js';
import {
computeCurrentLocale,
computePreferredLocale,
computePreferredLocaleList,
} from './context.js';

const clientAddressSymbol = Symbol.for('astro.clientAddress');
const responseSentSymbol = Symbol.for('astro.responseSent');
Expand Down Expand Up @@ -47,6 +51,8 @@ export interface CreateResultArgs {
locals: App.Locals;
cookies?: AstroCookies;
locales: string[] | undefined;
defaultLocale: string | undefined;
routingStrategy: 'prefix-always' | 'prefix-other-locales' | undefined;
}

function getFunctionExpression(slot: any) {
Expand Down Expand Up @@ -148,6 +154,7 @@ export function createResult(args: CreateResultArgs): SSRResult {
let cookies: AstroCookies | undefined = args.cookies;
let preferredLocale: string | undefined = undefined;
let preferredLocaleList: string[] | undefined = undefined;
let currentLocale: string | undefined = undefined;

// Create the result object that will be passed into the render function.
// This object starts here as an empty shell (not yet the result) but then
Expand Down Expand Up @@ -218,6 +225,24 @@ export function createResult(args: CreateResultArgs): SSRResult {

return undefined;
},
get currentLocale(): string | undefined {
if (currentLocale) {
return currentLocale;
}
if (args.locales) {
currentLocale = computeCurrentLocale(
request,
args.locales,
args.routingStrategy,
args.defaultLocale
);
if (currentLocale) {
return currentLocale;
}
}

return undefined;
},
params,
props,
locals,
Expand Down
7 changes: 6 additions & 1 deletion packages/astro/src/vite-plugin-astro-server/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ export async function handleRoute({
env,
mod,
route,
locales: manifest.i18n?.locales,
routingStrategy: manifest.i18n?.routingStrategy,
defaultLocale: manifest.i18n?.defaultLocale,
});
} else {
return handle404Response(origin, incomingRequest, incomingResponse);
Expand Down Expand Up @@ -271,7 +274,9 @@ export async function handleRoute({
route: options.route,
mod,
env,
locales: i18n ? i18n.locales : undefined,
locales: i18n?.locales,
routingStrategy: i18n?.routingStrategy,
defaultLocale: i18n?.defaultLocale,
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
---
const currentLocale = Astro.currentLocale;
---
<html>
<head>
<title>Astro</title>
</head>
<body>
Start
Current Locale: {currentLocale ? currentLocale : "none"}

</body>
</html>
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
---
const currentLocale = Astro.currentLocale;
---
<html>
<head>
<title>Astro</title>
</head>
<body>
Oi essa e start
Current Locale: {currentLocale ? currentLocale : "none"}
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
const currentLocale = Astro.currentLocale;
---

<html>
<head>
<title>Astro</title>
</head>
<body>
Current Locale: {currentLocale ? currentLocale : "none"}
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

---
export function getStaticPaths() {
return [
{ id: "lorem" }
]
}
const currentLocale = Astro.currentLocale;

---

<html>
<head>
<title>Astro</title>
</head>
<body>
Current Locale: {currentLocale ? currentLocale : "none"}
</body>
</html>
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
---
const currentLocale = Astro.currentLocale;
---
<html>
<head>
<title>Astro</title>
</head>
<body>
Hola
Current Locale: {currentLocale ? currentLocale : "none"}
</body>
</html>
Loading

0 comments on commit e3dce21

Please sign in to comment.