mirror of
https://github.com/Drop-OSS/drop.git
synced 2026-01-31 15:37:09 +01:00
* feat: nginx + torrential basics & services system * fix: lint + i18n * fix: update torrential to remove openssl * feat: add torrential to Docker build * feat: move to self hosted runner * fix: move off self-hosted runner * fix: update nginx.conf * feat: torrential cache invalidation * fix: update torrential for cache invalidation * feat: integrity check task * fix: lint * feat: move to version ids * fix: client fixes and client-side checks * feat: new depot apis and version id fixes * feat: update torrential * feat: droplet bump and remove unsafe update functions * fix: lint * feat: v4 featureset: emulators, multi-launch commands * fix: lint * fix: mobile ui for game editor * feat: launch options * fix: lint * fix: remove axios, use $fetch * feat: metadata and task api improvements * feat: task actions * fix: slight styling issue * feat: fix style and lints * feat: totp backend routes * feat: oidc groups * fix: update drop-base * feat: creation of passkeys & totp * feat: totp signin * feat: webauthn mfa/signin * feat: launch selecting ui * fix: manually running tasks * feat: update add company game modal to use new SelectorGame * feat: executor selector * fix(docker): update rust to rust nightly for torrential build (#305) * feat: new version ui * feat: move package lookup to build time to allow for deno dev * fix: lint * feat: localisation cleanup * feat: apply localisation cleanup * feat: potential i18n refactor logic * feat: remove args from commands * fix: lint * fix: lockfile --------- Co-authored-by: Aden Lindsay <140392385+AdenMGB@users.noreply.github.com>
123 lines
3.5 KiB
TypeScript
123 lines
3.5 KiB
TypeScript
import path from "node:path";
|
|
import fs from "node:fs";
|
|
import prettier from "prettier";
|
|
const prettierConfig = JSON.parse(
|
|
fs.readFileSync("./.prettierrc.json", "utf-8"),
|
|
);
|
|
|
|
const paths = ["./components", "./layouts", "./pages", "./server"];
|
|
const constPaths = ["error.vue", "app.vue"];
|
|
const extensions = [".vue", ".ts"];
|
|
|
|
function recursiveFindFiles(root: string): string[] {
|
|
const results = [];
|
|
const subpaths = fs.readdirSync(root);
|
|
for (const subpath of subpaths) {
|
|
const absPath = path.join(root, subpath);
|
|
if (extensions.some((v) => absPath.endsWith(v))) {
|
|
results.push(absPath);
|
|
continue;
|
|
}
|
|
const stat = fs.statSync(absPath);
|
|
if (stat.isDirectory()) {
|
|
results.push(...recursiveFindFiles(absPath));
|
|
continue;
|
|
}
|
|
}
|
|
return [...results, ...constPaths];
|
|
}
|
|
|
|
/**
|
|
* Fetches the paths of all files available to be localised
|
|
*/
|
|
export function allLocalisableFiles(): string[] {
|
|
const files = paths.map((k) => recursiveFindFiles(k)).flat();
|
|
|
|
return files;
|
|
}
|
|
|
|
const I18N_UTIL_REGEX = /(?<=[^a-zA-Z]t\(\s*?["']).*?(?=["'])/g;
|
|
const I18N_KEYPATH_REGEX = /(?<=keypath=["']).*?(?=["'])/g;
|
|
/**
|
|
* Uses regex to match all i18n keys in content
|
|
* @param content The file content to match against
|
|
*/
|
|
export function keysFromContent(content: string): string[] {
|
|
const matches = [
|
|
...content.matchAll(I18N_UTIL_REGEX),
|
|
...content.matchAll(I18N_KEYPATH_REGEX),
|
|
];
|
|
return matches.map((v) => v[0]);
|
|
}
|
|
|
|
export type Localisation = { [key: string]: Localisation | string };
|
|
|
|
export function flattenLocalisation(localisation: Localisation) {
|
|
const map = new Map<string, string>();
|
|
flattenLocalisationRecursive(map, [], localisation);
|
|
return map;
|
|
}
|
|
|
|
function flattenLocalisationRecursive(
|
|
map: Map<string, string>,
|
|
key: string[],
|
|
localisationBranch: Localisation | string,
|
|
) {
|
|
if (typeof localisationBranch === "string") {
|
|
map.set(key.join("."), localisationBranch);
|
|
return;
|
|
}
|
|
for (const [subKey, value] of Object.entries(localisationBranch)) {
|
|
const newKey = [...key, subKey];
|
|
flattenLocalisationRecursive(map, newKey, value);
|
|
}
|
|
}
|
|
|
|
export function deleteLocalisation(localisation: Localisation, key: string) {
|
|
const parts = key.split(".");
|
|
let current: Localisation | string = localisation;
|
|
for (const part of parts.slice(0, -1)) {
|
|
if (typeof current === "string")
|
|
throw new Error(`${key} not found in localisation`);
|
|
current = current[part];
|
|
}
|
|
if (typeof current === "string")
|
|
throw new Error(`${key} not found in localisation`);
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
delete current[parts.at(-1)!];
|
|
}
|
|
|
|
export function fetchLocalisation(
|
|
localisation: Localisation,
|
|
key: string,
|
|
): string {
|
|
const parts = key.split(".");
|
|
let current: Localisation | string = localisation;
|
|
for (const part of parts.slice(0, -1)) {
|
|
if (typeof current === "string")
|
|
throw new Error(`${key} not found in localisation`);
|
|
current = current[part];
|
|
}
|
|
if (typeof current === "string")
|
|
throw new Error(`${key} not found in localisation`);
|
|
|
|
return current[parts.at(-1)!] as string;
|
|
}
|
|
|
|
export async function writeJSON<T>(path: string, object: T) {
|
|
const flatStr = JSON.stringify(object);
|
|
const formatted = await prettier.format(flatStr, {
|
|
parser: "json",
|
|
...prettierConfig,
|
|
});
|
|
fs.writeFileSync(path, formatted);
|
|
}
|
|
|
|
/**
|
|
* Strips some sort of English language string down to something that can be compared to be basically equivalent
|
|
*/
|
|
export function stripEquivalence(value: string): string {
|
|
return value.replaceAll(/[.,\s]/g, "").toLowerCase();
|
|
}
|