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(i18n): add Astro.currentLocale #9101

Merged
merged 4 commits into from
Nov 16, 2023
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
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also checking that this is a patch, so only waiting for the feature to merge but not for the next minor release? If so, please help me remember when the corresponding docs PR should merge, since it's not on the normal release schedule! 😄 withastro/docs#5410

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once the PR is merged, this new thing will go out in the next release (regardless of its entity).

remember when the corresponding docs PR should merge

Ideally, we should merge it before the next release. Although we don't have a schedule for that, I think it's also okay if the docs PR is released 1/2 day after.

---

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;
ematipico marked this conversation as resolved.
Show resolved Hide resolved
}

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
Loading