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:
8
node_modules/@proload/core/lib/cjs/index.cjs
generated
vendored
Normal file
8
node_modules/@proload/core/lib/cjs/index.cjs
generated
vendored
Normal 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
25
node_modules/@proload/core/lib/error.cjs
generated
vendored
Normal 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
15
node_modules/@proload/core/lib/error.cjs.d.ts
generated
vendored
Normal 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
284
node_modules/@proload/core/lib/esm/index.mjs
generated
vendored
Normal 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
30
node_modules/@proload/core/lib/esm/requireOrImport.mjs
generated
vendored
Normal 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);
|
||||
}
|
||||
})
|
||||
}
|
1
node_modules/@proload/core/lib/esm/requireOrImport.mjs.d.ts
generated
vendored
Normal file
1
node_modules/@proload/core/lib/esm/requireOrImport.mjs.d.ts
generated
vendored
Normal 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
120
node_modules/@proload/core/lib/index.d.ts
generated
vendored
Normal 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;
|
Reference in New Issue
Block a user