Add internationalization support with astro-i18next integration

- Implemented astro-i18next for multi-language support, including English, Dutch, and Italian.
- Configured default locale and language fallback settings.
- Defined routes for localized content in the configuration.
- Updated package.json and package-lock.json to include new dependencies for i18next and related plugins.
This commit is contained in:
becarta
2025-05-23 15:10:00 +02:00
parent 8a3507dce0
commit 3168826fa8
581 changed files with 88691 additions and 494 deletions

8
node_modules/@proload/core/lib/cjs/index.cjs generated vendored Normal file
View File

@@ -0,0 +1,8 @@
const { ProloadError } = require('../error.cjs');
function load(...args) {
return import('../esm/index.mjs').then(({ default: loader }) => loader(...args));
}
load.default = load;
load.ProloadError = ProloadError;
module.exports = load;

25
node_modules/@proload/core/lib/error.cjs generated vendored Normal file
View File

@@ -0,0 +1,25 @@
/**
* @type import('./error.cjs').ProloadError
*/
class ProloadError extends Error {
constructor(opts={}) {
super(opts.message);
this.name = 'ProloadError';
this.code = opts.code || 'ERR_PROLOAD_INVALID';
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
}
/**
* @type import('./error.cjs').assert
*/
function assert(bool, message, code) {
if (bool) return;
if (message instanceof Error) throw message;
throw new ProloadError({ message, code });
}
module.exports.ProloadError = ProloadError;
module.exports.assert = assert;

15
node_modules/@proload/core/lib/error.cjs.d.ts generated vendored Normal file
View File

@@ -0,0 +1,15 @@
export type Message = string | Error;
export type PROLOAD_ERROR_CODE = 'ERR_PROLOAD_INVALID' | 'ERR_PROLOAD_NOT_FOUND';
export class ProloadError extends Error {
name: 'ProloadError';
code: PROLOAD_ERROR_CODE;
message: string;
constructor(options?: {
message: string;
code?: string
});
}
export function assert(condition: boolean, message: Message, code?: PROLOAD_ERROR_CODE): asserts condition;

284
node_modules/@proload/core/lib/esm/index.mjs generated vendored Normal file
View File

@@ -0,0 +1,284 @@
import escalade from "escalade";
import { join, dirname, extname, resolve } from "path";
import deepmerge from "deepmerge";
import { existsSync, readdir, readFile, stat } from "fs";
import { promisify } from "util";
import { createRequire } from "module";
import requireOrImport from "./requireOrImport.mjs";
import { assert, ProloadError } from "../error.cjs";
export { ProloadError };
const toStats = promisify(stat);
const toRead = promisify(readdir);
const toReadFile = promisify(readFile);
const require = createRequire(import.meta.url);
let merge = deepmerge;
const defaultExtensions = ['js', 'cjs', 'mjs'];
const defaultFileNames = ['[name].config'];
const validNames = (namespace) => {
const extensionPlugins = load.plugins.filter(p => Array.isArray(p.extensions));
const fileNamePlugins = load.plugins.filter(p => Array.isArray(p.fileNames));
const validExtensions = [...defaultExtensions].concat(...extensionPlugins.map(p => p.extensions));
const validFileNames = [...defaultFileNames].concat(...fileNamePlugins.map(p => p.fileNames));
const result = validFileNames
.map(fileName => fileName.replace('[name]', namespace))
.reduce((acc, fileName) => {
return [...acc].concat(...validExtensions.map(ext => `${fileName}${ext ? '.' + ext.replace(/^\./, '') : ''}`))
}, []);
return result;
}
/**
* @param {any} val
* @returns {val is Record<any, any>}
*/
const isObject = (val) =>
val != null && typeof val === "object" && Array.isArray(val) === false;
const requireOrImportWithMiddleware = (filePath) => {
let registerPlugins = load.plugins.filter(
(plugin) => typeof plugin.register !== "undefined"
);
let transformPlugins = load.plugins.filter(
(plugin) => typeof plugin.transform !== "undefined"
);
return requireOrImport(filePath, { middleware: registerPlugins }).then(
async (mdl) => Promise.all(
transformPlugins.map((plugin) => {
return Promise.resolve(plugin.transform(mdl)).then((result) => {
if (result) mdl = result;
});
})
).then(() => mdl)
);
};
/**
*
* @param {string} namespace
* @param {{ filePath: string, extension: string }} opts
* @returns {Promise<{ filePath: string, value: string }>}
*/
async function resolveExtension(namespace, { filePath, extension }) {
let resolvedPath;
if (extension.startsWith("./") || extension.startsWith("../")) {
if (extname(extension) === "") {
resolvedPath = resolve(
dirname(filePath),
`${extension}${extname(filePath)}`
);
}
if (!existsSync(resolvedPath)) resolvedPath = null;
if (!resolvedPath) {
resolvedPath = resolve(dirname(filePath), extension);
}
if (!existsSync(resolvedPath)) resolvedPath = null;
}
if (!resolvedPath) {
const pkg = require.resolve(extension, {
cwd: dirname(filePath),
});
const accepted = validNames(namespace);
for (const config of accepted) {
try {
resolvedPath = `${pkg}/${config}`;
if (resolvedPath && existsSync(resolvedPath)) {
break;
} else {
resolvedPath = null
}
} catch (e) {}
}
}
if (!resolvedPath) {
resolvedPath = require.resolve(extension, { cwd: dirname(filePath) });
}
if (!resolvedPath) return
const value = await requireOrImportWithMiddleware(resolvedPath);
return { filePath: resolvedPath, value };
}
async function resolveExtensions(
namespace,
{ filePath, value: raw, context },
acc = {}
) {
let value = typeof raw === "function" ? await raw(context) : raw;
if (Array.isArray(value)) return value;
assert(
isObject(value),
`${namespace} configuration expects an "object" but encountered ${value}`
);
acc = merge(acc, value);
if (!("extends" in value)) return acc;
assert(
Array.isArray(value.extends),
`${namespace} "extends" must be an array`
);
const configs = await Promise.all(
value.extends.map((extension) =>
resolveExtension(namespace, { filePath, extension }).then((config) =>
resolveExtensions(namespace, { ...config, context }, acc)
)
)
);
for (const config of configs) {
acc = merge(acc, config);
}
delete acc.extends;
return acc;
}
/**
*
* @param {string} namespace
* @param {import('../index').LoadOptions} opts
*/
async function resolveConfig(namespace, opts = {}) {
const accepted = validNames(namespace);
const { context, accept } = opts;
const input = opts.cwd || process.cwd();
let mustExist = true;
if (typeof opts.mustExist !== "undefined") {
mustExist = opts.mustExist;
}
if (typeof opts.merge === "function") {
merge = opts.merge;
}
let filePath;
if (typeof opts.filePath === "string") {
const absPath = opts.filePath.startsWith(".")
? resolve(opts.filePath, input)
: opts.filePath;
if (existsSync(absPath)) {
filePath = absPath;
}
} else {
filePath = await escalade(input, async (dir, names) => {
if (accept) {
for (const n of names) {
if (accept(n, { directory: dir }) === true) return n;
}
}
for (const n of accepted) {
if (names.includes(n)) return n;
}
if (names.includes("config")) {
let d = join(dir, "config");
let _,
stats = await toStats(d);
let entries = [];
if (stats.isDirectory()) {
entries = await toRead(d);
for (const n of accepted) {
if (entries.includes(n)) return join("config", n);
}
}
}
if (names.includes("package.json")) {
let file = join(dir, "package.json");
let _,
contents = await toReadFile(file).then((r) =>
JSON.parse(r.toString())
);
if (contents[namespace]) return "package.json";
}
});
}
if (mustExist) {
assert(
!!filePath,
`Unable to resolve a ${namespace} configuration`,
"ERR_PROLOAD_NOT_FOUND"
);
} else if (!filePath) {
return;
}
return filePath;
}
/**
*
* @param {string} namespace
* @param {import('../index').LoadOptions} opts
*/
async function load(namespace, opts = {}) {
const { context } = opts;
let mustExist = true;
if (typeof opts.mustExist !== 'undefined') {
mustExist = opts.mustExist
}
const filePath = await resolveConfig(namespace, opts);
if (mustExist) {
assert(!!filePath, `Unable to resolve a ${namespace} configuration`, 'ERR_PROLOAD_NOT_FOUND');
} else if (!filePath) {
return;
}
let rawValue = await requireOrImportWithMiddleware(filePath);
if (filePath.endsWith('package.json')) rawValue = rawValue[namespace];
// Important: "empty" config files will be returned as `Module {}`
// We should handle them here
if (rawValue && !(rawValue instanceof Object)) {
if (mustExist) {
assert(
true,
`Resolved a ${namespace} configuration, but no configuration was exported`,
"ERR_PROLOAD_NOT_FOUND"
);
} else {
return;
}
}
const resolvedValue = await resolveExtensions(namespace, {
filePath,
value: rawValue,
context,
});
return {
filePath,
raw: rawValue,
value: resolvedValue,
};
}
const defaultPlugins = [
{
name: "@proload/extract-default",
transform(mdl) {
if (mdl.default && Object.keys(mdl).length === 1) {
return mdl.default;
};
return mdl;
},
},
];
/** @type import('../index').Plugin[] */
load.plugins = defaultPlugins;
load.use = (plugins) => {
load.plugins = [...load.plugins, ...plugins];
};
export default load;
export { resolveConfig as resolve };

30
node_modules/@proload/core/lib/esm/requireOrImport.mjs generated vendored Normal file
View File

@@ -0,0 +1,30 @@
"use strict";
import { createRequire } from 'module';
import { pathToFileURL } from 'url';
let require = createRequire(import.meta.url);
/**
*
* @param {string} filePath
*/
export default async function requireOrImport(filePath, { middleware = [] } = {}) {
await Promise.all(middleware.map(plugin => plugin.register(filePath)));
return new Promise(async (resolve, reject) => {
try {
let mdl = require(filePath);
resolve(mdl);
} catch (e) {
if (e.code === 'ERR_REQUIRE_ESM') {
const fileUrl = pathToFileURL(filePath).toString();
try {
const mdl = await import(fileUrl);
return resolve(mdl);
} catch (e) {
reject(e);
}
};
reject(e);
}
})
}

View File

@@ -0,0 +1 @@
export default function requireOrImport(filePath: string, opts?: { middleware: any[] }): Promise<any>;

120
node_modules/@proload/core/lib/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,120 @@
export { ProloadError } from './error.cjs';
export interface Config<T> {
/** An absolute path to a resolved configuration file */
filePath: string;
/** The raw value of a resolved configuration file, before being merged with any `extends` configurations */
raw: any;
/** The final, resolved value of a resolved configuration file */
value: T;
}
export interface ResolveOptions {
/**
* An exact filePath to a configuration file which should be loaded. If passed, this will keep proload from searching
* for matching files.
*
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#filepath)
*/
filePath?: string;
/**
* The location from which to begin searching up the directory tree
*
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#cwd)
*/
cwd?: string;
/**
* If a configuration _must_ be resolved. If `true`, Proload will throw an error when a configuration is not found
*
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#mustExist)
*/
mustExist?: boolean;
/**
* A function to completely customize module resolution
*
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#accept)
*/
accept?(fileName: string, context: { directory: string }): boolean|void;
}
export interface LoadOptions<T> {
/**
* An exact filePath to a configuration file which should be loaded. If passed, this will keep proload from searching
* for matching files.
*
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#filepath)
*/
filePath?: string;
/**
* The location from which to begin searching up the directory tree
*
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#cwd)
*/
cwd?: string;
/**
* If a configuration _must_ be resolved. If `true`, Proload will throw an error when a configuration is not found
*
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#mustExist)
*/
mustExist?: boolean;
/**
* If a resolved configuration file exports a factory function, this value will be passed as arguments to the function
*
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#context)
*/
context?: any;
/**
* A function to customize the `merge` behavior when a config with `extends` is encountered
*
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#merge)
*/
merge?(x: Partial<T>, y: Partial<T>): Partial<T>;
/**
* A function to completely customize module resolution
*
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#accept)
*/
accept?(fileName: string, context: { directory: string }): boolean|void;
}
export interface Plugin {
/** a unique identifier for your plugin */
name: string;
/** extensions which should be resolved, including the leading period */
extensions?: string[];
/** fileName patterns which should be resolved, excluding the trailing extension */
fileNames?: string[];
/** Executed before require/import of config file */
register?(filePath: string): Promise<void>;
/** Modify the config file before passing it along */
transform?(module: any): Promise<any>;
}
/**
* An `async` function which searches for a configuration file
*
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#resolve)
*/
export async function resolve(namespace: string, opts?: ResolveOptions): Promise<string|undefined>;
interface Load<T extends Record<any, any> = Record<any, any>> {
/**
* @param namespace The namespace which will be searched for the configuration file.
*
* For example, passing `"donut"` would resolve a files like `donut.config.js`, `donut.config.cjs`, and `donut.config.mjs` as well as a `package.json` with a `donut` property.
*
* @param opts Options to customize loader behavior
*/
(namespace: string, opts?: LoadOptions<T>): Promise<Config<T>|undefined>;
use(plugins: Plugin[]): void;
}
/**
* An `async` function which searches for and loads a configuration file
*
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#load)
*/
declare const load: Load;
export = load;
export default load;