chore: turn cn comment to en for common space (#376)

This commit is contained in:
tecvan
2025-07-31 12:42:03 +08:00
committed by GitHub
parent f7d73cd391
commit a1f3a9aead
40 changed files with 390 additions and 390 deletions

View File

@@ -10,7 +10,7 @@ import { getCommentPatterns } from '../utils/language';
import { containsChinese, cleanCommentText } from '../utils/chinese';
/**
* 检查指定位置是否在字符串字面量内部
* Checks if the specified location is inside a string literal
*/
const isInsideStringLiteral = (line: string, position: number): boolean => {
let insideDoubleQuote = false;
@@ -44,7 +44,7 @@ const isInsideStringLiteral = (line: string, position: number): boolean => {
};
/**
* 解析单行注释
* Parsing single-line comments
*/
const parseSingleLineComments = (
content: string,
@@ -54,34 +54,34 @@ const parseSingleLineComments = (
const comments: ParsedComment[] = [];
const lines = content.split('\n');
// 添加安全检查
const maxLines = 5000; // 降低到5000行
// Add a security check
const maxLines = 5000; // Down to 5000 lines
if (lines.length > maxLines) {
console.warn(`⚠️ 文件行数过多 (${lines.length}行),跳过单行注释解析`);
return comments;
}
lines.forEach((line, index) => {
pattern.lastIndex = 0; // 重置正则表达式索引
pattern.lastIndex = 0; // Reset regular expression index
let match: RegExpExecArray | null;
// 查找所有匹配,但只保留不在字符串内的
// Find all matches, but keep only those not in the string
let matchCount = 0;
const maxMatches = 100; // 限制每行最多匹配100次
const maxMatches = 100; // Limit each line to a maximum of 100 matches
let lastIndex = 0;
while ((match = pattern.exec(line)) !== null) {
// 防止无限循环的多重保护
// Multiple protections against infinite loops
matchCount++;
if (matchCount > maxMatches) {
console.warn(`⚠️ 单行匹配次数过多,中断处理: ${line.substring(0, 50)}...`);
break;
}
// 检查 lastIndex 是否前进,防止无限循环
// Check if lastIndex is advancing to prevent an infinite loop
if (pattern.global) {
if (pattern.lastIndex <= lastIndex) {
// 如果 lastIndex 没有前进,手动前进一位避免无限循环
// If lastIndex does not advance, manually advance one bit to avoid infinite loops
pattern.lastIndex = lastIndex + 1;
if (pattern.lastIndex >= line.length) {
break;
@@ -93,9 +93,9 @@ const parseSingleLineComments = (
if (match[1]) {
const commentContent = match[1];
let commentStartIndex = match.index!;
let commentLength = 2; // 默认为 //
let commentLength = 2; // Default is//
// 根据语言确定注释符号
// Determine annotation symbols based on language
if (
language === 'yaml' ||
language === 'toml' ||
@@ -104,9 +104,9 @@ const parseSingleLineComments = (
language === 'ruby'
) {
commentStartIndex = line.indexOf('#', match.index!);
commentLength = 1; // # 长度为 1
commentLength = 1; // #length is 1
} else if (language === 'ini') {
// INI 文件可能使用 # 或 ;
// INI files may use #or;
const hashIndex = line.indexOf('#', match.index!);
const semicolonIndex = line.indexOf(';', match.index!);
if (
@@ -120,7 +120,7 @@ const parseSingleLineComments = (
commentLength = 1;
}
} else if (language === 'php') {
// PHP 可能使用 // 或 #
// PHP may use//or #
const slashIndex = line.indexOf('//', match.index!);
const hashIndex = line.indexOf('#', match.index!);
if (slashIndex >= 0 && (hashIndex < 0 || slashIndex < hashIndex)) {
@@ -139,7 +139,7 @@ const parseSingleLineComments = (
const startColumn = commentStartIndex;
const endColumn = startColumn + commentLength + commentContent.length;
// 检查注释开始位置是否在字符串内部
// Check if the comment starts inside the string
if (
commentStartIndex >= 0 &&
!isInsideStringLiteral(line, commentStartIndex)
@@ -155,7 +155,7 @@ const parseSingleLineComments = (
}
}
// 防止无限循环
// Prevent infinite loops
if (!pattern.global) break;
}
});
@@ -164,7 +164,7 @@ const parseSingleLineComments = (
};
/**
* 解析多行注释
* Parse multiline comments
*/
const parseMultiLineComments = (
content: string,
@@ -177,21 +177,21 @@ const parseMultiLineComments = (
let commentStart: { line: number; column: number } | null = null;
let commentLines: string[] = [];
// 添加安全检查
const maxLines = 5000; // 降低到5000行
// Add a security check
const maxLines = 5000; // Down to 5000 lines
if (lines.length > maxLines) {
console.warn(`⚠️ 文件行数过多 (${lines.length}行),跳过多行注释解析`);
return comments;
}
// 添加处理计数器,防止无限循环
// Add processing counters to prevent infinite loops
let processedLines = 0;
const maxProcessedLines = 10000;
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
const line = lines[lineIndex];
// 防止无限处理
// Prevent unlimited processing
processedLines++;
if (processedLines > maxProcessedLines) {
console.warn(`⚠️ 处理行数超限,中断解析`);
@@ -206,12 +206,12 @@ const parseMultiLineComments = (
inComment = true;
commentStart = { line: lineIndex + 1, column: startMatch.index! };
// 检查是否在同一行结束
// Check if they end on the same line
endPattern.lastIndex = startMatch.index! + startMatch[0].length;
const endMatch = endPattern.exec(line);
if (endMatch) {
// 单行多行注释
// single-line multi-line comment
const commentContent = line.substring(
startMatch.index! + startMatch[0].length,
endMatch.index!,
@@ -229,7 +229,7 @@ const parseMultiLineComments = (
inComment = false;
commentStart = null;
} else {
// 多行注释开始
// Start with a multi-line comment
const commentContent = line.substring(
startMatch.index! + startMatch[0].length,
);
@@ -237,12 +237,12 @@ const parseMultiLineComments = (
}
}
} else {
// 在多行注释中
// In a multi-line comment
endPattern.lastIndex = 0;
const endMatch = endPattern.exec(line);
if (endMatch) {
// 多行注释结束
// End of multiline comment
const commentContent = line.substring(0, endMatch.index!);
commentLines.push(commentContent);
@@ -260,7 +260,7 @@ const parseMultiLineComments = (
commentStart = null;
commentLines = [];
} else {
// 继续多行注释
// Continue with multi-line comments
commentLines.push(line);
}
}
@@ -270,7 +270,7 @@ const parseMultiLineComments = (
};
/**
* 解析文件中的所有注释
* Parse all comments in the file
*/
export const parseComments = (file: SourceFile): ParsedComment[] => {
const patterns = getCommentPatterns(file.language);
@@ -291,7 +291,7 @@ export const parseComments = (file: SourceFile): ParsedComment[] => {
};
/**
* 过滤包含中文的注释,对多行注释进行逐行处理
* Filter comments containing Chinese and process multi-line comments line by line
*/
export const filterChineseComments = (
comments: ParsedComment[],
@@ -301,11 +301,11 @@ export const filterChineseComments = (
for (const comment of comments) {
if (comment.type === 'multi-line' && comment.content.includes('\n')) {
// 多行注释:逐行处理
// Multi-line comments: line-by-line processing
const multiLineResults = processMultiLineCommentForChinese(comment, language);
result.push(...multiLineResults);
} else if (containsChinese(comment.content)) {
// 单行注释或单行多行注释
// Single-line comments or single-line multi-line comments
result.push({
...comment,
content: cleanCommentText(
@@ -321,7 +321,7 @@ export const filterChineseComments = (
};
/**
* 处理多行注释,提取含中文的行作为独立的注释单元
* Processing multi-line comments, extracting lines containing Chinese as independent comment units
*/
const processMultiLineCommentForChinese = (
comment: ParsedComment,
@@ -334,18 +334,18 @@ const processMultiLineCommentForChinese = (
const cleanedLine = cleanCommentText(line, 'multi-line', language);
if (containsChinese(cleanedLine)) {
// 计算这一行在原始文件中的位置
// Calculate the position of this line in the original file
const actualLineNumber = comment.startLine + lineIndex;
// 创建一个表示这一行的注释对象
// Create a comment object representing this line
const lineComment: ChineseComment = {
content: cleanedLine,
startLine: actualLineNumber,
endLine: actualLineNumber,
startColumn: 0, // 这个值需要更精确计算但对于多行注释内的行处理暂时用0
startColumn: 0, // This value needs to be calculated more precisely, but for line processing within a multi-line comment, use 0 for the time being.
endColumn: line.length,
type: 'multi-line',
// 添加多行注释的元数据,用于后续处理
// Add metadata with multi-line comments for subsequent processing
multiLineContext: {
isPartOfMultiLine: true,
originalComment: comment,
@@ -362,11 +362,11 @@ const processMultiLineCommentForChinese = (
};
/**
* 检测文件中的中文注释
* Detect Chinese comments in files
*/
export const detectChineseInFile = (file: SourceFile): ChineseComment[] => {
try {
// 简单防护:跳过大文件
// Simple protection: skipping large files
if (file.content.length > 500000) {
// 500KB
console.warn(
@@ -375,7 +375,7 @@ export const detectChineseInFile = (file: SourceFile): ChineseComment[] => {
return [];
}
// 简单防护:跳过行数过多的文件
// Simple protection: skip files with too many lines
const lines = file.content.split('\n');
if (lines.length > 10000) {
console.warn(`⚠️ 跳过多行文件: ${file.path} (${lines.length} 行)`);
@@ -391,7 +391,7 @@ export const detectChineseInFile = (file: SourceFile): ChineseComment[] => {
};
/**
* 批量检测多个文件中的中文注释
* Batch detection of Chinese comments in multiple files
*/
export const detectChineseInFiles = (files: SourceFile[]): FileWithComments[] => {
const results: FileWithComments[] = [];
@@ -417,7 +417,7 @@ export const detectChineseInFiles = (files: SourceFile[]): FileWithComments[] =>
);
} catch (error) {
console.error(`❌ 处理文件失败: ${fileName} - ${error}`);
// 继续处理其他文件
// Continue working on other documents
continue;
}
}
@@ -426,7 +426,7 @@ export const detectChineseInFiles = (files: SourceFile[]): FileWithComments[] =>
};
/**
* 获取注释统计信息
* Get annotation statistics
*/
export const getCommentStats = (files: SourceFile[]): {
totalFiles: number;

View File

@@ -9,14 +9,14 @@ import { tryCatch } from '../utils/fp';
/**
* 检查字符串是否包含中文字符
* Check if string contains Chinese characters
*/
const containsChinese = (text: string): boolean => {
return /[\u4e00-\u9fff]/.test(text);
};
/**
* 保持注释的原始格式,支持逐行翻译多行注释
* Maintain the original format of comments and support line-by-line translation of multi-line comments
*/
export const preserveCommentFormat = (
originalComment: string,
@@ -24,7 +24,7 @@ export const preserveCommentFormat = (
commentType: 'single-line' | 'multi-line',
): string => {
if (commentType === 'single-line') {
// 保持单行注释的前缀空格和注释符 - 支持多种语言
// Keep single-line comments prefixed with spaces and comment characters - supports multiple languages
let match = originalComment.match(/^(\s*\/\/\s*)/); // JavaScript/TypeScript style
if (match) {
return match[1] + translatedComment.trim();
@@ -40,13 +40,13 @@ export const preserveCommentFormat = (
return match[1] + translatedComment.trim();
}
// 如果无法识别,尝试从原始内容推断
// If not recognized, try to infer from the original content
if (originalComment.includes('#')) {
const hashMatch = originalComment.match(/^(\s*#\s*)/);
return (hashMatch ? hashMatch[1] : '# ') + translatedComment.trim();
}
// 默认使用 JavaScript 风格
// JavaScript style is used by default
return '// ' + translatedComment.trim();
}
@@ -54,7 +54,7 @@ export const preserveCommentFormat = (
const lines = originalComment.split('\n');
if (lines.length === 1) {
// 单行多行注释 /* ... *//** ... */
// Single-line multi-line comment/*... */or/**... */
const startMatch = originalComment.match(/^(\s*\/\*\*?\s*)/);
const endMatch = originalComment.match(/(\s*\*\/\s*)$/);
@@ -71,7 +71,7 @@ export const preserveCommentFormat = (
return prefix + translatedComment.trim() + suffix;
} else {
// 多行注释 - 需要逐行处理
// Multi-line comments - requires line-by-line processing
return processMultiLineComment(originalComment, translatedComment);
}
}
@@ -80,7 +80,7 @@ export const preserveCommentFormat = (
};
/**
* 处理多行注释,逐行翻译含中文的行,保持其他行原样
* Process multi-line comments, translate lines containing Chinese line by line, and keep other lines as they are
*/
export const processMultiLineComment = (
originalComment: string,
@@ -88,54 +88,54 @@ export const processMultiLineComment = (
): string => {
const originalLines = originalComment.split('\n');
// 提取每行的注释内容(去除 /** * 等前缀)
// Extract comments for each line (remove prefixes such as /** * )other prefixes)
const extractedLines = originalLines.map(line => {
// 匹配不同类型的注释行
Match different types of comment linesifferent types of comment lines
if (line.match(/^\s*\/\*\*?\s*/)) {
// 开始行: /** /*
// Start line:/** or/*
return { prefix: line.match(/^\s*\/\*\*?\s*/)![0], content: line.replace(/^\s*\/\*\*?\s*/, '') };
} else if (line.match(/^\s*\*\/\s*$/)) {
// 结束行: */
// End line: */
return { prefix: line.match(/^\s*\*\/\s*$/)![0], content: '' };
} else if (line.match(/^\s*\*\s*/)) {
// 中间行: * content
// Middle line: * content
const match = line.match(/^(\s*\*\s*)(.*)/);
return { prefix: match![1], content: match![2] };
} else {
// 其他情况
// Other situations
return { prefix: '', content: line };
}
});
// 收集需要翻译的行
// Collect lines that need to be translated
const linesToTranslate = extractedLines
.map((line, index) => ({ index, content: line.content }))
.filter(item => containsChinese(item.content));
// 如果没有中文内容,返回原始注释
// If there is no Chinese content, return the original comment
if (linesToTranslate.length === 0) {
return originalComment;
}
// 解析翻译结果 - 假设翻译服务按顺序返回翻译后的行
// Parse translation results - assuming the translation service returns translated rows in order
const translatedLines = translatedContent.split('\n');
const translations = new Map<number, string>();
// 将翻译结果映射到对应的行
// Map the translation result to the corresponding line
linesToTranslate.forEach((item, transIndex) => {
if (transIndex < translatedLines.length) {
translations.set(item.index, translatedLines[transIndex].trim());
}
});
// 重建注释,保持原始结构
// Rebuild the annotation, maintaining the original structure
return extractedLines
.map((line, index) => {
if (translations.has(index)) {
// 使用翻译内容,保持原始前缀
// Use translated content, keeping the original prefix
return line.prefix + translations.get(index);
} else {
// 保持原样
// Leave it as it is
return originalLines[index];
}
})
@@ -143,7 +143,7 @@ export const processMultiLineComment = (
};
/**
* 创建替换操作
* Create replacement operation
*/
export const createReplacements = (
file: SourceFile,
@@ -157,13 +157,13 @@ export const createReplacements = (
if (!translation) return;
if (comment.multiLineContext?.isPartOfMultiLine) {
// 处理多行注释中的单行
// Handling single lines in multi-line comments
const replacement = createMultiLineReplacement(file, comment, translation);
if (replacement) {
replacements.push(replacement);
}
} else {
// 处理普通注释(单行注释或整个多行注释)
// Processing normal comments (single-line comments or entire multi-line comments)
const replacement = createRegularReplacement(file, comment, translation);
if (replacement) {
replacements.push(replacement);
@@ -175,7 +175,7 @@ export const createReplacements = (
};
/**
* 为多行注释中的单行创建替换操作
* Create a replacement operation for a single line in a multi-line comment
*/
const createMultiLineReplacement = (
file: SourceFile,
@@ -189,10 +189,10 @@ const createMultiLineReplacement = (
const originalLine = lines[lineIndex];
// 查找这一行中中文内容的位置
// Find the location of Chinese content in this line
const cleanedContent = comment.content;
// 更精确地查找中文内容在原始行中的位置
// Find the position of Chinese content in the original line more accurately
const commentContentRegex = new RegExp(cleanedContent.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
const contentMatch = originalLine.match(commentContentRegex);
@@ -203,7 +203,7 @@ const createMultiLineReplacement = (
const chineseStart = contentMatch.index!;
const chineseEnd = chineseStart + contentMatch[0].length;
// 计算在整个文件中的位置
// Calculate the position in the entire file
let start = 0;
for (let i = 0; i < lineIndex; i++) {
start += lines[i].length + 1; // +1 for newline
@@ -221,7 +221,7 @@ const createMultiLineReplacement = (
};
/**
* 为普通注释创建替换操作
* Create a replacement operation for a normal comment
*/
const createRegularReplacement = (
file: SourceFile,
@@ -232,7 +232,7 @@ const createRegularReplacement = (
const startLineIndex = comment.startLine - 1;
const endLineIndex = comment.endLine - 1;
// 计算原始注释在文件中的精确位置
// Calculate the exact location of the original comment in the file
let start = 0;
for (let i = 0; i < startLineIndex; i++) {
start += lines[i].length + 1; // +1 for newline
@@ -241,10 +241,10 @@ const createRegularReplacement = (
let end = start;
if (comment.startLine === comment.endLine) {
// 同一行
// same line
end = start + (comment.endColumn - comment.startColumn);
} else {
// 跨行 - 重新计算end位置
// Interline recalculation of end position
end = 0;
for (let i = 0; i < endLineIndex; i++) {
end += lines[i].length + 1; // +1 for newline
@@ -252,10 +252,10 @@ const createRegularReplacement = (
end += comment.endColumn;
}
// 获取原始注释文本
// Get original comment text
const originalText = file.content.substring(start, end);
// 应用格式保持
// application format retention
const formattedTranslation = preserveCommentFormat(
originalText,
translation.translated,
@@ -271,13 +271,13 @@ const createRegularReplacement = (
};
/**
* 应用替换操作到文本内容
* Apply a replacement operation to text content
*/
export const applyReplacements = (
content: string,
replacements: Replacement[],
): string => {
// 按位置倒序排列,避免替换后位置偏移
// Arrange in reverse order to avoid position shift after replacement
const sortedReplacements = [...replacements].sort(
(a, b) => b.start - a.start,
);
@@ -294,7 +294,7 @@ export const applyReplacements = (
};
/**
* 替换文件中的注释
* Replace comments in the file
*/
export const replaceCommentsInFile = async (
file: SourceFile,
@@ -303,13 +303,13 @@ export const replaceCommentsInFile = async (
return tryCatch(async () => {
const fs = await import('fs/promises');
// 应用替换
// Application Replacement
const newContent = applyReplacements(
file.content,
operation.replacements,
);
// 写入文件
// Write file
await fs.writeFile(file.path, newContent, 'utf-8');
return { success: true };
@@ -329,7 +329,7 @@ export const replaceCommentsInFile = async (
};
/**
* 批量替换多个文件
* Batch replacement of multiple files
*/
export const batchReplaceFiles = async (
operations: ReplacementOperation[],
@@ -347,7 +347,7 @@ export const batchReplaceFiles = async (
const sourceFile: SourceFile = {
path: operation.file,
content,
language: 'other', // 临时值,实际应该检测
language: 'other', // Temporary value, which should actually be checked
};
const result = await replaceCommentsInFile(
@@ -375,7 +375,7 @@ export const batchReplaceFiles = async (
};
/**
* 验证替换操作
* Verify replacement operation
*/
export const validateReplacements = (
content: string,
@@ -383,7 +383,7 @@ export const validateReplacements = (
): { valid: boolean; errors: string[] } => {
const errors: string[] = [];
// 检查位置是否有效
// Check if the location is valid
replacements.forEach((replacement, index) => {
if (replacement.start < 0 || replacement.end > content.length) {
errors.push(`Replacement ${index}: Invalid position range`);
@@ -395,14 +395,14 @@ export const validateReplacements = (
);
}
// 检查原文是否匹配
// Check if the original text matches
const actualText = content.substring(replacement.start, replacement.end);
if (actualText !== replacement.original) {
errors.push(`Replacement ${index}: Original text mismatch`);
}
});
// 检查是否有重叠
// Check for overlap
const sortedReplacements = [...replacements].sort(
(a, b) => a.start - b.start,
);

View File

@@ -5,7 +5,7 @@ import { getGitTrackedFiles, getAllGitFiles } from '../utils/git';
import { tryCatch } from '../utils/fp';
/**
* 读取文件内容并创建SourceFile对象
* Read the file contents and create a SourceFile object
*/
export const readSourceFile = async (filePath: string): Promise<Result<SourceFile>> => {
return tryCatch(async () => {
@@ -21,7 +21,7 @@ export const readSourceFile = async (filePath: string): Promise<Result<SourceFil
};
/**
* 批量读取源文件
* Batch reading of source files
*/
export const readSourceFiles = async (filePaths: string[]): Promise<SourceFile[]> => {
const results = await Promise.allSettled(
@@ -36,13 +36,13 @@ export const readSourceFiles = async (filePaths: string[]): Promise<SourceFile[]
};
/**
* 获取Git仓库中的源码文件
* Get the source code file in the Git repository
*/
export const getSourceFiles = async (config: FileScanConfig): Promise<Result<string[]>> => {
const { root, extensions, includeUntracked } = config;
return tryCatch(async () => {
// 获取Git文件列表
// Get a list of Git files
const gitFilesResult = includeUntracked
? await getAllGitFiles(root)
: await getGitTrackedFiles(root);
@@ -53,10 +53,10 @@ export const getSourceFiles = async (config: FileScanConfig): Promise<Result<str
let files = gitFilesResult.data;
// 过滤文本文件
// Filter text files
files = files.filter(isTextFile);
// 根据扩展名过滤
// Filter by extension
files = filterFilesByExtensions(files, extensions);
return files;
@@ -64,7 +64,7 @@ export const getSourceFiles = async (config: FileScanConfig): Promise<Result<str
};
/**
* 扫描并读取所有源码文件
* Scan and read all source code files
*/
export const scanSourceFiles = async (config: FileScanConfig): Promise<Result<SourceFile[]>> => {
return tryCatch(async () => {
@@ -80,7 +80,7 @@ export const scanSourceFiles = async (config: FileScanConfig): Promise<Result<So
};
/**
* 检查文件是否存在且可读
* Check if the file exists and is readable
*/
export const isFileAccessible = async (filePath: string): Promise<boolean> => {
try {
@@ -92,7 +92,7 @@ export const isFileAccessible = async (filePath: string): Promise<boolean> => {
};
/**
* 获取文件统计信息
* Get file statistics
*/
export const getFileStats = async (filePaths: string[]): Promise<{
total: number;

View File

@@ -5,7 +5,7 @@ import {
} from '../types/index.js';
/**
* 报告收集器类
* report collector class
*/
export class ReportCollector {
private stats: ProcessingStats = {
@@ -21,7 +21,7 @@ export class ReportCollector {
private fileDetails: Map<string, FileProcessingDetail> = new Map();
/**
* 记录文件处理开始
* Record file processing begins
*/
recordFileStart(filePath: string): void {
this.stats.totalFiles++;
@@ -34,7 +34,7 @@ export class ReportCollector {
}
/**
* 记录文件处理完成
* Record file processing completed
*/
recordFileComplete(filePath: string, commentCount: number): void {
const detail = this.fileDetails.get(filePath);
@@ -48,7 +48,7 @@ export class ReportCollector {
}
/**
* 记录文件跳过
* log file skip
*/
recordFileSkipped(filePath: string, reason?: string): void {
const detail = this.fileDetails.get(filePath);
@@ -61,7 +61,7 @@ export class ReportCollector {
}
/**
* 记录处理错误
* Log processing errors
*/
recordError(filePath: string, error: Error): void {
const detail = this.fileDetails.get(filePath);
@@ -74,28 +74,28 @@ export class ReportCollector {
}
/**
* 完成统计
* Complete statistics
*/
finalize(): void {
this.stats.endTime = Date.now();
}
/**
* 获取统计信息
* Obtain statistical information
*/
getStats(): ProcessingStats {
return { ...this.stats };
}
/**
* 获取文件详情
* Get file details
*/
getFileDetails(): FileProcessingDetail[] {
return Array.from(this.fileDetails.values());
}
/**
* 生成完整报告
* Generate a full report
*/
generateReport(): ProcessingReport {
this.finalize();
@@ -109,7 +109,7 @@ export class ReportCollector {
}
/**
* 重置收集器
* Reset collector
*/
reset(): void {
this.stats = {
@@ -126,7 +126,7 @@ export class ReportCollector {
}
/**
* 生成控制台报告
* Generate console reports
*/
export const generateConsoleReport = (report: ProcessingReport): string => {
const { stats, duration } = report;
@@ -160,7 +160,7 @@ export const generateConsoleReport = (report: ProcessingReport): string => {
};
/**
* 生成Markdown报告
* Generating Markdown Reports
*/
export const generateMarkdownReport = (report: ProcessingReport): string => {
const { stats, details, duration } = report;
@@ -217,14 +217,14 @@ export const generateMarkdownReport = (report: ProcessingReport): string => {
};
/**
* 生成JSON报告
* Generate JSON reports
*/
export const generateJsonReport = (report: ProcessingReport): string => {
return JSON.stringify(report, null, 2);
};
/**
* 根据格式生成报告
* Generate reports according to the format
*/
export const generateReport = (
report: ProcessingReport,
@@ -242,7 +242,7 @@ export const generateReport = (
};
/**
* 保存报告到文件
* Save report to file
*/
export const saveReportToFile = async (
report: ProcessingReport,
@@ -255,7 +255,7 @@ export const saveReportToFile = async (
};
/**
* 在控制台显示实时进度
* Display real-time progress on the console
*/
export class ProgressDisplay {
private total: number = 0;
@@ -267,7 +267,7 @@ export class ProgressDisplay {
}
/**
* 更新进度
* update progress
*/
update(current: number, currentFile?: string): void {
this.current = current;
@@ -286,7 +286,7 @@ export class ProgressDisplay {
line += ` | 当前: ${currentFile}`;
}
// 清除当前行并输出新进度
// Clear the current line and output the new progress
process.stdout.write(
'\r' + ' '.repeat(process.stdout.columns || 80) + '\r',
);
@@ -294,7 +294,7 @@ export class ProgressDisplay {
}
/**
* 完成进度显示
* completion progress display
*/
complete(): void {
process.stdout.write('\n');

View File

@@ -10,7 +10,7 @@ import { isValidTranslation } from '../utils/chinese';
import { translate as volcTranslate, TranslateConfig as VolcTranslateConfig } from '../volc/translate';
/**
* 翻译服务类
* Translation services
*/
export class TranslationService {
private config: TranslationConfig;
@@ -21,7 +21,7 @@ export class TranslationService {
}
/**
* 转换为火山引擎翻译配置
* Convert to Volcano Engine Translation Configuration
*/
private toVolcConfig(): VolcTranslateConfig {
return {
@@ -34,17 +34,17 @@ export class TranslationService {
}
/**
* 计算翻译置信度(简单实现)
* Calculate translation confidence level (simple implementation)
*/
private calculateConfidence(translated: string, original: string): number {
// 基于长度比例和有效性的简单置信度计算
// Simple confidence level calculation based on length ratio and validity
const lengthRatio = translated.length / original.length;
if (!isValidTranslation(original, translated)) {
return 0;
}
// 理想的长度比例在0.8-2.0之间
// The ideal length ratio is between 0.8-2
let confidence = 0.8;
if (lengthRatio >= 0.8 && lengthRatio <= 2.0) {
confidence = 0.9;
@@ -54,7 +54,7 @@ export class TranslationService {
}
/**
* 调用火山引擎API进行翻译
* Call Volcano Engine API for translation
*/
private async callVolcTranslate(texts: string[]): Promise<string[]> {
const volcConfig = this.toVolcConfig();
@@ -64,13 +64,13 @@ export class TranslationService {
}
/**
* 翻译单个注释
* Translate a single comment
*/
async translateComment(
comment: string,
context?: TranslationContext,
): Promise<TranslationResult> {
// 检查缓存
// Check cache
const cacheKey = this.getCacheKey(comment, context);
const cached = this.cache.get(cacheKey);
if (cached) {
@@ -95,7 +95,7 @@ export class TranslationService {
confidence: this.calculateConfidence(translated, comment),
};
// 缓存结果
// cache results
this.cache.set(cacheKey, result);
return result;
@@ -108,7 +108,7 @@ export class TranslationService {
}
/**
* 生成缓存键
* generate cache key
*/
private getCacheKey(comment: string, context?: TranslationContext): string {
const contextStr = context
@@ -118,17 +118,17 @@ export class TranslationService {
}
/**
* 批量翻译注释
* batch translation annotations
*/
async batchTranslate(
comments: ChineseComment[],
concurrency: number = this.config.concurrency,
): Promise<TranslationResult[]> {
// 提取未缓存的注释
// Extract uncached comments
const uncachedComments: { comment: ChineseComment; index: number }[] = [];
const results: TranslationResult[] = new Array(comments.length);
// 检查缓存
// Check cache
comments.forEach((comment, index) => {
const cacheKey = this.getCacheKey(comment.content);
const cached = this.cache.get(cacheKey);
@@ -139,12 +139,12 @@ export class TranslationService {
}
});
// 如果所有注释都已缓存,直接返回
// If all comments are cached, return directly
if (uncachedComments.length === 0) {
return results;
}
// 分批翻译未缓存的注释
// Batch translation of uncached comments
const chunks = chunk(uncachedComments, concurrency);
for (const chunkItems of chunks) {
@@ -156,7 +156,7 @@ export class TranslationService {
1000,
);
// 处理翻译结果
// Processing translation results
chunkItems.forEach((item, chunkIndex) => {
const translated = translations[chunkIndex];
if (translated) {
@@ -166,26 +166,26 @@ export class TranslationService {
confidence: this.calculateConfidence(translated, item.comment.content),
};
// 缓存结果
// cache results
const cacheKey = this.getCacheKey(item.comment.content);
this.cache.set(cacheKey, result);
results[item.index] = result;
} else {
// 如果翻译失败,创建一个错误结果
// If the translation fails, an error result is created
results[item.index] = {
original: item.comment.content,
translated: item.comment.content, // 翻译失败时保持原文
translated: item.comment.content, // Keep the original text when translation fails
confidence: 0,
};
}
});
} catch (error) {
// 如果整个批次翻译失败,为这个批次的所有注释创建错误结果
// If the entire batch translation fails, an error result is created for all comments in that batch
chunkItems.forEach(item => {
results[item.index] = {
original: item.comment.content,
translated: item.comment.content, // 翻译失败时保持原文
translated: item.comment.content, // Keep the original text when translation fails
confidence: 0,
};
});
@@ -198,7 +198,7 @@ export class TranslationService {
}
/**
* 保存翻译缓存到文件
* Save translation cache to file
*/
async saveCache(filePath: string): Promise<void> {
const cacheData = Object.fromEntries(this.cache);
@@ -207,7 +207,7 @@ export class TranslationService {
}
/**
* 从文件加载翻译缓存
* Load translation cache from file
*/
async loadCache(filePath: string): Promise<void> {
try {
@@ -216,24 +216,24 @@ export class TranslationService {
const cacheData = JSON.parse(data);
this.cache = new Map(Object.entries(cacheData));
} catch {
// 缓存文件不存在或损坏,忽略
// The cache file does not exist or is corrupted, ignore it
}
}
/**
* 清空缓存
* clear cache
*/
clearCache(): void {
this.cache.clear();
}
/**
* 获取缓存统计
* Get cache statistics
*/
getCacheStats(): { size: number; hitRate: number } {
return {
size: this.cache.size,
hitRate: 0, // 需要实际统计命中率
hitRate: 0, // Actual statistical hit rate is required
};
}
}