diff --git a/js/i18n.js b/js/i18n.js
index 53d9abd..ba661b2 100644
--- a/js/i18n.js
+++ b/js/i18n.js
@@ -10,6 +10,7 @@ export const TRANSLATIONS = {
fr: { 'lang.name': 'Français' },
ja: { 'lang.name': '日本語' },
ko: { 'lang.name': '한국어' },
+ zh: { 'lang.name': '简体中文' },
};
// ── Module state ──────────────────────────────────────────────────────────────
diff --git a/js/i18n/zh.js b/js/i18n/zh.js
new file mode 100644
index 0000000..8a2234e
--- /dev/null
+++ b/js/i18n/zh.js
@@ -0,0 +1,210 @@
+export default {
+ "theme.dark": "深色主题",
+ "theme.light": "浅色主题",
+ "theme.toggleTitle": "切换浅色/深色模式",
+ "theme.toggleAriaLabel": "切换浅色/深色模式",
+ "dropHint.text": "将 .stl、.obj 或 .3mf 文件拖放到此处
或",
+ "ui.wireframe": "线框显示",
+ "ui.perspective": "透视视图",
+ "ui.controlsHint": "左键拖动:旋转 · 右键拖动:平移 · 滚轮:缩放",
+ "ui.meshInfo": "{n} 个三角形 · {mb} MB · {sx} × {sy} × {sz} mm",
+ "ui.loadStl": "加载模型…",
+ "ui.localProcessingNote": "所有处理都在您的浏览器中本地运行 — 不上传任何数据。",
+ "sections.displacementMap": "位移贴图",
+ "ui.uploadCustomMap": "上传自定义贴图",
+ "ui.noMapSelected": "未选择贴图",
+ "ui.customMap": "自定义贴图",
+ "ui.removeCustomMap": "移除自定义贴图",
+ "ui.loadingTextures": "正在加载纹理…",
+ "sections.projection": "投影",
+ "labels.mode": "模式",
+ "projection.triplanar": "三平面投影",
+ "projection.cubic": "立方体(盒子)",
+ "projection.cylindrical": "圆柱形",
+ "projection.spherical": "球形",
+ "projection.planarXY": "平面 XY",
+ "projection.planarXZ": "平面 XZ",
+ "projection.planarYZ": "平面 YZ",
+ "sections.transform": "变换",
+ "labels.scaleU": "缩放 U",
+ "labels.scaleV": "缩放 V",
+ "labels.offsetU": "偏移 U",
+ "labels.offsetV": "偏移 V",
+ "labels.rotation": "旋转",
+ "tooltips.proportionalScaling": "等比例缩放 (U = V)",
+ "tooltips.proportionalScalingAria": "等比例缩放 (U = V)",
+ "sections.displacement": "纹理深度",
+ "labels.textureHeight": "纹理高度 (mm)",
+ "labels.invertDisplacement": "反向(内推而非外推)",
+ "labels.seamBlend": "接缝混合 ⓘ",
+ "tooltips.seamBlend": "柔化投影面交接处的硬接缝。对立方体和圆柱形模式有效。",
+ "labels.transitionSmoothing": "过渡平滑 ⓘ",
+ "tooltips.transitionSmoothing": "接缝边缘附近混合区域的宽度。较低的值使过渡紧贴接缝;较高的值混合更宽的区域。",
+ "labels.textureSmoothing": "纹理平滑 ⓘ",
+ "tooltips.textureSmoothing": "对位移贴图应用高斯模糊。较高的值会产生更柔和、更渐进的表面细节。0 = 关闭。",
+ "labels.capAngle": "封盖角度 ⓘ",
+ "tooltips.capAngle": "与垂直方向的夹角(度),决定顶部/底部盖投影的生效范围。较小的值会将盖投影限制在接近平坦的面上。",
+ "sections.masking": "遮罩",
+ "sections.maskAngles": "按角度 ⓘ",
+ "tooltips.maskAngles": "0° = 无遮罩。与水平面夹角在此角度内的表面不会被纹理化。",
+ "labels.bottomFaces": "底面",
+ "tooltips.bottomFaces": "在与水平面夹角为此范围内的向下表面上抑制纹理",
+ "labels.topFaces": "顶面",
+ "tooltips.topFaces": "在与水平面夹角为此范围内的向上表面上抑制纹理",
+ "sections.surfaceMasking": "按表面 ⓘ",
+ "sections.surfaceSelection": "表面选择",
+ "tooltips.surfaceMasking": "遮罩表面,以控制哪些区域接收位移。",
+ "tooltips.surfaceSelection": "选定的表面显示为绿色,导出时只有这些表面才会接收位移。",
+ "excl.modeExclude": "排除",
+ "excl.modeExcludeTitle": "排除模式:绘制的表面将不会接收纹理位移",
+ "excl.modeIncludeOnly": "仅包含",
+ "excl.modeIncludeOnlyTitle": "仅包含模式:只有绘制的表面会接收纹理位移",
+ "excl.toolBrush": "笔刷",
+ "excl.toolBrushTitle": "笔刷:绘制要排除的三角形",
+ "excl.toolFill": "填充",
+ "excl.toolFillTitle": "桶形填充:在阈值角度内泛洪填充表面",
+ "excl.shiftHint": "按住 Shift 键以擦除",
+ "labels.type": "类型",
+ "brushType.single": "单个",
+ "brushType.circle": "圆形",
+ "labels.size": "大小",
+ "labels.maxAngle": "最大角度",
+ "tooltips.maxAngle": "填充可跨越的相邻三角形之间的最大二面角",
+ "ui.clearAll": "全部清除",
+ "excl.initExcluded": "0 个面被遮罩",
+ "excl.faceExcluded": "{n} 个面被遮罩",
+ "excl.facesExcluded": "{n} 个面被遮罩",
+ "excl.faceSelected": "{n} 个面被选中",
+ "excl.facesSelected": "{n} 个面被选中",
+ "excl.hintExclude": "被遮罩的表面显示为橙色,导出时不会接收位移。",
+ "excl.hintInclude": "选定的表面显示为绿色,导出时只有这些表面才会接收位移。",
+ "precision.label": "精度 (Beta) ⓘ",
+ "precision.labelTitle": "在后台细分网格,以便笔刷以更精细的粒度进行选择",
+ "precision.outdated": "⚠ 已过期",
+ "precision.refreshTitle": "重新细分网格以匹配当前笔刷大小",
+ "precision.triCount": "{n} △",
+ "precision.refining": "正在细化…",
+ "precision.warningBody": "估计约 {n} 个三角形。这可能会减慢您的浏览器运行速度。确定继续吗?",
+ "labels.boundaryFalloff": "平滑遮罩 ⓘ",
+ "tooltips.boundaryFalloff": "在遮罩边界附近逐渐将位移减至零,防止纹理化区域与非纹理化区域交界处的三角形重叠。",
+ "labels.symmetricDisplacement": "对称位移 ⓘ",
+ "tooltips.symmetricDisplacement": "启用后,50% 灰色 = 无位移;白色向外推,黑色向内推。可保持零件体积大致恒定。",
+ "labels.displacementPreview": "3D 预览 ⓘ",
+ "tooltips.displacementPreview": "细分网格并实时位移顶点,以便您判断实际深度。在复杂模型上会大量占用 GPU 资源。",
+ "ui.placeOnFace": "放置在面上",
+ "ui.placeOnFaceTitle": "点击一个面,使其朝下放置在打印平台上",
+ "ui.rotate": "旋转",
+ "ui.rotateTitle": "手动围绕 X、Y、Z 轴旋转模型",
+ "ui.rotateApply": "应用",
+ "ui.rotateReset": "重置",
+ "progress.subdividingPreview": "正在准备预览…",
+ "warnings.textureHeightOverlap": "⚠ 纹理高度超过了最小模型尺寸的 10% — 导出的 STL 中可能会出现几何重叠。",
+ "sections.advancedFeatures": "高级 / Beta 功能 ⓘ",
+ "tooltips.advancedFeatures": "实验性工具 — 行为可能会随版本变化。",
+ "ui.advancedBlurb": "实验性工具。行为可能会随版本变化。",
+ "ui.bakeTexturesHeading": "烘焙纹理",
+ "ui.bakeTexturesDesc": "将当前纹理应用到网格,并将结果重新加载为工作模型,以便继续编辑。",
+ "ui.bakeTextures": "烘焙纹理",
+ "tooltips.bakeTextures": "将当前纹理应用到网格,并将结果重新加载为工作模型。",
+ "ui.bakeMaskNewFaces": "遮罩刚烘焙的面,防止其被进一步纹理化",
+ "ui.noDownwardZHeading": "悬垂保护",
+ "ui.noDownwardZDesc": "某些纹理会将表面顶点向下推,产生新的悬垂。启用后,纹理化过程中顶点将永远不会沿 −Z 方向移动。X 和 Y 方向的移动不受影响。",
+ "ui.noDownwardZ": "防止向下 (−Z) 的顶点位移",
+ "alerts.bakeFailed": "烘焙失败:{msg}",
+ "progress.finalizing": "正在完成…",
+ "sections.export": "导出 ⓘ",
+ "tooltips.export": "边长越小,位移细节越精细。输出随后会根据三角形数量限制进行简化。",
+ "labels.resolution": "分辨率 (mm)",
+ "tooltips.resolution": "导出时,长度大于此值的边将被分割",
+ "warnings.resolutionTooCoarse": "⚠ 分辨率粗于模型包围盒对角线的 1/100 — 精细细节将丢失。请降低该值以获得更精细的结果。",
+ "labels.outputTriangles": "输出三角形数",
+ "tooltips.outputTriangles": "网格首先会被完全细分,然后再简化至该数量",
+ "warnings.safetyCapHit": "⚠ 细分过程中达到了 2000 万三角形的安全上限 — 结果可能仍比请求的边长要粗糙。",
+ "ui.exportStl": "导出 STL",
+ "ui.export3mf": "导出 3MF",
+ "tooltips.exportStl": "兼容所有切片软件",
+ "tooltips.export3mf": "文件体积更小 — 可能不兼容部分切片软件",
+ "progress.writing3mf": "正在写入 3MF…",
+ "progress.subdividing": "正在细分网格…",
+ "progress.refining": "正在优化:{cur} 个三角形,最长边 {edge}",
+ "progress.applyingDisplacement": "正在对 {n} 个三角形应用位移…",
+ "progress.displacingVertices": "正在位移顶点…",
+ "progress.decimatingTo": "正在简化 {from} → {to} 个三角形…",
+ "progress.decimating": "正在简化:{cur} → {to} 个三角形",
+ "progress.writingStl": "正在写入 STL…",
+ "progress.done": "完成!",
+ "progress.processing": "正在处理…",
+ "license.btn": "许可证与条款",
+ "license.title": "许可证与条款",
+ "license.item1": "可免费用于任何目的,包括商业用途(例如为客户或产品进行 STL 纹理化)。",
+ "license.item2": "按原样使用本工具时,感谢您的署名,但并非必需。",
+ "license.item3": "想支持本工具?请前往 CNCKitchen.STORE 购物,或通过 PayPal / Ko-fi 打赏。",
+ "license.item4": "此工具按原样提供,不提供任何形式的担保。使用风险自负。",
+ "license.item5": "不提供技术支持。作者没有义务修复错误、回答问题或更新本工具。不过,欢迎随时将错误报告和功能请求发送至 texturizer@cnckitchen.com。",
+ "license.item6": "对于因使用本工具而产生的任何损害、数据丢失或问题,作者不承担任何责任。",
+ "license.item7": "想要为您的业务或网站获取许可或嵌入本工具?请通过 contact@cnckitchen.com 联系我们。",
+ "license.item8": "源代码可在 GitHub 上获取。",
+ "imprint.btn": "版权与隐私",
+ "imprint.title": "版权与隐私政策",
+ "imprint.sectionImprint": "版权声明 (Impressum)",
+ "imprint.info": "CNC Kitchen
Stefan Hermann
Bahnhofstr. 2
88145 Hergatz
Germany",
+ "imprint.contact": "电子邮箱:contact@cnckitchen.com
电话:+49 175 2011824
该电话号码仅供法律/商业咨询,不提供技术支持。",
+ "imprint.odr": "欧盟在线争议解决平台:https://ec.europa.eu/consumers/odr",
+ "imprint.sectionPrivacy": "隐私政策 (Datenschutzerklärung)",
+ "imprint.privacyIntro": "责任方 (Verantwortlicher gem. Art. 4 Abs. 7 DSGVO):Stefan Hermann,Bahnhofstr. 2,88145 Hergatz,Germany。",
+ "imprint.privacyHosting": "本网站托管于 GitHub Pages(GitHub Inc. / Microsoft Corp.,美国加利福尼亚州旧金山市 Colin P Kelly Jr St 88 号,邮编 94107)。当您访问本网站时,GitHub 可能会在服务器日志中处理您的 IP 地址。法律依据:GDPR 第 6(1)(f) 条(为提供网站服务的正当权益)。请参阅 GitHub 隐私声明。",
+ "imprint.privacyLocal": "本工具将您的偏好设置(语言、主题)保存在浏览器的 localStorage 中。这些数据永远不会离开您的设备,也不会被传输到任何服务器。",
+ "imprint.privacyNoCookies": "本网站不使用 Cookie、分析或任何跟踪技术。",
+ "imprint.privacyExternal": "本网站包含指向外部网站的链接(例如 CNCKitchen.STORE、PayPal、Ko-fi)。这些网站有其独立的隐私政策,我们对此无法控制。",
+ "imprint.privacyRights": "根据 GDPR,您有权访问、更正、删除、限制处理、数据可移植,并有权向监管机构提出投诉。",
+ "sponsor.title": "感谢使用 CNC Kitchen 的 BumpMesh!",
+ "sponsor.body": "本工具由 CNC Kitchen 完全免费提供。
当您的 STL 正在处理时,何不看看让我们得以持续创作优质内容的商店?",
+ "sponsor.visitStore": "🛒 访问 CNCKitchen.STORE",
+ "sponsor.donate": "💙 通过 PayPal 打赏",
+ "sponsor.donateKofi": "☕ 通过 Ko-fi 打赏",
+ "sponsor.dontShow": "不再显示",
+ "sponsor.closeAndContinue": "关闭 & 继续",
+ "cta.store": "支持本工具?在 CNCKitchen.STORE 购物,或通过 PayPal / Ko-fi 打赏",
+ "cta.storeDismiss": "关闭",
+ "alerts.loadFailed": "无法加载模型:{msg}",
+ "alerts.exportFailed": "导出失败:{msg}",
+ "alerts.exportOOM": "导出失败:模型在细分过程中内存不足。\n\n当网格在所需的分辨率下需要过多三角形时,会出现此问题。\n\n解决方法:\n\u2022 增大分辨率 (mm) 的数值,以减少生成的三角形数量",
+ "alerts.fileTooLarge": "文件过大 ({size} MB)。允许的最大值:{max} MB。",
+ "alerts.degenerateTrianglesRemoved": "加载时,已从网格中移除 {n} 个无效三角形(坐标为 NaN 或面积为零)。模型仍可正常使用。",
+ "diag.runAdvanced": "运行高级检查",
+ "diag.runAdvancedTitle": "检查相交和重叠的三角形(大型网格的检查可能需要一些时间)",
+ "diag.running": "正在检查…",
+ "diag.meshOk": "\u2714 网格看起来没问题",
+ "diag.openEdges": "{n} 条开放边 \u2014 网格非封闭",
+ "diag.nonManifoldEdges": "{n} 条非流形边",
+ "diag.multipleShells": "{n} 个不连通的外壳",
+ "diag.intersectingTris": "{n} 对相交三角形",
+ "diag.overlappingTris": "{n} 个重叠/重复三角形",
+ "diag.advancedOk": "\u2714 未发现相交或重叠",
+ "diag.recommendFix": "进行纹理处理前,请先在您的 CAD 软件、切片软件或在线工具中修复这些问题。",
+ "diag.show": "显示",
+ "diag.hide": "隐藏",
+ "header.exportProject": "保存项目 (.bumpmesh)",
+ "header.importProject": "加载项目 (.bumpmesh)",
+ "header.resetSettings": "重置为默认值",
+ "header.undo": "撤销 (Ctrl+Z)",
+ "header.redo": "重做 (Ctrl+Shift+Z)",
+ "alerts.resetConfirm": "是否将所有设置重置为默认值?",
+ "header.exportSettingsLabel": "设置",
+ "header.exportModelLabel": "模型 (STL)",
+ "header.exportTextureLabel": "自定义纹理",
+ "header.exportGo": "保存",
+ "alerts.importFailed": "无法加载项目:{msg}",
+ "labels.snapSeamless": "吸附至无缝环绕 ⓘ",
+ "tooltips.snapSeamless": "将 U 轴缩放吸附到整数环绕值,使纹理在圆柱面上无缝环绕。",
+ "labels.cylinderAxis": "圆柱轴",
+ "ui.cylinderAutofit": "自动拟合",
+ "tooltips.cylinderAutofit": "使用最小二乘法将圆形拟合到零件的外向顶点。",
+ "ui.cylinderReset": "重置",
+ "tooltips.cylinderReset": "将轴重置为包围盒中心,半径重置为包围盒推导值。",
+ "ui.cylinderPanelAria": "圆柱轴放置",
+ "ui.cylinderPanelLabel": "定义圆柱投影",
+ "ui.cylinderNoModel1": "加载模型以定位",
+ "ui.cylinderNoModel2": "圆柱轴",
+ "ui.cylinderPanelMinimize": "最小化 / 还原"
+};