docs(scripts): translate comments and error messages to english

Update documentation and error messages in i18n-related scripts from Chinese to English to improve codebase accessibility for international teams.
This commit is contained in:
icarus 2025-10-23 12:25:14 +08:00
parent 16a69e240b
commit 7365c1ca1a
2 changed files with 45 additions and 42 deletions

View File

@ -1,5 +1,6 @@
/**
* baseLocale以外的文本[to be translated]
* This script is used for automatic translation of all text except baseLocale.
* Text to be translated must start with [to be translated]
*
*/
import OpenAI from '@cherrystudio/openai'
@ -72,10 +73,10 @@ const translate = async (systemPrompt: string) => {
}
/**
*
* @param originObj -
* @param systemPrompt -
* @returns
* Recursively translate string values in objects
* @param originObj - Original internationalization object
* @param systemPrompt - System prompt
* @returns Translated new object
*/
const translateRecursively = async (originObj: I18N, systemPrompt: string): Promise<I18N> => {
const newObj = {}
@ -90,7 +91,7 @@ const translateRecursively = async (originObj: I18N, systemPrompt: string): Prom
newObj[key] = result
} catch (e) {
newObj[key] = text
console.error('translate failed.', text)
console.error('Translation failed.', text)
}
} else {
newObj[key] = text
@ -131,7 +132,7 @@ const main = async () => {
const fileContent = fs.readFileSync(filePath, 'utf-8')
targetJson = JSON.parse(fileContent)
} catch (error) {
console.error(`解析 ${filename} 出错,跳过此文件。`, error)
console.error(`Error parsing ${filename}, skipping this file.`, error)
continue
}
const systemPrompt = PROMPT.replace('{{target_language}}', languageMap[filename])
@ -142,9 +143,9 @@ const main = async () => {
try {
fs.writeFileSync(filePath, JSON.stringify(result, null, 2) + '\n', 'utf-8')
console.log(`文件 ${filename} 已翻译完毕`)
console.log(`File ${filename} translation completed`)
} catch (error) {
console.error(`写入 ${filename} 出错。${error}`)
console.error(`Error writing ${filename}. ${error}`)
}
}
bar.stop()

View File

@ -12,39 +12,41 @@ type I18NValue = string | { [key: string]: I18NValue }
type I18N = { [key: string]: I18NValue }
/**
*
* 1.
* 2.
* 3.
* Recursively check and synchronize the key-value structure of target object with template object
* 1. If target object is missing keys from template object, throw error
* 2. If target object has keys that don't exist in template object, throw error
* 3. For nested objects, recursively perform synchronization operation
*
*
* 便
* This function ensures all translation files maintain completely consistent key-value structure
* with the base template (usually the base translation file).
* Any structural differences will cause errors to be thrown for timely detection and fixing
* of translation file issues.
*
* @param target
* @param template
* @throws {Error}
* @param target The target translation object to check
* @param template The template object used as base (usually the base translation file)
* @throws {Error} Thrown when key-value structure mismatch is found
*/
function checkRecursively(target: I18N, template: I18N): void {
for (const key in template) {
if (!(key in target)) {
throw new Error(`缺少属性 ${key}`)
throw new Error(`Missing property ${key}`)
}
if (key.includes('.')) {
throw new Error(`应该使用严格嵌套结构 ${key}`)
throw new Error(`Should use strict nested structure for key ${key}`)
}
if (typeof template[key] === 'object' && template[key] !== null) {
if (typeof target[key] !== 'object' || target[key] === null) {
throw new Error(`属性 ${key} 不是对象`)
throw new Error(`Property ${key} is not an object`)
}
// 递归检查子对象
// Recursively check child objects
checkRecursively(target[key], template[key])
}
}
// 删除 target 中存在但 template 中没有的 key
// Remove keys that exist in target but not in template
for (const targetKey in target) {
if (!(targetKey in template)) {
throw new Error(`多余属性 ${targetKey}`)
throw new Error(`Extra property ${targetKey}`)
}
}
}
@ -56,9 +58,9 @@ function isSortedI18N(obj: I18N): boolean {
}
/**
* JSON
* @param obj
* @returns
* Check for duplicate keys in JSON object and collect all duplicate keys
* @param obj The object to check
* @returns Array of duplicate keys (returns empty array if no duplicates)
*/
function checkDuplicateKeys(obj: I18N): string[] {
const keys = new Set<string>()
@ -69,7 +71,7 @@ function checkDuplicateKeys(obj: I18N): string[] {
const fullPath = path ? `${path}.${key}` : key
if (keys.has(fullPath)) {
// 发现重复键时,添加到数组中(避免重复添加)
// When duplicate key is found, add to array (avoid duplicate additions)
if (!duplicateKeys.includes(fullPath)) {
duplicateKeys.push(fullPath)
}
@ -77,7 +79,7 @@ function checkDuplicateKeys(obj: I18N): string[] {
keys.add(fullPath)
}
// 递归检查子对象
// Recursively check child objects
if (typeof obj[key] === 'object' && obj[key] !== null) {
checkObject(obj[key], fullPath)
}
@ -90,7 +92,7 @@ function checkDuplicateKeys(obj: I18N): string[] {
function checkTranslations() {
if (!fs.existsSync(baseFilePath)) {
throw new Error(`主模板文件 ${baseFileName} 不存在,请检查路径或文件名`)
throw new Error(`Base template file ${baseFileName} does not exist, please check path or filename`)
}
const baseContent = fs.readFileSync(baseFilePath, 'utf-8')
@ -98,23 +100,23 @@ function checkTranslations() {
try {
baseJson = JSON.parse(baseContent)
} catch (error) {
throw new Error(`解析 ${baseFileName} 出错。${error}`)
throw new Error(`Error parsing ${baseFileName}. ${error}`)
}
// 检查主模板是否存在重复键
// Check if base template has duplicate keys
const duplicateKeys = checkDuplicateKeys(baseJson)
if (duplicateKeys.length > 0) {
throw new Error(`主模板文件 ${baseFileName} 存在以下重复键:\n${duplicateKeys.join('\n')}`)
throw new Error(`Base template file ${baseFileName} has the following duplicate keys:\n${duplicateKeys.join('\n')}`)
}
// 检查主模板是否有序
// Check if base template is sorted
if (!isSortedI18N(baseJson)) {
throw new Error(`主模板文件 ${baseFileName} 的键值未按字典序排序。`)
throw new Error(`Base template file ${baseFileName} keys are not sorted in dictionary order.`)
}
const files = fs.readdirSync(translationsDir).filter((file) => file.endsWith('.json') && file !== baseFileName)
// 同步键
// Sync keys
for (const file of files) {
const filePath = path.join(translationsDir, file)
let targetJson: I18N = {}
@ -122,19 +124,19 @@ function checkTranslations() {
const fileContent = fs.readFileSync(filePath, 'utf-8')
targetJson = JSON.parse(fileContent)
} catch (error) {
throw new Error(`解析 ${file} 出错。`)
throw new Error(`Error parsing ${file}.`)
}
// 检查有序性
// Check if sorted
if (!isSortedI18N(targetJson)) {
throw new Error(`翻译文件 ${file} 的键值未按字典序排序。`)
throw new Error(`Translation file ${file} keys are not sorted.`)
}
try {
checkRecursively(targetJson, baseJson)
} catch (e) {
console.error(e)
throw new Error(`在检查 ${filePath} 时出错`)
throw new Error(`Error while checking ${filePath}`)
}
}
}
@ -142,10 +144,10 @@ function checkTranslations() {
export function main() {
try {
checkTranslations()
console.log('i18n 检查已通过')
console.log('i18n check passed')
} catch (e) {
console.error(e)
throw new Error(`检查未通过。尝试运行 yarn sync:i18n 以解决问题。`)
throw new Error(`Check failed. Try running yarn i18n:sync to fix the issue.`)
}
}