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

148
node_modules/i18next-fs-backend/README.md generated vendored Normal file
View File

@@ -0,0 +1,148 @@
# Introduction
[![Actions](https://github.com/i18next/i18next-fs-backend/workflows/node/badge.svg)](https://github.com/i18next/i18next-fs-backend/actions?query=workflow%3Anode)
[![Actions deno](https://github.com/i18next/i18next-fs-backend/workflows/deno/badge.svg)](https://github.com/i18next/i18next-fs-backend/actions?query=workflow%3Adeno)
[![npm version](https://img.shields.io/npm/v/i18next-fs-backend.svg?style=flat-square)](https://www.npmjs.com/package/i18next-fs-backend)
This is an i18next backend to be used in Node.js and Deno. It will load resources from the file system.
It's based on the deprecated [i18next-node-fs-backend](https://github.com/i18next/i18next-node-fs-backend) and can mostly be used as a drop-in replacement.
It will load resources from filesystem. Right now it supports following filetypes:
- .json
- .json5
- .jsonc
- .yml/.yaml
- .js (very limited, checks for `exports` or `export default`)
# Getting started
```bash
# npm package
$ npm install i18next-fs-backend
```
Wiring up:
```js
import i18next from 'i18next';
import Backend from 'i18next-fs-backend';
i18next.use(Backend).init(i18nextOptions);
```
for Deno:
```js
import i18next from 'https://deno.land/x/i18next/index.js'
import Backend from 'https://deno.land/x/i18next_fs_backend/index.js'
i18next.use(Backend).init(i18nextOptions);
```
- As with all modules you can either pass the constructor function (class) to the i18next.use or a concrete instance.
## Backend Options
```js
{
// path where resources get loaded from, or a function
// returning a path:
// function(lngs, namespaces) { return customPath; }
// the returned path will interpolate lng, ns if provided like giving a static path
loadPath: '/locales/{{lng}}/{{ns}}.json',
// path to post missing resources
addPath: '/locales/{{lng}}/{{ns}}.missing.json',
// if you use i18next-fs-backend as caching layer in combination with i18next-chained-backend, you can optionally set an expiration time
// an example on how to use it as cache layer can be found here: https://github.com/i18next/i18next-fs-backend/blob/master/example/caching/app.js
// expirationTime: 60 * 60 * 1000
}
```
Options can be passed in:
**preferred** - by setting options.backend in i18next.init:
```js
import i18next from 'i18next';
import Backend from 'i18next-fs-backend';
i18next.use(Backend).init({
backend: options,
});
```
on construction:
```js
import Backend from 'i18next-fs-backend';
const Backend = new Backend(null, options);
```
via calling init:
```js
import Backend from 'i18next-fs-backend';
const Backend = new Backend();
Backend.init(null, options);
```
## TypeScript
To properly type the backend options, you can import the `FsBackendOptions` interface and use it as a generic type parameter to the i18next's `init` method, e.g.:
```ts
import i18n from 'i18next'
import FsBackend, { FsBackendOptions } from 'i18next-fs-backend'
i18n
.use(FsBackend)
.init<FsBackendOptions>({
backend: {
// fs backend options
},
// other i18next options
})
```
# If set i18next initAsync option to false it will load the files synchronously
```js
// i18n.js
const { join } = require('path')
const { readdirSync, lstatSync } = require('fs')
const i18next = require('i18next')
const Backend = require('i18next-fs-backend')
i18next
.use(Backend)
.init({
// debug: true,
initAsync: false,
fallbackLng: 'en',
lng: 'en',
preload: readdirSync(join(__dirname, '../locales')).filter((fileName) => {
const joinedPath = join(join(__dirname, '../locales'), fileName)
const isDirectory = lstatSync(joinedPath).isDirectory()
return isDirectory
}),
ns: 'backend-app',
defaultNS: 'backend-app',
backend: {
loadPath: join(__dirname, '../locales/{{lng}}/{{ns}}.json')
}
})
```
---
<h3 align="center">Gold Sponsors</h3>
<p align="center">
<a href="https://locize.com/" target="_blank">
<img src="https://raw.githubusercontent.com/i18next/i18next/master/assets/locize_sponsor_240.gif" width="240px">
</a>
</p>

11
node_modules/i18next-fs-backend/cjs/extname.js generated vendored Normal file
View File

@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _default = exports.default = function _default(filename) {
if (filename.indexOf('.') < 0) return undefined;
return ".".concat(filename.split('.').pop());
};
module.exports = exports.default;

1126
node_modules/i18next-fs-backend/cjs/formats/json5.js generated vendored Normal file

File diff suppressed because one or more lines are too long

1771
node_modules/i18next-fs-backend/cjs/formats/jsonc.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

2703
node_modules/i18next-fs-backend/cjs/formats/yaml.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

50
node_modules/i18next-fs-backend/cjs/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,50 @@
import { BackendModule, ReadCallback } from "i18next";
type LoadPathOption =
| string
| ((language: string, namespace: string) => string);
type AddPathOption =
| string
| ((language: string, namespace: string) => string)
export interface FsBackendOptions {
/**
* path where resources get loaded from, or a function
* returning a path:
* function(language, namespace) { return customPath; }
* the returned path will interpolate lng, ns if provided like giving a static path
*/
loadPath?: LoadPathOption;
/**
* path to post missing resources, must be `string` or a `function` returning a path:
* function(language, namespace) { return customPath; }
*/
addPath?: AddPathOption;
ident?: number | undefined;
parse?(
data: string
): { [key: string]: any };
stringify?(
data: { [key: string]: any }
): string;
expirationTime?: number;
}
export default class I18NexFsBackend
implements BackendModule<FsBackendOptions>
{
static type: "backend";
constructor(services?: any, options?: FsBackendOptions);
init(services?: any, options?: FsBackendOptions): void;
read(language: string, namespace: string, callback: ReadCallback): void;
create?(
languages: string[],
namespace: string,
key: string,
fallbackValue: string
): void;
type: "backend";
services: any;
options: FsBackendOptions;
}

200
node_modules/i18next-fs-backend/cjs/index.js generated vendored Normal file
View File

@@ -0,0 +1,200 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _utils = require("./utils.js");
var _readFile = require("./readFile.js");
var _writeFile2 = require("./writeFile.js");
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
var getDefaults = function getDefaults() {
return {
loadPath: '/locales/{{lng}}/{{ns}}.json',
addPath: '/locales/{{lng}}/{{ns}}.missing.json',
ident: 2,
parse: JSON.parse,
stringify: JSON.stringify
};
};
var Backend = function () {
function Backend(services) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var allOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
_classCallCheck(this, Backend);
this.services = services;
this.options = options;
this.allOptions = allOptions;
this.type = 'backend';
this.init(services, options, allOptions);
}
return _createClass(Backend, [{
key: "init",
value: function init(services) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var allOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
this.services = services;
this.options = (0, _utils.defaults)(options, this.options || {}, getDefaults());
this.allOptions = allOptions;
this.queuedWrites = {};
this.debouncedWrite = (0, _utils.debounce)(this.write, 250);
}
}, {
key: "read",
value: function read(language, namespace, callback) {
var _this = this;
var loadPath = this.options.loadPath;
if (typeof this.options.loadPath === 'function') {
loadPath = this.options.loadPath(language, namespace);
}
var filename = this.services.interpolator.interpolate(loadPath, {
lng: language,
ns: namespace
});
if (this.allOptions.initAsync === false || this.allOptions.initImmediate === false) {
try {
var _readFileSync = (0, _readFile.readFileSync)(filename, this.options),
data = _readFileSync.data,
stat = _readFileSync.stat;
var timestamp = stat && stat.mtime && stat.mtime.getTime();
if (this.options.expirationTime && timestamp && timestamp + this.options.expirationTime < Date.now()) {
this.removeFile(language, namespace);
return callback(new Error('File expired!'), false);
}
callback(null, data, timestamp);
} catch (err) {
callback(err, false);
}
return;
}
(0, _readFile.readFile)(filename, this.options).then(function (_ref) {
var data = _ref.data,
stat = _ref.stat;
var timestamp = stat && stat.mtime && stat.mtime.getTime();
if (_this.options.expirationTime && timestamp && timestamp + _this.options.expirationTime < Date.now()) {
_this.removeFile(language, namespace);
return callback(new Error('File expired!'), false);
}
callback(null, data, timestamp);
}).catch(function (err) {
return callback(err, false);
});
}
}, {
key: "create",
value: function create(languages, namespace, key, fallbackValue, callback) {
var _this2 = this;
if (typeof callback !== 'function') callback = function callback() {};
if (typeof languages === 'string') languages = [languages];
var todo = languages.length;
var done = function done() {
if (! --todo) callback();
};
languages.forEach(function (lng) {
_this2.queue.call(_this2, lng, namespace, key, fallbackValue, done);
});
}
}, {
key: "save",
value: function save(language, namespace, data, callback) {
var _this3 = this;
if (!callback) callback = function callback() {};
var keys = Object.keys(data);
var todo = keys.length;
var done = function done() {
if (! --todo) callback();
};
keys.forEach(function (key) {
_this3.queue.call(_this3, language, namespace, key, data[key], done);
});
}
}, {
key: "removeFile",
value: function removeFile(language, namespace) {
var addPath = this.options.addPath;
if (typeof this.options.addPath === 'function') {
addPath = this.options.addPath(language, namespace);
}
var filename = this.services.interpolator.interpolate(addPath, {
lng: language,
ns: namespace
});
(0, _writeFile2.removeFile)(filename, this.options).then(function () {}).catch(function () {});
}
}, {
key: "write",
value: function write() {
for (var lng in this.queuedWrites) {
var namespaces = this.queuedWrites[lng];
if (lng !== 'locks') {
for (var ns in namespaces) {
this.writeFile(lng, ns);
}
}
}
}
}, {
key: "writeFile",
value: function writeFile(lng, namespace) {
var _this4 = this;
var lock = (0, _utils.getPath)(this.queuedWrites, ['locks', lng, namespace]);
if (lock) return;
var addPath = this.options.addPath;
if (typeof this.options.addPath === 'function') {
addPath = this.options.addPath(lng, namespace);
}
var filename = this.services.interpolator.interpolate(addPath, {
lng: lng,
ns: namespace
});
var missings = (0, _utils.getPath)(this.queuedWrites, [lng, namespace]);
(0, _utils.setPath)(this.queuedWrites, [lng, namespace], []);
if (missings.length) {
(0, _utils.setPath)(this.queuedWrites, ['locks', lng, namespace], true);
var proceed = function proceed(_ref2) {
var data = _ref2.data;
missings.forEach(function (missing) {
var path = _this4.allOptions.keySeparator === false ? [missing.key] : missing.key.split(_this4.allOptions.keySeparator || '.');
try {
(0, _utils.setPath)(data, path, missing.fallbackValue);
} catch (e) {
if (path.length < 2 || !e.message || e.message.indexOf('Cannot create property') < 0) throw e;
(0, _utils.setPath)(data, [missing.key], missing.fallbackValue);
}
});
var proceedWrite = function proceedWrite() {
(0, _utils.setPath)(_this4.queuedWrites, ['locks', lng, namespace], false);
missings.forEach(function (missing) {
if (missing.callback) missing.callback();
});
_this4.debouncedWrite();
};
(0, _writeFile2.writeFile)(filename, data, _this4.options).then(proceedWrite).catch(proceedWrite);
};
(0, _readFile.readFile)(filename, this.options).then(proceed).catch(function () {
return proceed({
data: {}
});
});
}
}
}, {
key: "queue",
value: function queue(lng, namespace, key, fallbackValue, callback) {
(0, _utils.pushPath)(this.queuedWrites, [lng, namespace], {
key: key,
fallbackValue: fallbackValue || '',
callback: callback
});
this.debouncedWrite();
}
}]);
}();
Backend.type = 'backend';
var _default = exports.default = Backend;
module.exports = exports.default;

1
node_modules/i18next-fs-backend/cjs/package.json generated vendored Normal file
View File

@@ -0,0 +1 @@
{"type":"commonjs"}

161
node_modules/i18next-fs-backend/cjs/readFile.js generated vendored Normal file
View File

@@ -0,0 +1,161 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.readFile = readFile;
exports.readFileSync = readFileSync;
var _json = _interopRequireDefault(require("./formats/json5.js"));
var _jsonc = require("./formats/jsonc.js");
var _yaml = _interopRequireDefault(require("./formats/yaml.js"));
var _extname = _interopRequireDefault(require("./extname.js"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
var isDeno = typeof Deno !== 'undefined';
var isBun = typeof Bun !== 'undefined';
var YAML = typeof _yaml.default !== 'undefined' && _yaml.default.load ? _yaml.default : undefined;
var fs = !isDeno ? require('node:fs') : undefined;
var evalAlias = eval;
var readFileInNodeSync = function readFileInNodeSync(filename) {
var data = fs.readFileSync(filename, 'utf8');
var stat;
try {
stat = fs.statSync(filename);
} catch (e) {}
return {
data: data,
stat: stat
};
};
var readFileInNode = function readFileInNode(filename) {
return new Promise(function (resolve, reject) {
fs.readFile(filename, 'utf8', function (err, data) {
if (err) return reject(err);
fs.stat(filename, function (err, stat) {
if (err) return resolve({
data: data
});
return resolve({
data: data,
stat: stat
});
});
});
});
};
var readFileInDenoSync = function readFileInDenoSync(filename) {
var decoder = new TextDecoder('utf-8');
var d = Deno.readFileSync(filename);
var data = decoder.decode(d);
var stat;
try {
stat = Deno.statSync(filename);
} catch (e) {}
return {
data: data,
stat: stat
};
};
var readFileInDeno = function readFileInDeno(filename) {
return new Promise(function (resolve, reject) {
var decoder = new TextDecoder('utf-8');
Deno.readFile(filename).then(function (d) {
var data = decoder.decode(d);
Deno.stat(filename).then(function (stat) {
return resolve({
data: data,
stat: stat
});
}).catch(function () {
return resolve({
data: data
});
});
}).catch(reject);
});
};
var readFileInBunSync = readFileInNodeSync;
var readFileInBun = readFileInNode;
var replaceLast = function replaceLast(str, find, replace) {
var index = str.lastIndexOf(find);
if (index > -1) {
return str.substring(0, index) + replace + str.substring(index + find.length);
}
return str.toString();
};
var parseData = function parseData(extension, data, options) {
data = data.replace(/^\uFEFF/, '');
var result = {};
switch (extension) {
case '.js':
case '.ts':
if (typeof module === 'undefined') {
if (data.indexOf('exports') > -1) {
data = "(".concat(replaceLast(data.substring(data.indexOf('=') + 1), '};', ''), ")");
} else if (data.indexOf('export default ') > -1) {
data = "(".concat(replaceLast(data.substring(data.indexOf('export default ') + 15), '};', ''), ")");
}
}
result = evalAlias(data);
break;
case '.json5':
result = _json.default.parse(data);
break;
case '.jsonc':
result = (0, _jsonc.parse)(data);
break;
case '.yml':
case '.yaml':
result = YAML.load(data);
break;
default:
result = options.parse(data);
}
return result;
};
function readFileSync(filename, options) {
var ext = (0, _extname.default)(filename);
var data, stat;
if (isBun) {
var ret = readFileInBunSync(filename);
data = ret.data;
stat = ret.stat;
} else if (isDeno) {
var _ret = readFileInDenoSync(filename);
data = _ret.data;
stat = _ret.stat;
} else {
var _ret2 = readFileInNodeSync(filename);
data = _ret2.data;
stat = _ret2.stat;
}
return {
data: parseData(ext, data, options),
stat: stat
};
}
function readFile(filename) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
parse: JSON.parse
};
var ext = (0, _extname.default)(filename);
var fn = isBun ? readFileInBun : isDeno ? readFileInDeno : readFileInNode;
return new Promise(function (resolve, reject) {
fn(filename).then(function (_ref) {
var data = _ref.data,
stat = _ref.stat;
try {
var ret = parseData(ext, data, options);
resolve({
data: ret,
stat: stat
});
} catch (err) {
err.message = 'error parsing ' + filename + ': ' + err.message;
reject(err);
}
}).catch(reject);
});
}

77
node_modules/i18next-fs-backend/cjs/utils.js generated vendored Normal file
View File

@@ -0,0 +1,77 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.debounce = debounce;
exports.defaults = defaults;
exports.getPath = getPath;
exports.pushPath = pushPath;
exports.setPath = setPath;
var arr = [];
var each = arr.forEach;
var slice = arr.slice;
function defaults(obj) {
each.call(slice.call(arguments, 1), function (source) {
if (source) {
for (var prop in source) {
if (obj[prop] === undefined) obj[prop] = source[prop];
}
}
});
return obj;
}
function debounce(func, wait, immediate) {
var timeout;
return function () {
var context = this;
var args = arguments;
var later = function later() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
function getLastOfPath(object, path, Empty) {
function cleanKey(key) {
return key && key.indexOf('###') > -1 ? key.replace(/###/g, '.') : key;
}
var stack = typeof path !== 'string' ? [].concat(path) : path.split('.');
while (stack.length > 1) {
if (!object) return {};
var key = cleanKey(stack.shift());
if (!object[key] && Empty) object[key] = new Empty();
object = object[key];
}
if (!object) return {};
return {
obj: object,
k: cleanKey(stack.shift())
};
}
function setPath(object, path, newValue) {
var _getLastOfPath = getLastOfPath(object, path, Object),
obj = _getLastOfPath.obj,
k = _getLastOfPath.k;
if (Array.isArray(obj) && isNaN(k)) throw new Error("Cannot create property \"".concat(k, "\" here since object is an array"));
obj[k] = newValue;
}
function pushPath(object, path, newValue, concat) {
var _getLastOfPath2 = getLastOfPath(object, path, Object),
obj = _getLastOfPath2.obj,
k = _getLastOfPath2.k;
obj[k] = obj[k] || [];
if (concat) obj[k] = obj[k].concat(newValue);
if (!concat) obj[k].push(newValue);
}
function getPath(object, path) {
var _getLastOfPath3 = getLastOfPath(object, path),
obj = _getLastOfPath3.obj,
k = _getLastOfPath3.k;
if (!obj) return undefined;
return obj[k];
}

174
node_modules/i18next-fs-backend/cjs/writeFile.js generated vendored Normal file
View File

@@ -0,0 +1,174 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.removeFile = removeFile;
exports.removeFileSync = removeFileSync;
exports.writeFile = writeFile;
exports.writeFileSync = writeFileSync;
var _json = _interopRequireDefault(require("./formats/json5.js"));
var _yaml = _interopRequireDefault(require("./formats/yaml.js"));
var _extname = _interopRequireDefault(require("./extname.js"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
var isDeno = typeof Deno !== 'undefined';
var isBun = typeof Bun !== 'undefined';
var YAML = typeof _yaml.default !== 'undefined' && _yaml.default.load ? _yaml.default : undefined;
var fs = !isDeno ? require('node:fs') : undefined;
function dirname(path) {
if (path.length === 0) return '.';
var code = path.charCodeAt(0);
var hasRoot = code === 47;
var end = -1;
var matchedSlash = true;
for (var i = path.length - 1; i >= 1; --i) {
code = path.charCodeAt(i);
if (code === 47) {
if (!matchedSlash) {
end = i;
break;
}
} else {
matchedSlash = false;
}
}
if (end === -1) return hasRoot ? '/' : '.';
if (hasRoot && end === 1) return '//';
return path.slice(0, end);
}
var writeFileInNodeSync = function writeFileInNodeSync(filename, payload) {
try {
fs.mkdirSync(dirname(filename), {
recursive: true
});
} catch (err) {}
return fs.writeFileSync(filename, payload, 'utf8');
};
var writeFileInNode = function writeFileInNode(filename, payload) {
return new Promise(function (resolve, reject) {
fs.mkdir(dirname(filename), {
recursive: true
}, function () {
fs.writeFile(filename, payload, 'utf8', function (err, data) {
return err ? reject(err) : resolve(data);
});
});
});
};
var removeFileInNodeSync = function removeFileInNodeSync(filename) {
return fs.unlinkSync(filename);
};
var removeFileInNode = function removeFileInNode(filename) {
return new Promise(function (resolve, reject) {
return fs.unlink(filename, function (err) {
return err ? reject(err) : resolve();
});
});
};
var writeFileInDenoSync = function writeFileInDenoSync(filename, payload) {
var encoder = new TextEncoder();
var data = encoder.encode(payload);
try {
Deno.mkdirSync(dirname(filename), {
recursive: true
});
} catch (err) {}
Deno.writeFileSync(filename, data);
};
var writeFileInDeno = function writeFileInDeno(filename, payload) {
var encoder = new TextEncoder();
var data = encoder.encode(payload);
return new Promise(function (resolve, reject) {
Deno.mkdir(dirname(filename), {
recursive: true
}).then(function () {
Deno.writeFile(filename, data).then(resolve, reject);
}).catch(function () {
Deno.writeFile(filename, data).then(resolve, reject);
});
});
};
var removeFileInDenoSync = function removeFileInDenoSync(filename) {
Deno.removeSync(filename);
};
var removeFileInDeno = function removeFileInDeno(filename) {
return Deno.remove(filename);
};
var writeFileInBunSync = writeFileInNodeSync;
var writeFileInBun = writeFileInNode;
var removeFileInBunSync = removeFileInNodeSync;
var removeFileInBun = removeFileInNode;
var stringifyData = function stringifyData(extension, data, options) {
var result = '';
switch (extension) {
case '.js':
case '.ts':
if (typeof module === 'undefined') {
result = "export default ".concat(options.stringify(data, null, options.ident));
} else {
result = "module.exports = ".concat(options.stringify(data, null, options.ident));
}
break;
case '.json5':
result = _json.default.stringify(data, null, options.ident);
break;
case '.yml':
case '.yaml':
result = YAML.dump(data, {
ident: options.indent
});
break;
default:
result = options.stringify(data, null, options.ident);
}
return result;
};
function writeFileSync(filename, payload, options) {
var ext = (0, _extname.default)(filename);
var data;
try {
data = stringifyData(ext, payload, options);
} catch (err) {
err.message = 'error stringifying ' + filename + ': ' + err.message;
throw err;
}
if (isBun) {
return writeFileInBunSync(filename, data);
} else if (isDeno) {
return writeFileInDenoSync(filename, data);
} else {
return writeFileInNodeSync(filename, data);
}
}
function writeFile(filename, payload) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
stringify: JSON.stringify,
ident: 2
};
var ext = (0, _extname.default)(filename);
var data;
try {
data = stringifyData(ext, payload, options);
} catch (err) {
err.message = 'error stringifying ' + filename + ': ' + err.message;
throw err;
}
var fn = isBun ? writeFileInBun : isDeno ? writeFileInDeno : writeFileInNode;
return fn(filename, data);
}
function removeFileSync(filename) {
if (isBun) {
return removeFileInBunSync(filename);
} else if (isDeno) {
return removeFileInDenoSync(filename);
} else {
return removeFileInNodeSync(filename);
}
}
function removeFile(filename) {
var fn = isBun ? removeFileInBun : isDeno ? removeFileInDeno : removeFileInNode;
return fn(filename);
}

4
node_modules/i18next-fs-backend/esm/extname.js generated vendored Normal file
View File

@@ -0,0 +1,4 @@
export default (function (filename) {
if (filename.indexOf('.') < 0) return undefined;
return ".".concat(filename.split('.').pop());
});

1119
node_modules/i18next-fs-backend/esm/formats/json5.js generated vendored Normal file

File diff suppressed because one or more lines are too long

1758
node_modules/i18next-fs-backend/esm/formats/jsonc.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

2698
node_modules/i18next-fs-backend/esm/formats/yaml.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

5
node_modules/i18next-fs-backend/esm/index.d.mts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
import * as index from './index.js';
export default index.default;
export type FsBackendOptions = index.FsBackendOptions;

50
node_modules/i18next-fs-backend/esm/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,50 @@
import { BackendModule, ReadCallback } from "i18next";
type LoadPathOption =
| string
| ((language: string, namespace: string) => string);
type AddPathOption =
| string
| ((language: string, namespace: string) => string)
export interface FsBackendOptions {
/**
* path where resources get loaded from, or a function
* returning a path:
* function(language, namespace) { return customPath; }
* the returned path will interpolate lng, ns if provided like giving a static path
*/
loadPath?: LoadPathOption;
/**
* path to post missing resources, must be `string` or a `function` returning a path:
* function(language, namespace) { return customPath; }
*/
addPath?: AddPathOption;
ident?: number | undefined;
parse?(
data: string
): { [key: string]: any };
stringify?(
data: { [key: string]: any }
): string;
expirationTime?: number;
}
export default class I18NexFsBackend
implements BackendModule<FsBackendOptions>
{
static type: "backend";
constructor(services?: any, options?: FsBackendOptions);
init(services?: any, options?: FsBackendOptions): void;
read(language: string, namespace: string, callback: ReadCallback): void;
create?(
languages: string[],
namespace: string,
key: string,
fallbackValue: string
): void;
type: "backend";
services: any;
options: FsBackendOptions;
}

193
node_modules/i18next-fs-backend/esm/index.js generated vendored Normal file
View File

@@ -0,0 +1,193 @@
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
import { defaults, debounce, getPath, setPath, pushPath } from './utils.js';
import { readFile, readFileSync } from './readFile.js';
import { writeFile as _writeFile, removeFile as _removeFile } from './writeFile.js';
var getDefaults = function getDefaults() {
return {
loadPath: '/locales/{{lng}}/{{ns}}.json',
addPath: '/locales/{{lng}}/{{ns}}.missing.json',
ident: 2,
parse: JSON.parse,
stringify: JSON.stringify
};
};
var Backend = function () {
function Backend(services) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var allOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
_classCallCheck(this, Backend);
this.services = services;
this.options = options;
this.allOptions = allOptions;
this.type = 'backend';
this.init(services, options, allOptions);
}
return _createClass(Backend, [{
key: "init",
value: function init(services) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var allOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
this.services = services;
this.options = defaults(options, this.options || {}, getDefaults());
this.allOptions = allOptions;
this.queuedWrites = {};
this.debouncedWrite = debounce(this.write, 250);
}
}, {
key: "read",
value: function read(language, namespace, callback) {
var _this = this;
var loadPath = this.options.loadPath;
if (typeof this.options.loadPath === 'function') {
loadPath = this.options.loadPath(language, namespace);
}
var filename = this.services.interpolator.interpolate(loadPath, {
lng: language,
ns: namespace
});
if (this.allOptions.initAsync === false || this.allOptions.initImmediate === false) {
try {
var _readFileSync = readFileSync(filename, this.options),
data = _readFileSync.data,
stat = _readFileSync.stat;
var timestamp = stat && stat.mtime && stat.mtime.getTime();
if (this.options.expirationTime && timestamp && timestamp + this.options.expirationTime < Date.now()) {
this.removeFile(language, namespace);
return callback(new Error('File expired!'), false);
}
callback(null, data, timestamp);
} catch (err) {
callback(err, false);
}
return;
}
readFile(filename, this.options).then(function (_ref) {
var data = _ref.data,
stat = _ref.stat;
var timestamp = stat && stat.mtime && stat.mtime.getTime();
if (_this.options.expirationTime && timestamp && timestamp + _this.options.expirationTime < Date.now()) {
_this.removeFile(language, namespace);
return callback(new Error('File expired!'), false);
}
callback(null, data, timestamp);
}).catch(function (err) {
return callback(err, false);
});
}
}, {
key: "create",
value: function create(languages, namespace, key, fallbackValue, callback) {
var _this2 = this;
if (typeof callback !== 'function') callback = function callback() {};
if (typeof languages === 'string') languages = [languages];
var todo = languages.length;
var done = function done() {
if (! --todo) callback();
};
languages.forEach(function (lng) {
_this2.queue.call(_this2, lng, namespace, key, fallbackValue, done);
});
}
}, {
key: "save",
value: function save(language, namespace, data, callback) {
var _this3 = this;
if (!callback) callback = function callback() {};
var keys = Object.keys(data);
var todo = keys.length;
var done = function done() {
if (! --todo) callback();
};
keys.forEach(function (key) {
_this3.queue.call(_this3, language, namespace, key, data[key], done);
});
}
}, {
key: "removeFile",
value: function removeFile(language, namespace) {
var addPath = this.options.addPath;
if (typeof this.options.addPath === 'function') {
addPath = this.options.addPath(language, namespace);
}
var filename = this.services.interpolator.interpolate(addPath, {
lng: language,
ns: namespace
});
_removeFile(filename, this.options).then(function () {}).catch(function () {});
}
}, {
key: "write",
value: function write() {
for (var lng in this.queuedWrites) {
var namespaces = this.queuedWrites[lng];
if (lng !== 'locks') {
for (var ns in namespaces) {
this.writeFile(lng, ns);
}
}
}
}
}, {
key: "writeFile",
value: function writeFile(lng, namespace) {
var _this4 = this;
var lock = getPath(this.queuedWrites, ['locks', lng, namespace]);
if (lock) return;
var addPath = this.options.addPath;
if (typeof this.options.addPath === 'function') {
addPath = this.options.addPath(lng, namespace);
}
var filename = this.services.interpolator.interpolate(addPath, {
lng: lng,
ns: namespace
});
var missings = getPath(this.queuedWrites, [lng, namespace]);
setPath(this.queuedWrites, [lng, namespace], []);
if (missings.length) {
setPath(this.queuedWrites, ['locks', lng, namespace], true);
var proceed = function proceed(_ref2) {
var data = _ref2.data;
missings.forEach(function (missing) {
var path = _this4.allOptions.keySeparator === false ? [missing.key] : missing.key.split(_this4.allOptions.keySeparator || '.');
try {
setPath(data, path, missing.fallbackValue);
} catch (e) {
if (path.length < 2 || !e.message || e.message.indexOf('Cannot create property') < 0) throw e;
setPath(data, [missing.key], missing.fallbackValue);
}
});
var proceedWrite = function proceedWrite() {
setPath(_this4.queuedWrites, ['locks', lng, namespace], false);
missings.forEach(function (missing) {
if (missing.callback) missing.callback();
});
_this4.debouncedWrite();
};
_writeFile(filename, data, _this4.options).then(proceedWrite).catch(proceedWrite);
};
readFile(filename, this.options).then(proceed).catch(function () {
return proceed({
data: {}
});
});
}
}
}, {
key: "queue",
value: function queue(lng, namespace, key, fallbackValue, callback) {
pushPath(this.queuedWrites, [lng, namespace], {
key: key,
fallbackValue: fallbackValue || '',
callback: callback
});
this.debouncedWrite();
}
}]);
}();
Backend.type = 'backend';
export default Backend;

150
node_modules/i18next-fs-backend/esm/readFile.js generated vendored Normal file
View File

@@ -0,0 +1,150 @@
import JSON5 from './formats/json5.js';
import { parse as parseJSONC } from './formats/jsonc.js';
import jsYaml from './formats/yaml.js';
import extname from './extname.js';
var isDeno = typeof Deno !== 'undefined';
var isBun = typeof Bun !== 'undefined';
var YAML = typeof jsYaml !== 'undefined' && jsYaml.load ? jsYaml : undefined;
var fs = !isDeno ? (await import('node:fs')).default : undefined;
var evalAlias = eval;
var readFileInNodeSync = function readFileInNodeSync(filename) {
var data = fs.readFileSync(filename, 'utf8');
var stat;
try {
stat = fs.statSync(filename);
} catch (e) {}
return {
data: data,
stat: stat
};
};
var readFileInNode = function readFileInNode(filename) {
return new Promise(function (resolve, reject) {
fs.readFile(filename, 'utf8', function (err, data) {
if (err) return reject(err);
fs.stat(filename, function (err, stat) {
if (err) return resolve({
data: data
});
return resolve({
data: data,
stat: stat
});
});
});
});
};
var readFileInDenoSync = function readFileInDenoSync(filename) {
var decoder = new TextDecoder('utf-8');
var d = Deno.readFileSync(filename);
var data = decoder.decode(d);
var stat;
try {
stat = Deno.statSync(filename);
} catch (e) {}
return {
data: data,
stat: stat
};
};
var readFileInDeno = function readFileInDeno(filename) {
return new Promise(function (resolve, reject) {
var decoder = new TextDecoder('utf-8');
Deno.readFile(filename).then(function (d) {
var data = decoder.decode(d);
Deno.stat(filename).then(function (stat) {
return resolve({
data: data,
stat: stat
});
}).catch(function () {
return resolve({
data: data
});
});
}).catch(reject);
});
};
var readFileInBunSync = readFileInNodeSync;
var readFileInBun = readFileInNode;
var replaceLast = function replaceLast(str, find, replace) {
var index = str.lastIndexOf(find);
if (index > -1) {
return str.substring(0, index) + replace + str.substring(index + find.length);
}
return str.toString();
};
var parseData = function parseData(extension, data, options) {
data = data.replace(/^\uFEFF/, '');
var result = {};
switch (extension) {
case '.js':
case '.ts':
if (typeof module === 'undefined') {
if (data.indexOf('exports') > -1) {
data = "(".concat(replaceLast(data.substring(data.indexOf('=') + 1), '};', ''), ")");
} else if (data.indexOf('export default ') > -1) {
data = "(".concat(replaceLast(data.substring(data.indexOf('export default ') + 15), '};', ''), ")");
}
}
result = evalAlias(data);
break;
case '.json5':
result = JSON5.parse(data);
break;
case '.jsonc':
result = parseJSONC(data);
break;
case '.yml':
case '.yaml':
result = YAML.load(data);
break;
default:
result = options.parse(data);
}
return result;
};
export function readFileSync(filename, options) {
var ext = extname(filename);
var data, stat;
if (isBun) {
var ret = readFileInBunSync(filename);
data = ret.data;
stat = ret.stat;
} else if (isDeno) {
var _ret = readFileInDenoSync(filename);
data = _ret.data;
stat = _ret.stat;
} else {
var _ret2 = readFileInNodeSync(filename);
data = _ret2.data;
stat = _ret2.stat;
}
return {
data: parseData(ext, data, options),
stat: stat
};
}
export function readFile(filename) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
parse: JSON.parse
};
var ext = extname(filename);
var fn = isBun ? readFileInBun : isDeno ? readFileInDeno : readFileInNode;
return new Promise(function (resolve, reject) {
fn(filename).then(function (_ref) {
var data = _ref.data,
stat = _ref.stat;
try {
var ret = parseData(ext, data, options);
resolve({
data: ret,
stat: stat
});
} catch (err) {
err.message = 'error parsing ' + filename + ': ' + err.message;
reject(err);
}
}).catch(reject);
});
}

67
node_modules/i18next-fs-backend/esm/utils.js generated vendored Normal file
View File

@@ -0,0 +1,67 @@
var arr = [];
var each = arr.forEach;
var slice = arr.slice;
export function defaults(obj) {
each.call(slice.call(arguments, 1), function (source) {
if (source) {
for (var prop in source) {
if (obj[prop] === undefined) obj[prop] = source[prop];
}
}
});
return obj;
}
export function debounce(func, wait, immediate) {
var timeout;
return function () {
var context = this;
var args = arguments;
var later = function later() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
function getLastOfPath(object, path, Empty) {
function cleanKey(key) {
return key && key.indexOf('###') > -1 ? key.replace(/###/g, '.') : key;
}
var stack = typeof path !== 'string' ? [].concat(path) : path.split('.');
while (stack.length > 1) {
if (!object) return {};
var key = cleanKey(stack.shift());
if (!object[key] && Empty) object[key] = new Empty();
object = object[key];
}
if (!object) return {};
return {
obj: object,
k: cleanKey(stack.shift())
};
}
export function setPath(object, path, newValue) {
var _getLastOfPath = getLastOfPath(object, path, Object),
obj = _getLastOfPath.obj,
k = _getLastOfPath.k;
if (Array.isArray(obj) && isNaN(k)) throw new Error("Cannot create property \"".concat(k, "\" here since object is an array"));
obj[k] = newValue;
}
export function pushPath(object, path, newValue, concat) {
var _getLastOfPath2 = getLastOfPath(object, path, Object),
obj = _getLastOfPath2.obj,
k = _getLastOfPath2.k;
obj[k] = obj[k] || [];
if (concat) obj[k] = obj[k].concat(newValue);
if (!concat) obj[k].push(newValue);
}
export function getPath(object, path) {
var _getLastOfPath3 = getLastOfPath(object, path),
obj = _getLastOfPath3.obj,
k = _getLastOfPath3.k;
if (!obj) return undefined;
return obj[k];
}

161
node_modules/i18next-fs-backend/esm/writeFile.js generated vendored Normal file
View File

@@ -0,0 +1,161 @@
import JSON5 from './formats/json5.js';
import jsYaml from './formats/yaml.js';
import extname from './extname.js';
var isDeno = typeof Deno !== 'undefined';
var isBun = typeof Bun !== 'undefined';
var YAML = typeof jsYaml !== 'undefined' && jsYaml.load ? jsYaml : undefined;
var fs = !isDeno ? (await import('node:fs')).default : undefined;
function dirname(path) {
if (path.length === 0) return '.';
var code = path.charCodeAt(0);
var hasRoot = code === 47;
var end = -1;
var matchedSlash = true;
for (var i = path.length - 1; i >= 1; --i) {
code = path.charCodeAt(i);
if (code === 47) {
if (!matchedSlash) {
end = i;
break;
}
} else {
matchedSlash = false;
}
}
if (end === -1) return hasRoot ? '/' : '.';
if (hasRoot && end === 1) return '//';
return path.slice(0, end);
}
var writeFileInNodeSync = function writeFileInNodeSync(filename, payload) {
try {
fs.mkdirSync(dirname(filename), {
recursive: true
});
} catch (err) {}
return fs.writeFileSync(filename, payload, 'utf8');
};
var writeFileInNode = function writeFileInNode(filename, payload) {
return new Promise(function (resolve, reject) {
fs.mkdir(dirname(filename), {
recursive: true
}, function () {
fs.writeFile(filename, payload, 'utf8', function (err, data) {
return err ? reject(err) : resolve(data);
});
});
});
};
var removeFileInNodeSync = function removeFileInNodeSync(filename) {
return fs.unlinkSync(filename);
};
var removeFileInNode = function removeFileInNode(filename) {
return new Promise(function (resolve, reject) {
return fs.unlink(filename, function (err) {
return err ? reject(err) : resolve();
});
});
};
var writeFileInDenoSync = function writeFileInDenoSync(filename, payload) {
var encoder = new TextEncoder();
var data = encoder.encode(payload);
try {
Deno.mkdirSync(dirname(filename), {
recursive: true
});
} catch (err) {}
Deno.writeFileSync(filename, data);
};
var writeFileInDeno = function writeFileInDeno(filename, payload) {
var encoder = new TextEncoder();
var data = encoder.encode(payload);
return new Promise(function (resolve, reject) {
Deno.mkdir(dirname(filename), {
recursive: true
}).then(function () {
Deno.writeFile(filename, data).then(resolve, reject);
}).catch(function () {
Deno.writeFile(filename, data).then(resolve, reject);
});
});
};
var removeFileInDenoSync = function removeFileInDenoSync(filename) {
Deno.removeSync(filename);
};
var removeFileInDeno = function removeFileInDeno(filename) {
return Deno.remove(filename);
};
var writeFileInBunSync = writeFileInNodeSync;
var writeFileInBun = writeFileInNode;
var removeFileInBunSync = removeFileInNodeSync;
var removeFileInBun = removeFileInNode;
var stringifyData = function stringifyData(extension, data, options) {
var result = '';
switch (extension) {
case '.js':
case '.ts':
if (typeof module === 'undefined') {
result = "export default ".concat(options.stringify(data, null, options.ident));
} else {
result = "module.exports = ".concat(options.stringify(data, null, options.ident));
}
break;
case '.json5':
result = JSON5.stringify(data, null, options.ident);
break;
case '.yml':
case '.yaml':
result = YAML.dump(data, {
ident: options.indent
});
break;
default:
result = options.stringify(data, null, options.ident);
}
return result;
};
export function writeFileSync(filename, payload, options) {
var ext = extname(filename);
var data;
try {
data = stringifyData(ext, payload, options);
} catch (err) {
err.message = 'error stringifying ' + filename + ': ' + err.message;
throw err;
}
if (isBun) {
return writeFileInBunSync(filename, data);
} else if (isDeno) {
return writeFileInDenoSync(filename, data);
} else {
return writeFileInNodeSync(filename, data);
}
}
export function writeFile(filename, payload) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
stringify: JSON.stringify,
ident: 2
};
var ext = extname(filename);
var data;
try {
data = stringifyData(ext, payload, options);
} catch (err) {
err.message = 'error stringifying ' + filename + ': ' + err.message;
throw err;
}
var fn = isBun ? writeFileInBun : isDeno ? writeFileInDeno : writeFileInNode;
return fn(filename, data);
}
export function removeFileSync(filename) {
if (isBun) {
return removeFileInBunSync(filename);
} else if (isDeno) {
return removeFileInDenoSync(filename);
} else {
return removeFileInNodeSync(filename);
}
}
export function removeFile(filename) {
var fn = isBun ? removeFileInBun : isDeno ? removeFileInDeno : removeFileInNode;
return fn(filename);
}

5
node_modules/i18next-fs-backend/index.d.mts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
import * as index from './index.js';
export default index.default;
export type FsBackendOptions = index.FsBackendOptions;

50
node_modules/i18next-fs-backend/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,50 @@
import { BackendModule, ReadCallback } from "i18next";
type LoadPathOption =
| string
| ((language: string, namespace: string) => string);
type AddPathOption =
| string
| ((language: string, namespace: string) => string)
export interface FsBackendOptions {
/**
* path where resources get loaded from, or a function
* returning a path:
* function(language, namespace) { return customPath; }
* the returned path will interpolate lng, ns if provided like giving a static path
*/
loadPath?: LoadPathOption;
/**
* path to post missing resources, must be `string` or a `function` returning a path:
* function(language, namespace) { return customPath; }
*/
addPath?: AddPathOption;
ident?: number | undefined;
parse?(
data: string
): { [key: string]: any };
stringify?(
data: { [key: string]: any }
): string;
expirationTime?: number;
}
export default class I18NexFsBackend
implements BackendModule<FsBackendOptions>
{
static type: "backend";
constructor(services?: any, options?: FsBackendOptions);
init(services?: any, options?: FsBackendOptions): void;
read(language: string, namespace: string, callback: ReadCallback): void;
create?(
languages: string[],
namespace: string,
key: string,
fallbackValue: string
): void;
type: "backend";
services: any;
options: FsBackendOptions;
}

2
node_modules/i18next-fs-backend/index.js generated vendored Normal file
View File

@@ -0,0 +1,2 @@
import backend from './lib/index.js'
export default backend

4
node_modules/i18next-fs-backend/lib/extname.js generated vendored Normal file
View File

@@ -0,0 +1,4 @@
export default (filename) => {
if (filename.indexOf('.') < 0) return undefined
return `.${filename.split('.').pop()}`
}

1426
node_modules/i18next-fs-backend/lib/formats/json5.js generated vendored Normal file

File diff suppressed because one or more lines are too long

1652
node_modules/i18next-fs-backend/lib/formats/jsonc.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

3851
node_modules/i18next-fs-backend/lib/formats/yaml.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

172
node_modules/i18next-fs-backend/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,172 @@
import { defaults, debounce, getPath, setPath, pushPath } from './utils.js'
import { readFile, readFileSync } from './readFile.js'
import { writeFile, removeFile } from './writeFile.js'
const getDefaults = () => {
return {
loadPath: '/locales/{{lng}}/{{ns}}.json',
addPath: '/locales/{{lng}}/{{ns}}.missing.json',
ident: 2,
parse: JSON.parse,
stringify: JSON.stringify
// expirationTime: 60 * 60 * 1000
}
}
class Backend {
constructor (services, options = {}, allOptions = {}) {
this.services = services
this.options = options
this.allOptions = allOptions
this.type = 'backend'
this.init(services, options, allOptions)
}
init (services, options = {}, allOptions = {}) {
this.services = services
this.options = defaults(options, this.options || {}, getDefaults())
this.allOptions = allOptions
this.queuedWrites = {}
this.debouncedWrite = debounce(this.write, 250)
}
read (language, namespace, callback) {
let loadPath = this.options.loadPath
if (typeof this.options.loadPath === 'function') {
loadPath = this.options.loadPath(language, namespace)
}
const filename = this.services.interpolator.interpolate(loadPath, { lng: language, ns: namespace })
if (this.allOptions.initAsync === false || this.allOptions.initImmediate === false) {
try {
const { data, stat } = readFileSync(filename, this.options)
const timestamp = stat && stat.mtime && stat.mtime.getTime()
if (this.options.expirationTime && timestamp && timestamp + this.options.expirationTime < Date.now()) {
this.removeFile(language, namespace)
return callback(new Error('File expired!'), false) // no retry
}
callback(null, data, timestamp)
} catch (err) {
callback(err, false) // no retry
}
return
}
readFile(filename, this.options)
.then(({ data, stat }) => {
const timestamp = stat && stat.mtime && stat.mtime.getTime()
if (this.options.expirationTime && timestamp && timestamp + this.options.expirationTime < Date.now()) {
this.removeFile(language, namespace)
return callback(new Error('File expired!'), false) // no retry
}
callback(null, data, timestamp)
})
.catch((err) => callback(err, false)) // no retry
}
create (languages, namespace, key, fallbackValue, callback) {
if (typeof callback !== 'function') callback = () => {}
if (typeof languages === 'string') languages = [languages]
let todo = languages.length
const done = () => {
if (!--todo) callback()
}
languages.forEach((lng) => {
// eslint-disable-next-line no-useless-call
this.queue.call(this, lng, namespace, key, fallbackValue, done)
})
}
// this way i18next-fs-backend can be used as cache layer in combination with i18next-chained-backend
save (language, namespace, data, callback) {
if (!callback) callback = () => {}
const keys = Object.keys(data)
let todo = keys.length
const done = () => {
if (!--todo) callback()
}
keys.forEach((key) => {
// eslint-disable-next-line no-useless-call
this.queue.call(this, language, namespace, key, data[key], done)
})
}
removeFile (language, namespace) {
let addPath = this.options.addPath
if (typeof this.options.addPath === 'function') {
addPath = this.options.addPath(language, namespace)
}
const filename = this.services.interpolator.interpolate(addPath, { lng: language, ns: namespace })
removeFile(filename, this.options)
.then(() => {})
.catch(() => {})
}
write () {
for (const lng in this.queuedWrites) {
const namespaces = this.queuedWrites[lng]
if (lng !== 'locks') {
for (const ns in namespaces) {
this.writeFile(lng, ns)
}
}
}
}
writeFile (lng, namespace) {
const lock = getPath(this.queuedWrites, ['locks', lng, namespace])
if (lock) return
let addPath = this.options.addPath
if (typeof this.options.addPath === 'function') {
addPath = this.options.addPath(lng, namespace)
}
const filename = this.services.interpolator.interpolate(addPath, { lng, ns: namespace })
const missings = getPath(this.queuedWrites, [lng, namespace])
setPath(this.queuedWrites, [lng, namespace], [])
if (missings.length) {
// lock
setPath(this.queuedWrites, ['locks', lng, namespace], true)
const proceed = ({ data }) => {
missings.forEach((missing) => {
const path = this.allOptions.keySeparator === false ? [missing.key] : (missing.key.split(this.allOptions.keySeparator || '.'))
try {
setPath(data, path, missing.fallbackValue)
} catch (e) {
if (path.length < 2 || !e.message || (e.message.indexOf('Cannot create property') < 0)) throw e
setPath(data, [missing.key], missing.fallbackValue)
}
})
const proceedWrite = () => {
// unlock
setPath(this.queuedWrites, ['locks', lng, namespace], false)
missings.forEach((missing) => {
if (missing.callback) missing.callback()
})
// rerun
this.debouncedWrite()
}
writeFile(filename, data, this.options)
.then(proceedWrite)
.catch(proceedWrite)
}
readFile(filename, this.options).then(proceed).catch(() => proceed({ data: {} }))
}
}
queue (lng, namespace, key, fallbackValue, callback) {
pushPath(this.queuedWrites, [lng, namespace], { key, fallbackValue: fallbackValue || '', callback })
this.debouncedWrite()
}
}
Backend.type = 'backend'
export default Backend

146
node_modules/i18next-fs-backend/lib/readFile.js generated vendored Normal file
View File

@@ -0,0 +1,146 @@
import JSON5 from './formats/json5.js'
import { parse as parseJSONC } from './formats/jsonc.js'
import jsYaml from './formats/yaml.js'
import extname from './extname.js'
const isDeno = typeof Deno !== 'undefined'
const isBun = typeof Bun !== 'undefined'
const YAML = typeof jsYaml !== 'undefined' && jsYaml.load ? jsYaml : undefined
const fs = (!isDeno/* && !isBun */) ? (await import('node:fs')).default : undefined
// eslint-disable-next-line no-eval
const evalAlias = eval
const readFileInNodeSync = (filename) => {
const data = fs.readFileSync(filename, 'utf8')
let stat
try {
stat = fs.statSync(filename)
} catch (e) {}
return { data, stat }
}
const readFileInNode = (filename) => {
return new Promise((resolve, reject) => {
fs.readFile(filename, 'utf8', (err, data) => {
if (err) return reject(err)
fs.stat(filename, (err, stat) => {
if (err) return resolve({ data })
return resolve({ data, stat })
})
})
})
}
const readFileInDenoSync = (filename) => {
const decoder = new TextDecoder('utf-8')
// eslint-disable-next-line no-undef
const d = Deno.readFileSync(filename)
const data = decoder.decode(d)
let stat
try {
// eslint-disable-next-line no-undef
stat = Deno.statSync(filename)
} catch (e) {}
return { data, stat }
}
const readFileInDeno = (filename) => {
return new Promise((resolve, reject) => {
const decoder = new TextDecoder('utf-8')
// eslint-disable-next-line no-undef
Deno.readFile(filename).then((d) => {
const data = decoder.decode(d)
// eslint-disable-next-line no-undef
Deno.stat(filename).then((stat) => resolve({ data, stat })).catch(() => resolve({ data }))
}).catch(reject)
})
}
const readFileInBunSync = readFileInNodeSync
const readFileInBun = readFileInNode
// const readFileInBun = async (filename) => {
// const f = Bun.file(filename)
// const data = await f.text()
// return { data } // Bun has no stat interface yet
// }
const replaceLast = (str, find, replace) => {
const index = str.lastIndexOf(find)
if (index > -1) {
return str.substring(0, index) + replace + str.substring(index + find.length)
}
return str.toString()
}
const parseData = (extension, data, options) => {
data = data.replace(/^\uFEFF/, '')
let result = {}
switch (extension) {
case '.js':
case '.ts':
if (typeof module === 'undefined') {
if (data.indexOf('exports') > -1) { // just to try...
data = `(${replaceLast(data.substring(data.indexOf('=') + 1), '};', '')})`
} else if (data.indexOf('export default ') > -1) { // just to try...
data = `(${replaceLast(data.substring(data.indexOf('export default ') + 15), '};', '')})`
}
}
result = evalAlias(data)
break
case '.json5':
result = JSON5.parse(data)
break
case '.jsonc':
result = parseJSONC(data)
break
case '.yml':
case '.yaml':
result = YAML.load(data)
break
default:
result = options.parse(data)
}
return result
}
// const resolvePath = (filename) => {
// return !path.isAbsolute(filename) && typeof process !== 'undefined' && process.cwd && !fs.existsSync(filename) ? path.join(process.cwd(), filename) : filename
// }
export function readFileSync (filename, options) {
const ext = extname(filename)
let data, stat
if (isBun) {
const ret = readFileInBunSync(filename)
data = ret.data
stat = ret.stat
} else if (isDeno) {
const ret = readFileInDenoSync(filename)
data = ret.data
stat = ret.stat
} else {
const ret = readFileInNodeSync(filename)
data = ret.data
stat = ret.stat
}
return { data: parseData(ext, data, options), stat }
}
export function readFile (filename, options = { parse: JSON.parse }) {
const ext = extname(filename)
// if (['.js', '.ts'].indexOf(ext) > -1) {
// return import(resolvePath(filename)).then((imp) => {
// return { data: (imp && imp.default) || imp }
// })
// }
const fn = isBun ? readFileInBun : isDeno ? readFileInDeno : readFileInNode
return new Promise((resolve, reject) => {
fn(filename).then(({ data, stat }) => {
try {
const ret = parseData(ext, data, options)
resolve({ data: ret, stat })
} catch (err) {
err.message = 'error parsing ' + filename + ': ' + err.message
reject(err)
}
}).catch(reject)
})
}

70
node_modules/i18next-fs-backend/lib/utils.js generated vendored Normal file
View File

@@ -0,0 +1,70 @@
const arr = []
const each = arr.forEach
const slice = arr.slice
export function defaults (obj) {
each.call(slice.call(arguments, 1), (source) => {
if (source) {
for (const prop in source) {
if (obj[prop] === undefined) obj[prop] = source[prop]
}
}
})
return obj
}
export function debounce (func, wait, immediate) {
let timeout
return function () {
const context = this
const args = arguments
const later = function () {
timeout = null
if (!immediate) func.apply(context, args)
}
const callNow = immediate && !timeout
clearTimeout(timeout)
timeout = setTimeout(later, wait)
if (callNow) func.apply(context, args)
}
}
function getLastOfPath (object, path, Empty) {
function cleanKey (key) {
return (key && key.indexOf('###') > -1) ? key.replace(/###/g, '.') : key
}
const stack = (typeof path !== 'string') ? [].concat(path) : path.split('.')
while (stack.length > 1) {
if (!object) return {}
const key = cleanKey(stack.shift())
if (!object[key] && Empty) object[key] = new Empty()
object = object[key]
}
if (!object) return {}
return {
obj: object,
k: cleanKey(stack.shift())
}
}
export function setPath (object, path, newValue) {
const { obj, k } = getLastOfPath(object, path, Object)
if (Array.isArray(obj) && isNaN(k)) throw new Error(`Cannot create property "${k}" here since object is an array`)
obj[k] = newValue
}
export function pushPath (object, path, newValue, concat) {
const { obj, k } = getLastOfPath(object, path, Object)
obj[k] = obj[k] || []
if (concat) obj[k] = obj[k].concat(newValue)
if (!concat) obj[k].push(newValue)
}
export function getPath (object, path) {
const { obj, k } = getLastOfPath(object, path)
if (!obj) return undefined
return obj[k]
}

170
node_modules/i18next-fs-backend/lib/writeFile.js generated vendored Normal file
View File

@@ -0,0 +1,170 @@
import JSON5 from './formats/json5.js'
import jsYaml from './formats/yaml.js'
import extname from './extname.js'
const isDeno = typeof Deno !== 'undefined'
const isBun = typeof Bun !== 'undefined'
const YAML = typeof jsYaml !== 'undefined' && jsYaml.load ? jsYaml : undefined
const fs = (!isDeno/* && !isBun */) ? (await import('node:fs')).default : undefined
function dirname (path) {
if (path.length === 0) return '.'
let code = path.charCodeAt(0)
const hasRoot = code === 47
let end = -1
let matchedSlash = true
for (let i = path.length - 1; i >= 1; --i) {
code = path.charCodeAt(i)
if (code === 47) {
if (!matchedSlash) {
end = i
break
}
} else {
// We saw the first non-path separator
matchedSlash = false
}
}
if (end === -1) return hasRoot ? '/' : '.'
if (hasRoot && end === 1) return '//'
return path.slice(0, end)
}
const writeFileInNodeSync = (filename, payload) => {
try {
fs.mkdirSync(dirname(filename), { recursive: true })
} catch (err) {}
return fs.writeFileSync(filename, payload, 'utf8')
}
const writeFileInNode = (filename, payload) => {
return new Promise((resolve, reject) => {
fs.mkdir(dirname(filename), { recursive: true }, () => {
fs.writeFile(filename, payload, 'utf8', (err, data) => err ? reject(err) : resolve(data))
})
})
}
const removeFileInNodeSync = (filename) => {
return fs.unlinkSync(filename)
}
const removeFileInNode = (filename) => {
return new Promise((resolve, reject) => fs.unlink(filename, (err) => err ? reject(err) : resolve()))
}
const writeFileInDenoSync = (filename, payload) => {
const encoder = new TextEncoder()
const data = encoder.encode(payload)
try {
// eslint-disable-next-line no-undef
Deno.mkdirSync(dirname(filename), { recursive: true })
} catch (err) {}
// eslint-disable-next-line no-undef
Deno.writeFileSync(filename, data)
}
const writeFileInDeno = (filename, payload) => {
const encoder = new TextEncoder()
const data = encoder.encode(payload)
return new Promise((resolve, reject) => {
// eslint-disable-next-line no-undef
Deno.mkdir(dirname(filename), { recursive: true }).then(() => {
// eslint-disable-next-line no-undef
Deno.writeFile(filename, data).then(resolve, reject)
}).catch(() => {
// eslint-disable-next-line no-undef
Deno.writeFile(filename, data).then(resolve, reject)
})
})
}
const removeFileInDenoSync = (filename) => {
// eslint-disable-next-line no-undef
Deno.removeSync(filename)
}
const removeFileInDeno = (filename) => {
// eslint-disable-next-line no-undef
return Deno.remove(filename)
}
const writeFileInBunSync = writeFileInNodeSync // not yet a specific Bun interface
const writeFileInBun = writeFileInNode
// Bun.write generates some error warnings yet...
// const writeFileInBun = (filename, payload) => Bun.write(filename, payload)
const removeFileInBunSync = removeFileInNodeSync // not yet a specific Bun interface
const removeFileInBun = removeFileInNode // not yet a specific Bun interface
const stringifyData = (extension, data, options) => {
let result = ''
switch (extension) {
case '.js':
case '.ts':
if (typeof module === 'undefined') {
result = `export default ${options.stringify(data, null, options.ident)}`
} else {
result = `module.exports = ${options.stringify(data, null, options.ident)}`
}
break
case '.json5':
result = JSON5.stringify(data, null, options.ident)
break
case '.yml':
case '.yaml':
result = YAML.dump(data, { ident: options.indent })
break
default:
result = options.stringify(data, null, options.ident)
}
return result
}
export function writeFileSync (filename, payload, options) {
const ext = extname(filename)
let data
try {
data = stringifyData(ext, payload, options)
} catch (err) {
err.message = 'error stringifying ' + filename + ': ' + err.message
throw err
}
if (isBun) {
return writeFileInBunSync(filename, data)
} else if (isDeno) {
return writeFileInDenoSync(filename, data)
} else {
return writeFileInNodeSync(filename, data)
}
}
export function writeFile (filename, payload, options = { stringify: JSON.stringify, ident: 2 }) {
const ext = extname(filename)
let data
try {
data = stringifyData(ext, payload, options)
} catch (err) {
err.message = 'error stringifying ' + filename + ': ' + err.message
throw err
}
const fn = isBun ? writeFileInBun : isDeno ? writeFileInDeno : writeFileInNode
return fn(filename, data)
}
export function removeFileSync (filename) {
if (isBun) {
return removeFileInBunSync(filename)
} else if (isDeno) {
return removeFileInDenoSync(filename)
} else {
return removeFileInNodeSync(filename)
}
}
export function removeFile (filename) {
const fn = isBun ? removeFileInBun : isDeno ? removeFileInDeno : removeFileInNode
return fn(filename)
}

19
node_modules/i18next-fs-backend/licence generated vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2024 i18next
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

94
node_modules/i18next-fs-backend/package.json generated vendored Normal file
View File

@@ -0,0 +1,94 @@
{
"name": "i18next-fs-backend",
"version": "2.6.0",
"private": false,
"type": "module",
"main": "./cjs/index.js",
"exports": {
"./package.json": "./package.json",
".": {
"types": {
"require": "./cjs/index.d.ts",
"import": "./esm/index.d.mts"
},
"module": "./esm/index.js",
"import": "./esm/index.js",
"require": "./cjs/index.js",
"default": "./esm/index.js"
},
"./cjs": {
"types": "./cjs/index.d.ts",
"default": "./cjs/index.js"
},
"./esm": {
"types": "./esm/index.d.mts",
"default": "./esm/index.js"
}
},
"module": "./esm/index.js",
"types": "./index.d.mts",
"devDependencies": {
"@babel/cli": "7.25.9",
"@babel/core": "7.26.0",
"@babel/preset-env": "7.26.0",
"babel-plugin-add-module-exports": "1.0.4",
"dtslint": "4.2.1",
"esbuild": "0.24.0",
"eslint": "8.55.0",
"eslint-config-standard": "17.1.0",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-n": "16.3.1",
"eslint-plugin-promise": "6.1.1",
"eslint-plugin-require-path-exists": "1.1.9",
"eslint-plugin-standard": "5.0.0",
"expect.js": "0.3.1",
"i18next": "24.0.0",
"js-yaml": "4.1.0",
"jsonc-parser": "3.3.1",
"json5": "2.2.3",
"mocha": "10.8.2",
"tslint": "5.20.1",
"tsd": "0.31.2",
"typescript": "5.6.3",
"uglify-js": "3.19.3"
},
"description": "i18next-fs-backend is a backend layer for i18next using in Node.js and for Deno to load translations from the filesystem.",
"keywords": [
"i18next",
"i18next-backend",
"i18next-fs-backend"
],
"homepage": "https://github.com/i18next/i18next-fs-backend",
"repository": {
"type": "git",
"url": "git@github.com:i18next/i18next-fs-backend.git"
},
"bugs": {
"url": "https://github.com/i18next/i18next-fs-backend/issues"
},
"license": "MIT",
"config": {
"fixcjs": "fs.writeFileSync('cjs/writeFile.js', fs.readFileSync('cjs/writeFile.js').toString().replace(`(await Promise.resolve().then(function () {\n return _interopRequireWildcard(require('node:fs'));\n})).default`, `require('node:fs')`));fs.writeFileSync('cjs/readFile.js', fs.readFileSync('cjs/readFile.js').toString().replace(`(await Promise.resolve().then(function () {\n return _interopRequireWildcard(require('node:fs'));\n})).default`, `require('node:fs')`))"
},
"scripts": {
"copy:jsonc": "esbuild node_modules/jsonc-parser/lib/esm/main.js --bundle --format=esm --platform=neutral --banner:js=\"/*\n$(sed 's/\\r$//' node_modules/jsonc-parser/LICENSE.md)\n*/\" --outfile=lib/formats/jsonc.js",
"copy:json5": "cp node_modules/json5/dist/index.mjs lib/formats/json5.js",
"copy:yaml": "cp node_modules/js-yaml/dist/js-yaml.mjs lib/formats/yaml.js",
"copy": "rm -rf lib/formats && mkdir lib/formats && npm run copy:jsonc && npm run copy:json5 && npm run copy:yaml",
"lint": "eslint .",
"fixcjs": "node -e \"$npm_package_config_fixcjs\"",
"compile:esm": "rm -rf esm && mkdir esm && BABEL_ENV=esm babel lib -d esm && cp index.d.ts esm/index.d.ts && cp index.d.mts esm/index.d.mts",
"compile:cjs": "rm -rf cjs && mkdir cjs && BABEL_ENV=cjs babel lib -d cjs && cp index.d.ts cjs/index.d.ts && echo '{\"type\":\"commonjs\"}' > cjs/package.json && npm run fixcjs",
"compile": "npm run copy && npm run compile:esm && npm run compile:cjs",
"build": "npm run compile",
"test": "npm run lint && npm run build && mocha test -R spec --exit --experimental-modules && npm run test:typescript",
"test:typescript": "tslint --project tsconfig.json && tsd",
"test:deno": "deno test test/deno/*.js --allow-read --allow-write --no-check",
"test:bun": "bun test test/bun/*.js",
"preversion": "npm run test && npm run build && git push",
"postversion": "git push && git push --tags"
},
"tsd": {
"directory": "test/typescript"
}
}

7
node_modules/i18next-fs-backend/tslint.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"defaultSeverity": "error",
"extends": "dtslint/dtslint.json",
"rules": {
"semicolon": false
}
}