mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-07-23 04:52:58 +00:00
Complete Commonlib rc.6 integration and setup workflows
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import { writeFileSync } from "fs";
|
||||
import { allMessages } from "../src/common/messages/combinedMessages.dev.ts";
|
||||
import path from "path";
|
||||
const __dirname = import.meta.dirname;
|
||||
const currentPath = __dirname;
|
||||
const outDir = path.resolve(currentPath, "../src/common/messages/combinedMessages.prod.ts");
|
||||
|
||||
console.log(`Writing to ${outDir}`);
|
||||
writeFileSync(
|
||||
outDir,
|
||||
`export const allMessages: Readonly<Record<string, Readonly<Record<string, string>>>> = ${JSON.stringify(allMessages, null, 4)};`
|
||||
);
|
||||
@@ -0,0 +1,58 @@
|
||||
import { readFile } from "fs/promises";
|
||||
import { join, resolve } from "path";
|
||||
import { glob } from "tinyglobby";
|
||||
import { parse } from "yaml";
|
||||
import { objectToDotted } from "./messagelib.ts";
|
||||
|
||||
const __dirname = import.meta.dirname;
|
||||
const targetDir = resolve(join(__dirname, "../src/common/messagesYAML/"));
|
||||
const files = (await glob(`*.yaml`, { expandDirectories: false, absolute: true, cwd: targetDir })).sort();
|
||||
|
||||
function flattenMessages(src: Record<string, unknown>) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(objectToDotted(src))
|
||||
.map(([key, value]) => [key.endsWith("._value") ? key.slice(0, -7) : key, value] as const)
|
||||
.filter(([, value]) => typeof value === "string")
|
||||
.sort(([a], [b]) => a.localeCompare(b))
|
||||
) as Record<string, string>;
|
||||
}
|
||||
|
||||
const localeData = new Map<string, Record<string, string>>();
|
||||
for (const file of files) {
|
||||
const segments = file.split(/[/\\]/);
|
||||
const locale = segments[segments.length - 1]!.replace(/\.yaml$/, "");
|
||||
const content = await readFile(file, "utf-8");
|
||||
localeData.set(locale, flattenMessages(parse(content) ?? {}));
|
||||
}
|
||||
|
||||
const baseLocale = "en";
|
||||
const base = localeData.get(baseLocale);
|
||||
if (!base) {
|
||||
throw new Error("en.yaml not found");
|
||||
}
|
||||
|
||||
const baseKeys = Object.keys(base);
|
||||
const report = Object.fromEntries(
|
||||
[...localeData.entries()].map(([locale, data]) => {
|
||||
const keys = new Set(Object.keys(data));
|
||||
const missing = baseKeys.filter((key) => !keys.has(key));
|
||||
const identicalToEnglish = baseKeys.filter(
|
||||
(key) => keys.has(key) && locale !== baseLocale && data[key] === base[key]
|
||||
);
|
||||
const translated = baseKeys.length - missing.length;
|
||||
return [
|
||||
locale,
|
||||
{
|
||||
totalBaseKeys: baseKeys.length,
|
||||
translatedKeys: translated,
|
||||
missingKeys: missing.length,
|
||||
identicalToEnglishCount: identicalToEnglish.length,
|
||||
coverage: `${translated}/${baseKeys.length}`,
|
||||
missing,
|
||||
identicalToEnglish,
|
||||
},
|
||||
];
|
||||
})
|
||||
);
|
||||
|
||||
console.log(JSON.stringify(report, null, 2));
|
||||
@@ -0,0 +1,55 @@
|
||||
import { writeFileSync } from "fs";
|
||||
|
||||
import { SUPPORTED_I18N_LANGS, type I18N_LANGS } from "../src/common/rosetta";
|
||||
import { allMessages } from "../src/common/messages/combinedMessages.dev.ts";
|
||||
|
||||
import path from "path";
|
||||
const thisFileDir = __dirname;
|
||||
const outDir = path.join(thisFileDir, "i18n");
|
||||
|
||||
const out = {} as Record<string, { [key: string]: string | undefined }>;
|
||||
|
||||
for (const [key, value] of Object.entries(allMessages)) {
|
||||
for (const lang of [...SUPPORTED_I18N_LANGS, "def"]) {
|
||||
if (!out[lang]) out[lang] = {};
|
||||
if (lang in value) {
|
||||
out[lang][key] = value[lang as I18N_LANGS];
|
||||
} else {
|
||||
if (lang === "def") {
|
||||
out[lang][key] = key;
|
||||
} else {
|
||||
out[lang][key] = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const [lang, value] of Object.entries(out)) {
|
||||
const filename = `${lang}.ts`;
|
||||
const escapeString = (prefix: string, key: string, str: string) => {
|
||||
if (str.indexOf("\n") !== -1) {
|
||||
const encoded = JSON.stringify(str);
|
||||
const lineWrapped = encoded.split("\\n").join("\\\n" + prefix);
|
||||
|
||||
return `${prefix}${JSON.stringify(key)}: ${lineWrapped},`;
|
||||
}
|
||||
return `${prefix}${JSON.stringify(key)}: ${JSON.stringify(str)},`;
|
||||
};
|
||||
// const z ="a" "b" "c";
|
||||
const _stringify = (value: Record<string, string | undefined>) => {
|
||||
let res = "{\n";
|
||||
for (const key of Object.keys(value)) {
|
||||
const v = value[key];
|
||||
if (v) {
|
||||
res += escapeString("", key, v) + "\n";
|
||||
} else {
|
||||
res += escapeString("// ", key, out["def"]?.[key] ?? "") + "\n";
|
||||
}
|
||||
}
|
||||
return res + "\n}";
|
||||
};
|
||||
void writeFileSync(
|
||||
path.join(outDir, filename),
|
||||
`export const PartialMessages ={\n "${lang}":${_stringify(value)}\n} as const;`
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { writeFileSync } from "fs";
|
||||
|
||||
import { allMessages } from "../src/common/messages/combinedMessages.prod.ts";
|
||||
const __dirname = import.meta.dirname;
|
||||
import path from "path";
|
||||
const thisFileDir = __dirname;
|
||||
const outDir = path.resolve(thisFileDir, "../src/common/messagesJson");
|
||||
|
||||
const out = {} as Record<string, { [key: string]: string | undefined }>;
|
||||
|
||||
for (const [key, value] of Object.entries(allMessages)) {
|
||||
//@ts-ignore
|
||||
for (const [lang, langValue] of Object.entries(allMessages[key])) {
|
||||
if (!out[lang]) out[lang] = {};
|
||||
if (lang in value) {
|
||||
out[lang][key] = langValue as string;
|
||||
} else {
|
||||
if (lang === "def") {
|
||||
out[lang][key] = key;
|
||||
} else {
|
||||
out[lang][key] = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const [lang, value] of Object.entries(out)) {
|
||||
const filename = `${lang}.json`;
|
||||
void writeFileSync(path.join(outDir, filename), JSON.stringify(value, null, 4));
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Convert Application convenient Message Resources (JSON) to Human-Editable format (YAML)
|
||||
import { readFile, writeFile } from "fs/promises";
|
||||
import { join, resolve } from "path";
|
||||
import { stringify } from "yaml";
|
||||
import { glob } from "tinyglobby";
|
||||
import { dottedToObject } from "./messagelib";
|
||||
const __dirname = import.meta.dirname;
|
||||
|
||||
const targetDir = resolve(join(__dirname, "../src/common/messagesJson/"));
|
||||
console.log(`Target directory: ${targetDir}`);
|
||||
const files = await glob(`*.json`, { expandDirectories: false, absolute: true, cwd: targetDir });
|
||||
for (const file of files) {
|
||||
const filePath = resolve(file);
|
||||
console.log(`Processing file: ${filePath}`);
|
||||
const content = await readFile(filePath, "utf-8");
|
||||
const jsonDataSrc = JSON.parse(content);
|
||||
const jsonDataD2 = Object.fromEntries(
|
||||
Object.entries(jsonDataSrc).sort(([keyA], [keyB]) => keyA.localeCompare(keyB))
|
||||
);
|
||||
const jsonData = dottedToObject(jsonDataD2);
|
||||
const yamlData = stringify(jsonData, { indent: 2 });
|
||||
const yamlFilePath = filePath.replace(/\.json$/, ".yaml").replace("Json", "YAML");
|
||||
await writeFile(yamlFilePath, yamlData, "utf-8");
|
||||
console.log(`Converted ${filePath} to ${yamlFilePath}`);
|
||||
}
|
||||
|
||||
// console.dir(files, { depth: 0 });
|
||||
@@ -0,0 +1,38 @@
|
||||
export function objectToDotted(obj: any, prefix = ""): Record<string, any> {
|
||||
return Object.entries(obj).reduce(
|
||||
(acc, [key, value]) => {
|
||||
const newKey = prefix ? `${prefix}.${key}` : key;
|
||||
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
||||
Object.assign(acc, objectToDotted(value, newKey));
|
||||
} else {
|
||||
acc[newKey] = value;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, any>
|
||||
);
|
||||
}
|
||||
export function dottedToObject(obj: Record<string, any>): Record<string, any> {
|
||||
return Object.entries(obj).reduce(
|
||||
(acc, [key, value]) => {
|
||||
if (key.includes(" ")) {
|
||||
// Return as is.
|
||||
return { ...acc, [key]: value }; // Skip keys with spaces
|
||||
}
|
||||
const keys = key.split(".");
|
||||
keys.reduce((nestedAcc, currKey, index) => {
|
||||
if (currKey in nestedAcc && typeof nestedAcc[currKey] !== "object") {
|
||||
nestedAcc[currKey] = { _value: nestedAcc[currKey] }; // Convert to object if not already
|
||||
}
|
||||
if (index === keys.length - 1) {
|
||||
nestedAcc[currKey] = value;
|
||||
} else {
|
||||
nestedAcc[currKey] = nestedAcc[currKey] || {};
|
||||
}
|
||||
return nestedAcc[currKey];
|
||||
}, acc);
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, any>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Convert Human-Editable format (YAML) to Application convenient Message Resources (JSON)
|
||||
|
||||
import { readFile, writeFile } from "fs/promises";
|
||||
import { join, resolve } from "path";
|
||||
import { parse } from "yaml";
|
||||
import { glob } from "tinyglobby";
|
||||
import { objectToDotted } from "./messagelib";
|
||||
const __dirname = import.meta.dirname;
|
||||
|
||||
const targetDir = resolve(join(__dirname, "../src/common/messagesYAML/"));
|
||||
console.log(`Target directory: ${targetDir}`);
|
||||
const files = await glob(`*.yaml`, { expandDirectories: false, absolute: true, cwd: targetDir });
|
||||
for (const file of files) {
|
||||
const filePath = resolve(file);
|
||||
const content = await readFile(filePath, "utf-8");
|
||||
const jsonDataSrc = parse(content);
|
||||
const jsonDataD2 = objectToDotted(jsonDataSrc);
|
||||
const jsonData = Object.fromEntries(
|
||||
Object.entries(jsonDataD2)
|
||||
.map(([key, value]) => [key.endsWith("._value") ? key.slice(0, -7) : key, value])
|
||||
.sort(([keyA], [keyB]) => keyA.localeCompare(keyB))
|
||||
);
|
||||
const yamlData = JSON.stringify(jsonData, null, 4) + "\n";
|
||||
const yamlFilePath = filePath.replace(/\.yaml$/, ".json").replace("YAML", "Json");
|
||||
await writeFile(yamlFilePath, yamlData, "utf-8");
|
||||
console.log(`Converted ${filePath} to ${yamlFilePath}`);
|
||||
}
|
||||
|
||||
// console.dir(files, { depth: 0 });
|
||||
Reference in New Issue
Block a user