36 lines
2.9 KiB
JavaScript
36 lines
2.9 KiB
JavaScript
// Select literal locale strings from previously exported REA evidence; never execute target scripts.
|
|
import fs from 'node:fs/promises'
|
|
import crypto from 'node:crypto'
|
|
import { parse } from '@babel/parser'
|
|
const bundle = JSON.parse(await fs.readFile('.tmp/rea-runtime-scripts.json', 'utf8'))
|
|
const script = bundle.items.find(item => item.file_path?.endsWith('i18n-Cxy1Uuvv.js'))
|
|
if (!script?.source?.included) throw new Error('Missing REA-captured conversation locale')
|
|
const source = script.source.artifact.text
|
|
const hash = crypto.createHash('sha256').update(source).digest('hex')
|
|
if (hash !== script.source.artifact.sha256) throw new Error('REA source digest mismatch')
|
|
const literal = node => node?.type === 'StringLiteral' ? node.value : node?.type === 'TemplateLiteral' && node.expressions.length === 0 ? node.quasis[0].value.cooked : undefined
|
|
const objects = []
|
|
function visit(node) {
|
|
if (!node || typeof node !== 'object') return
|
|
if (node.type === 'ObjectExpression') {
|
|
const values = Object.fromEntries(node.properties.filter(p => p.type === 'ObjectProperty' && typeof p.key.value === 'string' && literal(p.value) !== undefined).map(p => [p.key.value, literal(p.value)]))
|
|
if (values['task.creating']) objects.push(values)
|
|
}
|
|
for (const value of Object.values(node)) {
|
|
if (Array.isArray(value)) value.forEach(visit)
|
|
else if (value && typeof value === 'object') visit(value)
|
|
}
|
|
}
|
|
visit(parse(source, { sourceType: 'module' }).program)
|
|
const chinese = objects.find(values => values['task.creating'] === '正在创建任务')
|
|
const english = objects.find(values => values['task.creating'] === 'Creating task')
|
|
if (!chinese || !english) throw new Error('Selected literal locale dictionaries not found')
|
|
const wanted = key => /^(tool\.planCreate\.|tool\.task\.|task\.|action\.(accept|reject)$|message\.loading\.thinking$|common\.loading$)/.test(key)
|
|
const zh = Object.fromEntries(Object.entries(chinese).filter(([key]) => wanted(key)))
|
|
const en = Object.fromEntries(Object.entries(english).filter(([key]) => wanted(key)))
|
|
const file = 'src/renderer/src/workbuddy/conversation/labels.ts'
|
|
const header = `// Generated from REA ${bundle.evidence_id}.\n// i18n-Cxy1Uuvv.js SHA-256 ${hash}.\n// Default zh-cn matches the captured package default and YCode's current Chinese interface.\n`
|
|
const text = header + `const zhCN = ${JSON.stringify(zh, null, 2)} as const\nconst en = ${JSON.stringify(en, null, 2)} as const\n\nexport function conversationLabel(key: keyof typeof zhCN, params: Record<string, string | number> = {}, locale: 'zh-cn' | 'en' = 'zh-cn'): string {\n const dictionary = locale === 'en' ? en : zhCN\n return dictionary[key].replace(/\\{([^{}]+)\\}/g, (match, name: string) => params[name] === undefined ? match : String(params[name]))\n}\n`
|
|
await fs.writeFile(file, text)
|
|
console.log(JSON.stringify({ file, evidence: bundle.evidence_id, sourceSha256: hash, keys: Object.keys(zh).length }))
|