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

333
node_modules/@proload/core/README.md generated vendored Normal file
View File

@@ -0,0 +1,333 @@
# `@proload/core`
Proload searches for and loads your tool's JavaScript configuration files. Users have complex expectations when it comes to configuration files—the goal of Proload is to offer a single, straightforward and extensible API for loading them.
```js
import load from '@proload/core';
await load('namespace');
```
> `@proload/core` can be used in `node@12.20.1` and up. It relies on Node's native ESM semantics.
## Motivation
Configuration files are really difficult to get right. Tool authors tend to think, "Easy solve! I'll just have everyone use one `namespace.config.js`!" In most cases that should work, but since `node@12.17.0`, plain `.js` files can be written in either ESM or CJS—both formats are officially supported and can be configured on a per-project basis. Additionally, `node` is able to load any file using a `.cjs` or `.mjs` extension, not just `.js`.
Many popular libraries get these semantics wrong, but maintaining and testing this resolution logic in library code can be a huge maintanence burden. As a library author, you don't need to know (or care) which module format your users choose—you just need to load the contents of the config file. `@proload/core` is a well-tested solution that gets these semantics right, so you can focus on more important things.
> You probably have TypeScript users, too! They would definitely appreciate being able to write a `.ts` config file. `@proload/core` uses a plugin system to load non-JavaScript files. See [Plugins](https://github.com/natemoo-re/proload/tree/main/packages/core#plugins) or [`@proload/plugin-typescript`](https://github.com/natemoo-re/proload/tree/main/packages/core#typescript) specifically.
## Resolution
Out of the box, `@proload/core` searches up the directory tree for the following files:
- a `[namespace].config.js`, `[namespace].config.cjs`, or `[namespace].config.mjs` file
- any of the `js/cjs/mjs` files inside of `config/` directory
- a `package.json` file with a top-level `[namespace]` key
Here's an overview of all the files supported by default for a tool named `donut`.
```
await load('donut');
.
├── donut.config.js // Either ESM or CJS supported
├── donut.config.cjs
├── donut.config.mjs
├── config/ // Great for organizing many configs
│ ├── donut.config.js
│ ├── donut.config.cjs
│ └── donut.config.mjs
└── package.json // with top-level "donut" property
```
## `resolve`
`resolve` is an additional named export of `@proload/core`. It is an `async` function that resolves **but does not load** a configuration file.
- `namespace` is the name of your tool. As an example, `donut` would search for `donut.config.[ext]`.
- `opts` configure the behavior of `load`. See [Options](https://github.com/natemoo-re/proload/tree/main/packages/core#options).
```ts
resolve(namespace: string, opts?: ResolveOptions);
```
## `load`
The `default` export of `@proload/core` is an `async` function to load a configuration file.
- `namespace` is the name of your tool. As an example, `donut` would search for `donut.config.[ext]`.
- `opts` configure the behavior of `load`. See [Options](https://github.com/natemoo-re/proload/tree/main/packages/core#options).
```ts
load(namespace: string, opts?: LoadOptions);
```
## Options
### cwd
`load` searches up the directory tree, beginning from this loaction. Defaults to `process.cwd()`.
```js
import load from '@proload/core';
await load('namespace', { cwd: '/path/to/user/project' });
```
### filePath
If you already have the exact (absolute or relative) `filePath` of your user's config file, set the `filePath` option to disable Proload's search algorithm.
```js
import load from '@proload/core';
await load('namespace', { cwd: '/path/to/user/project', filePath: './custom-user-config.js' });
```
### mustExist
`mustExist` controls whether a configuration _must_ be found. Defaults to `true`—Proload will throw an error when a configuration is not found. To customize error handling, you may check the shape of the thrown error.
Setting this option to `false` allows a return value of `undefined` when a configuration is not found.
```js
import load, { ProloadError } from '@proload/core';
try {
await load('namespace', { mustExist: true });
} catch (err) {
// Proload couldn't resolve a configuration, log a custom contextual error
if (err instanceof ProloadError && err.code === 'ERR_PROLOAD_NOT_FOUND') {
console.error(`See the "namespace" docs for configuration info`);
}
throw err;
}
```
### context
Users may want to dynamically generate a different configuration based on some contextual information passed from your tool. Any `{ context }` passed to the `load` function will be forwarded to configuration "factory" functions.
```js
// Library code
import load from '@proload/core';
await load('namespace', { context: { isDev: true }});
// namespace.config.js
export default ({ isDev }) => {
return { featureFlag: isDev }
}
```
### accept
If you need complete control over which file to load, the `accept` handler can customize resolution behavior. A return value of `true` marks a file to be loaded, any other return values (even truthy ones) is ignored.
See the [`accept`](https://github.com/natemoo-re/proload/blob/34413acf87d98d3ef310ce2873103455cb2eb379/packages/core/lib/index.d.ts#L11) interface.
> Note that [Plugins](https://github.com/natemoo-re/proload/tree/main/packages/core#plugins) are able to modify similar behavior. To load non-JavaScript files, you should use a plugin instead of `accept`.
```js
import load from '@proload/core';
await load('donut', {
accept(fileName) {
// Support alternative spelling for any European friends
return fileName.startsWith('doughnut.config');
}
})
```
The following example uses `@proload/plugin-typescript` to add support for loading `.ts` files and an `accept` handler to require all config files to use the `.ts` extension.
```js
import load from '@proload/core';
import typescript from '@proload/plugin-typescript';
load.use([typescript]);
await load('namespace', {
accept(fileName) {
// Only accept `.ts` config files
return fileName.endsWith('.ts');
}
})
```
### merge
To customize `extends` behavior, you may pass a custom `merge` function to the `load` function. By default, [`deepmerge`](https://github.com/TehShrike/deepmerge) is used.
```js
// Library code
import load from '@proload/core';
const shallowMerge = (a, b) => ({ ...a, ...b })
await load('namespace', { merge: shallowMerge });
// namespace.config.js
export default {
extends: ['./a.js', './b.js']
}
// a.js
export default {
a: true
}
// b.js
export default {
b: true
}
// result
{
a: true,
b: true
}
```
## Automatic `extends`
Tools like `typescript` and `babel` have popularized the ability to share configuration presets through a top-level `extends` clause. `extends` also allows you to share a local base configuration with other packages, which is extremely useful for monorepo users.
Custom implementation of this behavior can be difficult, so `@proload/core` automatically recognizes top-level `extends` clauses (`string[]`) for you. It recursively resolves and merges all dependent configurations.
```js
// namespace.config.js
export default {
extends: ['@namespace/preset', '../namespace.base.config.js']
}
```
### Extending local configuration files
In many cases, particularly in monorepos, it's useful to have a base configuration file and use `extends` in any sub-packages to inherit the base configuration. `@proload/core` resolves paths in `extends` relative to the configuration file itself.
```
.
├── namespace.base.config.js
└── packages/
├── package-a/
│ └── namespace.config.js
└── package-b/
└── namespace.config.js
```
### Extending configuration presets
`@proload/core` uses the same strategy to resolve a configuration file from project `dependencies` as it does for user configurations. When publishing a configuration preset, use the same file naming strategy as you would for local configuration.
```
.
├── node_modules/
│ └── @namespace/
│ └── preset-env/
│ ├── package.json
│ └── namespace.config.js
├── package.json
└── namespace.config.js
```
Assuming `@namespace/preset-env` is a project dependency, the top-level `namespace.config.js` file can use `extends` to reference the dependency.
```js
export default {
extends: ['@namespace/preset-env']
}
```
## Plugins
In order to support as many use cases as possible, `@proload/core` uses a plugin system. Plugins build on each other and are designed to be combined. For example, to support a `namespacerc.json` file, you could use both `@proload/plugin-json` and `@proload/plugin-rc`.
```js
import load from '@proload/core';
import rc from '@proload/plugin-rc';
import json from '@proload/plugin-json';
load.use([rc, json]);
await load('namespace');
```
### TypeScript
In order to load a `[namespace].config.ts` file, use `@proload/plugin-typescript`.
```js
import load from '@proload/core';
import typescript from '@proload/plugin-typescript';
load.use([typescript]);
await load('namespace');
```
### JSON
In order to load a `[namespace].config.json` file, use `@proload/plugin-json`.
```js
import load from '@proload/core';
import json from '@proload/plugin-json';
load.use([json]);
await load('namespace');
```
### YAML
In order to load a `[namespace].config.yaml` or `[namespace].config.yml` file, use `@proload/plugin-yaml`.
```js
import load from '@proload/core';
import yaml from '@proload/plugin-yaml';
load.use([yaml]);
await load('namespace');
```
### RC files
In order to load a `[namespace]rc` file with any extension, use `@proload/plugin-rc`.
```js
import load from '@proload/core';
import rc from '@proload/plugin-rc';
load.use([rc]);
await load('namespace');
```
### All Plugins
For illustrative purposes (please don't do this), combining all of these plugins would support the following resolution logic:
```
.
├── namespace.config.js
├── namespace.config.cjs
├── namespace.config.mjs
├── namespace.config.ts
├── namespace.config.json
├── namespace.config.yaml
├── namespace.config.yml
├── namespacerc.js
├── namespacerc.cjs
├── namespacerc.mjs
├── namespacerc.ts
├── namespacerc.json
├── namespacerc.yaml
├── namespacerc.yml
├── config/
│ ├── namespace.config.js
│ ├── namespace.config.cjs
│ ├── namespace.config.mjs
│ ├── namespace.config.ts
│ ├── namespace.config.json
│ ├── namespace.config.yaml
│ ├── namespace.config.yml
│ ├── namespacerc.js
│ ├── namespacerc.cjs
│ ├── namespacerc.mjs
│ ├── namespacerc.ts
│ ├── namespacerc.json
│ ├── namespacerc.yaml
│ └── namespacerc.yml
└── package.json
```
## Credits
Proload is heavily inspired by tools like [`cosmiconfig`](https://github.com/davidtheclark/cosmiconfig#readme) and [`rc`](https://github.com/dominictarr/rc).
Proload would not be possible without [@lukeed](https://github.com/lukeed)'s amazing work on [`escalade`](https://github.com/lukeed/escalade) and [`uvu`](https://github.com/lukeed/uvu).