Skip to content

Commit

Permalink
Merge branch 'main' into fix/release-iii
Browse files Browse the repository at this point in the history
  • Loading branch information
natemoo-re authored Jan 24, 2024
2 parents 0b5dd0e + 919bbe4 commit d819ff7
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 213 deletions.
5 changes: 5 additions & 0 deletions .changeset/tame-crabs-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"astro": patch
---

Refactors internals of the `astro:i18n` module to be more maintainable.
142 changes: 1 addition & 141 deletions packages/astro/client.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,147 +149,7 @@ declare module 'astro:prefetch' {
}

declare module 'astro:i18n' {
export type GetLocaleOptions = import('./dist/virtual-modules/i18n.js').GetLocaleOptions;

/**
* @param {string} locale A locale
* @param {string} [path=""] An optional path to add after the `locale`.
* @param {import('./dist/virtual-modules/i18n.js').GetLocaleOptions} options Customise the generated path
* @return {string}
*
* Returns a _relative_ path with passed locale.
*
* ## Errors
*
* Throws an error if the locale doesn't exist in the list of locales defined in the configuration.
*
* ## Examples
*
* ```js
* import { getRelativeLocaleUrl } from "astro:i18n";
* getRelativeLocaleUrl("es"); // /es
* getRelativeLocaleUrl("es", "getting-started"); // /es/getting-started
* getRelativeLocaleUrl("es_US", "getting-started", { prependWith: "blog" }); // /blog/es-us/getting-started
* getRelativeLocaleUrl("es_US", "getting-started", { prependWith: "blog", normalizeLocale: false }); // /blog/es_US/getting-started
* ```
*/
export const getRelativeLocaleUrl: (
locale: string,
path?: string,
options?: GetLocaleOptions
) => string;

/**
*
* @param {string} locale A locale
* @param {string} [path=""] An optional path to add after the `locale`.
* @param {import('./dist/virtual-modules/i18n.js').GetLocaleOptions} options Customise the generated path
* @return {string}
*
* Returns an absolute path with the passed locale. The behaviour is subject to change based on `site` configuration.
* If _not_ provided, the function will return a _relative_ URL.
*
* ## Errors
*
* Throws an error if the locale doesn't exist in the list of locales defined in the configuration.
*
* ## Examples
*
* If `site` is `https://example.com`:
*
* ```js
* import { getAbsoluteLocaleUrl } from "astro:i18n";
* getAbsoluteLocaleUrl("es"); // https://example.com/es
* getAbsoluteLocaleUrl("es", "getting-started"); // https://example.com/es/getting-started
* getAbsoluteLocaleUrl("es_US", "getting-started", { prependWith: "blog" }); // https://example.com/blog/es-us/getting-started
* getAbsoluteLocaleUrl("es_US", "getting-started", { prependWith: "blog", normalizeLocale: false }); // https://example.com/blog/es_US/getting-started
* ```
*/
export const getAbsoluteLocaleUrl: (
locale: string,
path?: string,
options?: GetLocaleOptions
) => string;

/**
* @param {string} [path=""] An optional path to add after the `locale`.
* @param {import('./dist/virtual-modules/i18n.js').GetLocaleOptions} options Customise the generated path
* @return {string[]}
*
* Works like `getRelativeLocaleUrl` but it emits the relative URLs for ALL locales:
*/
export const getRelativeLocaleUrlList: (path?: string, options?: GetLocaleOptions) => string[];
/**
* @param {string} [path=""] An optional path to add after the `locale`.
* @param {import('./dist/virtual-modules/i18n.js').GetLocaleOptions} options Customise the generated path
* @return {string[]}
*
* Works like `getAbsoluteLocaleUrl` but it emits the absolute URLs for ALL locales:
*/
export const getAbsoluteLocaleUrlList: (path?: string, options?: GetLocaleOptions) => string[];

/**
* A function that return the `path` associated to a locale (defined as code). It's particularly useful in case you decide
* to use locales that are broken down in paths and codes.
*
* @param {string} code The code of the locale
* @returns {string} The path associated to the locale
*
* ## Example
*
* ```js
* // astro.config.mjs
*
* export default defineConfig({
* i18n: {
* locales: [
* { codes: ["it", "it-VT"], path: "italiano" },
* "es"
* ]
* }
* })
* ```
*
* ```js
* import { getPathByLocale } from "astro:i18n";
* getPathByLocale("it"); // returns "italiano"
* getPathByLocale("it-VT"); // returns "italiano"
* getPathByLocale("es"); // returns "es"
* ```
*/
export const getPathByLocale: (code: string) => string;

/**
* A function that returns the preferred locale given a certain path. This is particularly useful if you configure a locale using
* `path` and `codes`. When you define multiple `code`, this function will return the first code of the array.
*
* Astro will treat the first code as the one that the user prefers.
*
* @param {string} path The path that maps to a locale
* @returns {string} The path associated to the locale
*
* ## Example
*
* ```js
* // astro.config.mjs
*
* export default defineConfig({
* i18n: {
* locales: [
* { codes: ["it-VT", "it"], path: "italiano" },
* "es"
* ]
* }
* })
* ```
*
* ```js
* import { getLocaleByPath } from "astro:i18n";
* getLocaleByPath("italiano"); // returns "it-VT" because that's the first code configured
* getLocaleByPath("es"); // returns "es"
* ```
*/
export const getLocaleByPath: (path: string) => string;
export * from 'astro/virtual-modules/i18n.js';
}

declare module 'astro:middleware' {
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/create-vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export async function createVite(
astroTransitions({ settings }),
astroDevToolbar({ settings, logger }),
vitePluginFileURL({}),
!!settings.config.i18n && astroInternationalization({ settings }),
astroInternationalization({ settings }),
],
publicDir: fileURLToPath(settings.config.publicDir),
root: fileURLToPath(settings.config.root),
Expand Down
12 changes: 12 additions & 0 deletions packages/astro/src/core/errors/errors-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,18 @@ export const UnhandledRejection = {
hint: 'Make sure your promises all have an `await` or a `.catch()` handler.',
} satisfies ErrorData;

/**
* @docs
* @description
* Astro could not find any code to handle a rejected `Promise`. Make sure all your promises have an `await` or `.catch()` handler.
*/
export const i18nNotEnabled = {
name: 'i18nNotEnabled',
title: 'i18n Not Enabled',
message: 'The `astro:i18n` module can not be used without enabling i18n in your Astro config.',
hint: 'See https://docs.astro.build/en/guides/internationalization for a guide on setting up i18n.',
} satisfies ErrorData;

/**
* @docs
* @kind heading
Expand Down
31 changes: 24 additions & 7 deletions packages/astro/src/i18n/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,14 @@ export function getLocaleAbsoluteUrl({ site, ...rest }: GetLocaleAbsoluteUrl) {
}
}

type GetLocalesBaseUrl = GetLocaleOptions & {
interface GetLocalesRelativeUrlList extends GetLocaleOptions {
base: string;
locales: Locales;
trailingSlash: AstroConfig['trailingSlash'];
format: AstroConfig['build']['format'];
routing?: RoutingStrategies;
defaultLocale: string;
};
}

export function getLocaleRelativeUrlList({
base,
Expand All @@ -103,7 +103,7 @@ export function getLocaleRelativeUrlList({
normalizeLocale = false,
routing = 'pathname-prefix-other-locales',
defaultLocale,
}: GetLocalesBaseUrl) {
}: GetLocalesRelativeUrlList) {
const locales = toPaths(_locales);
return locales.map((locale) => {
const pathsToJoin = [base, prependWith];
Expand All @@ -123,7 +123,11 @@ export function getLocaleRelativeUrlList({
});
}

export function getLocaleAbsoluteUrlList({ site, ...rest }: GetLocaleAbsoluteUrl) {
interface GetLocalesAbsoluteUrlList extends GetLocalesRelativeUrlList {
site?: string;
}

export function getLocaleAbsoluteUrlList({ site, ...rest }: GetLocalesAbsoluteUrlList) {
const locales = getLocaleRelativeUrlList(rest);
return locales.map((locale) => {
if (site) {
Expand All @@ -139,7 +143,7 @@ export function getLocaleAbsoluteUrlList({ site, ...rest }: GetLocaleAbsoluteUrl
* @param locale
* @param locales
*/
export function getPathByLocale(locale: string, locales: Locales) {
export function getPathByLocale(locale: string, locales: Locales): string {
for (const loopLocale of locales) {
if (typeof loopLocale === 'string') {
if (loopLocale === locale) {
Expand All @@ -153,6 +157,7 @@ export function getPathByLocale(locale: string, locales: Locales) {
}
}
}
throw new Unreachable();
}

/**
Expand All @@ -161,19 +166,20 @@ export function getPathByLocale(locale: string, locales: Locales) {
* @param path
* @param locales
*/
export function getLocaleByPath(path: string, locales: Locales): string | undefined {
export function getLocaleByPath(path: string, locales: Locales): string {
for (const locale of locales) {
if (typeof locale !== 'string') {
if (locale.path === path) {
// the first code is the one that user usually wants
const code = locale.codes.at(0);
if (code === undefined) throw new Unreachable();
return code;
}
} else if (locale === path) {
return locale;
}
}
return undefined;
throw new Unreachable();
}

/**
Expand Down Expand Up @@ -235,3 +241,14 @@ function peekCodePathToUse(locales: Locales, locale: string): undefined | string

return undefined;
}

class Unreachable extends Error {
constructor() {
super(
'Astro encountered an unexpected line of code.\n' +
'In most cases, this is not your fault, but a bug in astro code.\n' +
"If there isn't one already, please create an issue.\n" +
'https://astro.build/issues'
);
}
}
21 changes: 5 additions & 16 deletions packages/astro/src/i18n/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,16 @@ export function createI18nMiddleware(
base: SSRManifest['base'],
trailingSlash: SSRManifest['trailingSlash'],
buildFormat: SSRManifest['buildFormat']
): MiddlewareHandler | undefined {
if (!i18n) {
return undefined;
}
): MiddlewareHandler {
if (!i18n) return (_, next) => next();

return async (context, next) => {
if (!i18n) {
const routeData: RouteData | undefined = Reflect.get(context.request, routeDataSymbol);
// If the route we're processing is not a page, then we ignore it
if (routeData?.type !== 'page' && routeData?.type !== 'fallback') {
return await next();
}

const routeData = Reflect.get(context.request, routeDataSymbol);
if (routeData) {
// If the route we're processing is not a page, then we ignore it
if (
(routeData as RouteData).type !== 'page' &&
(routeData as RouteData).type !== 'fallback'
) {
return await next();
}
}

const url = context.url;
const { locales, defaultLocale, fallback, routing } = i18n;
const response = await next();
Expand Down
Loading

0 comments on commit d819ff7

Please sign in to comment.