scancscode 1.0.31 → 1.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.trae/specs/fix-doc-comment-boundary/checklist.md +7 -0
- package/.trae/specs/fix-doc-comment-boundary/spec.md +52 -0
- package/.trae/specs/fix-doc-comment-boundary/tasks.md +34 -0
- package/.trae/specs/fix-interpolated-string-nested-literals/checklist.md +7 -0
- package/.trae/specs/fix-interpolated-string-nested-literals/spec.md +55 -0
- package/.trae/specs/fix-interpolated-string-nested-literals/tasks.md +25 -0
- package/.trae/specs/fix-remaining-interpolated-string-index/checklist.md +9 -0
- package/.trae/specs/fix-remaining-interpolated-string-index/spec.md +59 -0
- package/.trae/specs/fix-remaining-interpolated-string-index/tasks.md +41 -0
- package/.trae/specs/fix-return-interpolated-string/checklist.md +8 -0
- package/.trae/specs/fix-return-interpolated-string/spec.md +60 -0
- package/.trae/specs/fix-return-interpolated-string/tasks.md +39 -0
- package/.trae/specs/handle-anonymous-function-strings/checklist.md +11 -0
- package/.trae/specs/handle-anonymous-function-strings/spec.md +137 -0
- package/.trae/specs/handle-anonymous-function-strings/tasks.md +65 -0
- package/.trae/specs/handle-interpolated-string-double-braces/checklist.md +9 -0
- package/.trae/specs/handle-interpolated-string-double-braces/spec.md +61 -0
- package/.trae/specs/handle-interpolated-string-double-braces/tasks.md +41 -0
- package/.trae/specs/handle-return-statement/checklist.md +11 -0
- package/.trae/specs/handle-return-statement/spec.md +76 -0
- package/.trae/specs/handle-return-statement/tasks.md +44 -0
- package/.trae/specs/handle-special-string-characters/checklist.md +13 -0
- package/.trae/specs/handle-special-string-characters/spec.md +94 -0
- package/.trae/specs/handle-special-string-characters/tasks.md +74 -0
- package/.trae/specs/unify-return-statement-string-extraction/checklist.md +10 -0
- package/.trae/specs/unify-return-statement-string-extraction/spec.md +70 -0
- package/.trae/specs/unify-return-statement-string-extraction/tasks.md +54 -0
- package/bin/scanliterals.js +3 -3
- package/bin/slimlangs.js +3 -3
- package/dist/debug-arg.js +30 -0
- package/dist/debug-args.js +34 -0
- package/dist/debug-comment-5.js +25 -0
- package/dist/debug-comment-strings.js +24 -0
- package/dist/debug-full.js +14 -0
- package/dist/debug-template-issue.js +33 -0
- package/dist/debug-test-5.js +23 -0
- package/dist/debug-test.js +21 -0
- package/dist/debug.js +15 -0
- package/dist/simple-debug.js +27 -0
- package/dist/simple-test.js +61 -0
- package/dist/src/CSharpStringExtractor.js +1791 -358
- package/dist/src/CmdExecutor.js +6 -8
- package/dist/temp-original-source.js +1 -0
- package/dist/test/CSharpStringExtractor.test.js +1587 -207
- package/dist/test-logic.js +79 -0
- package/dist/test-regex.js +13 -0
- package/docs/CSharpStringExtractor/344/273/243/347/240/201/347/224/237/346/210/220/346/217/220/347/244/272/350/257/215.txt +73 -0
- package/jest.config.js +9 -9
- package/package.json +1 -1
- package/src/CSCodeScanner.ts +305 -305
- package/src/CSVUtils.ts +181 -181
- package/src/CSharpStringExtractor.ts +2058 -479
- package/src/CmdExecutor.ts +107 -106
- package/src/LiteralCollector.ts +143 -143
- package/src/RunConvert.ts +3 -3
- package/src/RunSlimLangs.ts +3 -3
- package/src/TableScanner.ts +92 -92
- package/test/CSharpStringExtractor.test.ts +1673 -208
- package/test/KeeperDialog.cs +114 -0
- package/test/TestSpecialString.cs +24 -0
- package/tsconfig.json +109 -109
package/src/CmdExecutor.ts
CHANGED
|
@@ -1,106 +1,107 @@
|
|
|
1
|
-
import { CSVUtils } from "./CSVUtils";
|
|
2
|
-
import { LiteralCollector } from "./LiteralCollector";
|
|
3
|
-
import commandLineArgs from 'command-line-args'
|
|
4
|
-
|
|
5
|
-
function isNullOrEmpty<T>(arr: T[]): boolean {
|
|
6
|
-
return arr == null || arr.length == 0;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export class CmdExecutor {
|
|
10
|
-
static testConvert() {
|
|
11
|
-
let cwd = "E:/DATA/Projects/ZhiYou/ProjectFClient/GameClient/"
|
|
12
|
-
let cscodeFolders =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
{ name: '
|
|
32
|
-
{ name: '
|
|
33
|
-
{ name:
|
|
34
|
-
{ name: "
|
|
35
|
-
{ name: "
|
|
36
|
-
{ name: "
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
let
|
|
41
|
-
let
|
|
42
|
-
let
|
|
43
|
-
let
|
|
44
|
-
let
|
|
45
|
-
let
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
let
|
|
74
|
-
let
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
{ name: '
|
|
82
|
-
{ name: '
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
let
|
|
87
|
-
let
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
1
|
+
import { CSVUtils } from "./CSVUtils";
|
|
2
|
+
import { LiteralCollector } from "./LiteralCollector";
|
|
3
|
+
import commandLineArgs from 'command-line-args'
|
|
4
|
+
|
|
5
|
+
function isNullOrEmpty<T>(arr: T[]): boolean {
|
|
6
|
+
return arr == null || arr.length == 0;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class CmdExecutor {
|
|
10
|
+
static testConvert() {
|
|
11
|
+
let cwd = "E:/DATA/Projects/ZhiYou/ProjectFClient/GameClient/"
|
|
12
|
+
let cscodeFolders =
|
|
13
|
+
[cwd + "Assets/Bundles/FGUI/"]
|
|
14
|
+
|
|
15
|
+
// [
|
|
16
|
+
// "E:/DATA/Projects/ZhiYou/DXTSProject/Client/Assets/Bundles/UI/",
|
|
17
|
+
// "E:/DATA/Projects/ZhiYou/DXTSProject/Client/Assets/Bundles/Battle/",
|
|
18
|
+
// "E:/DATA/Projects/ZhiYou/DXTSProject/Client/Assets/Scripts/",
|
|
19
|
+
// ]
|
|
20
|
+
|
|
21
|
+
let gameConfigFolders = [cwd + "Assets/Bundles/GameConfigs/"]
|
|
22
|
+
let outCsvFile = "E:/DATA/Projects/e-gbl-client/client/Assets/Bundles/GameConfigs/Translation/hello.csv"
|
|
23
|
+
let langs = ["zh_cn"];
|
|
24
|
+
let literalCollector = new LiteralCollector();
|
|
25
|
+
// return literalCollector.convert(cscodeFolders, gameConfigFolders, outCsvFile, langs,undefined,false,true)
|
|
26
|
+
return literalCollector.convert(cscodeFolders, gameConfigFolders, outCsvFile, langs)
|
|
27
|
+
// node . --cscodedir ../../../GameClient/Assets/Bundles/FGUI/ --configdir ../../../GameClient/Assets/Bundles/GameConfigs/ --outcsv E:/DATA/Projects/e-gbl-client/client/Assets/Bundles/GameConfigs/Translation/hello.csv --langs zh_cn
|
|
28
|
+
}
|
|
29
|
+
static async runConvertWithCmdOptions() {
|
|
30
|
+
const optionDefinitions = [
|
|
31
|
+
{ name: 'cscodedir', type: String, multiple: true },
|
|
32
|
+
{ name: 'configdir', type: String, multiple: true },
|
|
33
|
+
{ name: 'outcsv', type: String },
|
|
34
|
+
{ name: "langs", type: String, multiple: true, defaultOption: true },
|
|
35
|
+
{ name: "verbose", alias: 'v', type: Boolean },
|
|
36
|
+
{ name: "scanonly", type: Boolean, defaultOption: false },
|
|
37
|
+
{ name: "trmethod", type: String }
|
|
38
|
+
]
|
|
39
|
+
const options = commandLineArgs(optionDefinitions)
|
|
40
|
+
let cscodedir: string[] = options.cscodedir ?? []
|
|
41
|
+
let configdir: string[] = options.configdir ?? []
|
|
42
|
+
let outcsv: string = options.outcsv
|
|
43
|
+
let langs: string[] = options.langs ?? ["zh_cn"]
|
|
44
|
+
let verbose: boolean = options.verbose ?? false
|
|
45
|
+
let scanonly: boolean = options.scanonly ?? false
|
|
46
|
+
let trmethod: string = options.trmethod ?? "Tr.TR"
|
|
47
|
+
|
|
48
|
+
let argv = process.argv
|
|
49
|
+
if (isNullOrEmpty(cscodedir) && isNullOrEmpty(configdir)) {
|
|
50
|
+
if (isNullOrEmpty(cscodedir)) {
|
|
51
|
+
console.error(`cscodedir missing:`, argv)
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
if (isNullOrEmpty(configdir)) {
|
|
55
|
+
console.error(`configdir missing:`, argv)
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (outcsv == null) {
|
|
60
|
+
console.error(`outcsv missing:`, argv)
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
if (isNullOrEmpty(langs)) {
|
|
64
|
+
console.error(`langs missing:`, argv)
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
console.log(`convert cmd options: `, cscodedir, configdir, outcsv, langs, verbose)
|
|
68
|
+
let literalCollector = new LiteralCollector();
|
|
69
|
+
await literalCollector.convert(cscodedir, configdir, outcsv, langs, trmethod, scanonly, verbose)
|
|
70
|
+
console.log("convert done.")
|
|
71
|
+
}
|
|
72
|
+
static testSlimCsv() {
|
|
73
|
+
let inCsvFile = ["E:/DATA/Projects/e-gbl-client/client/Assets/Bundles/GameConfigs/Translation/hello.csv"]
|
|
74
|
+
let outCsvFile = "E:/DATA/Projects/e-gbl-client/client/Assets/Bundles/GameConfigs/Translation/hello-out.csv"
|
|
75
|
+
let langs = ["zh_cn"];
|
|
76
|
+
CSVUtils.slimCsvWithLangs(inCsvFile, outCsvFile, langs);
|
|
77
|
+
// node bin/slimlangs.js --incsv E:/DATA/Projects/e-gbl-client/client/Assets/Bundles/GameConfigs/Translation/hello.csv --outcsv E:/DATA/Projects/e-gbl-client/client/Assets/Bundles/GameConfigs/Translation/hello-out.csv --langs zh_cn
|
|
78
|
+
}
|
|
79
|
+
static async runSlimCsvWithLangs() {
|
|
80
|
+
const optionDefinitions = [
|
|
81
|
+
{ name: 'incsv', type: String, multiple: true },
|
|
82
|
+
{ name: 'outcsv', type: String },
|
|
83
|
+
{ name: 'langs', type: String, multiple: true, defaultOption: true },
|
|
84
|
+
];
|
|
85
|
+
const options = commandLineArgs(optionDefinitions);
|
|
86
|
+
let incsv: string[] = options.incsv ?? [];
|
|
87
|
+
let outcsv: string = options.outcsv;
|
|
88
|
+
let langs: string[] = options.langs ?? ["zh_cn"]
|
|
89
|
+
|
|
90
|
+
console.log(`slim csv cmd options: `, incsv, outcsv, langs);
|
|
91
|
+
let argv = process.argv;
|
|
92
|
+
if (isNullOrEmpty(incsv)) {
|
|
93
|
+
console.error(`incsv missing:`, argv);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (outcsv == null) {
|
|
97
|
+
console.error(`outcsv missing:`, argv);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (isNullOrEmpty(langs)) {
|
|
101
|
+
console.error(`langs missing:`, argv);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
await CSVUtils.slimCsvWithLangs(incsv, outcsv, langs);
|
|
105
|
+
console.log("slim csv with langs done.");
|
|
106
|
+
}
|
|
107
|
+
}
|
package/src/LiteralCollector.ts
CHANGED
|
@@ -1,143 +1,143 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
2
|
-
import { glob } from "glob";
|
|
3
|
-
import { CSCodeScanner } from "./CSCodeScanner";
|
|
4
|
-
import { CSVUtils } from "./CSVUtils";
|
|
5
|
-
import { TableScanner } from "./TableScanner";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export class LiteralCollector {
|
|
9
|
-
|
|
10
|
-
async scanCodeInFolder(folder: string, literals: string[], unexpects: string[], trmethod: string, scanonly: boolean, verbose: boolean) {
|
|
11
|
-
if (fs.existsSync(folder) == false) {
|
|
12
|
-
console.warn(`代码目录不存在: ${folder}`);
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
let files = glob.sync("**/*.cs", { cwd: folder });
|
|
17
|
-
let testFullPath = "@";
|
|
18
|
-
// let testFullPath = "E:/DATA/Projects/ZhiYou/ProjectFClient/GameClient/Assets/Bundles/GameConfigs/Main/UnitAttributeTable-UnitAttributeTable.cs";
|
|
19
|
-
|
|
20
|
-
// 限制并行处理的文件数量,避免内存占用过高
|
|
21
|
-
const batchSize = 10;
|
|
22
|
-
for (let i = 0; i < files.length; i += batchSize) {
|
|
23
|
-
const batchFiles = files.slice(i, i + batchSize);
|
|
24
|
-
const batchPromises = batchFiles.map(async (filePath) => {
|
|
25
|
-
let fullPath = folder + filePath;
|
|
26
|
-
if (testFullPath != "@") {
|
|
27
|
-
fullPath = testFullPath;
|
|
28
|
-
}
|
|
29
|
-
if (verbose) {
|
|
30
|
-
console.log(`处理文件: ${filePath}, ${fullPath}`);
|
|
31
|
-
}
|
|
32
|
-
try {
|
|
33
|
-
const content = await fs.promises.readFile(fullPath, "utf-8");
|
|
34
|
-
const snippets = CSCodeScanner.scanFile(fullPath, content, trmethod);
|
|
35
|
-
CSCodeScanner.filterSnippets(snippets);
|
|
36
|
-
|
|
37
|
-
if (snippets.length > 0) {
|
|
38
|
-
if (!scanonly) {
|
|
39
|
-
let convertedContent = CSCodeScanner.replaceInFile(content, snippets);
|
|
40
|
-
if (convertedContent != content) {
|
|
41
|
-
await fs.promises.writeFile(fullPath, convertedContent, "utf-8");
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const fileLiterals: string[] = [];
|
|
46
|
-
const fileUnexpects: string[] = [];
|
|
47
|
-
for (const snippet of snippets) {
|
|
48
|
-
fileLiterals.push(...snippet.literals);
|
|
49
|
-
fileUnexpects.push(...snippet.unexpects);
|
|
50
|
-
}
|
|
51
|
-
return { literals: fileLiterals, unexpects: fileUnexpects };
|
|
52
|
-
}
|
|
53
|
-
} catch (error) {
|
|
54
|
-
console.error(`处理文件失败: ${fullPath}`, error);
|
|
55
|
-
}
|
|
56
|
-
return { literals: [], unexpects: [] };
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const batchResults = await Promise.all(batchPromises);
|
|
60
|
-
for (const result of batchResults) {
|
|
61
|
-
literals.push(...result.literals);
|
|
62
|
-
unexpects.push(...result.unexpects);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (testFullPath != "@") {
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
unexpects = [...new Set(unexpects)];
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async scanTablesInFolder(folder: string, literals: string[], verbose: boolean) {
|
|
75
|
-
if (fs.existsSync(folder) == false) {
|
|
76
|
-
console.warn(`表格目录不存在: ${folder}`);
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
let scanner = new TableScanner();
|
|
80
|
-
await scanner.scanTablesLiterals(folder + "Main/", literals, verbose);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
static needTranslate(literal: string): boolean {
|
|
84
|
-
let match = literal.match(/^[\da-zA-Z!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/? ]+$/m);
|
|
85
|
-
return match == null;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* 去重
|
|
90
|
-
* @param literals
|
|
91
|
-
*/
|
|
92
|
-
filterLiterals(literals: string[]) {
|
|
93
|
-
let literalsSet = new Set(literals);
|
|
94
|
-
literalsSet.delete("");
|
|
95
|
-
for (let literal of literals) {
|
|
96
|
-
let needTr = LiteralCollector.needTranslate(literal);
|
|
97
|
-
if (!needTr) {
|
|
98
|
-
literalsSet.delete(literal)
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
literals.length = 0;
|
|
102
|
-
literals.push(...literalsSet);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async convert(cscodeFolders: string[], gameConfigFolders: string[], outCsvFile: string, langs: string[], trmethod: string = "Tr.TR", scanonly: boolean = false, verbose: boolean = false) {
|
|
106
|
-
|
|
107
|
-
let literals: string[] = [];
|
|
108
|
-
let unexpects: string[] = [];
|
|
109
|
-
|
|
110
|
-
// 并行处理代码文件夹
|
|
111
|
-
const codeFolderPromises = cscodeFolders.map(async (cscodeFolder) => {
|
|
112
|
-
const folderLiterals: string[] = [];
|
|
113
|
-
const folderUnexpects: string[] = [];
|
|
114
|
-
await this.scanCodeInFolder(cscodeFolder, folderLiterals, folderUnexpects, trmethod, scanonly, verbose);
|
|
115
|
-
return { literals: folderLiterals, unexpects: folderUnexpects };
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
const codeFolderResults = await Promise.all(codeFolderPromises);
|
|
119
|
-
for (const result of codeFolderResults) {
|
|
120
|
-
literals.push(...result.literals);
|
|
121
|
-
unexpects.push(...result.unexpects);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// 并行处理表格文件夹
|
|
125
|
-
const tableFolderPromises = gameConfigFolders.map(async (gameConfigFolder) => {
|
|
126
|
-
await this.scanTablesInFolder(gameConfigFolder, literals, verbose);
|
|
127
|
-
});
|
|
128
|
-
await Promise.all(tableFolderPromises);
|
|
129
|
-
|
|
130
|
-
// 去重和过滤
|
|
131
|
-
this.filterLiterals(literals);
|
|
132
|
-
|
|
133
|
-
if (verbose) {
|
|
134
|
-
console.log("扫描合并结果:", literals);
|
|
135
|
-
}
|
|
136
|
-
if (!scanonly) {
|
|
137
|
-
await CSVUtils.updateToFile(outCsvFile, literals, langs);
|
|
138
|
-
}
|
|
139
|
-
for (const unexpect of unexpects) {
|
|
140
|
-
console.error(unexpect);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import { glob } from "glob";
|
|
3
|
+
import { CSCodeScanner } from "./CSCodeScanner";
|
|
4
|
+
import { CSVUtils } from "./CSVUtils";
|
|
5
|
+
import { TableScanner } from "./TableScanner";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export class LiteralCollector {
|
|
9
|
+
|
|
10
|
+
async scanCodeInFolder(folder: string, literals: string[], unexpects: string[], trmethod: string, scanonly: boolean, verbose: boolean) {
|
|
11
|
+
if (fs.existsSync(folder) == false) {
|
|
12
|
+
console.warn(`代码目录不存在: ${folder}`);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let files = glob.sync("**/*.cs", { cwd: folder });
|
|
17
|
+
let testFullPath = "@";
|
|
18
|
+
// let testFullPath = "E:/DATA/Projects/ZhiYou/ProjectFClient/GameClient/Assets/Bundles/GameConfigs/Main/UnitAttributeTable-UnitAttributeTable.cs";
|
|
19
|
+
|
|
20
|
+
// 限制并行处理的文件数量,避免内存占用过高
|
|
21
|
+
const batchSize = 10;
|
|
22
|
+
for (let i = 0; i < files.length; i += batchSize) {
|
|
23
|
+
const batchFiles = files.slice(i, i + batchSize);
|
|
24
|
+
const batchPromises = batchFiles.map(async (filePath) => {
|
|
25
|
+
let fullPath = folder + filePath;
|
|
26
|
+
if (testFullPath != "@") {
|
|
27
|
+
fullPath = testFullPath;
|
|
28
|
+
}
|
|
29
|
+
if (verbose) {
|
|
30
|
+
console.log(`处理文件: ${filePath}, ${fullPath}`);
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const content = await fs.promises.readFile(fullPath, "utf-8");
|
|
34
|
+
const snippets = CSCodeScanner.scanFile(fullPath, content, trmethod);
|
|
35
|
+
CSCodeScanner.filterSnippets(snippets);
|
|
36
|
+
|
|
37
|
+
if (snippets.length > 0) {
|
|
38
|
+
if (!scanonly) {
|
|
39
|
+
let convertedContent = CSCodeScanner.replaceInFile(content, snippets);
|
|
40
|
+
if (convertedContent != content) {
|
|
41
|
+
await fs.promises.writeFile(fullPath, convertedContent, "utf-8");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const fileLiterals: string[] = [];
|
|
46
|
+
const fileUnexpects: string[] = [];
|
|
47
|
+
for (const snippet of snippets) {
|
|
48
|
+
fileLiterals.push(...snippet.literals);
|
|
49
|
+
fileUnexpects.push(...snippet.unexpects);
|
|
50
|
+
}
|
|
51
|
+
return { literals: fileLiterals, unexpects: fileUnexpects };
|
|
52
|
+
}
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error(`处理文件失败: ${fullPath}`, error);
|
|
55
|
+
}
|
|
56
|
+
return { literals: [], unexpects: [] };
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const batchResults = await Promise.all(batchPromises);
|
|
60
|
+
for (const result of batchResults) {
|
|
61
|
+
literals.push(...result.literals);
|
|
62
|
+
unexpects.push(...result.unexpects);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (testFullPath != "@") {
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
unexpects = [...new Set(unexpects)];
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async scanTablesInFolder(folder: string, literals: string[], verbose: boolean) {
|
|
75
|
+
if (fs.existsSync(folder) == false) {
|
|
76
|
+
console.warn(`表格目录不存在: ${folder}`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
let scanner = new TableScanner();
|
|
80
|
+
await scanner.scanTablesLiterals(folder + "Main/", literals, verbose);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static needTranslate(literal: string): boolean {
|
|
84
|
+
let match = literal.match(/^[\da-zA-Z!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/? ]+$/m);
|
|
85
|
+
return match == null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 去重
|
|
90
|
+
* @param literals
|
|
91
|
+
*/
|
|
92
|
+
filterLiterals(literals: string[]) {
|
|
93
|
+
let literalsSet = new Set(literals);
|
|
94
|
+
literalsSet.delete("");
|
|
95
|
+
for (let literal of literals) {
|
|
96
|
+
let needTr = LiteralCollector.needTranslate(literal);
|
|
97
|
+
if (!needTr) {
|
|
98
|
+
literalsSet.delete(literal)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
literals.length = 0;
|
|
102
|
+
literals.push(...literalsSet);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async convert(cscodeFolders: string[], gameConfigFolders: string[], outCsvFile: string, langs: string[], trmethod: string = "Tr.TR", scanonly: boolean = false, verbose: boolean = false) {
|
|
106
|
+
|
|
107
|
+
let literals: string[] = [];
|
|
108
|
+
let unexpects: string[] = [];
|
|
109
|
+
|
|
110
|
+
// 并行处理代码文件夹
|
|
111
|
+
const codeFolderPromises = cscodeFolders.map(async (cscodeFolder) => {
|
|
112
|
+
const folderLiterals: string[] = [];
|
|
113
|
+
const folderUnexpects: string[] = [];
|
|
114
|
+
await this.scanCodeInFolder(cscodeFolder, folderLiterals, folderUnexpects, trmethod, scanonly, verbose);
|
|
115
|
+
return { literals: folderLiterals, unexpects: folderUnexpects };
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const codeFolderResults = await Promise.all(codeFolderPromises);
|
|
119
|
+
for (const result of codeFolderResults) {
|
|
120
|
+
literals.push(...result.literals);
|
|
121
|
+
unexpects.push(...result.unexpects);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 并行处理表格文件夹
|
|
125
|
+
const tableFolderPromises = gameConfigFolders.map(async (gameConfigFolder) => {
|
|
126
|
+
await this.scanTablesInFolder(gameConfigFolder, literals, verbose);
|
|
127
|
+
});
|
|
128
|
+
await Promise.all(tableFolderPromises);
|
|
129
|
+
|
|
130
|
+
// 去重和过滤
|
|
131
|
+
this.filterLiterals(literals);
|
|
132
|
+
|
|
133
|
+
if (verbose) {
|
|
134
|
+
console.log("扫描合并结果:", literals);
|
|
135
|
+
}
|
|
136
|
+
if (!scanonly) {
|
|
137
|
+
await CSVUtils.updateToFile(outCsvFile, literals, langs);
|
|
138
|
+
}
|
|
139
|
+
for (const unexpect of unexpects) {
|
|
140
|
+
console.error(unexpect);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
package/src/RunConvert.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { CmdExecutor } from "./CmdExecutor";
|
|
2
|
-
|
|
3
|
-
CmdExecutor.runConvertWithCmdOptions()
|
|
1
|
+
import { CmdExecutor } from "./CmdExecutor";
|
|
2
|
+
|
|
3
|
+
CmdExecutor.runConvertWithCmdOptions()
|
package/src/RunSlimLangs.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { CmdExecutor } from "./CmdExecutor";
|
|
2
|
-
|
|
3
|
-
CmdExecutor.runSlimCsvWithLangs()
|
|
1
|
+
import { CmdExecutor } from "./CmdExecutor";
|
|
2
|
+
|
|
3
|
+
CmdExecutor.runSlimCsvWithLangs()
|