mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-11 20:08:37 +00:00
129 lines
3.3 KiB
TypeScript
129 lines
3.3 KiB
TypeScript
import { readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
import { parse } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
import { Package } from '@affine-tools/utils/workspace';
|
|
import { runCli } from '@magic-works/i18n-codegen';
|
|
|
|
const isDev = process.argv.includes('--dev');
|
|
|
|
const i18nPkg = new Package('@affine/i18n');
|
|
const resourcesDir = i18nPkg.join('src', 'resources').toString();
|
|
|
|
function readResource(lang: string): Record<string, string> {
|
|
const filePath = `${resourcesDir}/${lang}.json`;
|
|
const fileContent = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
return fileContent;
|
|
}
|
|
|
|
function writeResource(lang: string, resource: Record<string, string>) {
|
|
const filePath = `${resourcesDir}/${lang}.json`;
|
|
writeFileSync(filePath, JSON.stringify(resource, null, 2) + '\n');
|
|
}
|
|
|
|
function calcCompletenesses() {
|
|
const langs = readdirSync(resourcesDir)
|
|
.filter(file => file.endsWith('.json'))
|
|
.reduce(
|
|
(langs, file) => {
|
|
const lang = parse(file).name;
|
|
langs[lang] = readResource(lang);
|
|
return langs;
|
|
},
|
|
{} as Record<string, Record<string, string>>
|
|
);
|
|
|
|
const base = Object.keys(langs.en).length;
|
|
|
|
const completenesses = {};
|
|
|
|
for (const key in langs) {
|
|
const [langPart, variantPart] = key.split('-');
|
|
|
|
const completeness = Object.keys(
|
|
variantPart ? { ...langs[langPart], ...langs[key] } : langs[key]
|
|
).length;
|
|
|
|
completenesses[key] = Math.min(
|
|
Math.ceil(/* avoid 0% */ (completeness / base) * 100),
|
|
100
|
|
);
|
|
}
|
|
|
|
writeFileSync(
|
|
i18nPkg.join('src', 'i18n-completenesses.json').toString(),
|
|
JSON.stringify(completenesses, null, 2) + '\n'
|
|
);
|
|
}
|
|
|
|
function i18nnext() {
|
|
runCli(
|
|
{
|
|
config: fileURLToPath(new URL('./.i18n-codegen.json', import.meta.url)),
|
|
watch: isDev,
|
|
},
|
|
error => {
|
|
console.error(error);
|
|
if (!isDev) {
|
|
process.exit(1);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
async function appendErrorI18n() {
|
|
const server = new Package('@affine/server');
|
|
const defFilePath = server.srcPath.join('base/error/def.ts');
|
|
|
|
if (!defFilePath.exists()) {
|
|
throw new Error(
|
|
`Can not find Server I18n error definition file. It's not placed at [${defFilePath.relativePath}].`
|
|
);
|
|
}
|
|
|
|
const { USER_FRIENDLY_ERRORS } = await import(
|
|
defFilePath.toFileUrl().toString()
|
|
);
|
|
|
|
if (!USER_FRIENDLY_ERRORS) {
|
|
throw new Error(
|
|
`Can not find Server I18n error definition file. It's not placed at [${defFilePath.relativePath}] with name [USER_FRIENDLY_ERRORS].`
|
|
);
|
|
}
|
|
|
|
const en = readResource('en');
|
|
|
|
Object.keys(en).forEach(key => {
|
|
if (key.startsWith('error.')) {
|
|
delete en[key];
|
|
}
|
|
});
|
|
|
|
for (const key in USER_FRIENDLY_ERRORS) {
|
|
const def = USER_FRIENDLY_ERRORS[key] as {
|
|
type: string;
|
|
args?: Record<string, any>;
|
|
message: string | ((args: any) => string);
|
|
};
|
|
|
|
en[`error.${key.toUpperCase()}`] =
|
|
typeof def.message === 'string'
|
|
? def.message
|
|
: def.message(
|
|
Object.keys(def.args ?? {}).reduce(
|
|
(args, key) => {
|
|
args[key] = `{{${key}}}`;
|
|
return args;
|
|
},
|
|
{} as Record<string, string>
|
|
)
|
|
);
|
|
}
|
|
|
|
writeResource('en', en);
|
|
}
|
|
|
|
await appendErrorI18n();
|
|
i18nnext();
|
|
calcCompletenesses();
|