Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
locale-json: src/locales/en.json src/locales/zh-cn.json
locale-json:
node_modules/.bin/tsx scripts/generate-locale-json.ts

locale-json-watch:
watch make locale-json
Expand All @@ -9,11 +10,4 @@ format:
build: .PHONY
npm run build

src/locales/en.json: src/locales/messages.yaml
node_modules/.bin/tsx scripts/generate-locale-json.ts

src/locales/zh-cn.json: src/locales/messages.yaml
node_modules/.bin/tsx scripts/generate-locale-json.ts


.PHONY:
232 changes: 231 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
"@fortawesome/react-fontawesome": "^0.1.19",
"@jokester/ts-commonutil": "^0.6.1",
"@reduxjs/toolkit": "^1.9.7",
"@xsai-ext/providers-cloud": "^0.4.0-beta.2",
"@xsai/generate-object": "^0.4.0-beta.2",
"@zip.js/zip.js": "^2.7.60",
"antd": "^4.24.16",
"antd-img-crop": "^3.16.0",
Expand Down Expand Up @@ -43,7 +45,10 @@
"redux-saga": "^1.3.0",
"store": "^2.0.12",
"use-debounce": "^10.0.4",
"uuid": "^7.0.3"
"uuid": "^7.0.3",
"xsai": "^0.4.0-beta.2",
"zod": "^3.25.76",
"zod-to-json-schema": "^3.24.6"
},
"scripts": {
"build": "vite build",
Expand Down
38 changes: 26 additions & 12 deletions scripts/generate-locale-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@ import yaml from 'js-yaml';
const assetDir = path.join(__dirname, '../src/locales');
const messageYaml = path.join(assetDir, 'messages.yaml');
Comment on lines 5 to 6

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 Analysis chain

Confirm module system for __dirname usage

This script relies on CommonJS (__dirname). If the repo uses ESM for scripts, this will throw at runtime.

Run:


🏁 Script executed:

#!/bin/bash
# Verify TS module target and any Node ESM flags
rg -nP '"module"\s*:\s*"(commonjs|esnext|nodenext)"' tsconfig*.json -n -C2
rg -nP 'type\s*:\s*"module"' package.json -n -C2

Length of output: 166


Fix ESM __dirname usage (scripts/generate-locale-json.ts)

tsconfig*.json sets "module": "esnext", so __dirname (CommonJS) will be undefined when this script runs. Update the script or build config.

  • Location: scripts/generate-locale-json.ts (lines 5–6)
const assetDir = path.join(__dirname, '../src/locales');
const messageYaml = path.join(assetDir, 'messages.yaml');
  • Fix options (choose one):
    • Use ESM-safe code: import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename);
    • Or ensure the script is executed/compiled as CommonJS (e.g., set TS module to "commonjs" for scripts or run with a CommonJS runtime).
🤖 Prompt for AI Agents
In scripts/generate-locale-json.ts around lines 5 to 6, the script uses
__dirname which is undefined under ES modules; replace the CommonJS-specific
__dirname usage with an ESM-safe approach: derive __filename from
import.meta.url via fileURLToPath and then compute __dirname with
path.dirname(__filename), or alternatively ensure this script is run/compiled as
CommonJS (e.g., set module to "commonjs" for scripts or run with a CommonJS node
runtime); update the path.join calls to use the computed ESM __dirname
equivalent so messageYaml resolves correctly.


/**
* yield [path, message] pairs
*/
function* extractPathedMessages(obj: object, locale: string, pathPrefix: readonly string[] = []): Generator<[string, string]> {
for (const [key, value] of Object.entries(obj)) {
if (typeof value === 'object' && value) {
yield* extractPathedMessages(value, locale, [...pathPrefix, key]);
} else if (typeof value === 'string') {
if (key === locale) yield [pathPrefix.join('.'), value];
} else {
throw new Error(`unexpected value type at ${[...pathPrefix, key].join('.')}: ${typeof value}`);
}
}
}

const lang2Basename = Object.entries({
zhCn: 'zh-cn.json',
en: 'en.json',
})

setTimeout(async function main() {
/**
* key => locale => message
Expand All @@ -13,22 +33,16 @@ setTimeout(async function main() {
await fsp.readFile(messageYaml, { encoding: 'utf-8' }),
) as Record<string, Record<string, string>>;

for (const [locale, basename] of Object.entries({
zhCn: 'zh-cn.json',
en: 'en.json',
})) {
const path2count: Record<string, number> = {};
for (const [locale, basename] of lang2Basename ) {
/**
* key => message
*/
const value: Record<string, string> = {};
Object.keys(messages).forEach((messageKey) => {
const msg = (value[messageKey] = messages[messageKey][locale]);
if (!msg) {
throw new Error(
`translated message not found for key=${messageKey} / locale=${locale}`,
);
}
});
for(const [path, msg] of extractPathedMessages(messages, locale)) {
path2count[path] = (path2count[path] ?? 0) + 1;
value[path] = msg;
}
const dest = path.join(assetDir, basename);
await fsp.writeFile(dest, JSON.stringify(value, null, 2));
console.info(`written to ${dest}`);
Expand Down
Loading
Loading