fix(i18n): complete prompt v4 pipeline path

This commit is contained in:
Tianyi Cui
2026-07-23 22:41:53 +08:00
parent db99f6881d
commit caaf4f8d18
13 changed files with 361 additions and 27 deletions

View File

@@ -3,11 +3,14 @@
import { readFileSync } from 'node:fs'
import { join, resolve } from 'node:path'
import {
consumeTranslationResponse,
documentedTranslationPromptPlaceholders,
parseTranslationResponse,
renderTranslationPrompt,
renderTranslationRequest,
renderTranslationResponse,
TRANSLATION_PROMPT_PLACEHOLDERS,
type TranslationExample,
} from './translation-prompt.ts'
const root = resolve(import.meta.dirname, '..')
@@ -17,15 +20,38 @@ function read(path: string): string {
}
try {
const mode = process.argv[2]
if (mode !== undefined && mode !== '--snapshot') throw new Error(`unsupported argument ${JSON.stringify(mode)}`)
const document = read('docs/i18n/translation-prompt.md')
const terminology = read('docs/i18n/terminology.md')
const examplePaths = [
['README.md', 'README.zh.md'],
['docs/development.md', 'docs/development.zh.md'],
['docs/i18n/README.md', 'docs/i18n/README.zh.md'],
['docs/i18n/translation-rules.md', 'docs/i18n/translation-rules.zh.md'],
[
'.agents/notes/implemented/process/2026-07-02-bilingual-docs-and-pairing-gate.md',
'.agents/notes/implemented/process/2026-07-02-bilingual-docs-and-pairing-gate.zh.md',
],
] as const
const examples: TranslationExample[] = examplePaths.map(([english, chinese]) => ({
english: read(english),
chinese: read(chinese),
}))
const sourceDocument = read('scripts/fixtures/translation-prompt/snapshot-note.md')
const recordedResponse = read('scripts/fixtures/translation-prompt/response.txt')
const documented = documentedTranslationPromptPlaceholders(document)
if (documented.join('\n') !== TRANSLATION_PROMPT_PLACEHOLDERS.join('\n')) {
throw new Error(`placeholder table must list exactly: ${TRANSLATION_PROMPT_PLACEHOLDERS.join(', ')}`)
}
const englishSource = renderTranslationPrompt(document, { sourceLanguage: 'English', terminology })
const chineseSource = renderTranslationPrompt(document, { sourceLanguage: 'Chinese', terminology })
const englishInput = { sourceLanguage: 'English' as const, sourceFilename: 'snapshot-note.md', terminology }
const englishSource = renderTranslationPrompt(document, englishInput)
const chineseSource = renderTranslationPrompt(document, {
sourceLanguage: 'Chinese',
sourceFilename: 'snapshot-note.zh.md',
terminology,
})
if (englishSource.includes('{{') || chineseSource.includes('{{')) throw new Error('rendered prompt contains an unresolved placeholder')
if (!englishSource.includes('from English to Chinese')) throw new Error('English-source render does not translate into Chinese')
if (!chineseSource.includes('from Chinese to English')) throw new Error('Chinese-source render does not translate into English')
@@ -38,7 +64,22 @@ try {
const parsed = parseTranslationResponse(renderTranslationResponse(roundTrip))
if (JSON.stringify(parsed) !== JSON.stringify(roundTrip)) throw new Error('three-section response does not round-trip')
console.log('verify-translation-prompt: both directions render and the three-section response contract parses.')
const request = renderTranslationRequest(document, { ...englishInput, sourceDocument, examples })
if (request.targetFilename !== 'snapshot-note.zh.md') throw new Error('English request resolves the wrong target filename')
const expectedRoles = ['system', ...examples.flatMap(() => ['user', 'assistant']), 'user']
if (request.messages.map(message => message.role).join('\n') !== expectedRoles.join('\n')) {
throw new Error('reviewed examples are not assembled as system, example pairs, then source')
}
const consumed = consumeTranslationResponse(recordedResponse, englishInput)
if (consumed.final.split('\n')[2] !== '[English](snapshot-note.md) | 中文') {
throw new Error('recorded new-pair response does not receive the canonical target switcher')
}
if (mode === '--snapshot') {
process.stdout.write(`${JSON.stringify({ request, response: consumed }, null, 2)}\n`)
} else {
console.log('verify-translation-prompt: both directions render, reviewed examples assemble, and the consumed response is target-path correct.')
}
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
console.error(`verify-translation-prompt: ${message}`)