ttmg-pack 0.3.10 → 0.4.3

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.
Files changed (46) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/__TEST__/tests/fixtures/check-project/non-unity/src/game.js +1 -0
  3. package/__TEST__/tests/fixtures/check-project/non-unity/src/game.json +3 -0
  4. package/__TEST__/tests/fixtures/check-project/subpackages-camel-case/src/game.js +1 -0
  5. package/__TEST__/tests/fixtures/check-project/subpackages-camel-case/src/game.json +4 -0
  6. package/__TEST__/tests/fixtures/check-project/unity-large-config-disabled/src/game.js +1 -0
  7. package/__TEST__/tests/fixtures/check-project/unity-large-config-disabled/src/game.json +4 -0
  8. package/__TEST__/tests/fixtures/check-project/unity-large-config-disabled/src/webgl-wasm-split.json +3 -0
  9. package/__TEST__/tests/fixtures/check-project/unity-large-config-enabled/src/game.js +1 -0
  10. package/__TEST__/tests/fixtures/check-project/unity-large-config-enabled/src/game.json +4 -0
  11. package/__TEST__/tests/fixtures/check-project/unity-large-config-enabled/src/webgl-wasm-split.json +3 -0
  12. package/__TEST__/tests/fixtures/check-project/unity-large-no-config/src/game.js +1 -0
  13. package/__TEST__/tests/fixtures/check-project/unity-large-no-config/src/game.json +4 -0
  14. package/__TEST__/tests/fixtures/check-project/unity-small/src/game.js +1 -0
  15. package/__TEST__/tests/fixtures/check-project/unity-small/src/game.json +4 -0
  16. package/__TEST__/tests/fixtures/game-cocos/game.json +3 -0
  17. package/__TEST__/tests/fixtures/game-invalid-json/game.json +1 -0
  18. package/__TEST__/tests/fixtures/game-no-config/game.js +1 -0
  19. package/__TEST__/tests/fixtures/game-no-engine/game.json +3 -0
  20. package/__TEST__/tests/fixtures/game-unity/game.json +15 -0
  21. package/__TEST__/tests/libs/checkProject.test.js +68 -0
  22. package/__TEST__/tests/runner-simple.js +120 -0
  23. package/__TEST__/tests/runner.js +102 -0
  24. package/__TEST__/tests/utils/Deferred.test.js +69 -0
  25. package/__TEST__/tests/utils/asyncPool.test.js +48 -0
  26. package/__TEST__/tests/utils/getCheckConfig.test.js +24 -0
  27. package/__TEST__/tests/utils/getGameEngine.test.js +32 -0
  28. package/__TEST__/tests/utils/getIndependentPackagesConfig.test.js +27 -0
  29. package/__TEST__/tests/utils/getMd5.test.js +31 -0
  30. package/__TEST__/tests/utils/getSubpackagesConfig.test.js +26 -0
  31. package/__TEST__/tests/utils/unity.test.js +30 -0
  32. package/dist/constants/index.d.ts +1 -0
  33. package/dist/index.js +367 -101
  34. package/dist/index.js.map +1 -1
  35. package/dist/libs/buildPkgs/index.d.ts +2 -2
  36. package/dist/libs/checkPkgs/checkAPI.d.ts +2 -1
  37. package/dist/libs/checkPkgs/checkIndependentPackages.d.ts +4 -2
  38. package/dist/libs/checkPkgs/checkMainpackage.d.ts +4 -3
  39. package/dist/libs/checkPkgs/checkProject.d.ts +4 -3
  40. package/dist/libs/checkPkgs/checkSubpackages.d.ts +2 -1
  41. package/dist/libs/checkPkgs/index.d.ts +2 -2
  42. package/dist/libs/debugPkgs/index.d.ts +2 -2
  43. package/dist/typings/index.d.ts +7 -0
  44. package/dist/utils/i18n.d.ts +158 -0
  45. package/dist/utils/index.d.ts +2 -0
  46. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * ==========================================
3
3
  * @Description: ttmg pack
4
- * @Version: 0.3.10
4
+ * @Version: 0.4.3
5
5
  * @Author: zhanghongyang.mocha
6
- * @Date: 2026-03-06 15:56:48
6
+ * @Date: 2026-03-12 18:19:30
7
7
  * ==========================================
8
8
  */
9
9
  'use strict';
@@ -157,6 +157,7 @@ const GAME_PKG_SIZE_LIMIT = {
157
157
  independent: null,
158
158
  },
159
159
  };
160
+ const WASM_FUNC_COUNT_LIMIT = 80000;
160
161
 
161
162
  /**
162
163
  * 递归统计目录下所有文件的大小,支持过滤文件夹和文件
@@ -278,8 +279,184 @@ function deleteNoJsFilesSync(dir) {
278
279
  }
279
280
  }
280
281
 
282
+ const messages = {
283
+ 'en-US': {
284
+ 'log.check.start': 'Start checking project.',
285
+ 'log.check.project.start': 'Start checking project dimension.',
286
+ 'log.check.project.success': 'Project checks passed.',
287
+ 'log.check.config.start': 'Start checking config.',
288
+ 'log.check.projectSize.start': 'Start checking project size.',
289
+ 'log.check.subpackages.start': 'Start checking subpackages in game.json.',
290
+ 'log.check.subpackages.success': 'Subpackages config checks passed.',
291
+ 'log.check.mainPackage.start': 'Start checking main package.',
292
+ 'log.check.mainPackageEntry.start': 'Start checking main package entry.',
293
+ 'log.check.mainPackageEntry.success': 'Main package entry check passed.',
294
+ 'log.check.mainPackageSize.start': 'Start checking main package size.',
295
+ 'log.check.mainPackage.success': 'Main package checks passed.',
296
+ 'log.check.independent.start': 'Start checking independent subpackages in game.json.',
297
+ 'log.check.independent.success': 'Independent subpackages config checks passed.',
298
+ 'log.setup.startGeneratePackageConfig': 'Start generating packageConfig.json from game.json.',
299
+ 'log.setup.generatePackageConfigSuccess': 'Generated packageConfig.json from game.json successfully.',
300
+ 'log.collectMaps.start': 'Start collecting JS files from game source packages.',
301
+ 'log.collectMaps.openDataContextDir': 'Open data context directory: {dir}',
302
+ 'log.collectMaps.done': 'Collected JS files from game source packages successfully.',
303
+ 'log.makePkgs.start': 'Pack start, startTime: {startTime}',
304
+ 'log.makePkgs.startPackBySource': 'Start packing from game source, package: {pkgName}',
305
+ 'log.makePkgs.finishPackBySource': 'Finished packing and partitioning from game source, package: {pkgName}',
306
+ 'log.makePkgs.packBySourceCost': 'Pack and partition cost, package: {pkgName}, duration: {duration}ms',
307
+ 'log.makePkgs.startOpenData': 'Start packing from open data context source.',
308
+ 'log.makePkgs.finishOpenData': 'Finished packing from open data context source.',
309
+ 'log.makePkgs.openDataCost': 'Open data context packing cost: {duration}ms',
310
+ 'log.makePkgs.end': 'Pack end, duration: {duration}ms',
311
+ 'log.build.version': 'TTMG_PACK_VERSION: {version}',
312
+ 'log.build.start': 'Pack start, startTime: {startTime}',
313
+ 'log.build.end': 'Pack end: {duration}ms',
314
+ 'log.pack.start': 'Pack start, startTime: {startTime}',
315
+ 'log.pack.end': 'Pack end, package: {pkgName}',
316
+ 'log.safeBuild.initStart': 'Attempting to initialize esbuild service...',
317
+ 'log.safeBuild.initSuccess': 'esbuild service initialized successfully.',
318
+ 'log.safeBuild.initFailed': 'Failed to initialize esbuild service:',
319
+ 'log.cleanup.start': 'Start cleaning useless files, total entries: {total}',
320
+ 'log.cleanup.accessDirFailed': 'Cannot access directory: {dir}, {error}',
321
+ 'log.cleanup.deletedDir': 'Deleted useless directory: {path}',
322
+ 'log.cleanup.deletedFile': 'Deleted useless file: {path}',
323
+ 'log.cleanup.processFailed': 'Cannot process entry: {path}, {error}',
324
+ 'log.cleanup.progress': 'Progress: {processed}/{total} ({percentage}%)',
325
+ 'log.cleanup.done': 'Cleanup finished.',
326
+ 'log.cleanup.summary.total': '- Total entries: {total}',
327
+ 'log.cleanup.summary.deletedDirs': '- Deleted directories: {deletedDirs}',
328
+ 'log.cleanup.summary.deletedFiles': '- Deleted files: {deletedFiles}',
329
+ 'log.cleanup.summary.errors': '- Errors: {errors}',
330
+ 'check.project.gameJson.missing': 'Cannot find game.json in the project source. Please make sure game.json exists.',
331
+ 'check.project.gameJson.subPackagesInvalid': "'subPackages' is found in game.json. Please use 'subpackages' (all lowercase) instead.",
332
+ 'check.project.gameJson.success': 'Check game.json config successfully.',
333
+ 'check.project.size.failed': 'Project size check failed: {sizeMB}MB. It must not exceed {limitMB}MB.',
334
+ 'check.project.size.success': 'Project size check passed: {sizeMB}MB.',
335
+ 'check.project.perf.noSplitNeeded': 'wasmFuncCount < {limit}. No wasm code splitting is needed.',
336
+ 'check.project.perf.needSplit': 'The Wasm function count in wasmcode/ exceeds {limit}. Please enable code splitting to optimize performance.',
337
+ 'check.project.perf.splitEnabled': 'wasmFuncCount >= {limit}, and wasm split is enabled.',
338
+ 'check.main.size.failed': 'Main package size check failed: {sizeMB}MB. It must not exceed {limitMB}MB.',
339
+ 'check.main.size.success': 'Main package size check passed: {sizeMB}MB.',
340
+ 'check.main.entry.missing': 'Main package entry check failed: game.js must exist in the main package.',
341
+ 'check.main.entry.success': 'Main package entry check passed: game.js exists in the main package.',
342
+ 'check.subpackages.config.empty': 'Subpackages config check failed: one or more subpackages have an empty root or name. Please ensure every subpackage has non-empty root and name.',
343
+ 'check.subpackages.config.invalidPath': 'Subpackages config check failed: subpackage<{name}> has invalid {invalidFields}. Only A-Za-z0-9 _ - . / \\ are allowed.',
344
+ 'check.subpackages.config.success': 'Subpackage<{name}> config check passed.',
345
+ 'check.subpackages.config.missingDir': 'Subpackages config check failed: cannot find entry directory for subpackage<{name}>. Please verify its root path in game.json.',
346
+ 'check.independent.config.empty': 'Independent subpackages config check failed: one or more independent subpackages have an empty root or name. Please ensure every independent subpackage has non-empty root and name.',
347
+ 'check.independent.config.missingDir': 'Independent subpackages config check failed: cannot find entry directory for independent subpackage<{name}>. Please verify its root path in game.json.',
348
+ 'check.independent.config.success': 'Independent subpackage<{name}> config check passed.',
349
+ 'check.pkgSize.success': 'Package<{pkgName}> size check passed: {sizeMB}MB.',
350
+ 'check.pkgSize.exceeds': 'Package<{pkgName}> size check failed: {sizeMB}MB exceeds limit {limitMB}MB.',
351
+ 'check.api.integrated': '{name} integrated.',
352
+ 'check.api.notIntegrated': '{name} not integrated.',
353
+ 'check.api.suggestedActionSuffix': 'Please resolve this before submission to avoid review rejection.',
354
+ 'debug.validation.failed': 'Project validation failed (Errors):\n{errorMsg}',
355
+ },
356
+ 'zh-CN': {
357
+ 'log.check.start': '开始校验项目。',
358
+ 'log.check.project.start': '开始校验项目维度。',
359
+ 'log.check.project.success': '项目校验通过。',
360
+ 'log.check.config.start': '开始校验配置。',
361
+ 'log.check.projectSize.start': '开始校验项目大小。',
362
+ 'log.check.subpackages.start': '开始校验 game.json 中的分包配置。',
363
+ 'log.check.subpackages.success': '分包配置校验通过。',
364
+ 'log.check.mainPackage.start': '开始校验主包。',
365
+ 'log.check.mainPackageEntry.start': '开始校验主包入口。',
366
+ 'log.check.mainPackageEntry.success': '主包入口校验通过。',
367
+ 'log.check.mainPackageSize.start': '开始校验主包大小。',
368
+ 'log.check.mainPackage.success': '主包校验通过。',
369
+ 'log.check.independent.start': '开始校验 game.json 中的独立分包配置。',
370
+ 'log.check.independent.success': '独立分包配置校验通过。',
371
+ 'log.setup.startGeneratePackageConfig': '开始基于源代码中的 game.json 生成 packageConfig.json。',
372
+ 'log.setup.generatePackageConfigSuccess': '基于源代码中的 game.json 生成 packageConfig.json 成功。',
373
+ 'log.collectMaps.start': '开始基于游戏源代码收集分包中的 JS 文件。',
374
+ 'log.collectMaps.openDataContextDir': '开放数据域目录:{dir}',
375
+ 'log.collectMaps.done': '基于游戏源代码收集分包中的 JS 文件完成。',
376
+ 'log.makePkgs.start': '打包开始,开始时间:{startTime}',
377
+ 'log.makePkgs.startPackBySource': '开始基于游戏源代码打包,包名:{pkgName}',
378
+ 'log.makePkgs.finishPackBySource': '基于游戏源代码打包分包完成,包名:{pkgName}',
379
+ 'log.makePkgs.packBySourceCost': '基于游戏源代码打包分包耗时,包名:{pkgName},耗时:{duration}ms',
380
+ 'log.makePkgs.startOpenData': '开始基于开放数据域源代码打包。',
381
+ 'log.makePkgs.finishOpenData': '基于开放数据域源代码打包完成。',
382
+ 'log.makePkgs.openDataCost': '基于开放数据域源代码打包耗时,耗时:{duration}ms',
383
+ 'log.makePkgs.end': '打包结束,总耗时:{duration}ms',
384
+ 'log.build.version': 'TTMG_PACK_VERSION: {version}',
385
+ 'log.build.start': '打包开始,开始时间:{startTime}',
386
+ 'log.build.end': '打包结束:{duration}ms',
387
+ 'log.pack.start': '打包开始,开始时间:{startTime}',
388
+ 'log.pack.end': '打包结束,包名:{pkgName}',
389
+ 'log.safeBuild.initStart': '尝试初始化 esbuild 服务...',
390
+ 'log.safeBuild.initSuccess': 'esbuild 服务初始化成功。',
391
+ 'log.safeBuild.initFailed': '初始化 esbuild 服务失败:',
392
+ 'log.cleanup.start': '开始清理无用文件,共 {total} 个条目',
393
+ 'log.cleanup.accessDirFailed': '无法访问目录: {dir}, {error}',
394
+ 'log.cleanup.deletedDir': '已删除无用目录: {path}',
395
+ 'log.cleanup.deletedFile': '已删除无用文件: {path}',
396
+ 'log.cleanup.processFailed': '无法处理: {path}, {error}',
397
+ 'log.cleanup.progress': '进度: {processed}/{total} ({percentage}%)',
398
+ 'log.cleanup.done': '清理完成!',
399
+ 'log.cleanup.summary.total': '- 总条目: {total}',
400
+ 'log.cleanup.summary.deletedDirs': '- 已删除目录: {deletedDirs}',
401
+ 'log.cleanup.summary.deletedFiles': '- 已删除文件: {deletedFiles}',
402
+ 'log.cleanup.summary.errors': '- 错误数: {errors}',
403
+ 'check.project.gameJson.missing': '未在项目源码中找到 game.json,请确认 game.json 文件存在。',
404
+ 'check.project.gameJson.subPackagesInvalid': "在 game.json 中发现了 'subPackages' 字段,请改为全小写的 'subpackages'。",
405
+ 'check.project.gameJson.success': 'game.json 配置检查通过。',
406
+ 'check.project.size.failed': '项目大小检查失败:当前 {sizeMB}MB,不能超过 {limitMB}MB。',
407
+ 'check.project.size.success': '项目大小检查通过:当前 {sizeMB}MB。',
408
+ 'check.project.perf.noSplitNeeded': 'wasmFuncCount < {limit},无需进行 wasm 代码拆分。',
409
+ 'check.project.perf.needSplit': 'wasmcode/ 中的 Wasm 函数数量超过 {limit},请开启代码拆分以优化性能。',
410
+ 'check.project.perf.splitEnabled': 'wasmFuncCount >= {limit},且已开启 wasm 拆分。',
411
+ 'check.main.size.failed': '主包大小检查失败:当前 {sizeMB}MB,不能超过 {limitMB}MB。',
412
+ 'check.main.size.success': '主包大小检查通过:当前 {sizeMB}MB。',
413
+ 'check.main.entry.missing': '主包入口检查失败:主包中必须存在 game.js。',
414
+ 'check.main.entry.success': '主包入口检查通过:主包中存在 game.js。',
415
+ 'check.subpackages.config.empty': '分包配置检查失败:一个或多个分包的 root 或 name 为空,请确保所有分包都配置了非空的 root 和 name。',
416
+ 'check.subpackages.config.invalidPath': '分包配置检查失败:分包<{name}> 的 {invalidFields} 含有非法字符,仅允许 A-Za-z0-9 _ - . / \\。',
417
+ 'check.subpackages.config.success': '分包<{name}> 配置检查通过。',
418
+ 'check.subpackages.config.missingDir': '分包配置检查失败:找不到分包<{name}> 的入口目录,请检查 game.json 中的 root 路径。',
419
+ 'check.independent.config.empty': '独立分包配置检查失败:一个或多个独立分包的 root 或 name 为空,请确保所有独立分包都配置了非空的 root 和 name。',
420
+ 'check.independent.config.missingDir': '独立分包配置检查失败:找不到独立分包<{name}> 的入口目录,请检查 game.json 中的 root 路径。',
421
+ 'check.independent.config.success': '独立分包<{name}> 配置检查通过。',
422
+ 'check.pkgSize.success': '包<{pkgName}> 大小检查通过:{sizeMB}MB。',
423
+ 'check.pkgSize.exceeds': '包<{pkgName}> 大小检查失败:当前 {sizeMB}MB,超过限制 {limitMB}MB。',
424
+ 'check.api.integrated': '{name} 已接入。',
425
+ 'check.api.notIntegrated': '{name} 未接入。',
426
+ 'check.api.suggestedActionSuffix': '请在提审之前完成问题处理,避免审核阶段被拒审。',
427
+ 'debug.validation.failed': '项目校验失败(错误项):\n{errorMsg}',
428
+ },
429
+ };
430
+ function format(template, params) {
431
+ if (!params)
432
+ return template;
433
+ return template.replace(/\{(\w+)\}/g, (_, key) => {
434
+ const value = params[key];
435
+ return value === undefined ? `{${key}}` : String(value);
436
+ });
437
+ }
438
+ function resolvePackLanguage(lang) {
439
+ return lang === 'zh-CN' ? 'zh-CN' : 'en-US';
440
+ }
441
+ let runtimePackLang = 'en-US';
442
+ function setPackRuntimeLanguage(lang) {
443
+ runtimePackLang = resolvePackLanguage(lang);
444
+ }
445
+ function createPackTranslator(lang) {
446
+ const currentLang = resolvePackLanguage(lang);
447
+ return (key, params) => {
448
+ var _a, _b;
449
+ const template = (_b = (_a = messages[currentLang][key]) !== null && _a !== void 0 ? _a : messages['en-US'][key]) !== null && _b !== void 0 ? _b : key;
450
+ return format(template, params);
451
+ };
452
+ }
453
+ function getPackTranslator() {
454
+ return createPackTranslator(runtimePackLang);
455
+ }
456
+
281
457
  const uselessFiles = ['.DS_Store', 'Thumbs.db'];
282
458
  function removeSystemUseless(gameEntry, uselessDirs) {
459
+ const t = getPackTranslator();
283
460
  const progress = {
284
461
  total: 0,
285
462
  processed: 0,
@@ -292,10 +469,13 @@ function removeSystemUseless(gameEntry, uselessDirs) {
292
469
  try {
293
470
  files = fs.readdirSync(gameEntry);
294
471
  progress.total = files.length;
295
- logger.info(`开始清理无用文件,共 ${progress.total} 个条目`);
472
+ logger.info(t('log.cleanup.start', { total: progress.total }));
296
473
  }
297
474
  catch (err) {
298
- logger.warn(`无法访问目录: ${gameEntry}, ${err.message}`);
475
+ logger.warn(t('log.cleanup.accessDirFailed', {
476
+ dir: gameEntry,
477
+ error: err.message,
478
+ }));
299
479
  progress.errors++;
300
480
  return progress;
301
481
  }
@@ -309,21 +489,24 @@ function removeSystemUseless(gameEntry, uselessDirs) {
309
489
  logger.debug(`正在删除目录: ${filePath}`);
310
490
  fs.rmSync(filePath, { recursive: true, force: true });
311
491
  progress.deletedDirs++;
312
- logger.info(`✅ 已删除无用目录: ${filePath}`);
492
+ logger.info(t('log.cleanup.deletedDir', { path: filePath }));
313
493
  }
314
494
  else if (stat.isFile() && uselessFiles.includes(file)) {
315
495
  // 删除无用文件
316
496
  logger.debug(`正在删除文件: ${filePath}`);
317
497
  fs.rmSync(filePath, { force: true });
318
498
  progress.deletedFiles++;
319
- logger.info(`✅ 已删除无用文件: ${filePath}`);
499
+ logger.info(t('log.cleanup.deletedFile', { path: filePath }));
320
500
  }
321
501
  else {
322
502
  logger.debug(`跳过: ${filePath} (非目标文件/目录)`);
323
503
  }
324
504
  }
325
505
  catch (err) {
326
- logger.warn(`❌ 无法处理: ${filePath}, ${err.message}`);
506
+ logger.warn(t('log.cleanup.processFailed', {
507
+ path: filePath,
508
+ error: err.message,
509
+ }));
327
510
  progress.errors++;
328
511
  }
329
512
  // 更新进度
@@ -331,15 +514,23 @@ function removeSystemUseless(gameEntry, uselessDirs) {
331
514
  // 可选:每处理10个条目输出一次进度
332
515
  if ((index + 1) % 10 === 0 || index + 1 === progress.total) {
333
516
  const percentage = Math.round(((index + 1) / progress.total) * 100);
334
- logger.info(`进度: ${index + 1}/${progress.total} (${percentage}%)`);
517
+ logger.info(t('log.cleanup.progress', {
518
+ processed: index + 1,
519
+ total: progress.total,
520
+ percentage,
521
+ }));
335
522
  }
336
523
  });
337
524
  // 3. 输出总结
338
- logger.info(`清理完成!`);
339
- logger.info(`- 总条目: ${progress.total}`);
340
- logger.info(`- 已删除目录: ${progress.deletedDirs}`);
341
- logger.info(`- 已删除文件: ${progress.deletedFiles}`);
342
- logger.info(`- 错误数: ${progress.errors}`);
525
+ logger.info(t('log.cleanup.done'));
526
+ logger.info(t('log.cleanup.summary.total', { total: progress.total }));
527
+ logger.info(t('log.cleanup.summary.deletedDirs', {
528
+ deletedDirs: progress.deletedDirs,
529
+ }));
530
+ logger.info(t('log.cleanup.summary.deletedFiles', {
531
+ deletedFiles: progress.deletedFiles,
532
+ }));
533
+ logger.info(t('log.cleanup.summary.errors', { errors: progress.errors }));
343
534
  return progress;
344
535
  }
345
536
 
@@ -459,8 +650,9 @@ function ensureOnce(fn) {
459
650
  // 它会执行一次 esbuild.build,目的是为了“唤醒”并安全地启动 esbuild 的后台服务。
460
651
  // 我们选择一个几乎无害的操作,比如转换一个空字符串。
461
652
  const initializeEsbuild = async () => {
653
+ const t = getPackTranslator();
462
654
  try {
463
- logger.info('Attempting to initialize esbuild service...');
655
+ logger.info(t('log.safeBuild.initStart'));
464
656
  // 执行一个非常轻量的 build 操作来触发服务启动。
465
657
  await esbuild.build({
466
658
  stdin: { contents: '' },
@@ -468,10 +660,10 @@ const initializeEsbuild = async () => {
468
660
  bundle: false,
469
661
  logLevel: "silent"
470
662
  });
471
- logger.info('esbuild service initialized successfully.');
663
+ logger.info(t('log.safeBuild.initSuccess'));
472
664
  }
473
665
  catch (e) {
474
- logger.error('Failed to initialize esbuild service:');
666
+ logger.error(t('log.safeBuild.initFailed'));
475
667
  // 如果初始化失败,允许重试
476
668
  throw e;
477
669
  }
@@ -888,27 +1080,28 @@ async function buildOdrPkgs({ tempDir }) {
888
1080
  const defaultCheckConfig$3 = {
889
1081
  name: 'project',
890
1082
  dimension: CHECK_DIMENSION.Project,
1083
+ required: true,
891
1084
  };
892
- function checkProject(config) {
893
- logger.info('start check project');
894
- const gameJsonCheckResult = checkGameJson(config);
895
- const checkSizeResult = checkProjectSize(config);
896
- const checkPerfResult = checkPerformance(config);
1085
+ function checkProject(config, t) {
1086
+ logger.info(t('log.check.project.start'));
1087
+ const gameJsonCheckResult = checkGameJson(config, t);
1088
+ const checkSizeResult = checkProjectSize(config, t);
1089
+ const checkPerfResult = checkPerformance(config, t);
897
1090
  /**
898
1091
  * 过滤掉空的
899
1092
  */
900
1093
  const result = [gameJsonCheckResult, checkSizeResult, checkPerfResult].filter(Boolean);
901
1094
  if (result.every(item => item.passed)) {
902
- logger.info('check project successfully');
1095
+ logger.info(t('log.check.project.success'));
903
1096
  }
904
1097
  return result;
905
1098
  }
906
- function checkGameJson(config) {
1099
+ function checkGameJson(config, t) {
907
1100
  var _a, _b;
908
- logger.info('start check config');
1101
+ logger.info(t('log.check.config.start'));
909
1102
  const gameJsonPath = path.join(config.entry, GAME_ORIGIN_CONFIG_FILE_NAME);
910
1103
  if (!fs.existsSync(gameJsonPath)) {
911
- const errMsg = 'Can not find game.json in game source code, please check it';
1104
+ const errMsg = t('check.project.gameJson.missing');
912
1105
  logger.error(errMsg);
913
1106
  if ((_a = config === null || config === void 0 ? void 0 : config.dev) === null || _a === void 0 ? void 0 : _a.enable) {
914
1107
  return Object.assign({ passed: false, msg: errMsg, type: 'config', level: 'error', file: GAME_ORIGIN_CONFIG_FILE_NAME, name: 'project' }, defaultCheckConfig$3);
@@ -920,7 +1113,7 @@ function checkGameJson(config) {
920
1113
  else {
921
1114
  const gameJson = JSON.parse(fs.readFileSync(gameJsonPath, 'utf-8'));
922
1115
  if (gameJson.subPackages) {
923
- const errMsg = `'subPackages' is found in ${GAME_ORIGIN_CONFIG_FILE_NAME}. Please use 'subpackages' (all lowercase) instead.`;
1116
+ const errMsg = t('check.project.gameJson.subPackagesInvalid');
924
1117
  logger.error(errMsg);
925
1118
  if ((_b = config === null || config === void 0 ? void 0 : config.dev) === null || _b === void 0 ? void 0 : _b.enable) {
926
1119
  return Object.assign({ passed: false, msg: errMsg, type: 'config', name: 'project', level: 'error', file: GAME_ORIGIN_CONFIG_FILE_NAME }, defaultCheckConfig$3);
@@ -929,7 +1122,7 @@ function checkGameJson(config) {
929
1122
  throw new Error(errMsg);
930
1123
  }
931
1124
  }
932
- const msg = 'Check game.json config successfully';
1125
+ const msg = t('check.project.gameJson.success');
933
1126
  logger.info(msg);
934
1127
  return Object.assign({ passed: true, msg, type: 'config', level: 'info', file: GAME_ORIGIN_CONFIG_FILE_NAME }, defaultCheckConfig$3);
935
1128
  }
@@ -939,8 +1132,8 @@ function checkGameJson(config) {
939
1132
  * @param param0
940
1133
  * @returns
941
1134
  */
942
- function checkProjectSize(config) {
943
- logger.info('start check project size');
1135
+ function checkProjectSize(config, t) {
1136
+ logger.info(t('log.check.projectSize.start'));
944
1137
  const { entry: entryDir, dev } = config;
945
1138
  const { pkgSizeLimit } = getCheckConfig(config);
946
1139
  const enableDev = dev === null || dev === void 0 ? void 0 : dev.enable;
@@ -948,7 +1141,7 @@ function checkProjectSize(config) {
948
1141
  const gameSizeMB = (gameSize / (1024 * 1024)).toFixed(2);
949
1142
  const limitMB = (pkgSizeLimit / (1024 * 1024)).toFixed(2);
950
1143
  if (gameSize > pkgSizeLimit) {
951
- const errMsg = `Check project size failed, size: ${gameSizeMB}MB, must not exceed ${limitMB}MB`;
1144
+ const errMsg = t('check.project.size.failed', { sizeMB: gameSizeMB, limitMB });
952
1145
  logger.error(errMsg);
953
1146
  if (enableDev) {
954
1147
  return Object.assign({ passed: false, name: 'project', msg: errMsg, type: 'size', level: 'warning', size: gameSize }, defaultCheckConfig$3);
@@ -961,23 +1154,30 @@ function checkProjectSize(config) {
961
1154
  /**
962
1155
  * 游戏大小检查通过
963
1156
  */
964
- const logMsg = `Check project size successfully, size: ${gameSizeMB}MB`;
1157
+ const logMsg = t('check.project.size.success', { sizeMB: gameSizeMB });
965
1158
  logger.info(logMsg);
966
1159
  return Object.assign({ passed: true, msg: logMsg, name: 'project', type: 'size', level: 'info', size: gameSize }, defaultCheckConfig$3);
967
1160
  }
968
1161
  }
969
- function checkPerformance(config) {
1162
+ function checkPerformance(config, t) {
970
1163
  const { entry } = config;
971
1164
  if (!isUnityEngine(entry)) {
972
1165
  return null;
973
1166
  }
974
1167
  const gameJsonPath = path.join(entry, GAME_ORIGIN_CONFIG_FILE_NAME);
975
1168
  const gameJson = JSON.parse(fs.readFileSync(gameJsonPath, 'utf-8'));
976
- if ((gameJson === null || gameJson === void 0 ? void 0 : gameJson.wasmFuncCount) < 80000) {
977
- return Object.assign(Object.assign({}, defaultCheckConfig$3), { passed: true, msg: `wasmFuncCount < 80000, no need to split wasm code`, type: 'performance', level: 'info', name: 'project' });
1169
+ if (!('wasmFuncCount' in gameJson)) {
1170
+ return null;
1171
+ }
1172
+ if ((gameJson === null || gameJson === void 0 ? void 0 : gameJson.wasmFuncCount) < WASM_FUNC_COUNT_LIMIT) {
1173
+ return Object.assign(Object.assign({}, defaultCheckConfig$3), { passed: true, msg: t('check.project.perf.noSplitNeeded', {
1174
+ limit: WASM_FUNC_COUNT_LIMIT,
1175
+ }), type: 'performance', level: 'info', name: 'project' });
978
1176
  }
979
1177
  const splitConfigPath = path.join(entry, GAME_WASM_SPLIT_CONFIG_FILE_NAME);
980
- const errResult = Object.assign(Object.assign({}, defaultCheckConfig$3), { passed: false, msg: 'The Wasm function count in wasmcode/ exceeds 80,000. Please enable code splitting to optimize performance.', type: 'performance', level: 'warning', name: 'project' });
1178
+ const errResult = Object.assign(Object.assign({}, defaultCheckConfig$3), { passed: false, msg: t('check.project.perf.needSplit', {
1179
+ limit: WASM_FUNC_COUNT_LIMIT,
1180
+ }), type: 'performance', level: 'warning', name: 'project' });
981
1181
  if (!fs.existsSync(splitConfigPath)) {
982
1182
  return errResult;
983
1183
  }
@@ -986,28 +1186,34 @@ function checkPerformance(config) {
986
1186
  return errResult;
987
1187
  }
988
1188
  else {
989
- return Object.assign(Object.assign({}, defaultCheckConfig$3), { passed: true, msg: 'wasmFuncCount >= 80000, wasm split is enabled', type: 'performance', level: 'info', name: 'project' });
1189
+ return Object.assign(Object.assign({}, defaultCheckConfig$3), { passed: true, msg: t('check.project.perf.splitEnabled', {
1190
+ limit: WASM_FUNC_COUNT_LIMIT,
1191
+ }), type: 'performance', level: 'info', name: 'project' });
990
1192
  }
991
1193
  }
992
1194
 
993
1195
  const defaultCheckConfig$2 = {
994
1196
  name: 'main',
995
1197
  dimension: CHECK_DIMENSION.MainPackage,
1198
+ required: true,
996
1199
  };
997
1200
  /**
998
1201
  * 检查主包大小是否超出限制
999
1202
  * @param param0
1000
1203
  * @returns
1001
1204
  */
1002
- function checkMainPackageSize(config) {
1003
- logger.info('start check main package size');
1205
+ function checkMainPackageSize(config, t) {
1206
+ logger.info(t('log.check.mainPackageSize.start'));
1004
1207
  const { entry: entryDir, dev } = config;
1005
1208
  const { mainPkgSizeLimit } = getCheckConfig(config);
1006
1209
  const mainPkgSize = getMainPkgSize({ entryDir });
1007
1210
  const mainPkgSizeMB = (mainPkgSize / (1024 * 1024)).toFixed(2);
1008
1211
  const limitMB = (mainPkgSizeLimit / (1024 * 1024)).toFixed(2);
1009
1212
  if (mainPkgSize > mainPkgSizeLimit) {
1010
- const errMsg = `Check main package size failed, main package size ${mainPkgSizeMB}MB, must not exceed ${limitMB}MB`;
1213
+ const errMsg = t('check.main.size.failed', {
1214
+ sizeMB: mainPkgSizeMB,
1215
+ limitMB,
1216
+ });
1011
1217
  logger.error(errMsg);
1012
1218
  if (dev === null || dev === void 0 ? void 0 : dev.enable) {
1013
1219
  return Object.assign({ passed: false, msg: errMsg, size: mainPkgSize, type: 'size', level: 'warning' }, defaultCheckConfig$2);
@@ -1017,37 +1223,40 @@ function checkMainPackageSize(config) {
1017
1223
  }
1018
1224
  }
1019
1225
  else {
1020
- return Object.assign({ passed: true, msg: `Check main package size successfully, size: ${mainPkgSizeMB}MB`, size: mainPkgSize, type: 'size', level: 'info' }, defaultCheckConfig$2);
1226
+ return Object.assign({ passed: true, msg: t('check.main.size.success', {
1227
+ sizeMB: mainPkgSizeMB,
1228
+ }), size: mainPkgSize, type: 'size', level: 'info' }, defaultCheckConfig$2);
1021
1229
  }
1022
1230
  }
1023
- function checkMainPackageEntry(config) {
1231
+ function checkMainPackageEntry(config, t) {
1024
1232
  var _a;
1025
- logger.info('start check main package entry');
1233
+ logger.info(t('log.check.mainPackageEntry.start'));
1026
1234
  const { entry: entryDir } = config;
1027
1235
  const gameJsPath = path__namespace.join(entryDir, 'game.js');
1028
1236
  if (!fs__namespace.existsSync(gameJsPath)) {
1029
- const errMsg = 'Check main package entry failed, game.js must exist in main package!';
1237
+ const errMsg = t('check.main.entry.missing');
1030
1238
  logger.error(errMsg);
1031
1239
  if ((_a = config.dev) === null || _a === void 0 ? void 0 : _a.enable) {
1032
1240
  return Object.assign({ passed: false, msg: errMsg, type: 'config', level: 'error', file: 'game.js' }, defaultCheckConfig$2);
1033
1241
  }
1242
+ throw new Error(errMsg);
1034
1243
  }
1035
- logger.info('check game.js successfully');
1036
- return Object.assign({ passed: true, msg: 'Check main package entry successfully, game.js must exist in main package!', type: 'config', level: 'info', file: 'game.js' }, defaultCheckConfig$2);
1244
+ logger.info(t('log.check.mainPackageEntry.success'));
1245
+ return Object.assign({ passed: true, msg: t('check.main.entry.success'), type: 'config', level: 'info', file: 'game.js' }, defaultCheckConfig$2);
1037
1246
  }
1038
- function checkMainPackage(config) {
1247
+ function checkMainPackage(config, t) {
1039
1248
  var _a;
1040
1249
  const checkResults = [];
1041
- logger.info('start check main package');
1250
+ logger.info(t('log.check.mainPackage.start'));
1042
1251
  /**
1043
1252
  * 检查 game.js 是否存在
1044
1253
  */
1045
- checkResults.push(checkMainPackageEntry(config));
1254
+ checkResults.push(checkMainPackageEntry(config, t));
1046
1255
  if ((_a = getCheckConfig(config)) === null || _a === void 0 ? void 0 : _a.mainPkgSizeLimit) {
1047
- checkResults.push(checkMainPackageSize(config));
1256
+ checkResults.push(checkMainPackageSize(config, t));
1048
1257
  }
1049
1258
  if (checkResults.every(item => item.passed)) {
1050
- logger.info('Check main package successfully');
1259
+ logger.info(t('log.check.mainPackage.success'));
1051
1260
  }
1052
1261
  return checkResults;
1053
1262
  }
@@ -1061,15 +1270,16 @@ function isValidPath(path) {
1061
1270
  const defaultCheckConfig$1 = {
1062
1271
  name: 'subpackage',
1063
1272
  dimension: 'subpackage',
1273
+ required: true,
1064
1274
  };
1065
- function checkSubpackages(config) {
1275
+ function checkSubpackages(config, t) {
1066
1276
  const { entry: entryDir } = config;
1067
1277
  const checkResults = [];
1068
1278
  /**
1069
1279
  * 校验 subpackage 大小
1070
1280
  * 开始校验 subpackages 配置是否有效
1071
1281
  */
1072
- logger.info('start check subpackages in game.json');
1282
+ logger.info(t('log.check.subpackages.start'));
1073
1283
  const subpackages = getSubpackagesConfig(entryDir);
1074
1284
  subpackages.forEach(sub => {
1075
1285
  var _a, _b, _c;
@@ -1077,7 +1287,7 @@ function checkSubpackages(config) {
1077
1287
  * 校验 subpackage 配置是否为空
1078
1288
  */
1079
1289
  if (!sub.name || !sub.root) {
1080
- const errMsg = 'Check subpackages config failed, the subpackages configuration in game.json is invalid: the root or name field in one or more subpackages is empty. Please ensure that all subpackages have non-empty root and name values.';
1290
+ const errMsg = t('check.subpackages.config.empty');
1081
1291
  logger.error(errMsg);
1082
1292
  if ((_a = config === null || config === void 0 ? void 0 : config.dev) === null || _a === void 0 ? void 0 : _a.enable) {
1083
1293
  checkResults.push(Object.assign({ passed: false, msg: errMsg, type: 'config', level: 'error', file: GAME_ORIGIN_CONFIG_FILE_NAME }, defaultCheckConfig$1));
@@ -1087,7 +1297,16 @@ function checkSubpackages(config) {
1087
1297
  }
1088
1298
  }
1089
1299
  else if (!isValidPath(sub.root) || !isValidPath(sub.name)) {
1090
- const errMsg = `Check subpackages config failed, the subpackages configuration in game.json is invalid: the root field in subpackage<${sub.name}> is invalid. Your subpackage root contain invalid characters, only A-Za-z0-9 _ - . / \\ are allowed.`;
1300
+ const invalidFields = [
1301
+ !isValidPath(sub.root) ? 'root' : '',
1302
+ !isValidPath(sub.name) ? 'name' : '',
1303
+ ]
1304
+ .filter(Boolean)
1305
+ .join('/');
1306
+ const errMsg = t('check.subpackages.config.invalidPath', {
1307
+ name: sub.name,
1308
+ invalidFields,
1309
+ });
1091
1310
  logger.error(errMsg);
1092
1311
  if ((_b = config === null || config === void 0 ? void 0 : config.dev) === null || _b === void 0 ? void 0 : _b.enable) {
1093
1312
  checkResults.push(Object.assign({ passed: false, msg: errMsg, type: 'config', level: 'error', file: GAME_ORIGIN_CONFIG_FILE_NAME }, defaultCheckConfig$1));
@@ -1097,7 +1316,9 @@ function checkSubpackages(config) {
1097
1316
  }
1098
1317
  }
1099
1318
  else {
1100
- checkResults.push(Object.assign({ passed: true, msg: `Check subpackage<${sub.name}> config successfully`, type: 'config', level: 'error', file: GAME_ORIGIN_CONFIG_FILE_NAME }, defaultCheckConfig$1));
1319
+ checkResults.push(Object.assign({ passed: true, msg: t('check.subpackages.config.success', {
1320
+ name: sub.name,
1321
+ }), type: 'config', level: 'error', file: GAME_ORIGIN_CONFIG_FILE_NAME }, defaultCheckConfig$1));
1101
1322
  }
1102
1323
  /**
1103
1324
  * 校验 subpackage 配置是否有效
@@ -1105,7 +1326,9 @@ function checkSubpackages(config) {
1105
1326
  const subpackageEntryDir = path.join(entryDir, sub.root);
1106
1327
  // 检查是文件或者文件夹是否存在
1107
1328
  if (!fs.existsSync(subpackageEntryDir)) {
1108
- const errMsg = `Check subpackage<${sub.name}> config failed, the subpackages configuration in game.json is invalid: can not find subpackage ${sub.name} entry dir, please check it`;
1329
+ const errMsg = t('check.subpackages.config.missingDir', {
1330
+ name: sub.name,
1331
+ });
1109
1332
  logger.error(errMsg);
1110
1333
  if ((_c = config === null || config === void 0 ? void 0 : config.dev) === null || _c === void 0 ? void 0 : _c.enable) {
1111
1334
  checkResults.push(Object.assign({ passed: false, msg: errMsg, type: 'config', level: 'error', file: GAME_ORIGIN_CONFIG_FILE_NAME }, defaultCheckConfig$1));
@@ -1115,19 +1338,22 @@ function checkSubpackages(config) {
1115
1338
  }
1116
1339
  }
1117
1340
  else {
1118
- checkResults.push(Object.assign({ passed: true, msg: `Check subpackage<${sub.name}> config successfully`, type: 'config', level: 'error', file: GAME_ORIGIN_CONFIG_FILE_NAME }, defaultCheckConfig$1));
1341
+ checkResults.push(Object.assign({ passed: true, msg: t('check.subpackages.config.success', {
1342
+ name: sub.name,
1343
+ }), type: 'config', level: 'error', file: GAME_ORIGIN_CONFIG_FILE_NAME }, defaultCheckConfig$1));
1119
1344
  }
1120
1345
  });
1121
1346
  if (checkResults.length && checkResults.every(item => item.passed)) {
1122
- logger.info('Check subpackages config successfully');
1347
+ logger.info(t('log.check.subpackages.success'));
1123
1348
  }
1124
1349
  return checkResults;
1125
1350
  }
1126
1351
 
1127
1352
  const defaultCheckConfig = {
1128
1353
  dimension: CHECK_DIMENSION.IndependentPackage,
1354
+ required: true,
1129
1355
  };
1130
- function checkIndependentPackages(config) {
1356
+ function checkIndependentPackages(config, t) {
1131
1357
  var _a;
1132
1358
  const { entry: entryDir } = config;
1133
1359
  const isEnableDev = (_a = config === null || config === void 0 ? void 0 : config.dev) === null || _a === void 0 ? void 0 : _a.enable;
@@ -1135,14 +1361,14 @@ function checkIndependentPackages(config) {
1135
1361
  /**
1136
1362
  * 开始校验 subpackages 配置是否有效
1137
1363
  */
1138
- logger.info('start check independent subpackages in game.json');
1364
+ logger.info(t('log.check.independent.start'));
1139
1365
  const independentSubpackages = getIndependentPackagesConfig(entryDir);
1140
1366
  independentSubpackages.forEach(sub => {
1141
1367
  /**
1142
1368
  * 校验 independent subpackage 配置是否为空
1143
1369
  */
1144
1370
  if (!sub.name || !sub.root) {
1145
- const errMsg = 'Check independent subpackages config failed, the subpackages configuration in game.json is invalid: the root or name field in one or more independent subpackages is empty. Please ensure that all independent subpackages have non-empty root and name values.';
1371
+ const errMsg = t('check.independent.config.empty');
1146
1372
  logger.error(errMsg);
1147
1373
  if (isEnableDev) {
1148
1374
  checkResults.push(Object.assign(Object.assign({}, defaultCheckConfig), { passed: false, msg: errMsg, type: 'config', level: 'error', file: GAME_ORIGIN_CONFIG_FILE_NAME, name: sub.name }));
@@ -1152,7 +1378,9 @@ function checkIndependentPackages(config) {
1152
1378
  }
1153
1379
  }
1154
1380
  else {
1155
- checkResults.push(Object.assign(Object.assign({}, defaultCheckConfig), { passed: true, msg: `Check independent package<${sub.name}> config successfully`, type: 'config', level: 'error', file: GAME_ORIGIN_CONFIG_FILE_NAME, name: sub.name }));
1381
+ checkResults.push(Object.assign(Object.assign({}, defaultCheckConfig), { passed: true, msg: t('check.independent.config.success', {
1382
+ name: sub.name,
1383
+ }), type: 'config', level: 'error', file: GAME_ORIGIN_CONFIG_FILE_NAME, name: sub.name }));
1156
1384
  }
1157
1385
  /**
1158
1386
  * 校验 independent subpackage 配置是否有效
@@ -1160,7 +1388,9 @@ function checkIndependentPackages(config) {
1160
1388
  const subpackageEntryDir = path.join(entryDir, sub.root);
1161
1389
  // 检查是文件或者文件夹是否存在
1162
1390
  if (!fs.existsSync(subpackageEntryDir)) {
1163
- const errMsg = `Check independent package<${sub.name}> config failed, the subpackages configuration in game.json is invalid: can not find subpackage ${sub.name} entry dir, please check it`;
1391
+ const errMsg = t('check.independent.config.missingDir', {
1392
+ name: sub.name,
1393
+ });
1164
1394
  logger.error(errMsg);
1165
1395
  if (isEnableDev) {
1166
1396
  checkResults.push(Object.assign(Object.assign({}, defaultCheckConfig), { passed: false, msg: errMsg, type: 'config', level: 'error', file: GAME_ORIGIN_CONFIG_FILE_NAME, name: sub.name }));
@@ -1172,11 +1402,14 @@ function checkIndependentPackages(config) {
1172
1402
  else {
1173
1403
  checkResults.push({
1174
1404
  passed: true,
1175
- msg: `Check independent package<${sub.name}> config successfully`,
1405
+ msg: t('check.independent.config.success', {
1406
+ name: sub.name,
1407
+ }),
1176
1408
  type: 'config',
1177
1409
  level: 'error',
1178
1410
  file: GAME_ORIGIN_CONFIG_FILE_NAME,
1179
1411
  dimension: CHECK_DIMENSION.IndependentPackage,
1412
+ required: true,
1180
1413
  name: sub.name,
1181
1414
  });
1182
1415
  }
@@ -1191,6 +1424,7 @@ function checkIndependentPackages(config) {
1191
1424
  limit: independentSubPkgSizeLimit,
1192
1425
  dimension: CHECK_DIMENSION.IndependentPackage,
1193
1426
  level: isEnableDev ? 'warning' : 'error',
1427
+ t,
1194
1428
  });
1195
1429
  checkResults.push(checkSizeResult);
1196
1430
  logger.info(checkSizeResult.msg);
@@ -1203,11 +1437,11 @@ function checkIndependentPackages(config) {
1203
1437
  }
1204
1438
  });
1205
1439
  if (checkResults.length && checkResults.every(item => item.passed)) {
1206
- logger.info('Check independent subpackages config successfully');
1440
+ logger.info(t('log.check.independent.success'));
1207
1441
  }
1208
1442
  return checkResults;
1209
1443
  }
1210
- function checkPkgSize({ entryDir, limit, pkgName, dimension, level, }) {
1444
+ function checkPkgSize({ entryDir, limit, pkgName, dimension, level, t, }) {
1211
1445
  const size = getDirSizeSync({
1212
1446
  rootDir: entryDir,
1213
1447
  entryDir,
@@ -1218,12 +1452,20 @@ function checkPkgSize({ entryDir, limit, pkgName, dimension, level, }) {
1218
1452
  return {
1219
1453
  passed,
1220
1454
  msg: passed
1221
- ? `Check package ${pkgName} size ${sizeMB.toFixed(2)}MB check successfully`
1222
- : `Check package ${pkgName} size ${sizeMB.toFixed(2)}MB exceeds limit ${limitMB.toFixed(2)}MB`,
1455
+ ? t('check.pkgSize.success', {
1456
+ pkgName,
1457
+ sizeMB: sizeMB.toFixed(2),
1458
+ })
1459
+ : t('check.pkgSize.exceeds', {
1460
+ pkgName,
1461
+ sizeMB: sizeMB.toFixed(2),
1462
+ limitMB: limitMB.toFixed(2),
1463
+ }),
1223
1464
  type: 'size',
1224
1465
  level,
1225
1466
  size,
1226
1467
  dimension,
1468
+ required: true,
1227
1469
  name: pkgName,
1228
1470
  };
1229
1471
  }
@@ -1257,7 +1499,7 @@ const API_LIST = [
1257
1499
  desc: "Get entrance mission reward"
1258
1500
  }
1259
1501
  ];
1260
- function checkAPI(config) {
1502
+ function checkAPI(config, t) {
1261
1503
  var _a;
1262
1504
  if (!((_a = config === null || config === void 0 ? void 0 : config.build) === null || _a === void 0 ? void 0 : _a.enableAPICheck)) {
1263
1505
  return [];
@@ -1325,10 +1567,13 @@ function checkAPI(config) {
1325
1567
  }
1326
1568
  const results = API_LIST.map(({ name }) => {
1327
1569
  const files = Array.from(hitFilesMap.get(name) || []);
1570
+ const passed = files.length > 0;
1328
1571
  return {
1329
1572
  name,
1330
- msg: `${files.length > 0 ? `${name} integrated!` : `${name} not integrated!`}`,
1331
- passed: files.length > 0,
1573
+ msg: passed
1574
+ ? t('check.api.integrated', { name })
1575
+ : `${t('check.api.notIntegrated', { name })} ${t('check.api.suggestedActionSuffix')}`,
1576
+ passed,
1332
1577
  files,
1333
1578
  type: 'api',
1334
1579
  level: 'warning',
@@ -1345,28 +1590,30 @@ function escapeRegex(s) {
1345
1590
  return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1346
1591
  }
1347
1592
 
1348
- async function checkPkgs(config) {
1349
- logger.info('开始校验项目');
1593
+ async function checkPkgs(config, context = {}) {
1594
+ setPackRuntimeLanguage(context === null || context === void 0 ? void 0 : context.lang);
1595
+ const t = createPackTranslator(context === null || context === void 0 ? void 0 : context.lang);
1596
+ logger.info(getPackTranslator()('log.check.start'));
1350
1597
  /**
1351
1598
  * 1. 校验项目
1352
1599
  */
1353
- const projectCheckResult = checkProject(config);
1600
+ const projectCheckResult = checkProject(config, t);
1354
1601
  /**
1355
1602
  * 2. 如果有,校验分包
1356
1603
  */
1357
- const subpackagesCheckResult = checkSubpackages(config);
1604
+ const subpackagesCheckResult = checkSubpackages(config, t);
1358
1605
  /**
1359
1606
  * 3. 校验主包
1360
1607
  */
1361
- const mainPackageCheckResult = checkMainPackage(config);
1608
+ const mainPackageCheckResult = checkMainPackage(config, t);
1362
1609
  /**
1363
1610
  * 校验独立分包
1364
1611
  */
1365
- const independentPackagesCheckResult = checkIndependentPackages(config);
1612
+ const independentPackagesCheckResult = checkIndependentPackages(config, t);
1366
1613
  /**
1367
1614
  * 校验 API 调用
1368
1615
  */
1369
- const apiCheckResult = checkAPI(config);
1616
+ const apiCheckResult = checkAPI(config, t);
1370
1617
  return [
1371
1618
  ...projectCheckResult,
1372
1619
  ...mainPackageCheckResult,
@@ -1377,8 +1624,9 @@ async function checkPkgs(config) {
1377
1624
  }
1378
1625
 
1379
1626
  async function setup(config) {
1627
+ const t = getPackTranslator();
1380
1628
  const { entry: entryDir, output: outputDir } = config;
1381
- logger.info('开始基于源代码中的 game.json 生成 packageConfig.json');
1629
+ logger.info(t('log.setup.startGeneratePackageConfig'));
1382
1630
  const gameJsonPath = path.join(entryDir, GAME_ORIGIN_CONFIG_FILE_NAME);
1383
1631
  const gameJson = JSON.parse(fs.readFileSync(gameJsonPath, 'utf-8'));
1384
1632
  const packages = {};
@@ -1429,7 +1677,7 @@ async function setup(config) {
1429
1677
  }
1430
1678
  fs.mkdirSync(outputDir);
1431
1679
  fs.writeFileSync(path.join(outputDir, GAME_PACK_CONFIG_FILE_NAME), JSON.stringify(result, null, 2));
1432
- logger.info('基于源代码中的 game.json 生成 packageConfig.json 成功');
1680
+ logger.info(t('log.setup.generatePackageConfigSuccess'));
1433
1681
  return result;
1434
1682
  }
1435
1683
  function transformSubPackages(configs) {
@@ -1506,8 +1754,9 @@ function collectPkgJsFiles({ entry, root, exts = ['.js', '.ts', '.jsx', '.tsx'],
1506
1754
  }
1507
1755
  // 构建每个包的 map
1508
1756
  function collectMaps(config, packages) {
1757
+ const t = getPackTranslator();
1509
1758
  const { entry: entryDir } = config;
1510
- logger.info('开始基于游戏源代码收集分包中的 JS 文件');
1759
+ logger.info(t('log.collectMaps.start'));
1511
1760
  const result = {};
1512
1761
  // 1. 先收集所有分包根目录名(如 subpackages/level1、subpackages/level2)
1513
1762
  const subRoots = Object.values(packages)
@@ -1525,7 +1774,9 @@ function collectMaps(config, packages) {
1525
1774
  });
1526
1775
  if (openDataContextEntry) {
1527
1776
  uniqueSubRoots.push(openDataContextEntry);
1528
- logger.info(`开放数据域目录:${openDataContextEntry}`);
1777
+ logger.info(t('log.collectMaps.openDataContextDir', {
1778
+ dir: openDataContextEntry,
1779
+ }));
1529
1780
  }
1530
1781
  // 主包:只收集 entryDir 下非分包目录, 并排除 开放数据域的文件夹目录(如果有)
1531
1782
  jsFiles = collectPkgJsFiles({
@@ -1556,7 +1807,7 @@ function collectMaps(config, packages) {
1556
1807
  [packNameRoot ? `${packNameRoot}/game.pack.js` : 'game.pack.js']: list,
1557
1808
  };
1558
1809
  }
1559
- logger.info('基于游戏源代码收集分包中的 JS 文件完成');
1810
+ logger.info(t('log.collectMaps.done'));
1560
1811
  return result;
1561
1812
  }
1562
1813
 
@@ -1811,8 +2062,9 @@ function fileExistsWithExtensions(filePath) {
1811
2062
 
1812
2063
  async function pack({ gameEntry, pkgName, allDeps, allMaps, pkgConfig, destRoot, config, }) {
1813
2064
  var _a, _b, _c, _d;
2065
+ const t = getPackTranslator();
1814
2066
  let startTime = Date.now();
1815
- logger.info(`pack start,startTime:${startTime}`);
2067
+ logger.info(t('log.pack.start', { startTime }));
1816
2068
  const packMap = allMaps[pkgName];
1817
2069
  const moduleConfig = {
1818
2070
  main: pkgConfig.main,
@@ -1915,7 +2167,7 @@ async function pack({ gameEntry, pkgName, allDeps, allMaps, pkgConfig, destRoot,
1915
2167
  const fileContent = bundledCode + `\n//# sourceURL=${packFileName}`;
1916
2168
  fs.writeFileSync(outFile, fileContent, 'utf-8');
1917
2169
  }
1918
- logger.info(`pack end,packName:${pkgName}`);
2170
+ logger.info(t('log.pack.end', { pkgName }));
1919
2171
  }
1920
2172
  }
1921
2173
 
@@ -1955,9 +2207,10 @@ async function partition({ pkgRoot, destRoot, packedFiles, gameEntry, gameOutput
1955
2207
  }
1956
2208
 
1957
2209
  async function makePkgs(config) {
2210
+ const t = getPackTranslator();
1958
2211
  const { entry: gameEntry, output: gameOutput } = config;
1959
2212
  let startTime = Date.now();
1960
- logger.info(`pack start,startTime:${startTime}`);
2213
+ logger.info(t('log.makePkgs.start', { startTime }));
1961
2214
  const { packages } = await setup(config);
1962
2215
  const allDeps = await collectDeps(config, packages);
1963
2216
  const allMaps = collectMaps(config, packages);
@@ -1967,7 +2220,7 @@ async function makePkgs(config) {
1967
2220
  */
1968
2221
  await asyncPool$1(10, Object.keys(allMaps), async (pkgName) => {
1969
2222
  var _a;
1970
- logger.info(`开始基于游戏源代码打包,包名:${pkgName}`);
2223
+ logger.info(t('log.makePkgs.startPackBySource', { pkgName }));
1971
2224
  let startTime = Date.now();
1972
2225
  const pkgConfig = packages[pkgName];
1973
2226
  const pkgRoot = path.join(gameEntry, pkgConfig.root);
@@ -1997,17 +2250,24 @@ async function makePkgs(config) {
1997
2250
  });
1998
2251
  const pkgRootDir = path.join(gameOutput, pkgName);
1999
2252
  removeEmptyDir(pkgRootDir);
2000
- logger.info(`基于游戏源代码打包分包完成,包名:${pkgName}`);
2001
- logger.info(`基于游戏源代码打包分包耗时,包名:${pkgName},耗时:${Date.now() - startTime}ms`);
2253
+ logger.info(t('log.makePkgs.finishPackBySource', { pkgName }));
2254
+ logger.info(t('log.makePkgs.packBySourceCost', {
2255
+ pkgName,
2256
+ duration: Date.now() - startTime,
2257
+ }));
2002
2258
  });
2003
2259
  /**
2004
2260
  * build open data context
2005
2261
  */
2006
- logger.info(`开始基于开放数据域源代码打包`);
2262
+ logger.info(t('log.makePkgs.startOpenData'));
2007
2263
  startTime = Date.now();
2008
- logger.info(`基于开放数据域源代码打包完成`);
2009
- logger.info(`基于开放数据域源代码打包耗时,耗时:${Date.now() - startTime}ms`);
2010
- logger.info(`pack end,duration:${Date.now() - startTime}ms`);
2264
+ logger.info(t('log.makePkgs.finishOpenData'));
2265
+ logger.info(t('log.makePkgs.openDataCost', {
2266
+ duration: Date.now() - startTime,
2267
+ }));
2268
+ logger.info(t('log.makePkgs.end', {
2269
+ duration: Date.now() - startTime,
2270
+ }));
2011
2271
  return pkgOutput;
2012
2272
  }
2013
2273
 
@@ -2085,7 +2345,9 @@ async function clearPkgs(config, uselessDirs = ['node_modules', '__MACOSX']) {
2085
2345
  removeSystemUseless(config.entry, uselessDirs);
2086
2346
  }
2087
2347
 
2088
- async function debugPkgs(config) {
2348
+ async function debugPkgs(config, context = {}) {
2349
+ setPackRuntimeLanguage(context === null || context === void 0 ? void 0 : context.lang);
2350
+ const t = createPackTranslator(context === null || context === void 0 ? void 0 : context.lang);
2089
2351
  const { output: outputDir, dev: { enableLog }, } = config;
2090
2352
  logger.init(outputDir, enableLog);
2091
2353
  try {
@@ -2096,7 +2358,7 @@ async function debugPkgs(config) {
2096
2358
  /**
2097
2359
  * 校验
2098
2360
  */
2099
- const checkResults = await checkPkgs(config);
2361
+ const checkResults = await checkPkgs(config, context);
2100
2362
  /**
2101
2363
  * 如果有任何 error 类型的校验项失败,则不再继续后续流程,直接返回错误
2102
2364
  */
@@ -2107,7 +2369,7 @@ async function debugPkgs(config) {
2107
2369
  .join('\n');
2108
2370
  return {
2109
2371
  isSuccess: false,
2110
- errorMsg: `Project validation failed (Errors):\n${errorMsg}`,
2372
+ errorMsg: t('debug.validation.failed', { errorMsg }),
2111
2373
  checkResults,
2112
2374
  };
2113
2375
  }
@@ -2138,12 +2400,16 @@ async function debugPkgs(config) {
2138
2400
  }
2139
2401
  }
2140
2402
 
2141
- async function buildPkgs(config) {
2403
+ async function buildPkgs(config, context = {}) {
2404
+ setPackRuntimeLanguage(context === null || context === void 0 ? void 0 : context.lang);
2405
+ const t = getPackTranslator();
2142
2406
  const { output: outputDir, build } = config;
2143
2407
  let startTime = Date.now();
2144
2408
  logger.init(outputDir, true);
2145
- logger.info(`TTMG_PACK_VERSION: ${"0.3.10"}`);
2146
- logger.info(`pack start, startTime:${startTime}`);
2409
+ logger.info(t('log.build.version', {
2410
+ version: "0.4.3",
2411
+ }));
2412
+ logger.info(t('log.build.start', { startTime }));
2147
2413
  /**
2148
2414
  * 清理
2149
2415
  */
@@ -2151,7 +2417,7 @@ async function buildPkgs(config) {
2151
2417
  /**
2152
2418
  * 校验
2153
2419
  */
2154
- await checkPkgs(config);
2420
+ await checkPkgs(config, context);
2155
2421
  /**
2156
2422
  * 打包
2157
2423
  */
@@ -2165,7 +2431,7 @@ async function buildPkgs(config) {
2165
2431
  * 分拆 odr 包
2166
2432
  */
2167
2433
  }
2168
- logger.info(`pack end:${Date.now() - startTime}ms`);
2434
+ logger.info(t('log.build.end', { duration: Date.now() - startTime }));
2169
2435
  }
2170
2436
 
2171
2437
  async function getPkgs({ entryDir, }) {