Przeglądaj źródła

Comprehensive proofreading and update of the Chinese part of Defold manuals and tutorials. (#562)

* 翻译校对

* 修正

* 完成翻译

* 添加工具说明

* 修正脚本更加通用
矢量工坊宝儿姐 1 tydzień temu
rodzic
commit
ab87153422
100 zmienionych plików z 5286 dodań i 3341 usunięć
  1. 153 110
      docs/zh/faq/faq.md
  2. 4 4
      docs/zh/manuals/2dgraphics.md
  3. 4 4
      docs/zh/manuals/3dgraphics.md
  4. 50 44
      docs/zh/manuals/adapting-graphics-to-screen-size.md
  5. 64 64
      docs/zh/manuals/addressing.md
  6. 27 27
      docs/zh/manuals/ads.md
  7. 36 31
      docs/zh/manuals/android.md
  8. 9 9
      docs/zh/manuals/animation.md
  9. 69 25
      docs/zh/manuals/app-manifest.md
  10. 38 38
      docs/zh/manuals/application-lifecycle.md
  11. 49 46
      docs/zh/manuals/application-security.md
  12. 73 60
      docs/zh/manuals/atlas.md
  13. 31 31
      docs/zh/manuals/bob.md
  14. 6 6
      docs/zh/manuals/buffer.md
  15. 36 36
      docs/zh/manuals/building-blocks.md
  16. 37 37
      docs/zh/manuals/bundling.md
  17. 16 16
      docs/zh/manuals/caching-assets.md
  18. 172 77
      docs/zh/manuals/camera.md
  19. 31 31
      docs/zh/manuals/collection-factory.md
  20. 71 56
      docs/zh/manuals/collection-proxy.md
  21. 46 47
      docs/zh/manuals/components.md
  22. 234 0
      docs/zh/manuals/compute.md
  23. 33 30
      docs/zh/manuals/debugging-game-and-system-logs.md
  24. 48 48
      docs/zh/manuals/debugging-game-logic.md
  25. 27 24
      docs/zh/manuals/debugging-native-code-android.md
  26. 71 52
      docs/zh/manuals/debugging-native-code-ios.md
  27. 68 52
      docs/zh/manuals/debugging-native-code.md
  28. 4 4
      docs/zh/manuals/debugging.md
  29. 17 17
      docs/zh/manuals/design.md
  30. 35 35
      docs/zh/manuals/dev-app.md
  31. 55 27
      docs/zh/manuals/editor-preferences.md
  32. 370 0
      docs/zh/manuals/editor-scripts-ui.md
  33. 641 118
      docs/zh/manuals/editor-scripts.md
  34. 12 12
      docs/zh/manuals/editor-styling.md
  35. 13 13
      docs/zh/manuals/editor-templates.md
  36. 100 82
      docs/zh/manuals/editor.md
  37. 46 0
      docs/zh/manuals/extender-docker-images.md
  38. 133 0
      docs/zh/manuals/extender-local-setup.md
  39. 64 66
      docs/zh/manuals/extension-facebook.md
  40. 21 21
      docs/zh/manuals/extension-fbinstant.md
  41. 29 29
      docs/zh/manuals/extension-googleplayinstant.md
  42. 5 5
      docs/zh/manuals/extension-gpgs.md
  43. 56 57
      docs/zh/manuals/extension-iap.md
  44. 34 34
      docs/zh/manuals/extension-push.md
  45. 2 2
      docs/zh/manuals/extension-websocket.md
  46. 72 72
      docs/zh/manuals/extension-webview.md
  47. 79 77
      docs/zh/manuals/extensions-best-practices.md
  48. 13 13
      docs/zh/manuals/extensions-build-variants.md
  49. 26 0
      docs/zh/manuals/extensions-cocoapods.md
  50. 2 2
      docs/zh/manuals/extensions-debugging-android.md
  51. 2 2
      docs/zh/manuals/extensions-debugging-ios.md
  52. 2 2
      docs/zh/manuals/extensions-debugging.md
  53. 3 35
      docs/zh/manuals/extensions-defold-sdk.md
  54. 15 15
      docs/zh/manuals/extensions-details.md
  55. 75 0
      docs/zh/manuals/extensions-ext-manifests.md
  56. 30 0
      docs/zh/manuals/extensions-gradle.md
  57. 30 30
      docs/zh/manuals/extensions-manifest-merge-tool.md
  58. 10 10
      docs/zh/manuals/extensions-script-api.md
  59. 66 103
      docs/zh/manuals/extensions.md
  60. 3 3
      docs/zh/manuals/facebook.md
  61. 64 64
      docs/zh/manuals/factory.md
  62. 122 46
      docs/zh/manuals/file-access.md
  63. 87 86
      docs/zh/manuals/flash.md
  64. 27 27
      docs/zh/manuals/flipbook-animation.md
  65. 154 79
      docs/zh/manuals/font.md
  66. 50 50
      docs/zh/manuals/getting-help.md
  67. 45 45
      docs/zh/manuals/glossary.md
  68. 2 2
      docs/zh/manuals/gpgs.md
  69. 6 6
      docs/zh/manuals/graphics.md
  70. 7 7
      docs/zh/manuals/gui-box.md
  71. 36 36
      docs/zh/manuals/gui-clipping.md
  72. 29 29
      docs/zh/manuals/gui-layouts.md
  73. 12 12
      docs/zh/manuals/gui-particlefx.md
  74. 19 19
      docs/zh/manuals/gui-pie.md
  75. 40 40
      docs/zh/manuals/gui-script.md
  76. 3 3
      docs/zh/manuals/gui-spine.md
  77. 19 19
      docs/zh/manuals/gui-template.md
  78. 19 19
      docs/zh/manuals/gui-text.md
  79. 214 137
      docs/zh/manuals/gui.md
  80. 30 30
      docs/zh/manuals/hot-reload.md
  81. 113 88
      docs/zh/manuals/html5.md
  82. 13 13
      docs/zh/manuals/http-requests.md
  83. 15 15
      docs/zh/manuals/iac.md
  84. 3 3
      docs/zh/manuals/iap.md
  85. 16 18
      docs/zh/manuals/importing-assets.md
  86. 28 28
      docs/zh/manuals/importing-graphics.md
  87. 27 33
      docs/zh/manuals/importing-models.md
  88. 103 102
      docs/zh/manuals/input-gamepads.md
  89. 16 16
      docs/zh/manuals/input-key-and-text.md
  90. 35 35
      docs/zh/manuals/input-mouse-and-touch.md
  91. 69 69
      docs/zh/manuals/input.md
  92. 3 3
      docs/zh/manuals/install.md
  93. 2 2
      docs/zh/manuals/instant-games.md
  94. 16 16
      docs/zh/manuals/introduction.md
  95. 97 99
      docs/zh/manuals/ios.md
  96. 38 39
      docs/zh/manuals/label.md
  97. 68 44
      docs/zh/manuals/libraries.md
  98. 7 7
      docs/zh/manuals/linux.md
  99. 25 25
      docs/zh/manuals/live-update-aws.md
  100. 39 39
      docs/zh/manuals/live-update-scripting.md

+ 153 - 110
docs/zh/faq/faq.md

@@ -1,175 +1,217 @@
 ---
-title: Defold 引擎与编辑器常见问题和解答
-brief: 有关 Defold 游戏引擎和编辑器及平台的常见问题和解答.
+title: Defold 引擎和编辑器常见问题
+brief: 关于 Defold 游戏引擎、编辑器和平台的常见问题。
 ---
 
 # 常见问题
 
-## 一般常见
+## 一般问题
 
-#### 问: Defold 真的免费吗?
+#### 问: Defold 真的免费吗
 
-答: 对, Defold 引擎与编辑器和所有功能完全免费. 没有暗扣费, 手续费和使用权费用. 完全免费.
+答: 是的,具有完整功能的 Defold 引擎和编辑器完全免费。没有隐藏成本、费用或版权使用费。就是免费。
 
 
-#### 问: Defold 基金会为什么开发并免费提供 Defold?
+#### 问: 为什么 Defold 基金会要免费提供 Defold?
 
-答: [Defold 基金会](/foundation) 的一大目标就是让 Defold 软件能够被世界上所有开发者免费使用并且源码也是公开免费的.
+答: [Defold 基金会](/foundation) 的目标之一是确保 Defold 软件可供全球开发者使用,并且源代码免费提供。
 
 
-#### 问: Defold 能持续维护多久?
+#### 问: 你们会支持 Defold 多久?
 
-答: 我们承诺维护 Defold. [Defold 基金会](/foundation) 的成立就是为了保证 Defold 能够被持续维护. 我们不会放弃.
+答: 我们对 Defold 深度投入。[Defold 基金会](/foundation) 的设立方式保证了它将作为 Defold 的负责任所有者存在多年。它不会消失。
 
 
-#### 问: 专业开发的话 Defold 值得信赖吗?
+#### 问: 我可以信任 Defold 用于专业开发吗?
 
-答: 必须值得信赖. Defold 已被越来越多的职业开发者和工作室所采用. 可以参考位于 [游戏展示页](/showcase) 上的用 Defold 开发的各种样例.
+答: 绝对可以。Defold 已被越来越多的专业游戏开发者和游戏工作室使用。查看 [游戏展示](/showcase) 了解使用 Defold 创建的游戏示例。
 
 
-#### 问: 你们做了什么样的用户跟踪?
+#### 问: 你们在进行什么样的用户跟踪?
 
-答: 我们的网站和 Defold 编辑器会使用匿名回报一些数据用以提升我们的服务和产品质量. 你编译出版的游戏里不带任何用户跟踪 (除非你自己加入分析服务功能). 详情请见我们的 [隐私政策](/privacy-policy).
+答: 我们记录来自我们网站和 Defold 编辑器的匿名使用数据,以改进我们的服务和产品。在你创建的游戏中没有用户跟踪(除非你自己添加分析服务)。在我们的 [隐私政策](/privacy-policy) 中阅读更多相关信息。
 
 
-#### 问: 谁制作了 Defold?
+#### 问: 谁创造了 Defold?
 
-答: Defold 由 Ragnar Svensson 和 Christian Murray 开发. 他们从2009年就开始了游戏引擎, 编辑器和配套服务的开发. King 和 Defold 在2013年建立了合作关系然后并于2014年获得 Defold. 详情请见 [这里](/about).
+答: Defold 由 Ragnar Svensson 和 Christian Murray 创造。他们从 2009 年开始开发引擎、编辑器和服务器。King 和 Defold 在 2013 年开始合作,King 于 2014 年收购了 Defold。阅读完整故事请点击[这里](/about)。
 
 
-#### 问: Defold 能做 3D 游戏吗?
+## 游戏开发问题
 
-答: 可以! 游戏引擎纯 3D. 然而, 工具都是针对 2D 游戏设计的, 所以 3D 游戏工具你得自己开发. 提升 3D 支持的计划进行中.
+#### 问: 我可以在 Defold 中制作 3D 游戏吗?
 
+答: 当然可以!引擎是一个完整的 3D 引擎。然而,工具集是为 2D 设计的,所以你必须自己完成大量繁重的工作。更好的 3D 支持正在计划中。
 
-#### 问: Defold 游戏开发用什么语言?
 
-答: Defold 项目游戏逻辑基本使用 Lua 语言 (特指 Lua 5.1/LuaJIT, 详情请见 [Lua 教程](/manuals/lua)). Lua 是一种强大快速的动态语言. 同时也支持使用原生 (C/C++, Objective-C, Java 和 JavaScript等) 语言来扩展 Defold 引擎功能. 自定义材质, 使用 OpenGL ES SL 语言编写的顶点和片元着色程序.
+## 编程语言问题
 
+#### 问: 我在 Defold 中使用什么编程语言?
 
-## 平台相关
+答: Defold 项目中的游戏逻辑主要使用 Lua 语言编写(特别是 Lua 5.1/LuaJIT,详情请参考 [Lua 手册](/manuals/lua))。Lua 是一种轻量级的动态语言,快速且非常强大。从 1.8.1 版本开始,Defold 支持使用能生成 Lua 代码的转译器。安装转译器扩展后,你可以使用替代语言——如 [Teal](https://github.com/defold/extension-teal)——来编写静态类型检查的 Lua。你也可以使用原生代码(根据平台不同,可以是 C/C++、Objective-C、Java 和 JavaScript)来[为 Defold 引擎扩展新功能](/manuals/extensions/)。在构建[自定义材质](/manuals/material/)时,使用 OpenGL ES SL 着色器语言来编写顶点和片段着色器。
 
-#### 问: Defold 可以运行在哪些平台上?
 
-答: 下表列出了编辑器工具与游戏引擎运行环境的支持情况:
+#### 问: 我可以使用 C++ 来编写游戏逻辑吗?
 
-  | System             | Version            | Architectures      | Supported            |
-  | ------------------ | ------------------ | ------------------ | -------------------- |
-  | macOS              | 11 Big Sur         | `x86-64`, `arm-64` | Editor               |
-  | macOS              | 10.15              | `x86-64`, `arm-64` | Engine               |
-  | Windows            | Vista              | `x86-32`, `x86-64` | Editor and Engine    |
-  | Ubuntu (1)         | 18.04              | `x86-64`           | Editor               |
-  | Linux (2)          | Any                | `x86-64`, `arm-64` | Engine               |
-  | iOS                | 11.0               | `arm-64`           | Engine               |
-  | Android            | 4.4 (API level 19) | `arm-32`, `arm-64` | Engine               |
-  | HTML5              |                    | `asm.js`, `wasm`   | Engine               |
+答: Defold 中的 C++ 支持主要用于编写与第三方 SDK 或平台特定 API 交互的原生扩展。[dmSDK](https://defold.com/ref/stable/dmGameObject/)(用于原生扩展的 Defold C++ API)将逐步扩展更多功能,使开发者可以选择完全使用 C++ 编写所有游戏逻辑。Lua 仍将是游戏逻辑的主要语言,但通过扩展的 C++ API,也可以使用 C++ 编写游戏逻辑。扩展 C++ API 的工作主要是将现有的私有头文件移至公共部分,并清理 API 以供公共使用。
 
-  (1 编辑器在 64-bit Ubuntu 18.04 平台上通过编译和测试. 其他版本应该同样可以运行但是未经过测试.)
 
-  (2 游戏引擎在大多数 64-bit Linux 版本上只要更新显卡驱动支持 OpenGL ES 2.0 的基本都能运行.)
+#### 问: 我可以在 Defold 中使用 TypeScript 吗?
 
+答: TypeScript 不是官方支持的。社区维护了一个工具包 [ts-defold](https://ts-defold.dev/),用于编写 TypeScript 并直接从 VSCode 将其转译为 Lua。
 
-#### 问: Defold 能输出哪些平台的游戏?
 
-答: 可以一键发布到 PS4™, 任天堂 Switch, iOS, Android 和 HTML5 游戏, 外加 macOS, Windows 和 Linux 游戏. 真正的一套代码平台通用.
+#### 问: 我可以在 Defold 中使用 Haxe 吗?
 
+答: Haxe 不是官方支持的。社区维护了 [hxdefold](https://github.com/hxdefold/hxdefold) 用于编写 Haxe 并将其转译为 Lua。
 
-#### 问: Defold 基于何种渲染引擎?
 
-A: 作爲開發者只需要關心可編程渲染管綫所支持的一種渲染 API [完全可程式化渲染管线](/manuals/render/). Defold 渲染脚本 API 会把渲染操作转换为如下图形 API:
+#### 问: 我可以在 Defold 中使用 C# 吗?
+
+答: Defold 基金会将添加 C# 支持并将其作为库依赖项提供。C# 是一种广泛采用的编程语言,它将帮助那些大量投资于 C# 的工作室和开发者过渡到 Defold。
+
+
+#### 问: 我担心添加 C# 支持会对 Defold 产生负面影响。我应该担心吗?
+
+答: Defold 不会放弃将 Lua 作为主要脚本语言。C# 支持将作为扩展的新语言添加。除非你在项目中选择使用 C# 扩展,否则它不会影响引擎。
+
+C# 支持是有代价的(可执行文件大小、运行时性能等),但这由个别开发者/工作室来决定。
+
+至于 C# 本身,这是一个相对较小的变化,因为扩展系统已经支持多种语言(C/C++/Java/Objective-C/Zig)。SDK 将通过生成 C# 绑定来保持同步。这将使绑定以最小的努力保持最新。
+
+Defold 基金会以前一直反对在 Defold 中添加 C# 支持,但由于多种原因改变了看法:
+
+* 工作室和开发者继续要求 C# 支持。
+* C# 支持的范围已缩小到仅扩展(即工作量小)。
+* 核心引擎不会受到影响。
+* 如果生成 C# API,可以以最小的努力保持同步。
+* C# 支持将基于带有 NativeAOT 的 DotNet 9,从而生成现有构建管道可以链接的静态库(就像任何其他 Defold 扩展一样)。
+
+
+## 平台问题
+
+#### 问: Defold 可以在哪些平台上运行?
+
+答: 以下平台支持编辑器/工具和引擎运行时:
+
+  | System             | Version            | Architectures      | Supported          |
+  | ------------------ | ------------------ | ------------------ | ------------------ |
+  | macOS              | 11 Big Sur         | `x86-64`, `arm-64` | Editor             |
+  | macOS              | 10.15              | `x86-64`, `arm-64` | Engine             |
+  | Windows            | Vista              | `x86-32`, `x86-64` | Editor and Engine  |
+  | Ubuntu (1)         | 22.04 LTS          | `x86-64`           | Editor             |
+  | Linux (2)          | Any                | `x86-64`, `arm-64` | Engine             |
+  | iOS                | 11.0               | `arm-64`           | Engine             |
+  | Android            | 4.4 (API level 19) | `arm-32`, `arm-64` | Engine             |
+  | HTML5              |                    | `asm.js`, `wasm`   | Engine             |
+
+  (1 编辑器为 64 位 Ubuntu 构建和测试。它应该也能在其他发行版上运行,但我们不提供保证。)
+
+  (2 只要图形驱动是最新的,引擎运行时应该在大多数 64 位 Linux 发行版上运行,有关图形 API 的更多信息见下文)
+
+
+#### 问: 使用 Defold 我可以为哪些目标平台开发游戏?
+
+答: 只需点击一下,您就可以发布到 PS4™、PS5™、Nintendo Switch、iOS(64 位)、Android(32 位和 64 位)和 HTML5,以及 macOS(x86-64 和 arm64)、Windows(32 位和 64 位)和 Linux(x86-64 和 arm64)。真正的一套代码库,多个支持的平台。
+
+
+#### 问: Defold 依赖哪种渲染 API?
+
+答: 作为开发者,您只需要担心使用[完全可编程渲染管线](/manuals/render/)的一种渲染 API。Defold 渲染脚本 API 将渲染操作转换为以下图形 API:
 
 :[图形 API](../shared/graphics-api.md)
 
-#### 问: 如何获取 Defold 版本信息?
+#### 问: 有什么方法可以知道我运行的是哪个版本?
 
-答: 点击菜单栏 "About" 项. 弹出窗口详细列出了 Defold 版本号, 和文件哈希 SHA1. 对于游戏引擎版本, 调用 [`sys.get_engine_info()`](/ref/sys/#sys.get_engine_info) 获取.
+答: 是的,在帮助菜单中选择"关于"选项。弹出窗口清楚地显示了 Defold 测试版版本,更重要的是,特定的发布 SHA1。对于运行时版本查找,请使用 [`sys.get_engine_info()`](/ref/sys/#sys.get_engine_info)。
 
-最新测试版位于 http://d.defold.com/beta 可以查看 http://d.defold.com/beta/info.json (正式版同样也有: http://d.defold.com/stable/info.json) 文件获取最新版本信息.
+可以从 http://d.defold.com/beta 下载的最新测试版可以通过打开 http://d.defold.com/beta/info.json 来检查(稳定版本也存在相同的文件:http://d.defold.com/stable/info.json)
 
 
-#### 问: 运行时如何获取系统信息?
+#### 问: 有什么方法可以在运行时知道游戏在哪个平台上运行?
 
-答: 调用 [`sys.get_sys_info()`](/ref/sys#sys.get_sys_info) 获取.
+答: 是的,请查看 [`sys.get_sys_info()`](/ref/sys#sys.get_sys_info)。
 
 
-## 編輯器相關
+## 编辑器问题
 :[Editor FAQ](../shared/editor-faq.md)
 
 
-## Linux 相關
+## Linux 问题
 :[Linux FAQ](../shared/linux-faq.md)
 
 
-## Android 相關
+## Android 问题
 :[Android FAQ](../shared/android-faq.md)
 
 
-## HTML5 相關
+## HTML5 问题
 :[HTML5 FAQ](../shared/html5-faq.md)
 
 
-## IOS 相關
+## iOS 问题
 :[iOS FAQ](../shared/ios-faq.md)
 
 
-## Windows 相關
+## Windows 问题
 :[Windows FAQ](../shared/windows-faq.md)
 
 
-## Consoles 相關
+## 主机问题
 :[Consoles FAQ](../shared/consoles-faq.md)
 
-## 发布相关
 
-#### 问: 我想把游戏发布到 AppStore. 如何设置 IDFA?
+## 发布游戏
 
-答: 提交游戏时, Apple 为广告商提供了3种 IDFA 用例:
+#### 问: 我正在尝试将我的游戏发布到 AppStore。我应该如何回答 IDFA 的问题?
 
-  1. 应用内展示广告
-  2. 用广告提升安装量
-  3. 用广告提升点击量
+答: 提交时,Apple 为其三个有效的 IDFA 用例提供了三个复选框:
 
-  如果选择第一个, 编辑会在你的游戏里找广告. 如果没找到, 游戏很可能会被拒. Defold 本身不使用广告商id.
+  1. 在应用内投放广告
+  2. 来自广告的安装归因
+  3. 来自广告的用户行为归因
 
+  如果您选择选项 1,应用审核人员会在应用中寻找广告。如果您的游戏不显示广告,游戏可能会被拒绝。Defold 本身不使用广告 ID。
 
-#### 问: 怎么用游戏获利?
 
-答: Defold 支持游戏内付费和多种广告服务. 最新相关信息详见 [资源中心的盈利类目](https://defold.com/tags/stars/monetization/).
+#### 问: 我如何通过游戏获利?
 
+答: Defold 支持应用内购买和各种广告解决方案。查看 [资源门户中的盈利类别](https://defold.com/tags/stars/monetization/) 获取最新的可用盈利选项列表。
 
-## Defold 报错
 
-#### 问: 游戏无法启动也没有报错. 怎么办?
+## 使用 Defold 时出现的错误
 
-答: 如果二次编译不通过很肯能由你最后做的改动导致. 从菜单栏选择 *Project > Rebuild And Launch* 试试.
+#### 问: 我无法启动游戏,也没有构建错误。出了什么问题?
 
+答: 在极少数情况下,构建过程可能无法重新构建文件,特别是当它之前遇到过您已经修复的构建错误时。通过从菜单中选择 *Project > Rebuild And Launch* 来强制完全重新构建。
 
 
-## 游戏内容相关
 
-#### 问: Defold 里有 prefab 吗?
+## 游戏内容
 
-答: 有. Defold 里叫 [集合](/manuals/building-blocks/#collections). 它能帮助建立储存游戏内容为树形结构以便在编辑器或者游戏运行时创建实例. 对于 GUI 节点类似结构称为 GUI 模板.
+#### 问: Defold 支持预制件吗?
 
+答: 是的,它支持。它们被称为[集合](/manuals/building-blocks/#collections)。它们允许您创建复杂的游戏对象层次结构,并将这些作为单独的构建块存储,您可以在编辑器中或在运行时(通过集合生成)实例化它们。对于 GUI 节点,支持 GUI 模板。
 
-#### 问: 为什么我不能在游戏对象下建立子游戏对象?
 
-答: 有一种可能是因为父级游戏对象是一个文件引用. 对于父子结构的游戏对象来说它们的位移关系通过 _场景结构_ 表达. 没有被加入到场景里的游戏对象无法于其他对象建立父子关系.
+#### 问: 我无法将游戏对象添加为另一个游戏对象的子对象,为什么?
 
+答: 可能是因为您试图在游戏对象文件中添加子对象,而这是不可能的。要理解为什么,您必须记住父子层次结构严格来说是_场景图_变换层次结构。尚未被放置(或生成)到场景(集合)中的游戏对象不是场景图的一部分,因此不能成为场景图层次结构的一部分。
 
-#### 问: 为什么我不能在所有子游戏对象间广播消息?
 
-答: 父子关系除了场景结构中表现相对位移以外别无其他特别之处. 如果需要跟踪子对象状态无需时刻向所有子对象发送消息. 这种情况下你需要使用 Lua 编写数据结构.
+#### 问: 为什么我不能向游戏对象的所有子对象广播消息?
 
+答: 父子关系只表达场景图变换关系,不应被误认为是对象导向的聚合。如果您尝试专注于您的游戏数据以及如何在游戏改变状态时最好地转换它,您可能会发现不需要一直向许多对象发送带有状态数据的消息。在需要数据层次结构的情况下,这些可以在 Lua 中轻松构建和处理。
 
-#### 问: 精灵对象周围出现黑白边?
 
-答: 这被称作 "边缘出血" 现象, 渲染精灵对象的时候把纹理旁边的一些像素也加入进来了. 解决办法是用纹理边缘的像素再扩充一圈. 好在 Defold 编辑器有工具能自动做这件事. 尝试打开图集并且设置 *Extrude Borders* 的值为 1.
+#### 问: 为什么我的精灵边缘周围会出现视觉瑕疵?
 
+答: 这是一种称为"边缘出血"的视觉瑕疵,其中图集中相邻像素的边缘像素会渗入分配给您的精灵的图像中。解决方案是用额外的相同像素行和列填充图集图像的边缘。幸运的是,这可以通过 Defold 中的图集编辑器自动完成。打开您的图集并将 *Extrude Borders* 值设置为 1。
 
-#### 问: 精灵变色, 透明效果如何制作?
 
-A: 精灵默认着色程序包含 "tint" 属性:
+#### 问: 我可以为我的精灵着色或使它们透明,还是必须为此编写自己的着色器?
+
+答: 所有精灵默认使用的内置精灵着色器定义了一个常量"tint":
 
   ```lua
   local red = 1
@@ -180,93 +222,94 @@ A: 精灵默认着色程序包含 "tint" 属性:
   ```
 
 
-#### 问: 为什么游戏对象的z值设为100就看不见了?
+#### 问: 如果我将精灵的 z 坐标设置为 100,那么它就不会被渲染。为什么?
+
+答: 游戏对象的 Z 位置控制渲染顺序。低值在高值之前绘制。在默认渲染脚本中,深度在 -1 和 1 之间的游戏对象被绘制,任何低于或高于此值的都不会被绘制。您可以在官方[渲染文档](/manuals/render)中阅读更多关于渲染脚本的信息。在 GUI 节点上,Z 值被忽略,根本不影响渲染顺序。相反,节点按照它们列出的顺序以及子层次结构(和分层)进行渲染。在官方[GUI 文档](/manuals/gui)中阅读更多关于 gui 渲染和使用分层优化绘制调用的信息。
 
-答: z值表示深度方向的遮挡关系. z值小的位于z值大的游戏对象前面. 默认渲染程序的z值范围是 -1 到 1, 此范围之外的不被渲染. 关于渲染脚本详情请见 [渲染教程](/manuals/render). 对于 GUI 节点来说z值毫无作用. 节点的遮挡顺序取决于树形结构 (以及层次设置). 关于用户界面节点的渲染详情请见 [GUI 教程](/manuals/gui).
 
+#### 问: 将视图投影 Z 范围更改为 -100 到 100 会影响性能吗?
 
-#### 问: 要是把视口深度范围设为 -100 到 100 会影响性能吗?
+答: 不会。唯一的影响是精度。z 缓冲区是对数的,对于接近 0 的 z 值具有非常精细的分辨率,而对于远离 0 的 z 值分辨率较低。例如,使用 24 位缓冲区,可以区分 10.0 和 10.000005,而 10000 和 10005 则不能。
 
-答: 不影响性能但是影响精度. z缓存是一种对数结构靠近 0 差别明显, 远离 0 差别不明显. 比如说, 用 24 位缓存 10.0 对比 10.000005 区别明显但是 10000 对比 10005 区别不明显.
 
+#### 问: 角度表示方式没有一致性,为什么?
 
-#### 问: 角度的单位为什么不一致?
+答: 实际上有一致性。在编辑器和游戏 API 中,角度处处表示为度数。数学库使用弧度。目前,对于 `angular_velocity` 物理属性,约定被打破,它当前表示为弧度/秒。这预计会改变。
 
-答: 实际上一致. 编辑器和游戏API使用角度制. 数学计算库使用弧度制. 目前对于物理 `angular_velocity` 是个例外使用了弧度制. 以后可能会矫正.
 
+#### 问: 当创建一个只有颜色(没有纹理)的 GUI 框节点时,它将如何被渲染?
 
-#### 问: 只有颜色没有纹理的GUI节点如何渲染?
+答: 它只是一个顶点着色的形状。请记住,它仍然会消耗填充率。
 
-答: 作为顶点着色形状渲染, 注意其性能消耗.
 
+#### 问: 如果我即时更改资源,引擎会自动卸载它们吗?
 
-#### 问: 如何释放资源所占用的内存?
+答: 所有资源在内部都有引用计数。一旦引用计数为零,资源就会被释放。
 
-答: 引擎对所有资源都有引用计数. 一旦引用为0则资源自动被释放.
 
+#### 问: 是否可以在不使用附加到游戏对象的音频组件的情况下播放音频?
 
-#### 问: 不用游戏对象能播放声音吗?
+答: 一切都是基于组件的。可以创建一个带有多个声音的无头游戏对象,并通过向声音控制器对象发送消息来播放声音。
 
-答: 游戏引擎设计模式基于组件. 可以建立一个不可见游戏对象把声音组件放入然后需要播放时给它发消息即可.
 
+#### 问: 是否可以在运行时更改与音频组件关联的音频文件?
 
-#### 问: 运行时声音组件播放的声音文件能更改吗?
+答: 通常所有资源都是静态声明的,好处是您可以免费获得资源管理。您可以使用[资源属性](/manuals/script-properties/#resource-properties)来更改分配给组件的资源。
 
-答: 一般资源都是静态声明随意管理的. 可以使用 [资源属性](/manuals/script-properties/#resource-properties) 来修改与组件关联的资源.
 
+#### 问: 有没有办法访问物理碰撞形状属性?
 
-#### 问: 存取物理碰撞形状属性的方法?
+答: 不,目前不可能。
 
-答: 目前尚未支持.
 
+#### 问: 有什么快速方法可以渲染场景中的碰撞对象吗?(就像 Box2D 的调试绘制)
 
-#### 问: 有办法快速渲染物理碰撞对象吗? (就像 Box2D 的 debugdraw 那样)
+答: 是的,在 *game.project* 中设置 *physics.debug* 标志。(请参考官方[项目设置文档](/manuals/project-settings/#debug))
 
-答: 有, 要在 *game.project* 里设置 *physics.debug* 项. (参见 [项目设置教程](/manuals/project-settings/#debug))
 
+#### 问: 拥有许多接触/碰撞的性能成本是多少?
 
-#### 问: 许多物理碰撞的主要性能消耗在哪里?
+答: Defold 在后台运行一个修改版本的 Box2D,性能成本应该相当相似。您可以通过调出[分析器](/manuals/debugging)来查看引擎在物理上花费了多少时间。您还应该考虑使用什么类型的碰撞对象。例如,静态对象在性能方面更便宜。有关更多详细信息,请参考 Defold 中的官方[物理文档](/manuals/physics)。
 
-答: Defold 包含的是 Box2D 略微修改版本, 所以性能应该和原版差不多. 可以使用 [调试器](/manuals/debugging) 跟踪物理碰撞数量. 确保用对碰撞对象. 比如静态碰撞对象性能高些. 详情请见 Defold 的 [物理教程](/manuals/physics).
 
+#### 问: 拥有许多粒子效果组件的性能影响是什么?
 
-#### 问: 如果有许多粒子效果, 对性能影响大不大?
+答: 这取决于它们是否正在播放。没有播放的 ParticleFx 性能成本为零。必须使用分析器评估播放中的 ParticleFx 的性能影响,因为它的影响取决于它的配置方式。与大多数其他事情一样,内存是为在 *game.project* 中定义为 max_count 的 ParticleFx 数量预先分配的。
 
-答: 这取决于粒子效果是否正在播放. 没有播放的粒子效果不消耗性能. 播放中的粒子效果性能消耗取决于其配置情况, 可以用调试器来观察. 粒子效果的内存消耗基本上取决于项目设置的 max_count 数.
 
+#### 问: 如何接收通过集合代理加载的集合中游戏对象的输入?
 
-#### 问: 如何得到集合代理加载的集合里的游戏对象的输入信息?
+答: 每个代理加载的集合都有自己的输入栈。输入从主集合输入栈通过代理组件路由到集合中的对象。这意味着,仅仅让加载集合中的游戏对象获取输入焦点是不够的,_持有_代理组件的游戏对象也需要获取输入焦点。有关详细信息,请参阅[输入文档](/manuals/input)。
 
-答: 每个集合都有自己的输入栈. 输入从主集合通过代理组件传递到被载入集合里的游戏对象. 换句话说仅游戏对象获得输入焦点是不够的, 那个代理组件 _所在的_ 游戏对象同样需要获得输入焦点. 详情请见 [输入教程](/manuals/input).
 
+#### 问: 我可以使用字符串类型的脚本属性吗?
 
-#### 问: 脚本属性有字符串类型的吗?
+答: 不可以。Defold 支持[hash](/ref/builtins#hash)类型的属性。这些可用于指示类型、状态标识符或任何类型的键。哈希也可用于存储游戏对象 id(路径),尽管[url](/ref/msg#msg.url)属性通常更可取,因为编辑器会自动为您填充相关 URL 的下拉列表。有关详细信息,请参阅[脚本属性文档](/manuals/script-properties)。
 
-答: 没有. Defold 只有 [哈希](/ref/builtins#hash) 类型的脚本属性. 用来表示枚举, 表示状态, 表示各种类型都没问题. 而且游戏对象的 id (路径) 也是用其 [url](/ref/msg#msg.url) 属性的哈希来保存, 遇到这样的属性时编辑器会自动建立相关路径弹框供你选择. 详情请见 [脚本属性教程](/manuals/script-properties).
 
+#### 问: 如何访问矩阵的各个单元格(使用 [`vmath.matrix4()`](/ref/vmath/#vmath.matrix4:m1) 或类似方法创建的)?
 
-#### 问: 如何存取矩阵 (使用 [vmath.matrix4()](/ref/vmath/#vmath.matrix4:m1) 之类的函数生成的) 内部数据?
+答: 您可以使用 `mymatrix.m11`、`mymatrix.m12`、`mymatrix.m21` 等访问单元格。
 
-答: 使用 `mymatrix.m11`, `mymatrix.m12`, `mymatrix.m21` 之类的属性可以访问内部数据.
 
+#### 问: 使用 [gui.clone()](/ref/gui/#gui.clone:node) 或 [gui.clone_tree()](/ref/gui/#gui.clone_tree:node) 时,我收到 `Not enough resources to clone the node` 错误
 
-#### 问: 使用 [gui.clone()](/ref/gui/#gui.clone:node) 或 [gui.clone_tree()](/ref/gui/#gui.clone_tree:node) 时报 `Not enough resources to clone the node` 的错误信息?
+答: 增加 gui 组件的 `Max Nodes` 值。您可以在大纲中选择组件的根时在属性面板中找到此值。
 
-答: 增加gui组件的 `Max Nodes` 值. 在大纲视图gui根节点的属性面板上就能看到.
 
+## 论坛
 
-## 论坛相关
+#### 问: 我可以发布一个宣传我作品的帖子吗?
 
-#### 问: 我能在论坛上打广告吗?
+答: 当然可以!我们有一个专门的["Work for hire" 类别](https://forum.defold.com/c/work-for-hire)。我们将始终鼓励任何有益于社区的事情,向社区提供您的服务——无论是否收费——就是一个很好的例子。
 
-答: 可以! 论坛有一个 ["Work for hire" 类目](https://forum.defold.com/c/work-for-hire). 能充实社区论坛的所有信息都欢迎, 这里可以发布求职广告.
 
+#### 问: 我发布了一个帖子并添加了我的作品——我可以添加更多吗?
 
-#### 问: 可以无限打广告?
+答: 为了减少"Work for hire"帖子的刷屏,您在自己的帖子中每 14 天只能发布一次(除非是对帖子中评论的直接回复,在这种情况下您可以回复)。如果您想在 14 天内向您的帖子添加更多作品,您必须编辑现有帖子来添加内容。
 
-答: 为避免 "Work for hire" 类目论坛被爆, 至少14天内不许再加广告 (除非有人回复找你, 此时你可以立即回复这个人). 14天内, 只能通过更新帖子的方式加入新内容.
 
+#### 问: 我可以使用 Work for Hire 类别来发布招聘信息吗?
 
-#### 问: 我能发布招聘广告吗?
+答: 当然可以,随意使用!它可以用于发布招聘信息,也可以用于请求,例如"程序员寻找 2D 像素艺术家;我很富有,我会给你很好的报酬"。
 
-答: 可以, 自己找! 招聘也行求职也行, 比如 “程序员找美工; 高价求不差钱”.

+ 4 - 4
docs/zh/manuals/2dgraphics.md

@@ -1,9 +1,9 @@
 ---
-title: Defold 2D 图像教程
-brief: 本教程已过时
+title: Defold 2D 图形手册
+brief: 本手册已过时
 ---
 
-# 2D Graphics
+# 2D 图形
 
-详见 [图像教程](/manuals/graphics).
+本手册已被 [图形概览手册](/manuals/graphics) 取代。
 

+ 4 - 4
docs/zh/manuals/3dgraphics.md

@@ -1,8 +1,8 @@
 ---
-title: Defold 3D 图像教程
-brief: 本教程已过时
+title: Defold 3D 图形手册
+brief: 本手册已过时
 ---
 
-# 3D graphics
+# 3D 图形
 
-详见 [图像教程](/manuals/graphics).
+本手册已被 [图形概览手册](/manuals/graphics) 取代。

+ 50 - 44
docs/zh/manuals/adapting-graphics-to-screen-size.md

@@ -1,120 +1,126 @@
 ---
-title: 适配游戏图像到不同的屏幕尺寸
-brief: 本教程解释了如何适配游戏和图像到不同的屏幕尺寸.
+title: 适配图形以适应不同屏幕尺寸
+brief: 本手册解释了如何将游戏和图形适配到不同的屏幕尺寸。
 ---
 
-# 介绍
+# 引言
 
-当适配游戏和图像到不同的屏幕尺寸时, 要考虑一些事情:
+在将游戏和图形适配到不同屏幕尺寸时,需要考虑几个方面:
 
-* 这是个低分辨率的像素对齐的复古游戏还是高分辨率的现代游戏?
-* 不同屏幕全屏模式下玩的时候游戏应该如何应对?
-  * 玩家应该在高分辨率屏幕中看到更多的游戏内容还是图像自适应缩放来显示同样多的内容?
-* 要是屏幕的长宽比跟在game.project中设置的不一样游戏该怎么办?
-  * 玩家看到更多的游戏内容? 还是显示黑边? 还是重新调整GUI大小?
-* 你需要什么样的菜单和屏幕gui组件, 他们怎么适应各种屏幕大小与方向?
-  * 当屏幕方向改变, 菜单和屏幕gui组件应该改变布局还是不管什么方向都不动?
+* 这是一款具有低分辨率像素完美图形的复古游戏,还是具有高清质量图形的现代游戏?
+* 在不同屏幕尺寸上以全屏模式玩游戏时,游戏应如何表现?
+  * 玩家应该在高分辨率屏幕上看到更多游戏内容,还是图形应该自适应缩放以始终显示相同内容?
+* 游戏应如何处理与您在 *game.project* 中设置的宽高比不同的宽高比?
+  * 玩家应该看到更多游戏内容?或者应该有黑边?或者调整大小的GUI元素?
+* 您需要什么类型的菜单和屏幕GUI组件,它们应如何适应不同的屏幕尺寸和屏幕方向?
+  * 当方向改变时,菜单和其他GUI组件是否应该改变布局,还是无论方向如何都保持相同布局?
 
-本教程将探讨这些事情然后提供建议.
+本手册将解决其中一些问题并提出最佳实践。
 
 
-## 内容渲染的方法如何改变
+## 如何更改内容渲染方式
 
-Defold 渲染脚本提供整个渲染流程的控制. 渲染脚本控制着显示什么, 怎么显示以及显示的顺序. 默认渲染脚本总是显示 *game.project* 文件里定义的长, 宽的一块区域, 不管窗口缩放和屏幕大小匹配. 如果窗口大小, 比例改变, 将会造成内容的拉伸. 有些游戏可能能接受, 但通常当屏幕分辨率或比例改变, 应该适当让游戏内容显示的多些或少些, 或者至少在不改变窗口比例的条件下缩放游戏内容. 要改变内容拉伸的现象详情请见 [渲染教程](https://www.defold.com/manuals/render/#默认视口映射).
+Defold渲染脚本为您提供了对整个渲染管道的完全控制。渲染脚本决定了绘制顺序以及绘制内容和方式。渲染脚本的默认行为是始终绘制由*game.project*文件中的宽度和高度定义的相同像素区域,无论窗口是否调整大小或实际屏幕分辨率是否匹配。如果宽高比改变,这将导致内容被拉伸,如果窗口大小改变,内容将被放大或缩小。在某些游戏中,这可能是可以接受的,但更有可能的是,如果屏幕分辨率或宽高比不同,您希望显示更多或更少的游戏内容,或者至少确保在不改变宽高比的情况下缩放内容。默认的拉伸行为可以轻松更改,您可以阅读[渲染手册](https://www.defold.com/manuals/render/#default-view-projection)了解更多关于如何执行此操作的信息。
 
 
-## 复古/8比特图像
+## 复古/8位图形
 
-复古/8比特图像游戏模拟了老式游戏机或者低分辨率低调色盘的电脑游戏. 比如任天堂红白机 (NES) 就是分辨率 256x240 的, Commodore 64 是 320x200 的,  Gameboy 是 160x144 的, 这些屏幕分辨率赶不上当前屏幕的零头. 为了在当今高分辨率屏幕上模拟这种风格的游戏需要把屏幕缩放好几倍. 一个简单的方法是先显示低分辨率图像然后再在渲染时放大. 这在Defold中使用渲染脚本就能做到, [固定映射](/manuals/render/#Fixed) 可以设置一个合适的放大值.
+复古/8位图形通常指模拟老式游戏机或计算机图形风格的游戏,具有低分辨率和有限的调色板。例如,任天堂娱乐系统(NES)的屏幕分辨率为256x240,Commodore 64为320x200,Gameboy为160x144,这些都只是现代屏幕尺寸的一小部分。为了使模拟这种图形风格和屏幕分辨率的游戏在现代高分辨率屏幕上可玩,图形必须被放大或缩放数次。实现这一点的一个简单方法是,以您希望模拟的低分辨率和风格绘制所有图形,并在渲染时缩放图形。这可以在Defold中使用渲染脚本和[固定投影](/manuals/render/#fixed-projection)设置为合适的缩放值轻松实现。
 
-比如使用这个瓷砖图源和角色 ([source](https://ansimuz.itch.io/grotto-escape-game-art-pack)) 来模拟一个8位 320x200 分辨率游戏:
+让我们使用这个图块集和玩家角色([来源](https://ansimuz.itch.io/grotto-escape-game-art-pack))来制作一个分辨率为320x200的8位复古游戏:
 
 ![](images/screen_size/retro-player.png)
 
 ![](images/screen_size/retro-tiles.png)
 
-在 *game.project* 文件中设置分辨率 320x200  然后编译, 游戏看起来是这样:
+在*game.project*文件中设置320x200并启动游戏,看起来会是这样:
 
 ![](images/screen_size/retro-original_320x200.png)
 
-对于现代分辨率屏幕来说窗口也太小了! 把窗口拖动放大到 1280x800 还舒服些:
+在现代高分辨率屏幕上,这个窗口绝对太小了!将窗口大小增加到四倍到1280x800,使其更适合现代屏幕:
 
 ![](images/screen_size/retro-original_1280x800.png)
 
-现在窗口感觉好多了, 我们还需调整图像, 因为太小了难以看清游戏内容. 我们用渲染脚本来设置一个固定放大的映射:
+现在窗口大小更合理了,我们还需要对图形做一些处理。它太小了,很难看清游戏中发生的事情。我们可以使用渲染脚本来设置固定和缩放的投影:
 
 ```Lua
 msg.post("@render:", "use_fixed_projection", { zoom = 4 })
 ```
 
-结果会变成这样:
+::: sidenote
+相同的结果也可以通过将[相机组件](/manuals/camera/)附加到游戏对象并勾选*正交投影*,将*正交缩放*设置为4.0来实现:
+
+![](images/screen_size/retro-camera_zoom.png)
+:::
+
+这将产生以下结果:
 
 ![](images/screen_size/retro-zoomed_1280x800.png)
 
-好多了. 窗口和图像都可以, 但是仔细看会发现一个明显的问题:
+这样更好。窗口和图形都有合适的大小,但如果我们仔细观察,会发现一个明显的问题:
 
 ![](images/screen_size/retro-zoomed_linear.png)
 
-图像模糊了! 因为GPU渲染纹理时放大了图形采样. 默认 *game.project* 文件里 Graphics 部分设置是 *linear*:
+图形看起来模糊了!这是由GPU渲染时从纹理中采样放大的图形的方式引起的。*game.project*文件中Graphics部分下的默认设置是*linear*:
 
 ![](images/screen_size/retro-settings_linear.png)
 
-现在改成 *nearest* 试试:
+将其更改为*nearest*将得到我们想要的结果:
 
 ![](images/screen_size/retro-settings_nearest.png)
 
 ![](images/screen_size/retro-zoomed_nearest.png)
 
-现在我们的游戏图像是像素对齐的了. 还可以想想其他办法, 比如在*game.project*的sprite里关闭 sub-pixels:
+现在我们的复古游戏有了清晰的像素完美图形。还有更多事情需要考虑,例如在*game.project*中禁用精灵的子像素:
 
 ![](images/screen_size/retro-subpixels.png)
 
-当Subpixels选项关闭后所有 sprites 就不会渲染在半个像素上而是永远像素对齐.
+当子像素选项被禁用时,精灵将永远不会在半个像素上渲染,而是始终对齐到最近的完整像素。
 
-## 高分辨率图
+## 高分辨率图
 
-处理高分辨率图像我们需要使用复古游戏不同的方法. 做位图时就要做成高分辨率屏幕下 1:1 大小的图.
+处理高分辨率图形时,我们需要采用与复古/8位图形不同的项目设置和内容设置方法。对于位图图形,您需要以这样的方式创建内容,使其在高分辨率屏幕上以1:1比例显示时看起来良好。
 
-同样也需要更改渲染脚本. 这次我们需要按原始比例显示图像:
+就像复古/8位图形一样,您需要更改渲染脚本。在这种情况下,您希望图形随屏幕尺寸缩放,同时保持原始宽高比:
 
 ```Lua
 msg.post("@render:", "use_fixed_fit_projection")
 ```
 
-这样就确保了游戏像 *game.project* 设置的那样始终显示等比的内容, 如果宽高比与设置不符, 游戏边缘可能会显示出额外的内容.
+这将确保屏幕将调整大小以始终显示与*game.project*文件中指定的相同数量的内容,可能会根据宽高比是否不同而在上方和下方或两侧显示额外内容。
 
-在 *game.project* 文件中可以设置设计时屏幕宽和高.
+您应该在*game.project*文件中将宽度和高度配置为允许您在不缩放的情况下显示游戏内容的尺寸。
 
-### 高分辨率视网膜屏幕
+### 高DPI设置和视网膜屏幕
 
-想要支持高分辨率视网膜屏幕可以在 *game.project* 文件里打开这个选项:
+如果您还希望支持高分辨率的视网膜屏幕,可以在*game.project*文件的Display部分启用此功能:
 
 ![](images/screen_size/highdpi-enabled.png)
 
-选中这个选项就打开了高分辨率后台缓冲. 游戏会以设置好的宽高双倍比例渲染, 但是游戏分辨率不变. 也就是说游戏内容是1倍大小的就照常显示. 但是如果内容是双倍大小再在游戏里缩小为1倍的话就是高清渲染了.
+这将在支持高DPI的显示器上创建高DPI的后台缓冲区。游戏将以宽度和高度设置中设置的双倍分辨率渲染,这些设置仍将是脚本和属性中使用的逻辑分辨率。这意味着所有测量值保持不变,任何以1x比例渲染的内容看起来都一样。但是,如果您导入高分辨率图像并将它们缩放到0.5x,它们在屏幕上将是高DPI的。
 
 
-## 创建可适配性 GUI
+## 创建自适应GUI
 
-系统的 GUI 组件由各种元素组成, 或称作 [节点](/manuals/gui/#节点类型), 虽然看起来很简单却能创造出从按钮到复杂的菜单和弹框等各种界面. GUI 可以设计成自动适配屏幕尺寸和方向的. 比如让节点保持在屏幕顶部, 底部或边上而不改变自身的大小. 也可以设置成对于不同屏幕尺寸和方向自动调整节点关系大小与形态.
+创建GUI组件的系统围绕许多基本构建块或[节点](/manuals/gui/#node-types)构建,虽然看起来可能过于简单,但它可以用来创建从按钮到复杂菜单和弹出窗口的任何内容。您创建的GUI可以配置为自动适应屏幕尺寸和方向的变化。例如,您可以将节点锚定在屏幕的顶部、底部或侧面,节点可以保持其大小或拉伸。节点之间的关系以及它们的大小和外观也可以配置为在屏幕尺寸或方向变化时发生变化。
 
 ### 节点属性
 
-gui中的节点包含锚点, 横轴纵轴以及一个调整模式.
+GUI中的每个节点都有一个枢轴点、水平和垂直锚点以及调整模式。
 
-* 锚点定义了节点的中心.
-* 锚点模式控制着当屏幕边界或者其父节点边界在适配物理屏幕时拉伸的话, 节点自身在水平和垂直方向位置如何修改.
-* 调整模式控制着当屏幕边界或者其父节点边界在适配物理屏幕时, 节点自身该怎样做.
+* 枢轴点定义节点的中心点。
+* 锚点模式控制当场景边界或父节点边界被拉伸以适应物理屏幕大小时,节点的垂直和水平位置如何改变。
+* 调整模式设置控制当场景边界或父节点边界被调整以适应物理屏幕大小时,节点会发生什么变化。
 
-详情请见 [GUI教程](/manuals/gui/#节点属性).
+您可以在[GUI手册](/manuals/gui/#node-properties)中了解更多关于这些属性的信息。
 
 ### 布局
 
-Defold支持GUI在手机上自动适配屏幕方向. 此功能让你能把GUI设计成适配各种各样屏幕比例和方向的. 也可以用来创建特定设备上的界面布局. 详情请见 [GUI 布局教程](/manuals/gui-layouts/)
+Defold支持GUI在移动设备上自动适应屏幕方向变化。通过使用此功能,您可以设计一个能够适应一系列屏幕尺寸的方向和宽高比的GUI。也可以创建匹配特定设备型号的布局。您可以在[GUI布局手册](/manuals/gui-layouts/)中了解更多关于此系统的信息。
 
 
 ## 测试不同的屏幕尺寸
 
-Debug 菜单有用来模拟特定设备分辨率或者自定义分辨率的选项. 当应用运行时你可以通过选择 <kbd>Debug->Simulate Resolution</kbd> 然后从列表中选择一个模拟设备. 运行中的应用会自动缩放来测试游戏运行在不同分辨率和屏幕比例的设备上的样子.
+调试菜单包含一个选项,用于模拟特定设备型号分辨率或自定义分辨率。当应用程序运行时,您可以选择<kbd>Debug->Simulate Resolution</kbd>并从列表中选择一个设备型号。运行的应用程序窗口将调整大小,您将能够看到您的游戏在不同分辨率或不同宽高比下的外观。
 
-![](images/screen_size/simulate-resolution.png)
+![](images/screen_size/simulate-resolution.png)

+ 64 - 64
docs/zh/manuals/addressing.md

@@ -1,15 +1,15 @@
 ---
-title: Defold 定位
-brief: 本教程解释了 Defold 如何实现地址定位功能.
+title: Defold 中的寻址
+brief: 本手册解释了 Defold 如何解决寻址问题。
 ---
 
-# 定位
+# 寻址
 
-为了让代码能够控制每个对象和组件的移动, 缩放, 播放动画或者添加删除各种视听元素, Defold 提供了地址定位机制.
+控制运行游戏的代码必须能够到达每个对象和组件,以便移动、缩放、制作动画、删除和操作玩家看到和听到的内容。Defold的寻址机制使这成为可能。
 
-## 标
+## 标识符
 
-Defold 使用地址 (称为 URL, 暂且不表) 来引用游戏对象和组件. 地址里包含各种标志. 下面列举了 Defold 使用地址的例子. 本教程将详述地址的用法:
+Defold使用地址(或URL,但我们暂时忽略这一点)来引用游戏对象和组件。这些地址由标识符组成。以下是Defold如何使用地址的所有示例。通过本手册,我们将详细研究它们的工作原理:
 
 ```lua
 local id = factory.create("#enemy_factory")
@@ -22,107 +22,107 @@ msg.post("#", "hello_there")
 local id = go.get_id(".")
 ```
 
-先看一个简单的例子. 比如你有一个含有Sprite的游戏对象. 然后附加一个脚本来控制这个对象. 在编辑器里的设置就差不多这样:
+让我们从一个非常简单的例子开始。假设你有一个带有单个精灵组件的游戏对象。你还有一个脚本组件来控制这个游戏对象。编辑器中的设置看起来会像这样:
 
 ![bean in editor](images/addressing/bean_editor.png)
 
-你想开始先关闭这个sprite, 留待以后显示. 我们来简单创建一个脚本 "controller.script":
+现在你想在游戏开始时禁用精灵,以便稍后让它出现。这可以通过在"controller.script"中放入以下代码轻松完成:
 
 ```lua
 function init(self)
     msg.post("#body", "disable") -- <1>
 end
 ```
-1. 不知道 '#' 是什么意思没关系, 一会儿就谈到.
+1. 如果你对'#'字符感到困惑,不用担心,我们很快会讲到它。
 
-就像设计的那样, 游戏一开始脚本组件 *定位* 到了sprite组件 "body" 对其地址发出了一个  "disable" 的 *消息* . 这个消息的结果就是把sprite隐藏了. 也就是说, 整个流程是这样的:
+这将按预期工作。当游戏启动时,脚本组件*通过其标识符"body"寻址*到精灵组件,并使用该地址向其发送一条带有"disable"的*消息*。这个特殊引擎消息的效果是精灵组件隐藏精灵图形。从示意图上看,设置如下:
 
 ![bean](images/addressing/bean.png)
 
-id可以随意设置. 当前我们对游戏对象设置了一个id "bean", sprite组件叫做 "body", 控制这个对象的脚本组件叫做 "controller".
+设置中的标识符是任意的。在这里,我们选择给游戏对象命名为"bean",其精灵组件命名为"body",而控制角色的脚本组件命名为"controller"。
 
 ::: sidenote
-如果你不手动命名, 编辑器会自动设置一个命名. 每当新建一个游戏对象或组件, 系统会将唯一 *Id* 赋值给它.
+如果你不选择名称,编辑器会为你选择。每当你在编辑器中创建新的游戏对象或组件时,会自动设置一个唯一的*Id*属性。
 
-- 游戏对象就是go后面跟一个数字 ("go2", "go3" 以此类推).
-- 组件就是组件名后面跟一个数字 ("sprite", "sprite2" 以此类推).
+- 游戏对象自动获得一个名为"go"的id,后面跟着枚举器("go2"、"go3"等)。
+- 组件获得一个对应于组件类型的id("sprite"、"sprite2"等)。
 
-自动命名虽然能用, 但是我们鼓励你自己将命名设计的更好, 更有意义.
+如果你愿意,可以坚持使用这些自动分配的名称,但我们鼓励你将标识符改为好的、描述性的名称。
 :::
 
-现在, 再增加一个sprite来给豆子先生添加一个盾牌:
+现在,让我们添加另一个精灵组件并给豆子一个盾牌:
 
 ![bean](images/addressing/bean_shield_editor.png)
 
-每个游戏对象的组件id必须唯一. 再叫 "body" 的话脚本就不知道该给谁发送 "disable" 信息了. 所以我们选择了 (更具意义的) id "shield". 这样不管是 "body" 还是 "shield" 我们都能自由控制了.
+新组件必须在游戏对象内唯一标识。如果你给它命名为"body",脚本代码将不清楚应该向哪个精灵发送"disable"消息。因此我们选择了唯一(且描述性)的标识符"shield"。现在我们可以随意启用和禁用"body"和"shield"精灵。
 
 ![bean](images/addressing/bean_shield.png)
 
 ::: sidenote
-如果你非要设置成一样的id, 系统会提示错误阻止你这样做:
+如果你确实尝试多次使用同一标识符,编辑器会发出错误信号,因此在实践中这永远不会成为问题:
 
 ![bean](images/addressing/name_collision.png)
 :::
 
-现在再多加一些游戏对象进来试试. 假设你要让两个 "豆子先生" 组个队. 一个叫 "bean" 另一个叫 "buddy". 然后, 当 "bean" 等待一段时间后, 它就让 "buddy" 开始跳舞. 也就是从 "bean" 的脚本组件 "controller" 发送一个自定义消息 "dance" 到 "buddy" 的 "controller" :
+现在,让我们看看如果添加更多游戏对象会发生什么。假设你想将两个"豆子"配对成一个小队。你决定将其中一个豆子游戏对象命名为"bean",另一个命名为"buddy"。此外,当"bean"闲置一段时间后,它应该告诉"buddy"开始跳舞。这是通过从"bean"中的"controller"脚本组件向"buddy"中的"controller"脚本发送一个名为"dance"的自定义消息来完成的:
 
 ![bean](images/addressing/bean_buddy.png)
 
 ::: sidenote
-这两个脚本组件都叫 "controller", 但是由于唯一性是对每个游戏对象来说的, 所以这样做是可以的.
+有两个名为"controller"的独立组件,每个游戏对象中一个,但这是完全合法的,因为每个游戏对象都创建了一个新的命名上下文。
 :::
 
-这次的消息是发给本游戏对象 ("bean") 之外的地方, 代码需要知道哪个 "controller" 来接收这个消息. 既需要对象id也需要组件id. 完整的地址是 `"buddy#controller"` 它包含两个方面内容.
+由于消息的接收者在发送消息的游戏对象("bean")之外,代码需要指定哪个"controller"应该接收消息。它需要指定目标游戏对象id以及组件id。组件的完整地址变为`"buddy#controller"`,这个地址由两个独立部分组成。
 
-- 首先需要指定目标对象的id ("buddy"),
-- 然后是对象/组件分隔符 ("#"),
-- 最后是组件的id ("controller").
+- 首先是目标游戏对象的标识("buddy"),
+- 然后是游戏对象/组件分隔符("#"),
+- 最后你写上目标组件的标识("controller")。
 
-回过头来看上个例子我们没有指定对象的id, 系统默认对象就是脚本所在的 *当前游戏对象*.
+回到前面只有一个游戏对象的例子,我们看到通过省略目标地址的游戏对象标识符部分,代码可以寻址*当前游戏对象*中的组件。
 
-比如, `"#body"` 就是在当前游戏对象里找 "body" 组件. 这就很方便因为脚本可以在 *任何* 游戏对象上运行, 只要它有 "body" 组件.
+例如,`"#body"`表示当前游戏对象中组件"body"的地址。这非常有用,因为这段代码可以在*任何*游戏对象中工作,只要存在"body"组件。
 
 ## 集合
 
-集合可以用来创建一组游戏对象, 或者嵌套游戏对象然后在需要的时候使用它们. 当你在编辑器里做实例化操作时集合文件就可作为模板 (有的叫 "prototypes" 有的叫 "prefabs").
+集合使得创建游戏对象的组或层次结构,并以受控方式重用它们成为可能。当你在游戏中填充内容时,可以在编辑器中使用集合文件作为模板(或"原型"或"预制件")。
 
-比如你想建立许多 bean/buddy 二人组. 最好把它们做成 *集合文件* (命名为 "team.collection"). 编译并保存好. 然后在引导启动集合里就可以实例化并命名 (比如 "team_1"):
+假设你想要创建大量的bean/buddy团队。一个好的方法是在一个新的*集合文件*中创建一个模板(命名为"team.collection")。在集合文件中构建团队游戏对象并保存它。然后将该集合文件内容的实例放入你的主引导集合中,并给该实例一个标识符(命名为"team_1"):
 
 ![bean](images/addressing/team_editor.png)
 
-这种结构下, "bean" 游戏对象依旧可以使用地址 `"buddy#controller"` 来引用"buddy"的"controller"组件.
+有了这种结构,"bean"游戏对象仍然可以通过地址`"buddy#controller"`引用"buddy"中的"controller"组件。
 
 ![bean](images/addressing/collection_team.png)
 
-如果你再实例化一个 "team.collection" (命名 "team_2"), 那么 "team_2" 的脚本也能顺利运行. "team_2"中的"bean" 对象同样使用地址 `"buddy#controller"` 来引用"buddy"的"controller"组件.
+如果你添加"team.collection"的第二个实例(命名为"team_2"),在"team_2"脚本组件中运行的代码将同样工作良好。来自集合"team_2"的"bean"游戏对象实例仍然可以通过地址`"buddy#controller"`寻址"buddy"中的"controller"组件。
 
 ![bean](images/addressing/teams_editor.png)
 
-## 相对
+## 相对
 
-地址 `"buddy#controller"` 在两组实例下都能运行因为它是一个 *相对* 地址. 集合 "team_1" 和 "team_2" 都有自己的上下文, 或者叫做 "命名空间". Defold 认为集合内这样的相对地址与命名是合理的:
+地址`"buddy#controller"`对两个集合中的游戏对象都有效,因为它是一个*相对*地址。每个集合"team_1"和"team_2"都创建了一个新的命名上下文,或者如果你愿意,可以称为"命名空间"。Defold通过考虑集合创建的命名上下文来避免命名冲突:
 
 ![relative id](images/addressing/relative_same.png)
 
-- "team_1"的命名空间里 "bean" 和 "buddy" 都是唯一id.
-- 同样在"team_2"的命名空间里 "bean" 和 "buddy" 也都是唯一id.
+- 在命名上下文"team_1"中,游戏对象"bean"和"buddy"被唯一标识。
+- 类似地,在命名上下文"team_2"中,游戏对象"bean"和"buddy"也被唯一标识。
 
-实际上相对地址在后台已经把上下文考虑在内. 这同样很方便因为你可以用同样的代码创建很多个集合的实例.
+相对寻址通过在解析目标地址时自动添加当前命名上下文来工作。这再次非常有用和强大,因为你可以创建带有代码的游戏对象组,并在整个游戏中高效地重用它们。
 
 ### 简化符
 
-Defold 提供两种简化写法用来简化消息传递时需要输入的完整地址:
+Defold提供了两个方便的简化符,你可以使用它们来发送消息而无需指定完整的URL:
 
 :[Shorthands](../shared/url-shorthands.md)
 
 ## 游戏对象路径
 
-为了正确理解命名机制, 我们来看看游戏编译运行时发生了什么:
+为了正确理解命名机制,让我们看看当你构建和运行项目时会发生什么:
 
-1. 编辑器读取引导启动集合 ("main.collection") 与其所有内容 (游戏对象和其他集合).
-2. 对于每个静态的游戏对象, 编译器分配唯一id. 游戏对象 "路径" 从引导启动集合根节点起, 到嵌套关系里找到这个对象为止. 每个 '/' 符号代表嵌套的每一层.
+1. 编辑器读取引导集合("main.collection")及其所有内容(游戏对象和其他集合)。
+2. 对于每个静态游戏对象,编译器创建一个标识符。这些被构建为从引导根开始,沿着集合层次结构到对象的"路径"。每层都添加一个'/'字符。
 
-如上示例, 游戏里就有四个游戏对象路径:
+对于我们上面的示例,游戏将运行以下4个游戏对象:
 
 - /team_1/bean
 - /team_1/buddy
@@ -130,34 +130,34 @@ Defold 提供两种简化写法用来简化消息传递时需要输入的完整
 - /team_2/buddy
 
 ::: sidenote
-游戏里的各种id存储为哈希值. 包括集合里的相对路径也哈希成绝对路径.
+标识符存储为哈希值。运行时还存储每个集合标识符的哈希状态,用于将相对字符串哈希到绝对id。
 :::
 
-运行时, 不存在集合的概念. 编译前, 对象是不属于集合的. 也无法对集合本身施加操作. 有必要的话, 需要用代码维护集合里的对象. 每个对象id都是静态的, 并且在它们的生命周期中都保持不变. 所以保存一个对象的id后总可以使用此id引用它.
+在运行时,集合分组不存在。无法找出特定游戏对象在编译前属于哪个集合。也不可能一次操作集合中的所有对象。如果你需要执行此类操作,你可以在代码中轻松地自己进行跟踪。每个对象的标识符是静态的,保证在整个对象生命周期内保持不变。这意味着你可以安全地存储对象的标识符并在以后使用它。
 
-## 绝对
+## 绝对
 
-定位的时候完全可以使用上述完整的标记. 多数情况下相对地址有助于代码重用, 但是有些情况下还得使用绝对地址定位.
+在寻址时可以使用上述的完整标识符。在大多数情况下,相对寻址是首选的,因为它允许内容重用,但在某些情况下,绝对寻址变得必要。
 
-比如, 你需要一个 AI 管理器管理每个豆子先生. 豆子先生要向管理器报告自身的激活状态, 管理器根据它们的状态决定它们的排序. 这就需要创建一个带脚本的管理器对象然后把它放在引导启动集合的根目录下.
+例如,假设你想要一个AI管理器来跟踪每个豆子对象的状态。你希望豆子向管理器报告它们的活跃状态,管理器根据它们的状态做出战术决策并向豆子下达命令。在这种情况下,创建一个带有脚本组件的单个管理器游戏对象并将其与团队集合一起放在引导集合中是完全合理的。
 
 ![manager object](images/addressing/manager_editor.png)
 
-然后每个豆子先生负责向管理器发送状态消息: "contact" 表明碰到了敌人, 或者 "ouch!" 表明受到了袭击. 为了这项工作, 豆子控制器脚本使用相对地址向 "manager" 里的 "controller" 组件发送消息.
+然后每个豆子负责向管理器发送状态消息:如果发现敌人则发送"contact",如果被击中并受到伤害则发送"ouch!"。为了使这个工作,豆子控制器脚本使用绝对寻址向"manager"中的"controller"组件发送消息。
 
-任何以 '/' 开头的地址都从游戏世界的根上进行索引. 这对应了游戏启动时载入的 *bootstrap collection* 的根.
+任何以'/'开头的地址将从游戏世界的根解析。这对应于游戏启动时加载的*引导集合*的根。
 
-控制器脚本的绝对地址是`"/manager#controller"` 而且不管组件用在哪里该绝对地址总能定位到该组件.
+管理器脚本的绝对地址是`"/manager#controller"`,这个绝对地址将解析到正确的组件,无论它在哪里使用。
 
 ![teams and manager](images/addressing/teams_manager.png)
 
 ![absolute addressing](images/addressing/absolute.png)
 
-## 哈希标
+## 哈希标识符
 
-引擎把每个 id 都存为哈希值. 所有以组件或游戏对象为参数的方法可以接受字符串, 哈希或者 URL 对象. 我们已经在上面看到如何使用字符串进行定位了.
+引擎将所有标识符存储为哈希值。所有以组件或游戏对象为参数的函数接受字符串、哈希或URL对象。我们已经在上文看到了如何使用字符串进行寻址。
 
-当你获取游戏对象的 id , 引擎总是返回一个绝对路径 id 的哈希值:
+当你获取游戏对象的标识符时,引擎将总是返回一个哈希化的绝对路径标识符:
 
 ```lua
 local my_id = go.get_id()
@@ -167,10 +167,10 @@ local spawned_id = factory.create("#some_factory")
 print(spawned_id) --> hash: [/instance42]
 ```
 
-你可以用该标记代替字符串 id, 或者自己写一个. 注意虽然哈希化 id 对应了对象的路径, 比如绝对地址:
+你可以在字符串id的地方使用这样的标识符,或者自己构造一个。但请注意,哈希id对应于对象的路径,即绝对地址:
 
 ::: sidenote
-相对地址必须作为字符串使用因为引擎会基于当前命名上下文(集合)的哈希状态, 把字符串添加到哈希后面, 计算出新的哈希id.
+相对地址必须作为字符串给出,因为引擎将基于当前命名上下文(集合)的哈希状态,通过将给定字符串添加到哈希中来计算新的哈希id。
 :::
 
 ```lua
@@ -186,32 +186,32 @@ local relative_id = hash("my_object")
 go.set_position(pos, relative_id)
 ```
 
-## URLs
+## URL
 
-最后我们来看 Defold 定位的完全体: URL.
+为了完整理解,让我们看看Defold地址的完整格式:URL。
 
-URL 是一个对象, 通常用特定格式的字符串表示. 一般一个 URL 包含三个部分:
+URL是一个对象,通常写为特殊格式的字符串。通用URL由三部分组成:
 
 `[socket:][path][#fragment]`
 
 socket
-: 代表目标的游戏世界. 使用 [集合代理](/manuals/collection-proxy) 时, 它用来表示 _动态加载的集合_.
+: 标识目标的游戏世界。在使用[集合代理](/manuals/collection-proxy)时这很重要,然后用于标识_动态加载的集合_。
 
 path
-: 该部分包含目标游戏对象的完整 id.
+: URL的这部分包含目标游戏对象的完整id。
 
 fragment
-: 标志了指定游戏对象内的目标组件.
+: 指定游戏对象内目标组件的标识。
 
-上面已经看到, 你可以省略一些, 或者大多数情况下省略许多部分. 几乎可以不用到 socket, 经常, 不是所有情况下, 需要指定路径. 需要定位其他游戏世界里的东西的情况下需要指定 URL 的 socket 部分. 例如,  上述 "manager" 游戏对象里的 "controller" 脚本的完整 URL 字符串为:
+正如我们在上面看到的,在大多数情况下,你可以省略部分或大部分信息。你几乎不需要指定socket,你经常(但不总是)需要指定路径。在你确实需要寻址另一个游戏世界中的事物的情况下,你需要指定URL的socket部分。例如,上面"manager"游戏对象中"controller"脚本的完整URL字符串是:
 
 `"main:/manager#controller"`
 
-然后 team_2 里的 buddy 控制器为:
+而team_2中的buddy控制器是:
 
 `"main:/team_2/buddy#controller"`
 
-我们可以向它们发送消息:
+我们可以向它们发送消息
 
 ```lua
 -- Send "hello" to the manager script and team buddy bean
@@ -219,9 +219,9 @@ msg.post("main:/manager#controller", "hello_manager")
 msg.post("main:/team_2/buddy#controller", "hello_buddy")
 ```
 
-## 构建 URL 对象
+## 构建URL对象
 
-URL 对象也可以使用 Lua 代码构建:
+URL对象也可以在Lua代码中以编程方式构造:
 
 ```lua
 -- Construct URL object from a string:

+ 27 - 27
docs/zh/manuals/ads.md

@@ -1,61 +1,61 @@
 ---
-title: 在 Defold 中播放广告
-brief: 广告是网页游戏和手机游戏的基本盈利方式. 本教程介绍了在 Defold 中如何通过广告盈利.
+title: 在 Defold 中展示广告
+brief: 展示各种类型的广告是网页和手机游戏盈利的常见方式。本手册介绍了使用广告为游戏盈利的多种方法。
 ---
 
 # 广告
 
-广告作为网页游戏和手机游戏的一种普遍盈利方式日趋壮大. 玩家观看游戏里的广告, 开发者有机会获利. 一般看的越多获利越多, 但是最终受益还要取决于下面几项:
+广告已成为网页和手机游戏盈利的非常普遍的方式,并已发展成为一个价值数十亿美元的产业。作为开发者,你的收入基于观看游戏中广告的人数。通常情况很简单,观看者越多收入越多,但其他因素也会影响你的收入:
 
-* 广告质量 - 游戏内容相关的广告容易获得玩家点击与关注.
-* 广告类型 - 广告条的利润低而从头看到尾的全屏广告利润高.
-* 广告商 - 不同广告供应商的广告利润有高有低.
+* 广告质量 - 相关广告更容易获得玩家的互动和关注。
+* 广告格式 - 横幅广告通常收入较低,而从头到尾观看的全屏广告收入更高。
+* 广告网络 - 你获得的收入因广告网络而异。
 
 ::: sidenote
-CPM = 千人成本. 广告商为一千个浏览量支付的报酬. 不同广告商不同广告类型费用也不同.
+CPM = 千人成本。广告商为每千次观看支付的金额。CPM因广告网络和广告格式而异。
 :::
 
-## 类型
+## 格式
 
-游戏中可以放各种广告. 常见的有广告条, 插播广告和奖励广告:
+游戏中可以使用许多不同类型的广告格式。一些更常见的格式是横幅广告、插页广告和奖励广告:
 
-### 广告
+### 横幅广告
 
-广告条可以是文字的, 图片的或者视频的并且占据一部分屏幕, 一般不是屏幕上边就是底边. 广告条很容易植入, 休闲小游戏也容易空出广告条的位置来. 曝光率高, 玩家反感较少.
+横幅广告基于文本、图像或视频,覆盖屏幕的相对较小部分,通常位于屏幕的顶部或底部。横幅广告非常容易实现,并且非常适合休闲单屏游戏,因为很容易为广告预留屏幕区域。横幅广告最大化了曝光率,因为用户可以在不中断游戏的情况下玩你的游戏。
 
-### 插广告
+### 插广告
 
-插播广告是一种带动画有的还有多媒体交互的全屏广告. 插播广告通常出现在游戏关与关之间或者游戏暂停等时候. 插播广告曝光不高, 但是付费较高, 可以带来不菲收入.
+插页广告是带有动画的大型全屏体验,有时还包含交互式富媒体内容。插页广告通常在关卡之间或游戏会话之间展示,因为这是游戏体验中的自然中断。插页广告通常产生的观看次数少于横幅广告,但其成本(CPM)远高于横幅广告,从而带来可观的总体广告收入。
 
 ### 奖励广告
 
-奖励广告 (也叫激励广告) 是一种玩家最不反感的广告. 样子通常跟插播广告类似. 玩家可以通过观看广告获得游戏虚拟奖励 - 比如财产, 金币, 命, 游戏延时等等. 奖励广告通常付费最高, 但是观看率取决于玩家. 在关键时刻给予玩家渴望的奖励才能取得激励的效果.
+奖励广告(也称为激励广告)是可选的,因此比许多其他形式的广告侵入性更小。奖励广告通常是像插页广告一样的全屏体验。用户可以选择观看广告以换取奖励 - 例如战利品、硬币、生命、时间或其他游戏内货币或福利。奖励广告通常具有最高的成本(CPM),但观看次数直接与用户选择率相关。只有当奖励足够有价值并在适当时机提供时,奖励广告才能产生良好的效果。
 
 
-## 广告
+## 广告网络
 
-在 [Defold 资源中心](/tags/stars/ads/) 提供了一些广告商的支持程序:
+[Defold 资源门户](/tags/stars/ads/)包含几个与广告提供商集成的资源:
 
-* [AdMob](https://defold.com/assets/admob-defold/) - 谷歌 AdMob 广告.
-* [Enhance](https://defold.com/assets/enhance/) - 广告商大集合. 编译后需要额外的安装步骤.
-* [Facebook Instant Games](https://defold.com/assets/facebookinstantgames/) - 脸书广告.
-* [IronSource](https://defold.com/assets/ironsource/) - IronSource 广告.
-* [Unity Ads](https://defold.com/assets/defvideoads/) - Unity 广告.
+* [AdMob](https://defold.com/assets/admob-defold/) - 使用 Google AdMob 网络展示广告。
+* [Enhance](https://defold.com/assets/enhance/) - 支持多种不同的广告网络。需要额外的构建后步骤。
+* [Facebook Instant Games](https://defold.com/assets/facebookinstantgames/) - 在你的 Facebook Instant Game 中展示广告。
+* [IronSource](https://defold.com/assets/ironsource/) - 使用 IronSource 广告网络展示广告。
+* [Unity Ads](https://defold.com/assets/defvideoads/) - 使用 Unity Ads 网络展示广告。
 
 
-# 广告游戏整合
+# 如何在游戏中整合广告
 
-决定好合作广告商就可以按步骤地植入广告资源了. 一般都要首先加入 [项目依赖](/manuals/libraries/#设置库依赖). 之后载入广告资源, 展示广告内容.
+当你决定要在游戏中整合广告网络后,你需要遵循该特定资源的安装和使用说明。通常你要做的是首先将该扩展添加为[项目依赖](/manuals/libraries/#setting-up-library-dependencies)。一旦将资源添加到项目中,你就可以继续进行集成,并调用特定于该资源的函数来加载和展示广告。
 
 
-# 广告与内支付
+# 结合广告和应用内购买
 
-手机游戏通常含有 [应用内支付](/manuals/iap) 功能以便获得更大收益.
+在手机游戏中,提供[应用内购买](/manuals/iap)以永久移除广告是相当常见的。
 
 
-## 更多资源
+## 了解更多
 
-网上也有很多关于优化广告的教程:
+有许多在线资源可供学习优化广告收入:
 
 * Google AdMob [Monetize mobile games with ads](https://admob.google.com/home/resources/monetize-mobile-game-with-ads/)
 * Game Analytics [Popular ad formats and how to use them](https://gameanalytics.com/blog/popular-mobile-game-ad-formats.html)

+ 36 - 31
docs/zh/manuals/android.md

@@ -1,58 +1,58 @@
 ---
-title: Defold 的 Android 平台开发
-brief: 本教程介绍了如何在 Defold 中进行 Android 设备应用的开发
+title: Android 平台开发
+brief: 本手册描述了如何在 Android 设备上构建和运行 Defold 应用程序
 ---
 
 # Android 开发
 
-Android 设备允许自由允许你开发的应用. 可以很容易地编译好游戏拷贝到 Android 设备上. 本手册介绍了对于 Android 游戏的打包步骤. 推荐开发时, 从 [开发应用](/manuals/dev-app) 上运行游戏因为可以通过无线连接设备进行代码和内容的热重载.
+Android 设备允许你自由运行自己的应用程序。构建游戏版本并将其复制到 Android 设备上非常容易。本手册解释了为 Android 打包游戏所涉及的步骤。在开发过程中,通过[开发应用](/manuals/dev-app)运行游戏通常是首选,因为它允许你直接将内容和代码热重载到设备上。
 
-## Android 和 Google Play 签名
+## Android 和 Google Play 签名流程
 
-Android 要求每个 APK 文件在被安装到设备上或者在设备上更新之前必须进行数字签名. 如果你是安卓开发者, 只需要在把程序包上传到 Play Console 之前, 经过 [Play App Signing](https://developer.android.com/studio/publish/app-signing#app-signing-google-play) 的自动处理即可. 然而, 你还可以选择手动对程序包进行签名以便上传到 Google Play, 其他应用商店以及在整个互联网上传播.
+Android 要求所有 APK 在安装到设备上或更新之前都必须使用证书进行数字签名。如果你使用 Android App Bundles,只需在上传到 Play Console 之前对你的应用包进行签名,[Play App Signing](https://developer.android.com/studio/publish/app-signing#app-signing-google-play)会处理其余部分。但是,你也可以手动为应用签名,以便上传到 Google Play、其他应用商店以及在任何商店之外分发。
 
-从 Defold 编辑器或者 [命令行工具](/manuals/bob) 打包安卓包需要提供一个 keystore (包括证书和公匙), 然后对应用签名时还要用到私匙. 没有的话, Defold 会自动生成一个临时调试用 keystore 用于打包和签名.
+当你从 Defold 编辑器或[命令行工具](/manuals/bob)创建 Android 应用包时,你可以提供一个密钥库(包含你的证书和密钥)和密钥库密码,这些将在签名你的应用程序时使用。如果你不提供,Defold 会生成一个调试密钥库并在签名应用程序包时使用它。
 
-::: sidenote
-千万 **不要** 带着调试签名就上传到 Google Play 上去. 开发者必须自己制作属于自己的签名.
+::: important
+你**绝对不应该**将使用调试密钥库签名的应用程序上传到 Google Play。始终使用你自己创建的专用密钥库。
 :::
 
-## 制作 keystore
+## 创建密钥库
 
 ::: sidenote
-Defold 应对安卓应用包签名的改变是从 1.2.173 版开始的, 就是使用单独的证书和密码来合成 keystore. [详见论坛帖子](https://forum.defold.com/t/upcoming-change-to-the-android-build-pipeline/66084).
+Defold 中的 Android 签名流程在版本 1.2.173 中发生了变化,从使用独立的密钥和证书改为使用密钥库。[更多信息请参阅此论坛帖子](https://forum.defold.com/t/upcoming-change-to-the-android-build-pipeline/66084)。
 :::
 
-也可以 [使用 Android Studio](https://developer.android.com/studio/publish/app-signing#generate-key) 或者通过使用控制台命令来生成签名:
+你可以[使用 Android Studio](https://developer.android.com/studio/publish/app-signing#generate-key)或从终端/命令提示符创建密钥库:
 
 ```bash
 keytool -genkey -v -noprompt -dname "CN=John Smith, OU=Area 51, O=US Air Force, L=Unknown, ST=Nevada, C=US" -keystore mykeystore.keystore -storepass 5Up3r_53cR3t -alias myAlias -keyalg RSA -validity 9125
 ```
 
-这个命令会生成一个叫做 `mykeystore.keystore` 的签名, 其中包含了证书和密码. 密匙 `5Up3r_53cR3t` 保护其不备破解. 这个签名有效期为 25 年 (9125 天). 这个签名的id叫做 `myAlias`.
+这将创建一个名为 `mykeystore.keystore` 的密钥库文件,其中包含一个密钥和证书。对密钥和证书的访问将受到密码 `5Up3r_53cR3t` 的保护。密钥和证书将在 25 年(9125 天)内有效。生成的密钥和证书将通过别名 `myAlias` 进行标识。
 
-::: sidenote
-要把签名和密匙保存好. 如果要手动上传 Google Play 但是签名密码丢失的话就没办法使用 Google Play 来更新你的应用了. 图省事的话就用 Google Play App Signing 搞定签名吧.
+::: important
+确保将密钥库和相关密码存储在安全的地方。如果你自己签名并将应用程序上传到 Google Play,而密钥库或密钥库密码丢失,你将无法在 Google Play 上更新应用程序。你可以通过使用 Google Play App Signing 并让 Google 为你签名应用程序来避免这种情况。
 :::
 
 
-## 安卓应用打
+## 创建 Android 应用
 
-编辑器打包安卓包十分方便. 打包之前可以为应用指定图标, 设置版本号等等, 都在 *game.project* [项目配置文件](/manuals/project-settings/#Android) 里设置.
+编辑器允许你轻松地为游戏创建独立的应用包。在打包之前,你可以在 *game.project* [项目设置文件](/manuals/project-settings/#android) 中指定要使用的图标、设置版本代码等。
 
-选择菜单栏 <kbd>Project ▸ Bundle... ▸ Android Application...</kbd> 就可以打包了.
+要从菜单中选择打包,请选择 <kbd>Project ▸ Bundle... ▸ Android Application...</kbd>。
 
-要让编辑器自动生成调试用签名, 只需把 *Keystore* 和 *Keystore password* 字段留空即可:
+如果你希望编辑器自动创建随机调试证书,请将 *Keystore* 和 *Keystore password* 字段留空:
 
 ![Signing Android bundle](images/android/sign_bundle.png)
 
-要让编辑器使用你自己指定的签名打包, 就要设置好 *Keystore* 和 *Keystore password* 字段. *Keystore* 的扩展名是 `.keystore`, 而密码要保存成文本 `.txt` 文件. 如果 keystore 里的 key 使用了自己的密码, 也可在 *Key password* 里指定:
+如果你想使用特定的密钥库为你的包签名,请指定 *Keystore* 和 *Keystore password*。*Keystore* 预期具有 `.keystore` 文件扩展名,而密码预期存储在具有 `.txt` 扩展名的文本文件中。如果密钥库中的密钥使用与密钥库本身不同的密码,也可以指定 *Key password*:
 
 ![Signing Android bundle](images/android/sign_bundle2.png)
 
-Defold 支持创建 APK 和 AAB 文件. 从打包格式下拉菜单中选择.
+Defold 支持创建 APK 和 AAB 文件。从 Bundle Format 下拉菜单中选择 APK 或 AAB。
 
-点击 <kbd>Create Bundle</kbd> 会提示选择打包文件存放位置.
+配置好应用包设置后,按 <kbd>Create Bundle</kbd>。然后系统会提示你指定在计算机上创建包的位置。
 
 ![Android Application Package file](images/android/apk_file.png)
 
@@ -62,7 +62,9 @@ Defold 支持创建 APK 和 AAB 文件. 从打包格式下拉菜单中选择.
 
 #### 安装 APK
 
-编辑器生成 Android 应用包 *.apk* 文件. 应用包可以通过 `adb` 工具安装到设备上, 或者通过 [Google Play 开发者控制台](https://play.google.com/apps/publish/) 发布到 Google Play 上.
+一个 *`.apk`* 文件可以使用 `adb` 工具复制到你的设备上,或者通过 [Google Play 开发者控制台](https://play.google.com/apps/publish/) 复制到 Google Play。
+
+:[Android ADB](../shared/android-adb.md)
 
 ```
 $ adb install Defold\ examples.apk
@@ -73,29 +75,32 @@ Success
 
 #### 使用编辑器安装 APK
 
-你可以在编辑器的打包对话框中勾选 "Install on connected device" 和 "Launch installed app"  安装并启动 *.apk*:
+你可以使用编辑器打包对话框中的"在连接的设备上安装"和"启动已安装的应用"复选框来安装和启动 *`.apk`* 文件:
 
 ![Install and Launch APK](images/android/install_and_launch.png)
 
-为了顺利运行, 你要安装好 ADB 并打开连接设备的 *USB debugging*. 如果编辑器无法找到 ADB 命令行工具的地址, 你要在 [Preferences](/manuals/editor-preferences/#tools) 中指定好.
+要使此功能正常工作,你需要安装 ADB 并在连接的设备上启用 *USB 调试*。如果编辑器无法检测到 ADB 命令行工具的安装位置,你需要在[首选项](/manuals/editor-preferences/#tools)中指定它。
 
 #### 安装 AAB
 
-对于 *.aab* 文件可以通过 [Google Play 开发者控制台](https://play.google.com/apps/publish/) 上传给 Google Play. 也可以使用 *.aab* 文件制作 *.apk* 以便使用 [Android 打包工具](https://developer.android.com/studio/command-line/bundletool) 在本地安装.
+一个 *.aab* 文件可以通过 [Google Play 开发者控制台](https://play.google.com/apps/publish/) 上传到 Google Play。也可以使用 *.aab* 文件制作 *.apk* 以便使用 [`bundletool`](https://developer.android.com/studio/command-line/bundletool) 在本地安装。
 
 ## 权限
 
-Defold 引擎需要一些权限来运行各种功能. 权限在 `AndroidManifest.xml` 文件中定义, 并在 *game.project* [项目配置文件](/manuals/project-settings/#Android) 中配置. 关于 Android 权限详见 [官方文档](https://developer.android.com/guide/topics/permissions/overview). 默认配置需要如下权限:
+Defold 引擎需要许多不同的权限才能使所有引擎功能正常工作。权限在 `AndroidManifest.xml` 中定义,在 *game.project* [项目设置文件](/manuals/project-settings/#android) 中指定。你可以在[官方文档](https://developer.android.com/guide/topics/permissions/overview)中阅读更多关于 Android 权限的信息。默认清单中请求以下权限:
 
-### android.permission.INTERNET and android.permission.ACCESS_NETWORK_STATE (Protection level: normal)
-允许应用打开网络连接访问互联网. 需要上网时需要此权限. 见 ([Android 官方文档-网络](https://developer.android.com/reference/android/Manifest.permission#INTERNET)) 和 ([Android 官方文档-网络状态](https://developer.android.com/reference/android/Manifest.permission#ACCESS_NETWORK_STATE)).
+### android.permission.INTERNET 和 android.permission.ACCESS_NETWORK_STATE (保护级别: normal)
 
-### android.permission.WAKE_LOCK (Protection level: normal)
-允许应用阻止屏幕息屏和调光. 接收通知保持亮屏时需要此权限. ([[Android 官方文档-亮屏锁定](https://developer.android.com/reference/android/Manifest.permission#WAKE_LOCK))
+允许应用程序打开网络套接字并访问网络信息。这些权限是访问互联网所必需的。([Android 官方文档](https://developer.android.com/reference/android/Manifest.permission#INTERNET))和([Android 官方文档](https://developer.android.com/reference/android/Manifest.permission#ACCESS_NETWORK_STATE))。
+
+### android.permission.WAKE_LOCK (保护级别: normal)
+
+允许使用 PowerManager WakeLocks 来防止处理器休眠或屏幕变暗。在接收推送通知时暂时防止设备休眠需要此权限。([Android 官方文档](https://developer.android.com/reference/android/Manifest.permission#WAKE_LOCK))
 
 
 ## 使用 AndroidX
-AndroidX 一個較大改動就是, 不再維護 Android Support Library 了. AndroidX 應用使用雲計算功能和新庫完整取代了 Support Library. [Asset Portal](/assets) 裏的绝大多数擴展包已經支持 AndroidX. 如果希望使用旧版安卓库而不是 AndroidX, 可以创建新的 app manifest 文件或在 Defold Manifest 文件里勾選 "Use Android Support lib" 選項.
+
+AndroidX 是对原始 Android 支持库重大改进,该支持库已不再维护。AndroidX 包通过提供功能对等和新库完全取代了支持库。[资源门户](/assets) 中的大多数 Android 扩展都支持 AndroidX。如果你不想使用 AndroidX,可以通过在[应用程序清单](https://defold.com/manuals/app-manifest/)中勾选 `Use Android Support Lib` 来明确禁用它,转而使用旧的 Android 支持库。
 
 ![](images/android/enable_supportlibrary.png)
 

+ 9 - 9
docs/zh/manuals/animation.md

@@ -1,17 +1,17 @@
 ---
-title: Defold 动画教程
-brief: 本教程介绍了 Defold 的动画支持.
+title: Defold 中的动画
+brief: 本手册描述了 Defold 的动画支持。
 ---
 
 # 动画
 
-Defold 内置组件支持多种动画:
+Defold 内置支持多种类型的动画,你可以将其用作组件的图形源:
 
-* [逐帧动画](/manuals/flipbook-animation) - 按顺序显示图片而形成的动画
-* [3D 模型动画](/manuals/model-animation) - 3D 蒙皮动画
-* [属性动画](/manuals/property-animation) - 以position, scale, rotation 等属性插值变换而形成的动画
+* [翻页书动画](/manuals/flipbook-animation) - 按顺序播放一系列静态图像
+* [模型动画](/manuals/model-animation) - 播放 3D 蒙皮动画
+* [属性动画](/manuals/property-animation) - 对位置、缩放、旋转等许多属性进行动画处理
 
-其他动画格式要使用扩展支持:
+可以通过扩展添加其他动画格式:
 
-* [Rive animation](/extension-rive) - 播放基于矢量的 2D 骨骼动画
-* [Spine animation](/extension-spine) - 播放贴图 2D 骨骼动画
+* [Rive 动画](/extension-rive) - 播放基于矢量的 2D 骨骼动画
+* [Spine 动画](/extension-spine) - 播放带纹理的 2D 骨骼动画

+ 69 - 25
docs/zh/manuals/app-manifest.md

@@ -1,60 +1,104 @@
 ---
-title: App manifest
-brief: 本教程介绍了如何使用应用清单来去掉引擎的特性.
+title: 应用程序清单
+brief: 本手册描述了如何使用应用程序清单来排除引擎中的功能。
 ---
 
-# App manifest
+# 应用程序清单
 
-应用清单控制为引擎加入或去掉功能特性. 推荐为引擎去掉不用的特性因为可以减小游戏包体.
+应用程序清单用于排除或控制要在引擎中包含哪些功能。排除引擎中未使用的功能是推荐的最佳实践,因为它会减小游戏的最终二进制文件大小。
+此外,应用程序清单还包含一些用于控制 HTML5 平台代码编译的选项,如最低支持的浏览器版本/内存设置,这些也会影响结果二进制文件的大小。
 
 ![](images/app_manifest/create-app-manifest.png)
 
 ![](images/app_manifest/app-manifest.png)
 
-## Physics
+# 应用清单
 
-控制使用哪个物理引擎, 或者选择 None 来完全去掉物理引擎.
+在 `game.project` 中,将清单分配给 `Native Extensions` -> `App Manifest`。
 
+## 物理
 
-## Exclude Record
+控制使用哪个物理引擎,或选择 None 来完全排除物理功能。
 
-从引擎中去掉视频录制功能 (参见手册 [`start_record`](https://defold.com/ref/stable/sys/#start_record) 消息).
+## 物理 2D
 
+选择使用哪个版本的 Box2D。
 
-## Exclude Profiler
+## 骨骼 + 模型
 
-从引擎中去掉分析器. 分析器用来收集性能和使用计数器. 参见 [分析器教程](/manuals/profiling/).
+控制骨骼和模型功能,或选择 None 来完全排除模型和骨骼功能。(参见[`模型`](https://defold.com/manuals/model/#model-component)文档)。
 
+## 排除录制
 
-## Exclude Sound
+从引擎中排除视频录制功能(参见[`start_record`](https://defold.com/ref/stable/sys/#start_record)消息文档)。
 
-从引擎中去掉所有声音播放功能.
+## 排除分析器
 
+从引擎中排除分析器。分析器用于收集性能和使用计数器。在[分析手册](/manuals/profiling/)中学习如何使用分析器。
 
-## Exclude Input
+## 排除声音
 
-从引擎中去掉所有输入处理.
+从引擎中排除所有声音播放功能。
 
+## 排除输入
 
-## Exclude Live Update
+从引擎中排除所有输入处理功能。
 
-从引擎中去掉 [热更新功能](/manuals/live-update).
+## 排除热更新
 
+从引擎中排除[热更新功能](/manuals/live-update)。
 
-## Exclude Basis Universal
+## 排除图像
 
-从引擎中去掉基础通用 [纹理压缩库](/manuals/texture-profiles).
+从引擎中排除`image`脚本模块[链接](https://defold.com/ref/stable/image/)。
 
+## 排除类型
 
-## Use Android Support Lib
+从引擎中排除`types`脚本模块[链接](https://defold.com/ref/stable/types/)。
 
-使用安卓支持库而不使用 Android X. [更多详情参见这里](https://defold.com/manuals/android/#using-androidx).
+## 排除 Basis Universal
 
+从引擎中排除 Basis Universal[纹理压缩库](/manuals/texture-profiles)。
 
-## Graphics
+## 使用 Android 支持库
 
-选择使用的图形后端.
+使用已弃用的 Android 支持库而不是 Android X。[更多信息](https://defold.com/manuals/android/#using-androidx)。
 
-* OpenGL - 只包含 OpenGL.
-* Vulkan - 只包含 Vulkan.
-* OpenGL and Vulkan - 同时包含 OpenGL 和 Vulkan. Vulkan 是默认的, Vulkan 不可以时使用 OpenGL.
+## 图形
+
+选择使用哪个图形后端。
+
+* OpenGL - 仅包含 OpenGL。
+* Vulkan - 仅包含 Vulkan。
+* OpenGL and Vulkan - 同时包含 OpenGL 和 Vulkan。Vulkan 将是默认选项,如果 Vulkan 不可用则回退到 OpenGL。
+
+## 最低 Safari 版本(仅适用于 js-web 和 wasm-web)
+YAML 字段名称:**`minSafariVersion`**
+默认值:**90000**
+
+支持的最低 Safari 版本。不能低于 90000。更多信息请查看 Emscripten 编译器选项[链接](https://emscripten.org/docs/tools_reference/settings_reference.html?highlight=environment#min-safari-version)。
+
+## 最低 Firefox 版本(仅适用于 js-web 和 wasm-web)
+YAML 字段名称:**`minFirefoxVersion`**
+默认值:**34**
+
+支持的最低 Firefox 版本。不能低于 34。更多信息请查看 Emscripten 编译器选项[链接](https://emscripten.org/docs/tools_reference/settings_reference.html?highlight=environment#min-firefox-version)。
+
+## 最低 Chrome 版本(仅适用于 js-web 和 wasm-web)
+YAML 字段名称:**`minChromeVersion`**
+默认值:**32**
+
+支持的最低 Chrome 版本。不能低于 32。更多信息请查看 Emscripten 编译器选项[链接](https://emscripten.org/docs/tools_reference/settings_reference.html?highlight=environment#min-chrome-version)。
+
+## 初始内存(仅适用于 js-web 和 wasm-web)
+YAML 字段名称:**`initialMemory`**
+默认值:**33554432**
+
+为 Web 应用程序分配的内存大小。如果 ALLOW_MEMORY_GROWTH=0(js-web)- 这是 Web 应用程序可以使用的内存总量。更多信息请查看[链接](https://emscripten.org/docs/tools_reference/settings_reference.html?highlight=environment#initial-memory)。单位为字节。注意该值必须是 WebAssembly 页面大小(64KiB)的倍数。
+该选项与 *game.project* 中的 `html5.heap_size` [相关](https://defold.com/manuals/html5/#heap-size)。通过应用程序清单配置的选项在编译期间设置,并用作 `INITIAL_MEMORY` 选项的默认值。*game.project* 中的值会覆盖应用程序清单中的值,并在运行时使用。
+
+## 栈大小(仅适用于 js-web 和 wasm-web)
+YAML 字段名称:**`stackSize`**
+默认值:**5242880**
+
+应用程序的栈大小。更多信息请查看[链接](https://emscripten.org/docs/tools_reference/settings_reference.html?highlight=environment#stack-size)。单位为字节。

+ 38 - 38
docs/zh/manuals/application-lifecycle.md

@@ -1,41 +1,41 @@
 ---
-title: Defold 应用生命周期教程
-brief: 本教程详述了 Defold 游戏的生命周期.
+title: Defold 应用程序生命周期手册
+brief: 本手册详述了 Defold 游戏和应用程序的生命周期。
 ---
 
 # 应用生命周期
 
-Defold 应用或者游戏的生命周期相当简单. 引擎切换运行三种状态: 初始化, 更新循环 (游戏主要耗时状态) 以及析构.
+Defold 应用程序或游戏的生命周期总体上很简单。引擎会经历三个执行阶段:初始化、更新循环(应用程序和游戏大部分时间都在这里度过)和最终化。
 
 ![Lifecycle overview](images/application_lifecycle/application_lifecycle_overview.png)
 
-通常对于 Defold 的内部运作机制稍作了解就足够了. 然而, 有时了解 Defold 内部的运行顺序还是有必要的. 本教程介绍了 Defold 应用从始至终是按什么顺序运行的.
+在许多情况下,只需要对 Defold 的内部工作原理有一个基本的了解就足够了。然而,你可能会遇到一些边缘情况,此时 Defold 执行任务的精确顺序变得至关重要。本文档描述了引擎如何从头到尾运行应用程序。
 
-引擎一开始进行初始化操作. 载入启动集合然后在所有组件上调用 [`init()`](/ref/go#init) 函数 (包括脚本组件和GUI脚本). 这个函数用于进行用户自定义初始化操作.
+应用程序首先初始化运行引擎所需的一切。它加载主集合并调用所有具有 `init()` Lua 函数的已加载组件(脚本组件和带有 GUI 脚本的 GUI 组件)的 [`init()`](/ref/go#init) 函数。这允许你进行自定义初始化。
 
-接下来就是应用主要耗时环节更新循环. 每一帧, 每个游戏对象及其组件都会进行更新操作. 脚本和GUI脚本的 [`update()`](/ref/go#update) 函数被调用. 与此同时消息机制开始运作, 播放声音和渲染图像的程序开始运行.
+然后应用程序进入更新循环,应用程序将在此度过其生命周期的大部分时间。每一帧,游戏对象及其包含的组件都会被更新。任何脚本和 GUI 脚本的 [`update()`](/ref/go#update) 函数都会被调用。在更新循环期间,消息被分发给它们的接收者,声音被播放,所有图形都被渲染。
 
-应用最后会结束运行. 应用退出之前引擎会退出更新循环进入析构阶段. 准备删除所有被加载的游戏对象. 所有对象的 [`final()`](/ref/go#final) 函数被调用, 用于进行用户自定义析构操作. 然后删除所有游戏对象以及启动集合.
+在某个时刻,应用程序的生命周期将结束。在应用程序退出之前,引擎会退出更新循环并进入最终化阶段。它准备删除所有已加载的游戏对象。所有对象组件的 [`final()`](/ref/go#final) 函数都会被调用,这允许进行自定义清理。然后对象被删除,主集合被卸载。
 
 ## 初始化
 
-下图包含了初始化的分解步骤. 其中 "dispatch messages" 阶段 (在 "spawn dynamic objects" 上方) 单独在右侧图表进行详细分解.
+下图包含了初始化步骤的更详细分解。"dispatch messages"传递中涉及的步骤(在"spawn dynamic objects"之前)为了清晰起见已单独放在右侧的块中。
 
 ![Lifecycle overview](images/application_lifecycle/application_lifecycle_init.png)
 
-其实初始化阶段启动集合被加载之前引擎还做了许多别的工作. 内存分析, 接口, 图像, HID (输入设备), 声音, 物理等等的初始化. 应用配置文件 (*game.project*) 也在此时被加载.
+实际上,在主集合加载之前,引擎在初始化过程中会采取更多步骤。内存分析器、套接字、图形、HID(输入设备)、声音、物理等等都被设置。应用程序配置(*game.project*)也被加载和设置。
 
-最开始的用户可控的操作, 是在引擎初始化结束后, 对于渲染脚本 `init()` 函数的调用.
+在引擎初始化结束时,第一个用户可控制的入口点是对当前渲染脚本的 `init()` 函数的调用。
 
-然后启动集合被加载和初始化. 对其中所有游戏对象及其子对象设置位移 (位置, 旋转和缩放). 所有组件的 `init()` 函数被调用.
+然后加载并初始化主集合。集合中的所有游戏对象将其变换(平移(位置变化)、旋转和缩放)应用到它们的子对象。然后调用所有存在的组件 `init()` 函数。
 
 ::: sidenote
-每个 `init()` 函数调用顺序不确定. 调用顺序和集合里所处位置无关.
+游戏对象组件 `init()` 函数的调用顺序是未指定的。你不应该假设引擎以特定顺序初始化属于同一集合的对象。
 :::
 
-因为 `init()` 代码里可以有消息发布, 工厂创建对象, 删除对象等等操作, 引擎接下来会进入 "post-update" 阶段. 此时消息被发布出去, 工厂实际创建对象, 需要删除的对象进行删除操作. 注意 post-update 阶段包含的 "dispatch messages" 序列不仅发送消息队列还会处理发送给集合代理的消息. 代理子队列 (开启关闭, 载入和标记卸载) 等步骤在此时进行处理.
+由于你的 `init()` 代码可以发布新消息,告诉工厂生成新对象,标记对象以供删除以及执行各种操作,引擎接下来会执行完整的"后更新"传递。此传递执行消息传递、实际的工厂游戏对象生成和对象删除。请注意,后更新传递包含一个"分发消息"序列,它不仅发送任何排队的消息,还处理发送到集合代理的消息。代理的任何后续更新(启用和禁用、加载和标记为卸载)都在这些步骤中执行。
 
-也就是说在 `init()` 里进行 [集合代理](/manuals/collection-proxy) 加载操作是完全可行的, 集合初始化, 从代理卸载集合---这些都能在第一个 `update()` 被调用之前进行, 也就是在引擎退出初始化进入更新循环之前进行:
+研究上图可以发现,在 `init()` 期间加载[集合代理](/manuals/collection-proxy),确保其包含的所有对象都被初始化,然后通过代理卸载集合是完全可能的——所有这些都在第一个组件 `update()` 被调用之前,即在引擎离开初始化阶段并进入更新循环之前:
 
 ```lua
 function init(self)
@@ -44,7 +44,7 @@ function init(self)
 end
 
 function update(self, dt)
-    -- 运行到这里时代理集合已经被卸载了.
+    -- 在到达此代码之前,代理集合已被卸载。
     print("update()")
 end
 
@@ -54,71 +54,71 @@ function on_message(self, message_id, message, sender)
         msg.post("#collectionproxy", "init")
         msg.post("#collectionproxy", "enable")
         msg.post("#collectionproxy", "unload")
-        -- 代理集合 init() 和 final() 函数
-        -- 在 update() 调用之前完成
+        -- 代理集合对象的 init() 和 final() 函数
+        -- 在我们到达此对象的 update() 之前被调用
     end
 end
 ```
 
 ## 更新循环
 
-每帧都会循环更新长长的序列. 下图展示了更新循环的详细步骤. "Dispatch messages" 阶段还是单独在右侧独立详细展示:
+更新循环每帧运行一次长序列。下图中的更新序列为了清晰起见分为逻辑序列块。"分发消息"出于同样的原因也被单独分解出来:
 
 ![Update loop](images/application_lifecycle/application_lifecycle_update.png)
 
 ## 输入
 
-从可用设备中读取输入数据, 通过映射 [输入绑定表](/manuals/input) 把输入派发出去. 获得输入焦点的游戏对象里每个组件的 `on_input()` 函数都会获得输入数据. 不管是脚本组件还是GUI脚本 `on_input()` 函数都会被调用---只要它们被定义了而且获得了输入焦点.
+从可用设备读取输入,根据[输入绑定](/manuals/input)进行映射,然后分发。任何获得输入焦点的游戏对象都会将输入发送到其所有组件的 `on_input()` 函数。具有脚本组件和带有 GUI 脚本的 GUI 组件的游戏对象将获得输入到两个组件的 `on_input()` 函数——前提是它们已被定义并且已获得输入焦点。
 
-获得输入焦点并且包含集合代理组件的游戏对象会把输入发送到代理集合内部去. 这个过程在被开启的代理间递归进行下去.
+任何获得输入焦点并包含集合代理组件的游戏对象会将输入分发到代理集合内的组件。这个过程在启用的集合代理内的启用的集合代理中递归进行下去。
 
 ## 更新
 
-启动集合每个游戏对象组件都会被遍历到. 只要它们定义了 `update()` 函数, 就会在更新时被调用. 对于集合代理组件, 其内部 "update" 过程会递归进行下去.
+遍历主集合中的每个游戏对象组件。如果这些组件中的任何一个具有脚本 `update()` 函数,那么该函数将被调用。如果组件是集合代理,则代理集合中的每个组件都会递归地更新,执行上图"update"序列中的所有步骤。
 
 ::: sidenote
-如果 [物理模拟使用固定时间步](/manuals/physics/#physics-updates) 则每个脚本里的 `fixed_update()` 也可能会被自动调用. 这有助于物理模拟使用固定时间间隔而产生稳定模拟效果.
+如果[物理模拟使用固定时间步](/manuals/physics/#physics-updates),则所有脚本组件中也可能会有对 `fixed_update()` 函数的调用。在基于物理的游戏中,当你希望以固定间隔操作物理对象以实现稳定的物理模拟时,此函数很有用。
 :::
 
 ::: sidenote
-每个 `update()` 函数调用顺序不确定. 调用顺序和集合里所处位置无关.
+游戏对象组件 `update()` 函数的调用顺序是未指定的。你不应该假设引擎以特定顺序更新属于同一集合的对象。
 :::
 
-下个阶段所有消息被发送出去. 接收者的 `on_message()` 代码也可能包含消息发送, 所以消息会持续发送直至全部发送完成. 但是, 有一个发送消息最大轮数的限制. 详见 [消息传递教程](/manuals/message-passing).
+在下一步中,所有已发布的消息都被分发。由于任何接收者组件的 `on_message()` 代码可以发布额外的消息,消息分发器将继续分发已发布的消息,直到消息队列为空。然而,消息分发器通过消息队列运行的次数是有限制的。有关详细信息,请参阅[消息链](/manuals/message-passing#message-chains)。
 
-对于碰撞对象组件, 物理消息 (collisions, triggers, ray_cast 响应等) 会被发送给所有含有 `on_message()` 函数的组件.
+对于碰撞对象组件,物理消息(碰撞、触发器、ray_cast 响应等)被分发到包含具有 `on_message()` 函数的脚本的所有组件的整个游戏对象。
 
-然后进行位移操作, 对每个游戏对象及其子对象应用位置移动, 旋转和缩放.
+然后进行变换,应用任何游戏对象移动、旋转和缩放到每个游戏对象组件以及任何子游戏对象组件。
 
 ## 渲染更新
 
-渲染更新阶段发送消息到 `@render` 接口 (摄像机组件 `set_view_projection` 消息, `set_clear_color` 消息等). 渲染脚本的 `update()` 函数被调用.
+渲染更新块向 `@render` 套接字分发消息(摄像机组件 `set_view_projection` 消息、`set_clear_color` 消息等)。然后调用渲染脚本 `update()`。
 
 ## 后更新
 
-更新过程结束后, 一个后更新过程开始启动. 此时被标记为卸载的集合代理会从内存中卸载 (在 "dispatch messages" 阶段). 被标记为删除的游戏对象调用 `final()` 函数. 通常 `final()` 还包含消息发送代码所以接下来又是一轮 "dispatch messages" 阶段.
+更新之后,运行后更新序列。它从内存中卸载标记为卸载的集合代理(这发生在"分发消息"序列期间)。任何标记为删除的游戏对象将调用其所有组件的 `final()` 函数(如果有的话)。`final()` 函数中的代码通常会向队列发布新消息,因此之后会运行"分发消息"传递。
 
-然后工厂实际创建对象. 最后, 被标记为删除的游戏对象被删除.
+任何被告知生成游戏对象的工厂组件将在此执行此操作。最后,标记为删除的游戏对象实际上被删除。
 
-更新循环的最后一步是向 `@system` 发送消息 (`exit`, `reboot` 消息, 开关分析器, 开始结束视频捕获等等). 图像开始渲染. 与此同时, 视频捕获完成, 可视分析器渲染完成 (见 [调试教程](/manuals/debugging).)
+更新循环中的最后一步涉及分发 `@system` 消息(`exit`、`reboot` 消息,切换分析器,启动和停止视频捕获等)。然后渲染图形。在图形渲染期间,进行视频捕获,以及视觉分析器的任何渲染(参见[调试文档](/manuals/debugging))。
 
 ## 帧率和集合时间步
 
-每秒帧数 (即每秒更新循环运行次数) 可以在项目配置里设置, 或者通过发送 `set_update_frequency` 消息到 `@system` 接口手动设置. 而且, 可以通过发送 `set_time_step` 消息给代理来为集合单独设置 _时间步_. 修改集合时间步不影响帧率. 它影响的是物理时间步与发送到 `update()` 函数中的 `dt` 值. 注意修改时间步不影响 `update()` 调用的频率---永远是每帧调用一次.
+每秒帧更新数(等于每秒更新循环运行次数)可以在项目设置中设置,或者通过向 `@system` 套接字发送 `set_update_frequency` 消息以编程方式设置。此外,可以通过向代理发送 `set_time_step` 消息来为集合代理单独设置_时间步_。更改集合的时间步不会影响帧率。它确实会影响物理更新时间步以及传递给 `update()` 的 `dt` 变量。还要注意,更改时间步不会改变每帧调用 `update()` 的次数——它总是恰好一次。
 
-(See the [Collection proxy manual](/manuals/collection-proxy) and [`set_time_step`](/ref/collectionproxy#set-time-step) for details)
+(有关详细信息,请参阅[集合代理手册](/manuals/collection-proxy)和[`set_time_step`](/ref/collectionproxy#set-time-step))
 
-## 析构
+## 最终化
 
-应用退出时, 完成最后一次更新循环, 卸载所有集合代理: 析构和删除集合代理里的所有游戏对象.
+当应用程序退出时,首先它完成最后的更新循环序列,这将卸载任何集合代理:最终化并删除每个代理集合中的所有游戏对象。
 
-然后引擎进入析构阶段处理启动集合里的内容:
+当完成后,引擎进入处理主集合及其对象的最终化序列:
 
 ![Finalization](images/application_lifecycle/application_lifecycle_final.png)
 
-组件的 `final()` 函数被调用. 后跟一轮消息传递. 最后, 所有游戏对象被删除, 启动集合被卸载.
+首先调用组件 `final()` 函数。随后进行消息分发。最后,所有游戏对象都被删除,主集合被卸载。
 
-引擎还会继续做后续子系统处理: 删除项目配置, 关闭内存分析, 等等.
+引擎随后在幕后进行子系统的关闭:项目配置被删除,内存分析器被关闭等等。
 
-至此应用正式退出.
+现在应用程序已完全关闭。
 

+ 49 - 46
docs/zh/manuals/application-security.md

@@ -1,35 +1,35 @@
 ---
-title: Defold 应用加密教
-brief: 本教程涵盖了安全开发实践的若干方面.
+title: 应用程序安全手册
+brief: 本手册涵盖了安全开发实践的若干方面。
 ---
 
-# 应用加密
+# 应用安全
 
-应用加密是一个很大的主题, 内容包括从安全开发实践到应用上线后的数据保护. 本教程涵盖了安全与加密的部分内容, 讨论在使用 Defold 引擎, 工具和服务时与安全加密相关的技术:
+应用安全是一个广泛的主题,涵盖了从安全开发实践到游戏发布后保护游戏内容的各个方面。本手册将涵盖多个领域,并将其放在使用Defold引擎、工具和服务时的应用安全背景下:
 
 * 知识产权保护
 * 反作弊解决方案
-* 网络通信安全
+* 安全网络通信
 * 使用第三方软件
-* 使用云编译服务器
-* 可下载资源
+* 使用云构建服务器
+* 可下载内容
 
 
 ## 保护您的知识产权免遭盗窃
-大多数开发人员关心的问题是如何保护他们的作品不被盗. 从法律的角度来看, 版权, 专利和商标有助于保护视频游戏知识产权的方方面面. 版权赋予开发者发表创意作品的专项权力, 专利保护创造发明, 商标保护名字, 符号和标志.
+大多数开发者关心的问题是如何保护他们的创作不被盗用。从法律角度来看,版权、专利和商标可以用来保护视频游戏知识产权的不同方面。版权赋予其所有者分发创意作品的专有权,专利保护任何发明,而商标保护名称、符号和标志。
 
-为了保护游戏凝聚的创意和劳动, 技术手段也是有必要的. 要知道您的游戏一旦上市, 就无法阻止玩家想方设法提取游戏资源. 针对游戏文件的反向工程和各种动态提取工具都能搞到游戏资源, 因为无论如何, 贴图, 模型以及各种资源最终都要解压发送给 GPU 或者载入内存的.
+采取技术预防措施来保护游戏的创意作品也是可取的。然而,重要的是要记住,一旦游戏到了玩家手中,就有可能找到提取资源的方法。这可以通过对游戏应用程序和文件进行逆向工程来实现,也可以通过使用工具在资源发送到GPU时或加载到内存时提取纹理和模型。
 
-出于这个原因, 我们的看法是, 不怕贼偷, 就怕贼惦记.
+因此,我们的总体立场是,如果用户决心提取游戏的资源,他们将能够做到这一点。
 
-开发者可以提升游戏资源窃取的难度, __但永远不是不可能__. 这通常包括用各种手段加密, 混淆以达到保护和隐藏游戏资源的目的.
+开发者可以添加自己的保护措施,使提取资源变得更加困难,__但并非不可能__。这通常包括各种加密和混淆手段,以保护和隐藏游戏资源。
 
 ### 源代码混淆
-应用源代码混淆是一个故意降低代码可读性, 而不影响游戏输出的自动化过程. 目的不仅是为了防止被盗, 还能提高作弊的难度.
+应用源代码混淆是一个自动化过程,其中源代码被故意设计为难以被人理解,同时不影响程序的输出。目的通常是为了防止被盗,同时也使作弊变得更加困难。
 
-可以在 Defold 编辑器里进行代码混淆, 这一步要么作为预编译步骤要么整合成为 Defold 编译工作中的一部分. 预编译混淆就是在 Defold 编译开始之前用某个工具给代码进行混淆操作.
+在Defold中,可以应用源代码混淆,既可以作为预构建步骤,也可以作为Defold构建过程的集成部分。使用预构建混淆时,源代码在Defold构建过程开始之前使用混淆工具进行混淆。
 
-编译工作中混淆就是使用 Lua 编译插件把代码混淆作为编译工作的一部分. Lua 编译插件可以输入原始代码, 输出混淆后的代码. 具体示例可以参考 [Prometheus 扩展](https://github.com/defold/extension-prometheus), 它基于 GitHub 上的 Prometheus Lua 混淆器. 下面展示了使用 Prometheus 主动混淆一小段代码的例子 (注意这种高强度混淆会对 Lua 代码的运行效率产生影响):
+另一方面,构建时混淆通过使用Lua构建器插件集成到构建过程中。Lua构建器插件将原始源代码作为输入,并返回混淆后的源代码作为输出。构建时混淆的一个示例在[Prometheus扩展](https://github.com/defold/extension-prometheus)中展示,该扩展基于GitHub上可用的Prometheus Lua混淆器。下面您将找到一个使用Prometheus积极混淆代码片段的示例(请注意,这种重度混淆会影响Lua代码的运行时性能):
 
 示例:
 
@@ -47,60 +47,63 @@ local v={"+qdW","ZK0tEKf=";"XP/IX3+="}for o,J in ipairs({{1;3};{1,1},{2,3}})do w
 ```
 
 ### 资源加密
-在 Defold 编译过程中, 游戏资源会被处理为 Defold 引擎理解的格式. 贴图被编译成为 Basis Universal 格式, 碰撞器, 游戏对象和组件从原始可读文本被转化成为相应的二进制格式, Lua 源代码被编译为字节码. 其他资源比如音效则保持不变.
+在Defold构建过程中,游戏资源被处理并转换为适合Defold引擎运行时使用的格式。纹理被编译为Basis Universal格式,集合、游戏对象和组件从人类可读的文本表示转换为对应的二进制格式,Lua源代码被处理并编译为字节码。其他资源(如声音文件)则按原样使用。
 
-处理完成后游戏资源会被一个一个地打入游戏包. 游戏包是个大号二进制文件, 其中每个资源的位置被存储在一个包索引文件中. 格式文档参见 [这里](https://github.com/defold/defold/blob/dev/engine/docs/ARCHIVE_FORMAT.md).
+当这个过程完成后,资源会逐个添加到游戏存档中。游戏存档是一个大型二进制文件,存档中每个资源的位置存储在存档索引文件中。该格式在[这里](https://github.com/defold/defold/blob/dev/engine/docs/ARCHIVE_FORMAT.md)有文档说明。
 
-Lua 代码被打包前可以指定是否进行加密. Defold 提供了一种简单的分组加密算法用于保护代码中的字符串不至于被一些二进制预览工具打开就能看到. 这也不是很安全因为 Defold 已在 GitHub 上开源, 包括加密密钥.
+在Lua源文件被添加到存档之前,它们也可以选择性地进行加密。Defold中提供的默认加密是一种简单的分组加密,用于防止在使用二进制文件查看器工具检查游戏存档时,代码中的字符串立即可见。由于Defold源代码在GitHub上可用,且加密密钥在源代码中可见,因此不应将其视为密码学安全的。
 
-允许通过实现一个资源加密插件来对 Lua 源代码实施自定义加密手段. 资源加密插件由两部分组成, 一个编译时对资源进行加密的部分和一个运行时对资源进行解密的部分. 作为基本应用的开端, 有一个简单的资源加密插件实现 [在 GitHub 上](https://github.com/defold/extension-resource-encryption).
+可以通过实现资源加密插件为Lua源文件添加自定义加密。资源加密插件由构建时部分和运行时部分组成,构建时部分用于在构建过程中加密资源,运行时部分用于在从游戏存档中读取资源时解密资源。一个基本的资源加密插件(可用作您自己加密的起点)在[GitHub上可用](https://github.com/defold/extension-resource-encryption)。
 
 
-## 游戏防作弊
-游戏产业的历史就是作弊产业的历史. 以前作弊码常常被印刷在著名游戏杂志里, 有些外挂在早期家用电脑时代已经开始售卖. 随着游戏产业的进化, 作弊器和手段也在不断进化. 目前流行的作弊机制包括:
+### 编码项目配置值
+*game.project*文件将原样包含在您的应用程序包中。有时您可能希望存储公共API访问密钥或类似的敏感但非私密性质的值。为了加强这类值的安全性,可以将它们包含在应用程序二进制文件中,而不是存储在*game.project*中,同时仍然可以通过Defold API函数(如`sys.get_config_string()`等)访问它们。您可以通过在*game.project*中添加原生扩展,并使用`DM_DECLARE_CONFIGFILE_EXTENSION`宏来提供您自己的覆盖,以使用Defold API函数获取配置值。一个可用作起点的示例项目在[GitHub上可用](https://github.com/defold/example-configfile-extension/tree/master)。
 
-* 注入作弊代码重新打包游戏
-* 能让游戏更快或更慢执行的速度齿轮外挂
-* 通过屏幕可视化分析实现的自动瞄准或自动行动机器人
-* 实时代码注入和内存数值修改以增加分数, 子弹数, 命数等等
+## 保护您的游戏免受作弊者侵害
+视频游戏作弊的历史与游戏行业本身一样悠久。作弊码曾经流行于视频游戏杂志中,特殊的作弊盒卡带也在早期的家用电脑上销售。随着行业和游戏的演变,作弊者和他们的方法也在不断演变。一些最流行的游戏作弊机制包括:
 
-防止作弊很难, 难到接近不可能. 即使是云游戏, 那种运行在远程云服务器上, 然后把输出串流到用户设备上的游戏, 都不能完全杜绝作弊.
+* 重新打包游戏内容以注入自定义逻辑
+* 速度黑客,使游戏运行速度比正常更快或更慢
+* 自动化和视觉分析,用于自动瞄准和机器人
+* 代码和内存注入,以修改分数、生命值、弹药等
 
-Defold 不提供任何引擎内置反作弊方案或者工具, 而是把这些工作外包给专门做游戏反作弊技术的公司.
+防止作弊很困难,几乎是不可能的。即使是云游戏,即游戏在远程服务器上运行并直接流式传输到用户设备,也不能完全免受作弊的影响。
 
+Defold在引擎或工具中不提供任何反作弊解决方案,而是将这类工作交给众多专门为游戏提供反作弊解决方案的公司之一。
 
-## 网络通信安全
-Defold 套接字和 HTTP 通信支持使用安全套接字连接. 在客户端与服务器的双向通讯中, 推荐全部使用安全套接字连接以进行身份验证并保证任何交换数据的隐私和完整. Defold 使用流行并被广泛使用的 [Mbed TLS](https://github.com/Mbed-TLS/mbedtls) 作为 TLS 和 SSL 协议的实现. Mbed TLS 由 ARM 及其伙伴科技公司所开发.
 
-### SSL 证书验证
-为防止黑客在您的网络交流中实施中间人攻击, 可以在与服务器进行连接时的 SSL 握手期间验证证书链. 通过 Defold 向网络客户端提供公钥列表即可. 关于网络通信安全的更多信息请参阅 [网络教程](https://defold.com/manuals/networking/#secure-connections) 的 SSL 验证章节.
+## 保护您的网络通信
+Defold套接字和HTTP通信支持安全套接字连接。建议对任何服务器通信使用安全连接,以验证服务器并保护在客户端到服务器以及服务器到客户端传输过程中任何交换数据的隐私和完整性。Defold使用流行且广泛采用的TLS和SSL协议开源实现[Mbed TLS](https://github.com/Mbed-TLS/mbedtls)。Mbed TLS由ARM及其技术合作伙伴开发。
 
+### SSL证书验证
+为了防止网络通信中的中间人攻击,可以在与服务器协商连接时的SSL握手期间验证证书链。这可以通过在Defold中向网络客户端提供公钥列表来实现。有关保护网络通信的更多信息,请阅读[网络手册](/manuals/networking/#secure-connections)中关于SSL验证的部分。
 
-## 第三方软件使用安全
-虽然不用第三方库或者原生扩展也能做游戏, 但是从我们的官方 [资源大厅](https://defold.com/assets/) 获取资源提升开发效率已成为开发者的共识. 资源大厅里有超多资源, 从第三方 SDK 整合包, 到屏幕管理, UI 库, 摄像机控制等等等等.
 
-资源大厅里的资源未经 Defold 基金会审核, Defold 基金会不为使用它们造成的计算机系统损坏或设备损坏或数据丢失等任何后果负责. 详见我们的 [条款与条件](https://defold.com/terms-and-conditions/#3-no-warranties).
+## 保护您对第三方软件的使用
+虽然创建游戏不一定需要使用任何第三方库或原生扩展,但使用官方[资源门户](https://defold.com/assets/)中的资源来加速开发已成为开发者的常见做法。资源门户包含大量资源,从第三方SDK集成到屏幕管理器、UI库、摄像机等等。
 
-我们建议您在使用这些资源之前仔细审核, 确认资源适用于您的项目之后马上把它拷贝一份出来, 以保证它不会受到未来更新造成的未经审核的改变.
+资源门户中的任何资源都未经Defold基金会审核,我们不对通过资源门户获取的任何资源使用导致的计算机系统或其他设备损坏或数据丢失负责。您可以在我们的[条款与条件](https://defold.com/terms-and-conditions/#3-no-warranties)中阅读细则。
 
+我们建议您在使用任何资源之前进行审查,一旦您认为它适合在您的项目中使用,就创建该资源的分支或副本,以确保它不会在您不知情的情况下发生变化。
 
-## 云编译服务器的使用安全
-Defold 云编译服务器 (同时也是扩展编译服务器) 用于帮助开发者为游戏增加功能而不用重新编译 Defold 引擎. 当包含原生代码的 Defold 项目被第一次编译时, 所有相关资源都会被上传到云编译服务器用来编译一个自定义版本的 Defold 引擎然后回传给开发者. 类似流程也会发生于当项目使用自定义 application manifest 剔除了不必要的引擎组件时.
 
-云编译服务器被托关于 AWS 并且尽最大可能做好了安全工作. 然而 Defold 基金并不承诺云编译服务器完全满足您的需求, 没有缺陷, 没有病毒, 没有错误, 绝对安全或者永远在线, 使用安全. 详见我们的 [条款与条件](https://defold.com/terms-and-conditions/#3-no-warranties).
+## 保护您对云构建服务器的使用
+Defold云构建服务器(也称为扩展器服务器)的创建是为了帮助开发者为Defold引擎添加新功能,而无需重新构建引擎本身。当包含原生代码的Defold项目首次构建时,原生代码及任何相关资源会被发送到云构建服务器,在那里创建一个自定义版本的Defold引擎并返回给开发者。当项目使用自定义应用程序清单来移除引擎中未使用的组件时,也会应用相同的过程。
 
-如果安全性和可用性对您来说非常重要, 我们建议您自己架设私有编译服务器. 假设私有编译服务器的方法详见 GitHub 上扩展仓库的 [主 readme 文件](https://github.com/defold/extender).
+云构建服务器托管在AWS上,并根据安全最佳实践创建。然而,Defold基金会不保证云构建服务器将满足您的要求,没有缺陷、没有病毒、安全或没有错误,或者您对服务器的使用将是不间断或安全的。您可以在我们的[条款与条件](https://defold.com/terms-and-conditions/#3-no-warranties)中阅读细则。
 
+如果您对构建服务器的安全性和可用性感到担忧,我们建议您设置自己的私有构建服务器。有关如何设置自己的服务器的说明可以在GitHub上扩展器仓库的[主readme文件](https://github.com/defold/extender)中找到。
 
-## 可下载资源的安全
-Defold 的热更新系统允许开发者把主游戏包的部分内容划分出来以便随用随下. 典型的用例就是随着玩家游戏进程的推进, 按需下载关卡, 地图或者游戏世界.
 
-这些被划分出来的更新包被下载好准备用于游戏的时候, 引擎会对它们进行加密验证已确定它们没有被篡改. 该验证包括多项检查:
+## 保护您的可下载内容
+Defold的Live Update系统允许开发者将内容从主游戏包中排除,以便稍后下载和使用。典型的用例是随着玩家在游戏中的进展下载额外的关卡、地图或世界。
 
-* 二进制格式是否正确?
-* 当前运行的引擎版本是否支持下载的内容?
-* 下载的内容是否使用了正确的公私钥进行签名?
-* 下载的内容是否完整且没有遗漏任何文件?
+当被排除的内容被下载并准备在游戏中使用时,引擎会在使用前对其进行加密验证,以确保它没有被篡改。验证包括多项检查:
 
-该过程的详细步骤请参考 [热更新教程](https://defold.com/manuals/live-update/#manifest-verification).
+* 二进制格式是否正确?
+* 当前运行的引擎版本是否支持下载的内容?
+* 下载的内容是否使用了正确的公私钥对进行签名?
+* 下载的内容是否完整且没有遗漏任何文件?
+
+您可以在[Live Update手册](/manuals/live-update/#manifest-verification)中阅读有关此过程的更多信息。
 

+ 73 - 60
docs/zh/manuals/atlas.md

@@ -1,136 +1,145 @@
 ---
-title: 图集教程
-brief: 本教程介绍了 Defold 中图集资源是如何工作的.
+title: 图集手册
+brief: 本手册解释了 Defold 中图集资源的工作原理。
 ---
 
-# Atlas
+# 图集
 
-sprites 通常使用单个的小图片, 但是处于性能考虑, 最好把小图片合并成大图, 称为图集. 相比桌面设备和游戏机, 手机这种性能不太高的地方, 合并小图的做法就十分必要了.
+虽然单个图像通常用作精灵的源,但出于性能考虑,图像需要合并成更大的图像集,称为图集。将较小的图像集合并成图集在移动设备上尤其重要,因为与桌面计算机或专用游戏机相比,移动设备的内存和处理能力更为稀缺。
 
-在 Defold 中, 图集资源由一系列单个图片组成, 这些小图最终会自动合并成大图.
+在 Defold 中,图集资源是一个单独图像文件的列表,这些文件会自动合并成一个更大的图像。
 
 ## 创建图集
 
-在 *Assets* 浏览器右键菜单中选择 <kbd>New... ▸ Atlas</kbd>. 命名图集文件. 图集编辑器会自动打开.
-*Properties* 面板会显示出图集的可编辑属性 (详见下文).
+在 *Assets* 浏览器中的上下文菜单中选择 <kbd>New... ▸ Atlas</kbd>。命名新的图集文件。编辑器现在将在图集编辑器中打开该文件。图集属性显示在
+*Properties* 面板中,因此您可以编辑它们(详见下文)。
 
-先要向图集里填入图片或者动画才能在 Sprites 和 ParticleFX 之类的可视组件里使用.
+您需要先用图像或动画填充图集,然后才能将其用作精灵和粒子效果组件等对象组件的图形源。
 
-确保你需要的图片都存在项目里 (把图片文件拖放到 *Assets* 浏览器的适当位置).
+确保您已将图像添加到项目中(将图像文件拖放到 *Assets* 浏览器中的正确位置)。
 
-加入单张图片
-: 在 *Outline* 面板上 <kbd>右键点击</kbd> 图集根节点.
+添加单个图像
+
+: 从 *Asset* 面板将图像拖放到编辑器视图中。
   
-  从弹出菜单中选择 <kbd>Add Images</kbd> 来加入单张图片.
+  或者,在 *Outline* 面板中 <kbd>右键点击</kbd> 根 Atlas 条目。
+
+  从弹出的上下文菜单中选择 <kbd>Add Images</kbd> 以添加单个图像。
 
-  此时会弹出选择图片的菜单. 注意此菜单支持文件名过滤和多选功能.
+  将打开一个对话框,您可以从中查找并选择要添加到 Atlas 的图像。请注意,您可以过滤图像文件并一次选择多个文件。
 
   ![Creating an atlas, adding images](images/atlas/add.png)
 
-  被加入的图片会显示在 *Outline* 列表里, 而且编辑器里也会显示出图片合成的图集. 可以按 <kbd>F键</kbd> (菜单栏 <kbd>View ▸ Frame Selection</kbd>) 来居中显示.
+  添加的图像列在 *Outline* 中,完整的图集可以在中心编辑器视图中看到。您可能需要按 <kbd>F</kbd>(从菜单中选择 <kbd>View ▸ Frame Selection</kbd>)来框选选择。
 
   ![Images added](images/atlas/single_images.png)
 
-加入逐帧动画
-: 在 *Outline* 面板上 <kbd>右键点击</kbd> 图集根节点.
+添加翻书动画
 
-  从弹出菜单中选择 <kbd>Add Animation Group</kbd> 来加入逐帧动画.
+: 在 *Outline* 面板中 <kbd>右键点击</kbd> 根 Atlas 条目。
 
-  一个默认命名为 ("New Animation") 的新建空动画组就被加入图集了.
+  从弹出的上下文菜单中选择 <kbd>Add Animation Group</kbd> 以创建翻书动画组。
 
-  <kbd>右键点击</kbd> 动画组, 选择 <kbd>Add Images</kbd> 加入来图片.
+  一个新的、空的、具有默认名称("New Animation")的动画组被添加到图集中。
 
-  同样会弹出选择图片菜单, 选择的图片都会被加入到动画组.
+  从 *Asset* 面板将图像拖放到编辑器视图中,将它们添加到当前选定的组中。
   
+  或者,<kbd>右键点击</kbd> 新组并从上下文菜单中选择 <kbd>Add Images</kbd>。
+
+  将打开一个对话框,您可以从中查找并选择要添加到动画组的图像。
+
   ![Creating an atlas, adding images](images/atlas/add_animation.png)
 
-  选中动画组后按 <kbd>空格键</kbd> 即可预览动画, <kbd>Ctrl/Cmd+T</kbd> 关闭预览. 动画 *Properties* 可以自由修改 (见下文).
+  选定动画组后按 <kbd>空格键</kbd> 预览,按 <kbd>Ctrl/Cmd+T</kbd> 关闭预览。根据需要调整动画的 *Properties*(见下文)。
 
   ![Animation group](images/atlas/animation_group.png)
 
-选中图片后按 <kbd>Alt + Up/down</kbd> 可以更改顺序. 也可以拷贝粘贴任意图片 (通过 <kbd>Edit</kbd> 菜单栏, 右键菜单或者快捷键).
+您可以通过选择图像并按 <kbd>Alt + Up/down</kbd> 来重新排列 Outline 中的图像。您还可以通过在 Outline 中复制和粘贴图像(从 <kbd>Edit</kbd> 菜单、右键上下文菜单或键盘快捷键)轻松创建副本。
 
 ## 图集属性
 
-图集资源有一系列属性. 在 *Outline* 视图中选中图集后属性出现在 *Properties* 面板中.
+每个图集资源都有一组属性。当您在 *Outline* 视图中选择根项目时,这些属性会显示在 *Properties* 面板中。
 
 Size
-: 图集空间占用大小. 宽高取2的整数幂. 注意如果开启了纹理压缩, 某些格式需要纹理为正方形. 非正方形纹理将加入空白以建立正方形. 详情请见 [Texture profiles 教程](/manuals/texture-profiles/).
+: 显示生成的纹理资源的计算总大小。宽度和高度设置为最接近的2的幂。请注意,如果启用纹理压缩,某些格式需要方形纹理。非方形纹理将被调整大小并用空白填充以使纹理变为方形。有关详细信息,请参阅[纹理配置文件手册](/manuals/texture-profiles/)。
 
 Margin
-: 每两个图片之间的间隙.
+: 应在每个图像之间添加的像素数。
 
 Inner Padding
-: 每个图片四周加入的空白.
+: 应在每个图像周围填充的空白像素数。
 
 Extrude Borders
-: 每个图片四周的边缘挤出. 片元着色器采样图片边缘的时候, 相邻图片 (同个图集) 边缘可能会被采集到. 挤出边缘就可以解决这个问题.
+: 应在每个图像周围重复填充的边缘像素数。当片段着色器在图像边缘采样像素时,相邻图像(在同一图集纹理上)的像素可能会渗入。扩展边缘可以解决这个问题。
 
 Max Page Size
-: 多页图集的最大尺寸. 可以用来把一个图集切分成多页来限制图集尺寸同时仍然只用一个 draw call. 它必须与`/builtins/materials/*_paged_atlas.material` 里开启 multi-page atlas enabled materials 一起使用.
+: 多页图集中一页的最大尺寸。这可用于将图集拆分为同一图集的多个页面,以限制图集大小,同时仍仅使用单次绘制调用。此功能必须与位于 `/builtins/materials/*_paged_atlas.material` 中的启用多页图集的材料结合使用。
 
 ![Multi-page atlas](images/atlas/multipage_atlas.png)
 
 Rename Patterns
-: 以逗号 (´,´) 分隔的搜索和替换用的表达式列表, 每个表达式的形式为 `search=replace`.
-图片的原始名字 (文件名) 会用这些表达式改变. (比如 表达式 `hat=cat,_normal=`, 会重命名 `hat_normal` 为 `cat`). 这在多图集间匹配动画时很有用.
+: 以逗号(´,´)分隔的搜索和替换模式列表,其中每个模式的形式为 `search=replace`。
+每个图像的原始名称(文件基本名称)将使用这些模式进行转换。(例如,模式 `hat=cat,_normal=`,将把名为 `hat_normal` 的图像重命名为 `cat`)。这在匹配图集之间的动画时很有用。
 
-这里用四个 64x64 正方形图片做图集不同属性设置的演示. 注意这里图集一旦超过 128x128 就会跳到 256x256, 从而造成了资源浪费.
+以下是不同属性设置的示例,其中四个64x64的正方形图像被添加到图集中。请注意,一旦图像无法适应128x128,图集如何跳转到256x256,导致大量浪费的纹理空间。
 
 ![Atlas properties](images/atlas/atlas_properties.png)
 
-## 图属性
+## 图属性
 
-图集中的每个图片都有一系列属性:
+图集中的每个图像都有一组属性:
 
 Id
-: 图片名称 (只读).
+: 图像的ID(只读)。
 
 Size
-: 图片宽高 (只读).
+: 图像的宽度和高度(只读)。
+
+Pivot
+: 图像的轴心点(以单位为单位)。左上角是(0,0),右下角是(1,1)。默认是(0.5, 0.5)。轴心点可以在0-1范围之外。轴心点是图像在精灵等中使用时将被居中的位置。您可以通过拖动编辑器视图上的轴心手柄来修改轴心点。只有当选择单个图像时,手柄才可见。拖动时按住 <kbd>Shift</kbd> 可以启用捕捉。
 
 Sprite Trim Mode
-: 决定sprite如何渲染. 默认以矩形渲染 (Sprite Trim Mode 为 Off). 如果图片由许多透明的地方最好用4个或8个顶点设定非矩形渲染.
+: 精灵的渲染方式。默认是将精灵渲染为矩形(Sprite Trim Mode设置为Off)。如果精灵包含大量透明像素,使用4到8个顶点将精灵渲染为非矩形形状可能更有效。请注意,精灵修剪不与9宫格精灵一起工作。
 
 Image
-: 图片路径.
+: 图像本身的路径。
 
 ![Image properties](images/atlas/image_properties.png)
 
 ## 动画属性
 
-动画组除了组成动画的图片, 还提供了一些属性:
+除了作为动画组一部分的图像列表外,还有一组可用属性:
 
 Id
-: 动画名称.
+: 动画的名称。
 
 Fps
-: 动画播放速率, 以帧每秒 (FPS) 表示.
+: 动画的播放速度,以每秒帧数(FPS)表示。
 
 Flip horizontal
-: 动画水平翻转.
+: 水平翻转动画。
 
 Flip vertical
-: 动画垂直翻转.
+: 垂直翻转动画。
 
 Playback
-: 设置动画播放方式:
+: 指定动画应如何播放:
 
-  - `None` 不播放, 只显示第一张图片.
-  - `Once Forward` 从第一张图片到最后一张图片播放一次.
-  - `Once Backward` 从最后一张图片到第一张图片播放一次.
-  - `Once Ping Pong` 从第一张图片播放到最后一张图片再反向播放一次.
-  - `Loop Forward` 从第一张图片到最后一张图片循环播放.
-  - `Loop Backward` 从最后一张图片到第一张图片循环播放.
-  - `Loop Ping Pong` 从第一张图片播放到最后一张图片再反向循环播放.
+  - `None` 完全不播放,显示第一张图像。
+  - `Once Forward` 从第一张到最后一张图像播放动画一次。
+  - `Once Backward` 从最后一张到第一张图像播放动画一次。
+  - `Once Ping Pong` 从第一张到最后一张图像播放动画一次,然后回到第一张图像。
+  - `Loop Forward` 从第一张到最后一张图像重复播放动画。
+  - `Loop Backward` 从最后一张到第一张图像重复播放动画。
+  - `Loop Ping Pong` 从第一张到最后一张图像重复播放动画,然后回到第一张图像。
 
-## 运行时纹理及图集建立
+## 运行时纹理和图集创建
 
-自从 Defold 1.4.2 版本, 可以在运行时创建纹理和图集.
+从 Defold 1.4.2 开始,可以在运行时创建纹理和图集。
 
 ### 在运行时创建纹理资源
 
-使用 [`resource.create_texture(path, params)`](https://defold.com/ref/stable/resource/#resource.create_texture:path-table) 创建纹理资源:
+使用 [`resource.create_texture(path, params)`](https://defold.com/ref/stable/resource/#resource.create_texture:path-table) 创建新的纹理资源:
 
 ```lua
   local params = {
@@ -142,13 +151,14 @@ Playback
   local my_texture_id = resource.create_texture("/my_custom_texture.texturec", params)
 ```
 
-纹理创建好之后就可以用 [`resource.set_texture(path, params, buffer)`](https://defold.com/ref/stable/resource/#resource.set_texture:path-table-buffer) 设置纹理的像素:
+创建纹理后,您可以使用 [`resource.set_texture(path, params, buffer)`](https://defold.com/ref/stable/resource/#resource.set_texture:path-table-buffer) 设置纹理的像素
 
 ```lua
   local width = 128
   local height = 128
   local buf = buffer.create(width * height, { { name=hash("rgba"), type=buffer.VALUE_TYPE_UINT8, count=4 } } )
   local stream = buffer.get_stream(buf, hash("rgba"))
+
   for y=1, height do
       for x=1, width do
           local index = (y-1) * width * 4 + (x-1) * 4 + 1
@@ -164,18 +174,18 @@ Playback
 ```
 
 ::: sidenote
-可以使用 `resource.set_texture()` 更新局部纹理, 方法是设置 buffer 的 width 和 height 小于纹理完整尺寸, 然后指定 `resource.set_texture()` 的 x 和 y 参数.
+也可以使用 `resource.set_texture()` 通过使用小于纹理完整大小的缓冲区宽度和高度以及通过更改 `resource.set_texture()` 的 x 和 y 参数来更新纹理的子区域。
 :::
 
-纹理可以用 `go.set()` 直接应用于 [模型组件](/manuals/model/) 上:
+纹理可以直接在[模型组件](/manuals/model/)上使用 `go.set()`:
 
 ```lua
   go.set("#model", "texture0", my_texture_id)
 ```
 
-### 运行时创建图集
+### 运行时创建图集
 
-如果纹理要用在 [sprite 组件](/manuals/sprite/) 上, 要先转换成图集. 使用 [`resource.create_atlas(path, params)`](https://defold.com/ref/stable/resource/#resource.create_atlas:path-table) 创建图集:
+如果纹理应该在[精灵组件](/manuals/sprite/)上使用,它首先需要被图集使用。使用 [`resource.create_atlas(path, params)`](https://defold.com/ref/stable/resource/#resource.create_atlas:path-table) 创建图集
 
 ```lua
   local params = {
@@ -208,8 +218,11 @@ Playback
     }
   }
   local my_atlas_id = resource.create_atlas("/my_atlas.texturesetc", params)
-  -- 给当前游戏对象上的 'sprite' 组件指定图集
+
+  -- assign the atlas to the 'sprite' component on the same go
   go.set("#sprite", "image", my_atlas_id)
-  -- 播放 "逐帧动画"
+
+  -- play the "animation"
   sprite.play_flipbook("#sprite", "my_animation")
+
 ```

+ 31 - 31
docs/zh/manuals/bob.md

@@ -1,25 +1,25 @@
 ---
-title: Defold 项目编译教程
-brief: Bob 是用于 Defold 项目的命令行编译工具. 本教程详述如何使用这个工具.
+title: Defold 项目构建器手册
+brief: Bob 是用于构建 Defold 项目的命令行工具。本手册详述如何使用这个工具。
 ---
 
-# 编译器 Bob
+# 构建器 Bob
 
-Bob 是一个用于Defold项目编辑器之外的命令行编译工具.
+Bob 是一个命令行工具,用于在正常编辑器工作流程之外构建 Defold 项目。
 
-Bob 用来编译操作 (对应编辑器里的 <kbd>Project ▸ Build</kbd>), 来创建数据档或者创建可独立发布的应用 (对应编辑器里的 <kbd>Project ▸ Bundle ▸ ...</kbd> 选项)
+Bob 能够构建数据(对应于选择编辑器菜单项 <kbd>Project ▸ Build</kbd> 的构建步骤),创建数据存档,并创建独立的、可分发的应用程序包(对应于编辑器菜单项 <kbd>Project ▸ Bundle ▸ ...</kbd> 选项)。
 
-Bob 集合了编译所需的一切, 作为Java包 _JAR_ 发布. 最新的 *bob.jar* 发布在 [Defold 下载页](http://d.defold.com) 和 [GitHub 发布页](https://github.com/defold/defold/releases) 上. 选择一个版本, 下载 *bob/bob.jar*. 如果你使用的是 Defold 1.9.6, 您需要安装 OpenJDK 21. 对于 Defold 老版本, 你需要 openJDK 17.
+Bob 作为 Java _JAR_ 存档分发,其中包含构建所需的一切。您可以在 [GitHub 发布页面](https://github.com/defold/defold/releases) 上找到最新的 *bob.jar* 分发版本。选择一个发布版本,然后下载 *bob/bob.jar*。如果您使用的是 Defold 1.9.6,您将需要 OpenJDK 21 来运行它。对于旧版本的 Defold,您将需要 OpenJDK 17 或 11。
 
-兼容 OpenJDK 21 镜像 (自从 Defold 1.9.6):
-* https://docs.microsoft.com/en-us/java/openjdk/download#openjdk-21
-* https://github.com/adoptium/temurin21-binaries/releases / https://adoptium.net/
+兼容的 OpenJDK 21 镜像(从 Defold 1.9.6 开始):
+* [Microsoft 提供的 OpenJDK 21](https://docs.microsoft.com/en-us/java/openjdk/download#openjdk-21)
+* [Adoptium 工作组提供的 OpenJDK 21](https://github.com/adoptium/temurin21-binaries/releases) / [Adoptium.net](https://adoptium.net/)
 
-比如在 Windows 平台上, 需要下载 OpenJDK 21 的 .msi 安装包.
+如果您在 Windows 上,您需要 OpenJDK 的 `.msi` 文件安装程序。
 
 ## 用法
 
-Bob 运行于命令行界面 `java` (再Windows上是 `java.exe`) 后跟bob的jar包作为参数:
+Bob 通过在 shell 或命令行中调用 `java`(在 Windows 上是 `java.exe`)并提供 bob java 存档作为参数来运行:
 
 ```text
 $ java -jar bob.jar --help
@@ -144,55 +144,55 @@ usage: bob [options] [commands]
                                          applicable)
 ```
 
-支持的命令:
+可用命令:
 
 `clean`
-: 清空编译目录下的编译文件.
+: 删除构建目录中已构建的文件。
 
 `distclean`
-: 清空编译目录下的所有文件.
+: 删除构建目录中的所有文件。
 
 `build`
-: 编译所有项目文件. 加入 `--archive` 选项可生成编译数据包 (编译目录下生成 "game.darc" 文件).
+: 构建所有项目数据。添加 `--archive` 选项以构建数据存档文件(构建目录中的 "`game.darc`")。
 
 `bundle`
-: 指定平台打包. 打包需要数据包已经编译生成 (`build` 加入 `--archive` 选项) 然后指定打包平台 (使用 `--platform` 选项). Bob 会把应用打包到编译目录下, 除非使用 `--bundle-output` 选项手动指定打包输出目录. 包名根据 *game.project* 文件中设置的项目名命名. 使用 `--variant` 指定打何种运行类型的包, 连同 `--strip-executable` 选项代替了老的 `--debug` 选项. 如果 `--variant` 没有指定, 默认时release类型的 (去除 Android 和 iOS 的debug信息). 把 `--variant` 设置为 debug 而省略 `--strip-executable` 选项, 就相当于老的 `--debug`选项.
+: 创建特定于平台的应用程序包。打包需要存在已构建的存档(使用 `--archive` 选项的 `build`)并指定目标平台(使用 `--platform` 选项)。除非使用 `--bundle-output` 选项指定不同的目录,否则 Bob 会在输出目录中创建包。包根据 *game.project* 中的项目名称设置命名。`--variant` 指定打包时构建哪种类型的可执行文件,它与 `--strip-executable` 选项一起取代了 `--debug` 选项。如果没有指定 `--variant`,您将获得引擎的发布版本(在 Android 和 iOS 上剥离符号)。将 `--variant` 设置为 debug 并省略 `--strip-executable` 会产生与 `--debug` 过去相同的可执行文件类型。
 
 `resolve`
-: 解析所有外部依赖库.
+: 解析所有外部库依赖项。
 
-支持平台和架构:
+可用平台和架构:
 
-`x86_64-darwin` (Defold 1.3.5 及更版本)
+`x86_64-darwin` (Defold 1.3.5 及更版本)
 `x86_64-macos` (Defold 1.3.6 及更新版本)
-: macOS 64 bit
+: macOS 64 
 
-`arm64-macos` (Defold 1.5.0 and older)
+`arm64-macos` (Defold 1.5.0 及更早版本)
 : macOS Apple Silicon (ARM)
 
 `x86_64-win32`
-: Windows 64 bit
+: Windows 64 
 
 `x86-win32`
-: Windows 32 bit
+: Windows 32 
 
 `x86_64-linux`
-: Linux 64 bit
+: Linux 64 
 
 `x86_64-ios`
-: iOS macOS 64 bit (iOS 模拟器)
+: iOS macOS 64  (iOS 模拟器)
 
-`armv7-darwin` (Defold 1.3.5 及更版本)
+`armv7-darwin` (Defold 1.3.5 及更版本)
 `armv7-ios` (Defold 1.3.6 及更新版本)
-: iOS 支持 32-bit `armv7-darwin` 和 64-bit `arm64-darwin` 架构. 默认情况下, `--architectures` 参数值为 `armv7-darwin,arm64-darwin`.
+: iOS,具有可用的 32 位 `armv7-darwin` 和 64 位 `arm64-darwin` 架构。默认情况下,`--architectures` 参数值为 `armv7-darwin,arm64-darwin`。
 
 `armv7-android`
-: Android 支持 32 bit `armv7-android` 和 64 bit `arm64-android` 架构. 默认情况下, `--architectures` 参数值为 `armv7-android,arm64-android`.
+: Android,具有可用的 32 位 `armv7-android` 和 64 位 `arm64-android` 架构。默认情况下,`--architectures` 参数值为 `armv7-android,arm64-android`。
 
 `js-web`
-: HTML5 支持 `js-web` 和 `wasm-web` 架构. 默认情况下, `--architectures` 参数值为 `js-web,wasm-web`.
+: HTML5,具有可用的 `js-web` 和 `wasm-web` 架构。默认情况下,`--architectures` 参数值为 `js-web,wasm-web`。
 
-默认情况下, Bob 在当前目录下寻找项目来编译. 切换到 Defold 项目目录下使用 bob, 它会把数据编译到默认输出 *build/default* 目录下.
+默认情况下,Bob 在当前目录中寻找要构建的项目。如果您将当前目录更改为 Defold 项目并调用 bob,它将在默认输出目录 *build/default* 中构建项目的数据。
 
 ```sh
 $ cd /Applications/Defold-beta/branches/14/4/main
@@ -201,7 +201,7 @@ $ java -jar bob.jar
 $
 ```
 
-还可以把命令连成一行一起执行. 下面的例子包含了解析库, 清理编译目录, 编译数据包然后打包成 macOS 应用 (命名为 *My Game.app*):
+您可以将命令串联在一起以一次性执行一系列任务。以下示例解析库,清除构建目录,构建存档数据并将 macOS 应用程序捆绑(命名为 *My Game.app*):
 
 ```sh
 $ java -jar bob.jar --archive --platform x86-darwin resolve distclean build bundle

+ 6 - 6
docs/zh/manuals/buffer.md

@@ -1,11 +1,11 @@
 ---
-title: 缓存教程
-brief: 本教程介绍了 Defold 的缓存资源.
+title: Buffer手册
+brief: 本手册介绍了Defold中的Buffer资源的工作原理.
 ---
 
 # Buffer
 
-缓存资源用来描述一个或多个数据流, 比如位置或颜色. 每种流有名字, 数据类型, 数目及数据自身. 例如:
+Buffer资源用于描述一个或多个值流,例如位置或颜色。每个流都有名称、数据类型、计数和数据本身。示例:
 
 ```
 [
@@ -26,8 +26,8 @@ brief: 本教程介绍了 Defold 的缓存资源.
 ]
 ```
 
-上例描述了三维位置数据流, 用 32-bit 浮点数表示. 缓存类型是 JSON, 文件扩展名是 `.buffer`.
+上面的示例描述了三维位置流,表示为32位浮点数。Buffer文件的格式为JSON,文件扩展名为`.buffer`。
 
-缓存资源一般由扩展工具或脚本创建, 比如用 Blender 导出模型时创建. 
+Buffer资源通常使用外部工具或脚本创建,例如从Blender等建模工具导出时。 
 
-缓存资源可以用作 [模型资源](/manuals/mesh) 的数据. 缓存资源还可以使用 `buffer.create()` 和 [相关 API 函数](/ref/stable/buffer/#buffer.create:element_count-declaration) 在运行时创建. 
+Buffer资源可用作[Mesh组件](/manuals/mesh)的输入。也可以使用`buffer.create()`和[相关API函数](/ref/stable/buffer/#buffer.create:element_count-declaration)在运行时创建Buffer资源。

+ 36 - 36
docs/zh/manuals/building-blocks.md

@@ -1,65 +1,65 @@
 ---
-title: Defold 构成
-brief: 本教程详述游戏对象, 组件和集合是如何工作的.
+title: Defold的构建块
+brief: 本手册深入探讨游戏对象、组件和集合的工作原理细节。
 ---
 
-#  构
+#  构建块
 
-理解 Defold 核心设计中的各种概念是很重要的. 本教程介绍了 Defold 游戏的各个组成部分. 看完本教程后, 可以去参考 [定位教程](/manuals/addressing) 和 [消息传递教程](/manuals/message-passing). 编辑器中提供了一些 [教程](/tutorials/getting-started) 也可以帮助学习理解.
+Defold设计的核心是几个非常重要的概念,掌握这些概念至关重要。本手册解释了Defold的构建块由什么组成。阅读本手册后,请继续阅读[定位手册](/manuals/addressing)和[消息传递手册](/manuals/message-passing)。编辑器中还提供了一套[教程](/tutorials/getting-started),可以帮助您快速上手。
 
 ![Building blocks](images/building_blocks/building_blocks.png)
 
-Defold 游戏主要由三大部分组成:
+您可以使用三种基本类型的构建块来构建Defold游戏:
 
 Collection
-: 集合文件构成了你的游戏. 集合可以包含具有嵌套关系的游戏对象与其他集合. 可以用来构建诸如关卡, 敌人队伍, 多个游戏对象嵌套组成的一个角色之类的各种内容.
+: 集合是用于构建游戏结构的文件。在集合中,您可以构建游戏对象和其他集合的层次结构。它们通常用于构建游戏关卡、敌人群体或由多个游戏对象组成的角色。
 
 Game object
-: 游戏对象是一个带 id 的容器, 具有位置, 旋转和缩放. 用来容纳组件. 可以用来构建主角, 子弹, 游戏逻辑或者资源加载/卸载程序.
+: 游戏对象是具有ID、位置、旋转和缩放的容器。它用于容纳组件。它们通常用于创建玩家角色、子弹、游戏规则系统或关卡加载器。
 
 Component
-: 组件被放置在游戏对象中用来产生游戏里可视, 可听, 可运行的东西. 可以用来构建 sprite, 脚本, 音效或者粒子特效.
+: 组件是放置在游戏对象中的实体,为游戏对象提供视觉、听觉和/或逻辑表示。它们通常用于创建角色精灵、脚本文件、添加音效或添加粒子效果。
 
 ## 集合
 
-集合是包含嵌套游戏对象和其他集合的树形结构. 通常集合作为文件保存于项目中.
+集合是包含游戏对象和其他集合的树形结构。集合总是存储在文件中。
 
-Defold 游戏引擎启动时, 首先导入一个 *game.project* 配置文件中指定的 _启动集合_. 启动集合一般叫做 "main.collection",  当然也可以根据喜好随意设置.
+当Defold引擎启动时,它会加载一个在*game.project*设置文件中指定的_引导集合_。引导集合通常命名为"main.collection",但您可以自由使用任何您喜欢的名称。
 
-集合可以包含游戏对象和其他集合 (通过引用子集合文件), 它们可以随意嵌套. 下面是一个 "main.collection" 集合示例. 它包含了一个游戏对象 (id 叫做 "can") 和一个子集合 (id 叫做 "bean"). 这个子集合, 又包含了两个游戏对象: "bean" 和 "shield".
+集合可以包含游戏对象和其他集合(通过引用子集合文件),可以任意深度嵌套。下面是一个名为"main.collection"的文件示例。它包含一个游戏对象(ID为"can")和一个子集合(ID为"bean")。子集合又包含两个游戏对象:"bean"和"shield"。
 
 ![Collection](images/building_blocks/collection.png)
 
-注意这个 id 叫做 "bean" 的子集合也是一个集合文件, 路径是 "/main/bean.collection", 这个文件被 "main.collection" 引用:
+请注意,ID为"bean"的子集合存储在自己的文件中,名为"/main/bean.collection",仅在"main.collection"中被引用:
 
 ![Bean collection](images/building_blocks/bean_collection.png)
 
-运行时无法用集合的 id 对 "main" 和 "bean" 这样的集合定位. 但是, 使用 _路径_ 引用游戏对象时可能会用到集合的 id (详情请见 [定位教程](/manuals/addressing)):
+您无法对集合本身进行寻址,因为没有与"main"和"bean"集合对应的运行时对象。但是,您有时需要使用集合的标识作为游戏对象_路径_的一部分(详细信息请参阅[定位手册](/manuals/addressing)):
 
 ```lua
 -- file: can.script
--- 定位 "bean" 集合的 "bean" 对象
+-- 获取"bean"集合中"bean"游戏对象的位置
 local pos = go.get_position("bean/bean")
 ```
 
-集合只能用文件引用的方式添加到其他集合中:
+集合总是作为对集合文件的引用添加到另一个集合中:
 
-在 *Outline* 视图中 <kbd>右键点击</kbd> 选择 <kbd>Add Collection File</kbd>.
+在*Outline*视图中<kbd>右键单击</kbd>集合并选择<kbd>Add Collection File</kbd>。
 
 ## 游戏对象
 
-游戏对象在游戏运行时有自己的生命周期. 游戏对象有位置, 旋转和缩放. 这些属性可以在运行时进行控制也可用于属性动画.
+游戏对象是在游戏执行期间各自具有独立生命周期的简单对象。游戏对象具有位置、旋转和缩放,每个属性都可以在运行时进行操作和动画处理。
 
 ```lua
--- 将 "can" 游戏对象的 X 坐标位置创建属性动画 
+-- 为"can"游戏对象的X位置设置动画
 go.animate("can", "position.x", go.PLAYBACK_LOOP_PINGPONG, 100, go.EASING_LINEAR, 1.0)
 ```
 
-游戏对象可以是空的 (比如作为位置标记) 但通常包含各种组件, 比如 sprite, 声音, 脚本, 模型, 工厂什么的. 游戏对象可以使用编辑器进行创建, 放入集合, 或者在运行时使用 _factory_ 组件动态生成.
+游戏对象可以空着使用(例如作为位置标记),但通常配备各种组件,如精灵、声音、脚本、模型、工厂等。游戏对象要么在编辑器中创建,放置在集合文件中,要么在运行时通过_factory_组件动态生成。
 
-游戏对象可以直接放入集合, 或者作为文件被集合引用:
+游戏对象可以直接添加到集合中,或者作为对游戏对象文件的引用添加到集合中:
 
-在 *Outline* 视图中 <kbd>右键点击</kbd> 集合选择 <kbd>Add Game Object</kbd> (直接放入) 或者 <kbd>Add Game Object File</kbd> (作为文件引用).
+在*Outline*视图中<kbd>右键单击</kbd>集合并选择<kbd>Add Game Object</kbd>(就地添加)或<kbd>Add Game Object File</kbd>(作为文件引用添加)。
 
 
 ## 组件
@@ -68,43 +68,43 @@ go.animate("can", "position.x", go.PLAYBACK_LOOP_PINGPONG, 100, go.EASING_LINEAR
 
 可用组件列表详见 [组件概述](/manuals/components/).
 
-## 直接放入还是作为文件引用
+## 就地添加或通过引用添加的对象
 
-创建集合, 游戏对象或者组件 _文件_ 的时候, 实际上是创建了一个蓝图, 或者称为原型. 原型文件保存于项目中, 而不是游戏里. 要在游戏里使用这些原型的实例就需要在集合中把原型实例化.
+当您创建集合、游戏对象或组件_文件_时,您创建的是我们所说的原型(在其他引擎中也称为"预制件"或"蓝图")。这只是在项目文件结构中添加了一个文件,并没有在运行的游戏中添加任何内容。要添加基于原型文件的集合、游戏对象或组件的实例,您需要在其中一个集合文件中添加它的实例。
 
-在大纲视图中可以看到各个实例是基于哪个原型的. 下例中 "main.collection" 包含了3个基于文件的实例:
+您可以在大纲视图中看到对象实例基于哪个文件。"main.collection"文件包含三个基于文件的实例:
 
-1. "bean" 子集合.
-2. "bean" 子集合里 "bean" 对象的 "bean" 脚本组件.
-3. "can" 游戏对象的 "can" 脚本组件.
+1. "bean"子集合。
+2. "bean"子集合中"bean"游戏对象中的"bean"脚本组件。
+3. "can"游戏对象中的"can"脚本组件。
 
 ![Instance](images/building_blocks/instance.png)
 
-如果你有许多游戏对象或者集合的实例, 这种基于文件的设计就很方便:
+当您有多个游戏对象或集合的实例并希望更改所有实例时,创建原型文件的好处就变得明显:
 
 ![GO instances](images/building_blocks/go_instance.png)
 
-修改了原型文件, 那么它的所有实例都能一同被修改.
+通过更改原型文件,任何使用该文件的实例都将立即更新。
 
 ![GO changing prototype](images/building_blocks/go_change_blueprint.png)
 
-这里原型的 sprite 图片被更改, 同时所有使用该文件的实例都被更新:
+这里原型文件的精灵图像被更改,所有使用该文件的实例立即更新:
 
 ![GO instances updated](images/building_blocks/go_instance2.png)
 
-## 游戏对象层级
+## 创建游戏对象的父子关系
 
-在集合文件中, 可以将游戏对象设置成父子层级关系. 只需要 <kbd>拖拽</kbd> 游戏对象到父级对象 <kbd>放开鼠标</kbd> 即可完成父子层级的建立:
+在集合文件中,您可以构建游戏对象的层次结构,使一个或多个游戏对象成为单个父游戏对象的子对象。只需简单地<kbd>拖动</kbd>一个游戏对象并将其<kbd>放置</kbd>到另一个游戏对象上,被拖动的游戏对象就成为目标游戏对象的子对象:
 
 ![Childing game objects](images/building_blocks/childing.png)
 
-这种动态的父子关系影响了它们的变化方式. 不论是在编辑器还是运行时, 父级的各种变化 (包括位置, 旋转和缩放) 都会自动应用到它的所有子级上:
+对象父子层次结构是一种动态关系,影响对象如何响应变换。在编辑器和运行时,应用于对象的任何变换(移动、旋转或缩放)都会依次应用于对象的子对象:
 
 ![Child transform](images/building_blocks/child_transform.png)
 
-反过来说, 子级的变化都基于父级的坐标空间. 在编辑器中, 你可以使用 <kbd>Edit ▸ World Space</kbd> (默认设置) 或者 <kbd>Edit ▸ Local Space</kbd> 来设置一个对象变化基于的坐标空间.
+相反,子对象的平移是在父对象的局部空间中完成的。在编辑器中,您可以通过选择<kbd>Edit ▸ World Space</kbd>(默认)或<kbd>Edit ▸ Local Space</kbd>来选择在局部空间或世界空间中编辑子游戏对象。
 
-运行时可以通过发送 `set_parent` 消息改变对象的父级.
+也可以在运行时通过向对象发送`set_parent`消息来更改对象的父级。
 
 ```lua
 local parent = go.get_id("bean")
@@ -112,5 +112,5 @@ msg.post("child_bean", "set_parent", { parent_id = parent })
 ```
 
 ::: important
-一个常见的误解是对象层级改变了那么它的定位地址也会改变. 但是, 这其实是两码事. 父子关系改变的是场景的层级. 集合嵌套关系才决定对象地址. 在对象整个生命周期中, 地址是不会变化的.
+一个常见的误解是,当游戏对象成为父子层次结构的一部分时,它在集合层次结构中的位置会发生变化。然而,这是两个非常不同的概念。父子层次结构动态地改变场景图,允许对象在视觉上相互附加。决定游戏对象地址的唯一因素是它在集合层次结构中的位置。地址在对象的整个生命周期中是静态的。
 :::

+ 37 - 37
docs/zh/manuals/bundling.md

@@ -1,93 +1,93 @@
 ---
-title: 打包应用
-brief: 本教程介绍了如何打包应用.
+title: 打包应用程序
+brief: 本手册介绍了如何创建应用程序包.
 ---
 
-# 打包应用
+# 打包应用程序
 
-开发项目时常常需要在目标平台上进行测试. 开发中越早发现性能问题越好解决. 同样鼓励在各平台间做测试以便发现诸如shader之类的兼容问题. 在做手机开发时可以使用 [手机开发应用](/manuals/dev-app/) 把内容推送到手机上, 避免反复的安装和卸载.
+在开发应用程序时,您应该养成在目标平台上尽可能频繁地测试游戏的习惯。您应该这样做是为了在开发过程的早期阶段发现性能问题,这些问题在此时更容易解决。还建议在所有目标平台上进行测试,以发现着色器等方面的差异。在移动设备上开发时,您可以选择使用[移动开发应用](/manuals/dev-app/)将内容推送到应用程序,而不必进行完整的打包和卸载/安装循环。
 
-你可以在 Defold 编辑器中生成其支持的所有平台应用, 不需要外界工具辅助. 也可以在控制台使用命令行工具打包应用. 如果应用里包含 [原生扩展](/manuals/extensions) 的话打包时需要网络连接.
+您可以在Defold编辑器本身中为Defold支持的所有平台创建应用程序包,无需任何外部工具。您也可以使用我们的命令行工具从命令行打包。如果您的项目包含一个或多个[原生扩展](/manuals/extensions),应用程序打包需要网络连接。
 
 ## 从编辑器中打包
 
-使用 Project 菜单的 Bundle 选项进行打包:
+您可以通过项目菜单和Bundle选项创建应用程序包:
 
 ![](images/bundling/bundle_menu.png)
 
-选择不同的打包平台会出现不同的对话窗.
+选择任何菜单选项都会为该特定平台打开Bundle对话框。
 
-### 编译报告
+### 构建报告
 
-有一个编译选项控制编译时是否生成报告. 从报告中可以方便检查游戏包中各个资源占用的空间. 在编译时打开 *Generate build report* 选项即可.
+打包游戏时,有一个选项可以创建构建报告。这对于了解构成游戏包的所有资源的大小非常有用。只需在打包游戏时勾选*Generate build report*复选框即可。
 
 ![build report](images/profiling/build_report.png)
 
-关于编译报告详情请见 [调试教程](/manuals/profiling/#编译报告).
+要了解更多关于构建报告的信息,请参考[性能分析手册](/manuals/profiling/#build-reports)。
 
 
 ### Android
 
-建立安卓应用 (.apk 文件) 详见 [安卓教程](/manuals/android/#安卓应用打包).
+创建Android应用程序包(.apk文件)的文档记录在[Android手册](/manuals/android/#creating-an-android-application-bundle)中。
 
 ### iOS
 
-建立苹果移动应用 (.ipa 文件) 详见 [iOS 教程](/manuals/ios/#iOS应用打包).
+创建iOS应用程序包(.ipa文件)的文档记录在[iOS手册](/manuals/ios/#creating-an-ios-application-bundle)中。
 
 ### macOS
 
-建立Mac系统应用 (.app 文件) 详见 [macOS 教程](/manuals/macos).
+创建macOS应用程序包(.app文件)的文档记录在[macOS手册](/manuals/macos)中。
 
 ### Linux
 
-建立Linux应用无需特别设置.
+创建Linux应用程序包不需要特定设置,也不需要在*game.project*[项目设置文件](/manuals/project-settings/#linux)中进行可选的平台特定配置。
 
 ### Windows
 
-建立Windows应用 (.exe 文件) 详见 [Windows 教程](/manuals/windows).
+创建Windows应用程序包(.exe文件)的文档记录在[Windows手册](/manuals/windows)中。
 
 ### HTML5
 
-建立HTML5应用及其参数设置详见 [HTML5 教程](/manuals/html5/#HTML5游戏打包).
+创建HTML5应用程序包以及可选设置的文档记录在[HTML5手册](/manuals/html5/#creating-html5-bundle)中。
 
 #### Facebook Instant Games
 
-可以为 Facebook Instant Games 打包成 HTML5 应用的一种特殊版本. 这一过程详见 [Facebook Instant Games 教程](/manuals/instant-games/).
+可以为Facebook Instant Games创建一个特殊版本的HTML5应用程序包。这个过程在[Facebook Instant Games手册](/manuals/instant-games/)中有详细说明。
 
-## 命令行打包
+## 命令行打包
 
-编辑器使用命令行工具 [Bob](/manuals/bob/) 进行应用打包.
+编辑器使用我们的命令行工具[Bob](/manuals/bob/)来打包应用程序。
 
-日常开发中一般使用 Defold 编辑器编译和打包应用. 如果需要自动生成机制, 比如发布新版本时批处理所有平台或者使用持续集成环境持续生成最新版本. 可以使用 [Bob 命令行工具](/manuals/bob/) 编译和打包.
+在进行应用程序的日常开发时,您可能会在Defold编辑器内进行构建和打包。在其他情况下,您可能希望自动生成应用程序包,例如在发布新版本时为所有目标进行批量构建,或者创建最新版本游戏的夜间构建,也许在CI环境中。应用程序的构建和打包可以在正常编辑器工作流程之外使用[Bob命令行工具](/manuals/bob/)完成。
 
-## Bundle 结构
+## 包布局
 
-Bundle 的逻辑结构是这样的:
+逻辑包布局结构如下:
 
 ![](images/bundling/bundle_schematic_01.png)
 
-Bundle 会被输出到一个文件夹. 不同平台位置各异, 还有可能作为 zip 文件包含进 `.apk` 或者 `.ipa` 中.
-Bundle 文件夹的内容每个平台也不一样.
+包被输出到一个文件夹中。根据平台的不同,该文件夹也可能被zip归档到`.apk`或`.ipa`中。
+文件夹的内容取决于平台。
 
-除了可执行文件, 打包过程中也会收集相关平台所必须的资源 (比如安卓平台用的 .xml 资源文件).
+除了可执行文件外,我们的打包过程还会收集平台所需的资源(例如Android的.xml资源文件)。
 
-通过 [bundle_resources](https://defold.com/manuals/project-settings/#bundle-resources) 项, 设置应打包进 bundle 里的资源.
-可以针对不同平台分别设置.
+使用[bundle_resources](https://defold.com/manuals/project-settings/#bundle-resources)设置,您可以配置应原样放置在包中的资源。
+您可以按平台控制这一点。
 
-游戏资源被保存在 `game.arcd` 文件中, 使用 LZ4 算法逐个压缩.
-通过 [custom_resources](https://defold.com/manuals/project-settings/#custom-resources) 项, 设置应打包 (同时也被压缩) 进 game.arcd 里的资源.
-这类资源可以使用 [sys.load_resource()](https://defold.com/ref/sys/#sys.load_resource) 函数来进行访问.
+游戏资源位于`game.arcd`文件中,它们使用LZ4压缩单独压缩。
+使用[custom_resources](https://defold.com/manuals/project-settings/#custom-resources)设置,您可以配置应放置(并压缩)在`game.arcd`中的资源。
+这些资源可以通过[`sys.load_resource()`](https://defold.com/ref/sys/#sys.load_resource)函数访问。
 
 ## Release 与 Debug
 
-打包游戏时有个选项允许选择创建 debug 还是 release 应用. 这两种应用包类似但是要记得两者存在如下区别:
+创建应用程序包时,您可以选择创建debug或release包。这两种包之间的差异很小,但重要的是要记住:
 
-* Release 包不包含 [性能分析器](/manuals/profiling)
-* Release 包不包含 [屏幕录制器](/ref/stable/sys/#start_record)
-* Release 不输出调用 `print()` 产生的信息也不输出原生扩展产生的任何信息
-* Release 包的 `sys.get_engine_info()` 中的 `is_debug` 被设置为 `false`
-* Release 包调用 `tostring()` 时不会反查 `hash` 值. 也就是说对于一个类型为 `url` 或 `hash` 值的 `tostring()` 不会返回原值字符串而是返回一个数字表示的字符串 (`'hash: [/camera_001]'` 对比 `'hash: [11844936738040519888 (unknown)]'`)
-* Release 包不支持编辑器中设置的用于 [热重载](/manuals/hot-reload) 和类似功能的 target
+* Release构建不包含[性能分析器](/manuals/profiling)
+* Release构建不包含[屏幕录制器](/ref/stable/sys/#start_record)
+* Release构建不显示任何对`print()`的调用的输出或任何原生扩展的输出
+* Release构建在`sys.get_engine_info()`中将`is_debug`值设置为`false`
+* Release构建在调用`tostring()`时不会对`hash`值进行反向查找。这在实践中意味着,对于类型为`url`或`hash`的值的`tostring()`将返回其数字表示,而不是原始字符串(`'hash: [/camera_001]'`对比`'hash: [11844936738040519888 (unknown)]'`)
+* Release构建不支持来自编辑器的[热重载](/manuals/hot-reload)和类似功能的targeting
 
 
 

+ 16 - 16
docs/zh/manuals/caching-assets.md

@@ -1,51 +1,51 @@
 ---
-title: 资源缓存
-brief: 跟教程介绍了如何利用资源缓存提高编译速度.
+title: 缓存资源
+brief: 本手册解释了如何使用资源缓存来加速构建.
 ---
 
-# 资源缓存
+# 缓存资源
 
-Defold 编译通常需要几秒钟, 但是随着项目和资源的扩大, 耗时也会增加. 对于大项目而言, 编译时间大量消耗在编译字体和压缩纹理上, 所以引入资源缓存功能使得再次编译时只编译改变了的资源, 那些没改变的资源直接从缓存获取以提高编译效率.
+使用Defold创建的游戏通常在几秒钟内就能构建完成,但随着项目的增长,资源量也会增加。在大型项目中,编译字体和压缩纹理可能需要大量时间,而资源缓存的存在是为了通过只重新构建已更改的资源来加速构建,同时从缓存中使用已编译的资源来处理未更改的资源。
 
-Defold 使用了三重缓存:
+Defold使用三层缓存:
 
 1. 项目缓存
 2. 本地缓存
-3. 原创缓存
+3. 远程缓存
 
 
 ## 项目缓存
 
-Defold 默认把编译好的资源缓存到项目的 `build/default` 文件夹中. 下次编译时只编译改变了的资源, 未改变的资源从项目缓存中获取. 这种缓存在编辑器和命令行都会开启.
+Defold默认将编译的资源缓存在Defold项目的`build/default`文件夹中。项目缓存将加速后续构建,因为只有修改过的资源需要重新编译,而没有更改的资源将从项目缓存中使用。此缓存始终启用,编辑器和命令行工具都会使用它。
 
-可以手动删除项目目录下 `build/default` 中的文件, 或者使用 [命令行编译工具 Bob](/manuals/bob) 的 `clean` 命令, 达到清除项目缓存的目的.
+可以通过删除`build/default`中的文件或通过[命令行构建工具Bob](/manuals/bob)发出`clean`命令来手动删除项目缓存。
 
 
 ## 本地缓存
 
-自 Defold 1.2.187 版本引入
+Defold 1.2.187版本新增
 
-本地缓存作为可选功能, 把编译后的资源保存在本机或者云盘上. 这相当于是项目缓存的备份. 本地缓存还可以供项目的合作开发人员共享. 目前该缓存只能使用命令行工具开启. 即命令行参数 `resource-cache-local` 项:
+本地缓存是一个可选的第二层缓存,其中编译的资源存储在同一台机器上的外部文件位置或网络驱动器上。由于其外部位置,缓存内容在清理项目缓存后仍然存在。它也可以由在同一项目上工作的多个开发人员共享。该缓存目前仅在使用命令行工具构建时可用。它通过`resource-cache-local`选项启用:
 
 ```sh
 java -jar bob.jar --resource-cache-local /Users/john.doe/defold_local_cache
 ```
 
-本地缓存通过基于 Defold 引擎版本, 资源文件, 项目编译参数等计算出的校验码进行访问. 这样做就能保证不同 Defold 版本之间资源缓存的唯一性.
+从本地缓存访问编译资源是基于计算的校验和,该校验和考虑了Defold引擎版本、源资源的名称和内容以及项目构建选项。这将保证缓存的资源是唯一的,并且缓存可以在多个Defold版本之间共享。
 
 ::: sidenote
-本地缓存文件永远存在. 想要清除只能手动删除这些文件.
+存储在本地缓存中的文件将无限期存储。由开发人员手动删除旧/未使用的文件。
 :::
 
 
 ## 远程缓存
 
-自 Defold 1.2.187 版本引入
+Defold 1.2.187版本新增
 
-远程缓存作为可选功能, 把编译后的资源保存至服务器然后通过 HTTP 请求进行访问. 目前该缓存只能使用命令行工具开启. 即命令行参数 `resource-cache-remote` 项:
+远程缓存是一个可选的第三层缓存,其中编译的资源存储在服务器上并通过HTTP请求访问。该缓存目前仅在使用命令行工具构建时可用。它通过`resource-cache-remote`选项启用:
 
 ```sh
-java -jar bob.jar --resource-cache-remote https://http://192.168.0.100/
+java -jar bob.jar --resource-cache-remote http://192.168.0.100/
 ```
 
-远程缓存同样通过校验码进行访问. 使用 HTTP 请求的 GET, PUT 方法和 HEAD 获取缓存文件. Defold 不提供远程服务器程序. 开发者可以自行搭建. 比如 [这个使用 Python 做的简单的服务器程序](https://github.com/britzl/httpserver-python).
+与本地缓存一样,所有资源都是基于计算的校验和从远程缓存访问的。缓存的资源通过HTTP请求方法GET、PUT和HEAD访问。Defold不提供远程缓存服务器。这取决于每个开发人员来设置它。[一个基本的Python服务器示例可以在这里看到](https://github.com/britzl/httpserver-python)。

+ 172 - 77
docs/zh/manuals/camera.md

@@ -1,66 +1,109 @@
 ---
-title: 摄像机组件教程
-brief: 本教程介绍了 Defold 摄像机组件的功能.
+title: 摄像机组件手册
+brief: 本手册描述了Defold摄像机组件的功能.
 ---
 
 # 摄像机
 
-Defold 的摄像机组件控制游戏世界的视口与映射. 摄像机组件定义了透视和平视的视口与映射矩阵用于渲染脚本进行渲染.
+Defold中的摄像机是一种改变游戏世界视口和投影的组件。摄像机组件定义了一个基本的透视或正交摄像机,它为渲染脚本提供视图和投影矩阵。
 
-透视摄像机一般服务于 3D 游戏, 摄像机视口与物体透视基于视锥体, 摄像机到游戏物体的距离和视角.
+透视摄像机通常用于3D游戏,其中摄像机的视图以及物体的大小和透视基于视锥体以及从摄像机到游戏中物体的距离和视角。
 
-平视摄像机一般服务于 2D 游戏. 摄像机视口不是基于视锥体, 而是基于视立方体. 平视摄像机中的物体不因距离远近而缩放. 1000米远的物体和摄像机面前的物体是等大的.
+对于2D游戏,通常希望使用正交投影来渲染场景。这意味着摄像机的视图不再由视锥体决定,而是由一个立方体决定。正交投影是不现实的,因为它不会根据物体的距离改变物体的大小。一个1000单位远的物体将与摄像机正前方的物体以相同的大小渲染。
 
 ![projections](images/camera/projections.png)
 
 ## 创建摄像机
 
-要创建摄像机, 在游戏对象上 <kbd>右键点击</kbd> 选择 <kbd>Add Component ▸ Camera</kbd>. 或者先创建组件文件再链接到游戏对象上.
+要创建摄像机,<kbd>右键点击</kbd>一个游戏对象并选择<kbd>Add Component ▸ Camera</kbd>。您也可以在项目层次结构中创建一个组件文件,并将该组件文件添加到游戏对象中。
 
 ![create camera component](images/camera/create.png)
 
-摄像机有以下属性用以建立 *视锥*:
+摄像机组件具有以下定义摄像机*视锥体*的属性:
 
 ![camera settings](images/camera/settings.png)
 
 Id
-: 组件id
+: 组件的ID
 
 Aspect Ratio
-: (**透视摄像机可用**) - 视锥宽高比. 1.0 代表正方形视口.  4:3 显示器 1024x768 这样的分辨率用 1.33. 16:9 的显示器用 1.78. 如果设置了 *Auto Aspect Ratio* 则此属性无效.
+: (**仅透视摄像机**) - 视锥体宽度和高度之间的比率。1.0表示您假设的是方形视图。1.33适用于4:3视图,如1024x768。1.78适用于16:9视图。如果设置了*自动宽高比*,则此设置将被忽略。
 
 Fov
-: (**透视摄像机可用**) - 以 _弧度_ 表示的摄像机 *垂直* 视域. 视域越宽, 摄像机看到的内容越多. 注意目前默认值 (45) 有点误导. 要 45 度的视域, 要设置值为 0.785 (`π / 4`).
+: (**仅透视摄像机**) - 以_弧度_表示的摄像机*垂直*视野。视野越宽,摄像机将看到的内容越多。
 
 Near Z
-: 近端裁剪平面z值.
+: 近裁剪平面的Z值。
 
 Far Z
-: 远端裁剪平面z值.
+: 远裁剪平面的Z值。
 
 Auto Aspect Ratio
-: (**透视摄像机可用**) - 自动设置宽高比.
+: (**仅透视摄像机**) - 设置此项以让摄像机自动计算宽高比。
 
 Orthographic Projection
-: 切换摄像机为平视摄像机 (见下文).
+: 设置此项以将摄像机切换到正交投影(见下文)。
 
 Orthographic Zoom
-: (**基于平视摄像机**) - 正交透视倍数 (> 1 = 放大, < 1 = 缩小).
+: (**仅正交摄像机**) - 用于正交投影的缩放(> 1 = 放大,< 1 = 缩小)。
 
 
 ## 使用摄像机
 
-通过调用 `camera.acquire_focus` 函数或者向组件发送 `acquire_camera_focus` 消息, 激活摄像机并填充视口同时向渲染脚本提供映射矩阵:
+所有摄像机都会在帧期间自动启用和更新,并且lua `camera`模块在所有脚本上下文中都可用。自Defold 1.8.1起,不再需要通过向摄像机组件发送`acquire_camera_focus`消息来显式启用摄像机。旧的获取和释放消息仍然可用,但建议改为使用"enable"和"disable"消息,就像您希望启用或禁用的任何其他组件一样:
 
 ```lua
-camera.acquire_focus("#camera")
+msg.post("#camera", "disable")
+msg.post("#camera", "enable")
 ```
-或者
+
+要列出所有当前可用的摄像机,您可以使用camera.get_cameras():
+
+```lua
+-- 注意:渲染调用仅在渲染脚本中可用。
+--       camera.get_cameras()函数可以在任何地方使用,
+--       但render.set_camera只能在渲染脚本中使用。
+
+for k,v in pairs(camera.get_cameras()) do
+    -- 摄像机表包含所有摄像机的URL
+    render.set_camera(v)
+    -- 在这里进行渲染 - 这里渲染的任何使用指定了
+    -- 视图和投影矩阵的材质的内容,都将使用来自摄像机的矩阵。
+end
+-- 要禁用摄像机,将nil(或根本不传递参数)传递给render.set_camera。
+-- 此调用后,所有渲染调用将使用在渲染上下文中指定的
+-- 视图和投影矩阵(render.set_view和render.set_projection)
+render.set_camera()
+```
+
+脚本`camera`模块有多个可用于操作摄像机的函数。这里只是几个可以使用的函数,要查看所有可用函数,请查阅[API文档](/ref/camera/)中的手册。
+
 ```lua
-msg.post("#camera", "acquire_camera_focus")
+camera.get_aspect_ratio(camera) -- 获取宽高比
+camera.get_far_z(camera) -- 获取远z值
+camera.get_fov(camera) -- 获取视野
+camera.set_aspect_ratio(camera, ratio) -- 设置宽高比
+camera.set_far_z(camera, far_z) -- 设置远z值
+camera.set_near_z(camera, near_z) -- 设置近z值
+... 等等
 ```
 
-被激活的摄像机, 会在每一帧向 "@render" 接口发送 `set_view_projection` 消息, 也就是说渲染脚本会接收此消息:
+摄像机通过URL标识,它是组件的完整场景路径,包括集合、它所属的游戏对象和组件ID。在这个例子中,您将使用URL `/go#camera` 来从同一集合中标识摄像机组件,而在从不同集合或渲染脚本访问摄像机时使用 `main:/go#camera`。
+
+![create camera component](images/camera/create.png)
+
+```lua
+-- 从同一集合中的脚本访问摄像机:
+camera.get_fov("/go#camera")
+
+-- 从不同集合中的脚本访问摄像机:
+camera.get_fov("main:/go#camera")
+
+-- 从渲染脚本访问摄像机:
+render.set_camera("main:/go#camera")
+```
+
+每帧,当前具有摄像机焦点的摄像机组件将向"@render"套接字发送`set_view_projection`消息:
 
 ```lua
 -- builtins/render/default.render_script
@@ -72,113 +115,165 @@ function on_message(self, message_id, message)
     end
 end
 ```
-1. 这个消息中包含一个视口矩阵和一个映射矩阵.
+1. 从摄像机组件发布的消息包括一个视图矩阵和一个投影矩阵。
 
-摄像机组件支持基于摄像机属性 *Orthographic Projection* 的, 使用透视或者平视透视矩阵的渲染脚本. 投射矩阵还参考了定义好的远近裁切平面和摄像机的视角及宽高比.
+摄像机组件根据摄像机的*正交投影*属性为渲染脚本提供透视或正交投影矩阵。投影矩阵还考虑了定义的近和远裁剪平面、摄像机的视野和宽高比设置。
 
-摄相机提供的视图矩阵定义了摄相机的位置和方向. *Orthographic Projection* 的摄像机基于其父游戏对象的位置居中视口, 而 *Perspective Projection* 的摄像机会基于其父游戏对象的位置确定视口左下角的位置.
+摄像机提供的视图矩阵定义了摄像机的位置和方向。具有*正交投影*的摄像机将视图居中在它所附加的游戏对象的位置上,而具有*透视投影*的摄像机将视图的左下角定位在它所附加的游戏对象上。
 
-::: important
-出于向后兼容性的原因,默认渲染脚本会忽略相机提供的透视,并始终使用平视透视. 关于渲染脚本, 视口和透视矩阵更多详情参见 [渲染教程](/manuals/render/#default-view-projection).
-:::
 
-可以用以下代码告诉渲染脚本使用摄像机提供的透视:
+### 渲染脚本
+
+从Defold 1.9.6开始,当使用默认渲染脚本时,Defold将自动设置应使用的最后启用的摄像机。在此更改之前,项目中的某个脚本需要显式地向渲染器发送`use_camera_projection`消息,以通知它应使用摄像机组件的视图和投影。这不再必要,但为了向后兼容性,仍然可以这样做。
+
+或者,您可以在渲染脚本中设置应使用的特定摄像机。这在需要更具体控制应使用哪个摄像机进行渲染的情况下可能很有用,例如在多人游戏中。
+
+```lua
+-- render.set_camera将自动使用视图和投影矩阵
+-- 用于任何渲染,直到调用render.set_camera()。
+render.set_camera("main:/my_go#camera")
+```
+
+要检查摄像机是否处于活动状态,您可以使用[摄像机API](https://defold.com/ref/alpha/camera/#camera.get_enabled:camera)中的`get_enabled`函数:
 
 ```lua
-msg.post("@render:", "use_camera_projection")
+if camera.get_enabled("main:/my_go#camera") then
+    -- 摄像机已启用,使用它进行渲染!
+    render.set_camera("main:/my_go#camera")
+end
 ```
 
+::: sidenote
+要将`set_camera`函数与视锥体剔除一起使用,您需要将此作为选项传递给函数:
+`render.set_camera("main:/my_go#camera", {use_frustum = true})`
+:::
 
-### 摄像机平移
+### 平移摄像机
 
-平移摄像机所在游戏对象就相当于平移摄像机. 摄像机会根据当前x和y坐标更新视口矩阵.
+您通过移动摄像机组件所附加到的游戏对象来在世界中平移/移动摄像机。摄像机组件将根据摄像机的当前x和y轴位置自动发送更新的视图矩阵。
 
-### 摄像机缩放
+### 缩放摄像机
 
-延 z 轴移动透视摄像机所在游戏对象就相当于缩放摄像机. 摄像机会根据当前z坐标更新视口矩阵.
+使用透视摄像机时,您可以通过沿z轴移动摄像机所附加到的游戏对象来放大和缩小。摄像机组件将根据摄像机的当前z位置自动发送更新的视图矩阵。
 
-可以通过设置平视摄像机的 *Orthographic Zoom* 属性来进行缩放:
+使用正交摄像机时,您可以通过更改摄像机的*正交缩放*属性来放大和缩小:
 
 ```lua
 go.set("#camera", "orthographic_zoom", 2)
 ```
 
-### 摄像机跟随
+### 自适应缩放
 
-把摄像机对象放在要跟随的游戏对象子级就能实现摄像机跟随:
+自适应缩放背后的概念是当显示分辨率从*game.project*中设置的初始分辨率改变时调整摄像机缩放值。
 
-![follow game object](images/camera/follow.png)
+自适应缩放的两种常见方法是:
 
-或者自己写脚本每帧更新摄像机位置也可以.
+1. 最大缩放 - 计算一个缩放值,使得*game.project*中初始分辨率所覆盖的内容将填充并扩展到屏幕边界之外,可能会隐藏侧面或上方和下方的一些内容。
+2. 最小缩放 - 计算一个缩放值,使得*game.project*中初始分辨率所覆盖的内容将完全包含在屏幕边界内,可能会在侧面或上方和下方显示额外内容。
 
-### 鼠标位置转换为世界坐标
+示例:
 
-摄像机平移缩放后 `on_input()` 函数提供的鼠标位置就不再与世界坐标匹配了. 此时需要进行手动矫正. 把鼠标/屏幕坐标转换到世界坐标的代码如下:
+```lua
+local DISPLAY_WIDTH = sys.get_config_int("display.width")
+local DISPLAY_HEIGHT = sys.get_config_int("display.height")
+
+function init(self)
+    local initial_zoom = go.get("#camera", "orthographic_zoom")
+    local display_scale = window.get_display_scale()
+    window.set_listener(function(self, event, data)
+        if event == window.WINDOW_EVENT_RESIZED then
+            local window_width = data.width
+            local window_height = data.height
+            local design_width = DISPLAY_WIDTH / initial_zoom
+            local design_height = DISPLAY_HEIGHT / initial_zoom
+
+            -- 最大缩放:确保初始设计尺寸将填充并扩展到屏幕边界之外
+            local zoom = math.max(window_width / design_width, window_height / design_height) / display_scale
+
+            -- 最小缩放:确保初始设计尺寸将缩小并包含在屏幕边界内
+            --local zoom = math.min(window_width / design_width, window_height / design_height) / display_scale
+            
+            go.set("#camera", "orthographic_zoom", zoom)
+        end
+    end)
+end
+```
 
-::: sidenote
-[本教程第三方摄像机解决方案部分](/manuals/camera/#第三方摄像机解决方案) 提供了坐标转换方法.
-:::
+自适应缩放的完整示例可以在[此示例项目](https://github.com/defold/sample-adaptive-zoom)中看到。
+
+### 跟随游戏对象
+
+您可以通过将摄像机组件所附加到的游戏对象设置为要跟随的游戏对象的子对象来使摄像机跟随游戏对象:
+
+![follow game object](images/camera/follow.png)
+
+另一种方法是每帧更新摄像机组件所附加到的游戏对象的位置,随着要跟随的游戏对象移动。
+
+### 将鼠标转换为世界坐标
+
+当摄像机已经平移、缩放或将其投影从默认的正交Stretch投影更改时,`on_input()`生命周期函数中提供的鼠标坐标将不再与游戏对象的世界坐标匹配。您需要手动考虑视图或投影的变化。将鼠标/屏幕坐标转换为世界坐标的代码如下:
 
 ```Lua
--- 从屏幕坐标变换到世界坐标
--- @param sx 屏幕 x
--- @param sy 屏幕 y
--- @param sz 屏幕 z
--- @param window_width 窗口宽度 (使用 render.get_width() 或 window.get_size().x)
--- @param window_height 窗口高度 (使用 render.get_height() 或 window.get_size().y)
--- @param projection Camera/render 映射 (使用 go.get("#camera", "projection"))
--- @param view Camera/render 视口 (使用 go.get("#camera", "view"))
--- @return wx 世界 x
--- @return wy 世界 y
--- @return wz 世界 z
-local function screen_to_world(sx, sy, sz, window_width, window_height, projection, view)
-	local inv = vmath.inv(projection * view)
-	sx = (2 * sx / window_width) - 1
-	sy = (2 * sy / window_height) - 1
-	sz = (2 * sz) - 1
-	local wx = sx * inv.m00 + sy * inv.m01 + sz * inv.m02 + inv.m03
-	local wy = sx * inv.m10 + sy * inv.m11 + sz * inv.m12 + inv.m13
-	local wz = sx * inv.m20 + sy * inv.m21 + sz * inv.m22 + inv.m23
-	return wx, wy, wz
+--- 转换屏幕到世界坐标,考虑
+-- 特定摄像机的视图和投影
+-- @param camera 用于转换的摄像机URL
+-- @param screen_x 要转换的屏幕x坐标
+-- @param screen_y 要转换的屏幕y坐标
+-- @param z 可选的z坐标以通过转换,默认为0
+-- @return world_x 屏幕坐标的结果世界x坐标
+-- @return world_y 屏幕坐标的结果世界y坐标
+-- @return world_z 屏幕坐标的结果世界z坐标
+function M.screen_to_world(camera, screen_x, screen_y, z)
+    local projection = go.get(camera, "projection")
+    local view = go.get(camera, "view")
+    local w, h = window.get_size()
+
+    -- https://defold.com/manuals/camera/#converting-mouse-to-world-coordinates
+    local inv = vmath.inv(projection * view)
+    local x = (2 * screen_x / w) - 1
+    local y = (2 * screen_y / h) - 1
+    local x1 = x * inv.m00 + y * inv.m01 + z * inv.m02 + inv.m03
+    local y1 = x * inv.m10 + y * inv.m11 + z * inv.m12 + inv.m13
+    return x1, y1, z or 0
 end
 ```
 
-参见 [示例页面](https://defold.com/examples/render/screen_to_world/) 的屏幕坐标到世界坐标转换实例. 还有一个 [实例项目](https://github.com/defold/sample-screen-to-world-coordinates/) 介绍了屏幕坐标到世界坐标的转换.
+请记住,来自`on_input()`的值`action.screen_x`和`action.screen_y`应该用作此函数的参数。访问[示例页面](https://defold.com/examples/render/screen_to_world/)以查看屏幕到世界坐标转换的实际操作。还有一个[示例项目](https://github.com/defold/sample-screen-to-world-coordinates/)展示了如何进行屏幕到世界坐标的转换。
 
 ::: sidenote
-[本教程使用的第三方摄像机库](/manuals/camera/#third-party-camera-solutions) 提供了自屏幕坐标和到屏幕坐标的转换功能.
+[本手册中提到的第三方摄像机解决方案](/manuals/camera/#third-party-camera-solutions)提供了用于屏幕坐标之间转换的函数。
 :::
 
-## 运行时控制
-可以通过一些消息和属性控制运行时的摄像机 (用法参考 [API 文档](/ref/camera/)).
+## 运行时操作
+您可以通过多种不同的消息和属性在运行时操作摄像机(请参阅[API文档以了解用法](/ref/camera/))。
 
-摄像机的一些属性可以通过 `go.get()` 和 `go.set()` 控制:
+摄像机有许多不同的属性可以使用`go.get()`和`go.set()`进行操作:
 
 `fov`
-: 摄像机视野 (`number`).
+: 摄像机视野(`number`)。
 
 `near_z`
-: 摄像机近端Z值 (`number`).
+: 摄像机近Z值(`number`)。
 
 `far_z`
-: 摄像机远端Z值 (`number`).
+: 摄像机远Z值(`number`)。
 
 `orthographic_zoom`
-: 平视摄像机缩放 (`number`).
+: 正交摄像机缩放(`number`)。
 
 `aspect_ratio`
-: 自从 Defold 1.4.8 加入. 视口宽高比. 在计算透视摄像机投射时使用. (`number`).
+: Defold 1.4.8中添加。视锥体宽度和高度之间的比率。用于计算透视摄像机的投影。(`number`)。
 
 `view`
-: 自从 Defold 1.4.8 加入. 摄像机视口矩阵值. 只读. (`matrix4`).
+: Defold 1.4.8中添加。摄像机的计算视图矩阵。只读。(`matrix4`)。
 
 `projection`
-: 自从 Defold 1.4.8 加入. 摄像机投射矩阵值. 只读. (`matrix4`).
+: Defold 1.4.8中添加。摄像机的计算投影矩阵。只读。(`matrix4`)。
 
 
 ## 第三方摄像机解决方案
 
-社区制作了一些摄像机插件实现了屏幕抖动, 对象跟随, 屏幕与世界坐标转换等摄像机功能. 可以在 Defold 资源大厅找到:
+有社区制作的摄像机解决方案实现了常见功能,如屏幕抖动、跟随游戏对象、屏幕到世界坐标转换等等。它们可以从Defold资产门户下载:
 
-- [Ortographic camera](https://defold.com/assets/orthographic/) (仅 2D) 由 Björn Ritzl 开发.
-- [Defold Rendy](https://defold.com/assets/defold-rendy/) (2D 和 3D) 由 Klayton Kowalski 开发.
+- [正交摄像机](https://defold.com/assets/orthographic/)(仅2D)由Björn Ritzl开发。
+- [Defold Rendy](https://defold.com/assets/defold-rendy/)(2D和3D)由Klayton Kowalski开发。

+ 31 - 31
docs/zh/manuals/collection-factory.md

@@ -1,57 +1,57 @@
 ---
-title: 集合工厂教程
-brief: 本教程介绍了如何使用集合工厂创建一组嵌套的游戏对象.
+title: 集合工厂手册
+brief: 本手册解释了如何使用集合工厂组件来生成游戏对象的层级结构.
 ---
 
 # 集合工厂
 
-集合工厂组件用于在游戏运行时创建一组保存于集合之中的嵌套的游戏对象.
+集合工厂组件用于将存储在集合文件中的游戏对象组和层级结构生成到运行中的游戏中。
 
-Defold 提供了集合或者称为 "prefabs" 的可重用模板机制 . 关于集合概述, 请见 [Defold 组成](/manuals/building-blocks#collections). 使用集合可以在编辑器, 或者在运行时动态插入游戏内容.
+集合提供了一种强大的机制来创建可重用的模板,或称为Defold中的"预制件"。有关集合的概述,请参阅[构建块文档](/manuals/building-blocks#collections)。集合可以放置在编辑器中,也可以动态插入到您的游戏中。
 
-使用集合工厂可以依照一个集合文件向游戏世界插入内容. 这与游戏对象工厂的做法类似只不过集合工厂能创建一组含有父子嵌套层级关系的游戏对象. 典型用法比如动态生成一组敌人 (敌人对象和其武器对象的组合).
+使用集合工厂组件,您可以将集合文件的内容生成到游戏世界中。这类似于对集合内的所有游戏对象执行工厂生成,然后在对象之间构建父子层级关系。一个典型的用例是生成由多个游戏对象组成的敌人(例如,敌人+武器)。
 
-## 创建集合
+## 生成集合
 
-假设有一个角色对象, 在它的子集有个盾牌对象. 我们就可以把这种含嵌套层级关系的组合保存为一个集合文件 "bean.collection".
+假设我们想要一个角色游戏对象和一个单独的盾牌游戏对象作为角色的子对象。我们在一个集合文件中构建游戏对象层级结构,并将其保存为"bean.collection"。
 
 ::: sidenote
-*集合代理* 组件用于创建基于集合的游戏世界, 里面可以包含独立的物理世界. 通过新建一个接口, 集合中的所有内容通过集合代理加载. 这样可以实现诸如切换关卡之类的功能. 游戏世界通常包含很多东西, 如果加载少量内容, 不要使用集合代理. 详情请见 [集合代理教程](/manuals/collection-proxy).
+*集合代理*组件用于基于集合创建新的游戏世界,包括单独的物理世界。新世界通过新的套接字访问。当您向代理发送消息开始加载时,集合中包含的所有资产都通过代理加载。这使得它们对于例如在游戏中切换关卡非常有用。然而,新的游戏世界带来了相当多的开销,因此不要将它们用于少量内容的动态加载。有关更多信息,请参阅[集合代理文档](/manuals/collection-proxy)。
 :::
 
 ![Collection to spawn](images/collection_factory/collection.png)
 
-把 *集合工厂* 加入游戏对象然后设置其 *原型* 为 "bean.collection":
+然后,我们将*集合工厂*添加到一个游戏对象中,该游戏对象将负责生成,并将"bean.collection"设置为组件的*原型*:
 
 ![Collection factory](images/collection_factory/factory.png)
 
-这样只需调用 `collectionfactory.create()` 函数即可创建角色加盾牌的组合了:
+现在,生成bean和shield只需要调用`collectionfactory.create()`函数:
 
 ```lua
 local bean_ids = collectionfactory.create("#bean_factory")
 ```
 
-此函数有5个参数:
+该函数接受5个参数:
 
 `url`
-: 要使用的集合工厂组件的id.
+: 应该生成新游戏对象组的集合工厂组件的id。
 
 `[position]`
-: (可选) 新建游戏对象组合的世界坐标位置. 以 `vector3` 表示. 如果不指定位置, 默认位置是集合工厂所在游戏对象的位置.
+: (可选)生成的游戏对象的世界位置。这应该是一个`vector3`。如果您不指定位置,对象将在集合工厂组件的位置生成。
 
 `[rotation]`
-: (可选) 新创建游戏对象组合的世界坐标旋转. 以 `quat` 表示.
+: (可选)新游戏对象的世界旋转。这应该是一个`quat`。
 
 `[properties]`
-: (可选) 新创建游戏对象组合的 `id`-`table` 属性初始化 Lua 表. 关于此表结果见下文.
+: (可选)一个带有`id`-`table`对的Lua表,用于初始化生成的游戏对象。有关如何构造此表的信息,请参见下文。
 
 `[scale]`
-: (可选) 新创建游戏对象组合的等比缩放. 以 `number` (大于 0) 表示. 或者以 `vector3` 表示每个坐标轴上的非等比缩放.
+: (可选)生成的游戏对象的缩放比例。缩放可以表示为一个`number`(大于0),它指定所有轴上的均匀缩放。您也可以提供一个`vector3`,其中每个组件指定相应轴上的缩放。
 
-`collectionfactory.create()` 返回一个包含每个新建对象id的表. 表的内容是集合内每个对象id对应运行时每个对象id:
+`collectionfactory.create()`将生成的游戏对象的标识作为表返回。表键将每个对象的集合本地id的哈希映射到每个对象的运行时id:
 
 ::: sidenote
-"bean" 与 "shield" 的父子层级关系 *不会* 在表里反应出来. 只能从运行时画面看出这种层级关系, 即做变化时两个对象同时变化. 改变层级关系与游戏对象id无关.
+"bean"和"shield"之间的父子关系*不会*在返回的表中反映出来。这种关系仅存在于运行时场景图中,即对象如何一起变换。重新设置对象的父级永远不会改变其id。
 :::
 
 ```lua
@@ -64,11 +64,11 @@ pprint(bean_ids)
 --   hash: [/bean] = hash: [/collection0/bean],
 -- }
 ```
-1. 前缀 `/collection[N]/` 中, `[N]` 是计数器, 以确保每个id的唯一性:
+1. 添加了前缀`/collection[N]/`,其中`[N]`是一个计数器,以唯一标识每个实例:
 
 ## 属性
 
-创建集合的对象时, 可以把属性表作为参数传给集合工厂. 表里的键是对象id, 值是这个对象需要设置的属性表.
+生成集合时,您可以通过构造一个表来将属性参数传递给每个游戏对象,其中键是对象id,值是包含要设置的脚本属性的表。
 
 ```lua
 local props = {}
@@ -76,7 +76,7 @@ props[hash("/bean")] = { shield = false }
 local ids = collectionfactory.create("#bean_factory", nil, nil, props)
 ```
 
-假设 "bean.collection" 里的 "bean" 对象有一个叫 "shield" 的脚本属性. 关于脚本属性详情请见 [脚本属性教程](/manuals/script-properties).
+假设"bean.collection"中的"bean"游戏对象定义了"shield"属性。[脚本属性手册](/manuals/script-properties)包含有关脚本属性的信息。
 
 ```lua
 -- bean/controller.script
@@ -91,16 +91,16 @@ end
 
 ## 工厂资源的动态加载
 
-开启工厂属性的 *Load Dynamically*, 工厂资源将会被延迟加载.
+通过选中集合工厂属性中的*动态加载*复选框,引擎会推迟与工厂关联的资源的加载。
 
 ![Load dynamically](images/collection_factory/load_dynamically.png)
 
-关闭动态加载, 则加载集合工厂组件时会同时加载其需要的资源以便工厂可以尽快创建新游戏对象.
+取消选中该复选框时,引擎在加载集合工厂组件时加载原型资源,因此它们立即可用于生成。
 
-开启动态加载, 有两种用法:
+选中该复选框时,您有两种使用选项:
 
 同步加载
-: 调用 [`collectionfactory.create()`](/ref/collectionfactory/#collectionfactory.create:url-[position]-[rotation]-[properties]-[scale]) 函数创建新对象时. 资源会同步加载, 这意味着游戏可能会卡一下, 加载完成后再创建新对象.
+: 当您想要生成对象时调用[`collectionfactory.create()`](/ref/collectionfactory/#collectionfactory.create:url-[position]-[rotation]-[properties]-[scale])。这将同步加载资源,这可能会导致卡顿,然后生成新实例。
 
   ```lua
   function init(self)
@@ -123,7 +123,7 @@ end
   ```
 
 异步加载
-: 调用 [`collectionfactory.load()`](/ref/collectionfactory/#collectionfactory.load:[url]-[complete_function]) 函数进行资源的异步加载. 资源加载完毕后, 回调用回调函数.
+: 调用[`collectionfactory.load()`](/ref/collectionfactory/#collectionfactory.load:[url]-[complete_function])以异步方式显式加载资源。当资源准备好生成时,会收到一个回调。
 
   ```lua
   function load_complete(self, url, result)
@@ -150,13 +150,13 @@ end
   ```
 
 
-## 动态 prototype
+## 动态原型
 
-可以通过点选集合工厂的 *Dynamic Prototype* 选项来更改它的 *Prototype*.
+可以通过选中集合工厂属性中的*动态原型*复选框来更改集合工厂可以创建的*原型*。
 
-![动态 prototype](images/collection_factory/dynamic_prototype.png)
+![Dynamic prototype](images/collection_factory/dynamic_prototype.png)
 
-当 *Dynamic Prototype* 选项被选中, 则集合工厂组件就可使用 `collectionfactory.set_prototype()` 函数更改其原型. 例如:
+当*动态原型*选项被选中时,集合工厂组件可以使用`collectionfactory.set_prototype()`函数更改原型。示例:
 
 ```lua
 collectionfactory.unload("#factory") -- 卸载之前的资源
@@ -165,6 +165,6 @@ local ids = collectionfactory.create("#factory")
 ```
 
 ::: important
-当 *Dynamic Prototype* 被选中, 集合组件数优化则不可使用, 宿主集合将使用 *game.project* 文件中定义的默认最大组件数目.
+当设置*动态原型*选项时,集合组件计数无法优化,拥有集合将使用*game.project*文件中的默认组件计数。
 :::
 

+ 71 - 56
docs/zh/manuals/collection-proxy.md

@@ -1,54 +1,54 @@
 ---
-title: 集合代理教程
-brief: 本教程介绍了如何动态创建新游戏世界以及在游戏世界间进行切换.
+title: 集合代理手册
+brief: 本手册解释了如何动态创建新游戏世界以及在游戏世界间进行切换.
 ---
 
 # 集合代理
 
-集合代理组件用于基于集合文件内容动态加载卸载新的游戏 "世界". 可以用来实现切换关卡, GUI 屏幕, 在关卡里加载卸载插播 "场景", 加载卸载迷你游戏等等功能.
+集合代理组件用于基于集合文件内容动态加载和卸载新的游戏"世界"。它们可以用来实现游戏关卡之间的切换、GUI屏幕、在关卡中加载和卸载叙事"场景"、加载/卸载迷你游戏等等。
 
-Defold 把所有游戏对象组织在集合里. 集合可以包含游戏对象和其他集合 (即子集合). 集合代理可以让你把内容拆分到各个集合然后用脚本动态加载卸载这些集合.
+Defold将所有游戏对象组织在集合中。一个集合可以包含游戏对象和其他集合(即子集合)。集合代理允许您将内容拆分为单独的集合,然后通过脚本动态管理这些集合的加载和卸载。
 
-集合代理不像 [集合工厂组件](/manuals/collection-factory/). 集合工厂用于在当前游戏世界创建集合. 集合代理用于运行时创建全新游戏世界, 它们用处不同.
+集合代理与[集合工厂组件](/manuals/collection-factory/)不同。集合工厂将集合的内容实例化到当前游戏世界中。集合代理在运行时创建一个新的游戏世界,因此有不同的用例。
 
 ## 创建集合代理组件
 
-1. 把一个集合代理组件加入到游戏对象上 <kbd>右键点击</kbd> 并从上下文菜单中选择 <kbd>Add Component ▸ Collection Proxy</kbd>.
+1. 通过<kbd>右键点击</kbd>游戏对象并从上下文菜单中选择<kbd>Add Component ▸ Collection Proxy</kbd>,将集合代理组件添加到游戏对象。
 
-2. 设置 *Collection* 属性来引用一个集合, 就是你希望动态加载进运行环境的集合. 这些引用是静态的, 所以确保把游戏所需的各个部分都通过集合引用到.
+2. 将*Collection*属性设置为您希望稍后动态加载到运行时中的集合的引用。该引用是静态的,确保所引用集合的所有内容最终都会出现在游戏中。
 
 ![add proxy component](images/collection-proxy/create_proxy.png)
 
-(也可以编译时排除一部分内容需要的时候用代码下载而不使用 *Exclude* 选项和 [热更新功能](/manuals/live-update/).)
+(您可以通过勾选*Exclude*框并使用[实时更新功能](/manuals/live-update/)在构建中排除内容,然后通过代码下载。)
 
-## 启动集合
+## 引导集合
 
-当 Defold 引擎开始工作最先把 *启动集合* 导入运行环境并对其中的所有游戏对象进行初始化. 然后开启游戏对象和它们的组件. 在 [项目配置](/manuals/project-settings/#Main Collection) 里设置把哪个集合作为启动集合使用. 依照惯例启动集合都叫做 "main.collection".
+当Defold引擎启动时,它会从*引导集合*加载并实例化所有游戏对象到运行时。然后初始化并启用游戏对象及其组件。引擎应该使用哪个引导集合是在[项目设置](/manuals/project-settings/#main-collection)中设置的。按照惯例,这个集合文件通常命名为"main.collection"。
 
 ![bootstrap](images/collection-proxy/bootstrap.png)
 
-启动集合实例化时引擎会为 "游戏世界" 里的游戏对象和组件分配足够的内存空间. 对于物理模拟和碰撞对象, 引擎会为其建立另一个游戏世界.
+为了容纳游戏对象及其组件,引擎为整个"游戏世界"分配所需的内存,引导集合的内容被实例化到这个世界中。还为任何碰撞对象和物理模拟创建了一个单独的物理世界。
 
-因为脚本要能定位任何地方的游戏对象, 包括启动集合之外的集合里的对象, 所以集合必须有独立的属性: *Name*:
+由于脚本组件需要能够处理游戏中的所有对象,即使是来自引导世界之外的对象,它被赋予一个唯一的名称:您在集合文件中设置的*Name*属性:
 
 ![bootstrap](images/collection-proxy/collection_id.png)
 
-如果被加载集合里还有集合代理, 代理引用的集合 *不会* 被自动加载. 需要手动写代码进行加载.
+如果加载的集合包含集合代理组件,那些代理引用的集合*不会*被自动加载。您需要通过脚本控制这些资源的加载。
 
-## 载集合
+## 载集合
 
-通过代理动态载入集合需要用脚本给代理发送 `"load"` 消息:
+通过代理动态加载集合是通过从脚本向代理组件发送名为`"load"`的消息来完成的:
 
 ```lua
--- 让代理 "myproxy" 开始加载集合.
+-- 告诉代理 "myproxy" 开始加载。
 msg.post("#myproxy", "load")
 ```
 
 ![load](images/collection-proxy/proxy_load.png)
 
-集合代理会告诉引擎需要为新游戏世界分配多大空间内存. 另一个物理世界也被建立起来连同集合 "mylevel.collection" 里的游戏对象都会被实例化.
+代理组件将指示引擎为新世界分配空间。还会创建一个单独的运行时物理世界,并且集合`"mylevel.collection"`中的所有游戏对象都被实例化。
 
-新游戏世界的创建通过 *Name* 属性引用的集合文件为蓝图, 本例中是 "mylevel". 不能有重名. 如果集合文件 *Name* 重名, 引擎会报错:
+新世界从集合文件中的*Name*属性获取其名称,在本示例中设置为`"mylevel"`。名称必须是唯一的。如果在集合文件中设置的*Name*已被用于已加载的世界,引擎将发出名称冲突错误:
 
 ```txt
 ERROR:GAMEOBJECT: The collection 'default' could not be created since there is already a socket with the same name.
@@ -56,12 +56,12 @@ WARNING:RESOURCE: Unable to create resource: build/default/mylevel.collectionc
 ERROR:GAMESYS: The collection /mylevel.collectionc could not be loaded.
 ```
 
-当集合加载完毕, 集合代理会向发送 `"load"` 消息的脚本发回 `"proxy_loaded"` 消息. 收到此消息就可以进行集合初始化等工作了:
+当引擎完成加载集合后,集合代理组件将向发送`"load"`消息的脚本发送一个名为`"proxy_loaded"`的消息。然后脚本可以初始化并启用集合作为对该消息的响应:
 
 ```lua
 function on_message(self, message_id, message, sender)
     if message_id == hash("proxy_loaded") then
-        -- 新集合已加载完毕. 初始化并激活它.
+        -- 新世界已加载。初始化并启用它。
         msg.post(sender, "init")
         msg.post(sender, "enable")
         ...
@@ -70,56 +70,71 @@ end
 ```
 
 `"load"`
-: 此消息通知集合代理组件开始为新游戏世界加载集合. 完成后会发送 `"proxy_loaded"` 消息.
+: 此消息告诉集合代理组件开始将其集合加载到新世界中。完成后,代理将发送回一个名为 `"proxy_loaded"` 的消息。
 
 `"async_load"`
-: 此消息通知集合代理组件开始在后台为新游戏世界加载集合. 完成后会发送 `"proxy_loaded"` 消息.
+: 此消息告诉集合代理组件开始在后台将其集合加载到新世界中。完成后,代理将发送回一个名为 `"proxy_loaded"` 的消息。
 
 `"init"`
-: 此消息通知集合代理组件集合里的游戏对象和组件已实例化完毕, 可以进行初始化了. 此时所有脚本里的 `init()` 函数会被调用.
+: 此消息告诉集合代理组件所有已实例化的游戏对象和组件应该被初始化。此时会调用所有脚本的`init()`函数。
 
 `"enable"`
-: 此消息通知集合代理组件集合里的游戏对象和组件已实例化完毕, 可以激活它们了. 此时会进行sprite渲染等等工作.
+: 此消息告诉集合代理组件所有游戏对象和组件应该被启用。例如,所有精灵组件在启用时开始绘制。
 
-## 新游戏世界定位
+## 定位到新世界
 
-使用集合文件的 *Name* 属性用来定位其中的游戏对象和组件. 比如启动集合里有个加载器对象, 一关结束后让它加载下一关:
+在集合文件属性中设置的*Name*用于定位已加载世界中的游戏对象和组件。例如,如果您在引导集合中创建了一个加载器对象,您可能需要从任何已加载的集合中与它通信:
 
 ```lua
--- 告诉加载器加载下一关:
+-- 告诉加载器加载下一关
 msg.post("main:/loader#script", "load_level", { level_id = 2 })
 ```
 
 ![load](images/collection-proxy/message_passing.png)
 
-## 新游戏世界卸载
+如果您需要从加载器与已加载集合中的游戏对象通信,您可以使用[对象的完整URL](/manuals/addressing/#urls)发送消息:
 
-卸载需要发送的消息和加载相反:
+```lua
+msg.post("mylevel:/myobject", "hello")
+```
+
+::: important
+无法从集合外部直接访问已加载集合中的游戏对象:
+
+```lua
+local position = go.get_position("mylevel:/myobject")
+-- loader.script:42: function called can only access instances within the same collection.
+```
+:::
+
+## 卸载世界
+
+要卸载已加载的集合,您发送与加载步骤相反的消息:
 
 ```lua
--- 卸载当前关卡
+-- 卸载关卡
 msg.post("#myproxy", "disable")
 msg.post("#myproxy", "final")
 msg.post("#myproxy", "unload")
 ```
 
 `"disable"`
-: 此消息通知集合代理组件关闭游戏对象和组件. 此时sprite不再进行渲染工作.
+: 此消息告诉集合代理组件禁用世界中的所有游戏对象和组件。精灵在此阶段停止渲染。
 
 `"final"`
-: 此消息通知集合代理组件析构游戏对象和组件. 此时所有脚本里的 `final()` 函数会被调用.
+: 此消息告诉集合代理组件完成世界中的所有游戏对象和组件。此时会调用所有脚本的`final()`函数。
 
 `"unload"`
-: 此消息通知集合代理组件把游戏世界从内存中清除.
+: 此消息告诉集合代理将世界完全从内存中移除。
 
-如果不那么细致, 只发送 `"unload"` 消息就好. 在卸载前代理会自动进行关闭和析构工作.
+如果您不需要更细粒度的控制,可以直接发送`"unload"`消息,而无需先禁用和完成集合。代理将在卸载之前自动禁用并完成集合。
 
-当即和卸载完毕, 集合代理会向发送 `"unload"` 消息的脚本发回 `"proxy_unloaded"` 消息:
+当集合代理完成卸载集合后,它将向发送`"unload"`消息的脚本发送一个`"proxy_unloaded"`消息:
 
 ```lua
 function on_message(self, message_id, message, sender)
     if message_id == hash("proxy_unloaded") then
-        -- Ok, 游戏世界卸载完成...
+        -- 好的,世界已卸载...
         ...
     end
 end
@@ -128,25 +143,25 @@ end
 
 ## 时间步
 
-集合代理的更新周期可以使用 _time step_ 进行缩放. 也就是说即使游戏是 60 FPS 的, 集合代理游戏世界的速度还是可以变得可以更快或者更慢, 收以下几方面影响: 
+集合代理更新可以通过改变_时间步_来进行缩放。这意味着即使游戏以稳定的60 FPS运行,代理也可以以更高或更低的速度更新,影响诸如:
 
-* 物理模拟器步进
-* `update()` 函数里 `dt`
-* [游戏对象和gui属性动画](https://defold.com/manuals/animation/#property-animation-1)
-* [逐帧动画](https://defold.com/manuals/animation/#flip-book-animation)
-* [粒子特效模拟器](https://defold.com/manuals/particlefx/)
-* lua逻辑计时器速度
+* 物理模拟速度
+* 传递给`update()`的`dt`
+* [游戏对象和GUI属性动画](https://defold.com/manuals/animation/#property-animation-1)
+* [翻页动画](https://defold.com/manuals/animation/#flip-book-animation)
+* [粒子FX模拟](https://defold.com/manuals/particlefx/)
+* 计时器速度
 
-还可以设置刷新执行模式, 可以控制游戏刷新是分散的(速度缩放小于1.0有效) 还是连续的.
+您还可以设置更新模式,这允许您控制缩放是否应该离散执行(仅在缩放因子低于1.0时才有意义)或连续执行。
 
-通过发送 `set_time_step` 消息给集合代理组件来设置时间步缩放系数与执行模式:
+您通过向代理发送`set_time_step`消息来控制缩放因子和缩放模式:
 
 ```lua
--- 把加载的游戏世界时间放慢为1/5.
-msg.post("#myproxy", "set_time_step", {factor = 0.2, mode = 1}
+-- 以五分之一速度更新已加载的世界。
+msg.post("#myproxy", "set_time_step", {factor = 0.2, mode = 1})
 ```
 
-这样做的结果, 我们可以通过一段代码来进行观察:
+为了了解更改时间步时发生的情况,我们可以创建一个对象,在其脚本组件中放置以下代码,并将其放在我们正在更改时间步的集合中:
 
 ```lua
 function update(self, dt)
@@ -154,7 +169,7 @@ function update(self, dt)
 end
 ```
 
-时间步系数为 0.2, 控制台打印如下输出:
+时间步为0.2时,我们在控制台中得到以下结果:
 
 ```txt
 INFO:DLIB: SSDP started (ssdp://192.168.0.102:54967, http://0.0.0.0:62162)
@@ -172,21 +187,21 @@ DEBUG:SCRIPT: update() with timestep (dt) 0
 DEBUG:SCRIPT: update() with timestep (dt) 0.016666667535901
 ```
 
-`update()` 仍然是每秒调用 60 次, 但是 `dt` 值变了. 可以看到只有 1/5 (0.2) 的 `update()` 调用包含 1/60 秒的 `dt` 参数, 其他都是 0. 物理模拟也基于 dt 每 5 帧步进一次.
+`update()`仍然每秒调用60次,但`dt`的值发生了变化。我们看到只有1/5(0.2)的`update()`调用会有1/60(对应60 FPS)的`dt`——其余为零。所有物理模拟也将根据该`dt`更新,并且仅在五分之一的帧中前进。
 
 ::: sidenote
-可以使用集合的时间步功能来暂停游戏, 例如弹出窗口或者游戏窗口失去焦点时, 使用 `msg.post("#myproxy", "set_time_step", {factor = 0, mode = 0})` 暂停游戏, 然后使用 `msg.post("#myproxy", "set_time_step", {factor = 1, mode = 1})` 继续游戏.
+您可以使用集合时间步功能来暂停游戏,例如在显示弹出窗口或窗口失去焦点时。使用`msg.post("#myproxy", "set_time_step", {factor = 0, mode = 0})`暂停,使用`msg.post("#myproxy", "set_time_step", {factor = 1, mode = 1})`恢复。
 :::
 
-详情请见 [`set_time_step`](/ref/collectionproxy#set_time_step).
+有关更多详细信息,请参见[`set_time_step`](/ref/collectionproxy#set_time_step)。
 
-## 注意事项常见问题
+## 注意事项常见问题
 
 物理
-: 通过集合代理可以导入多个集合, 或称 *游戏世界*. 要注意的是每个顶级集合都有自己的物理世界. 物理交互 (碰撞, 触发, 射线) 只发生与同一物理世界的物体之间. 所以即使分别来自两个游戏世界的两个物体即使被放在一起, 也不会有碰撞发生.
+: 通过集合代理,可以将多个顶级集合或*游戏世界*加载到引擎中。这样做时,重要的是要知道每个顶级集合都是一个单独的物理世界。物理交互(碰撞、触发、射线投射)只发生在属于同一世界的对象之间。因此,即使来自两个世界的碰撞对象在视觉上恰好彼此重叠,它们之间也不会有任何物理交互。
 
 内存
-: 被载入的游戏世界都要占不少内存. 如果同时加载了很多集合, 推荐优化你的游戏规则. 创建多个游戏对象实例的话, [集合工厂](/manuals/collection-factory) 更加适用.
+: 每个加载的集合都会创建一个新的游戏世界,这带来了相对较大的内存占用。如果您通过代理同时加载几十个集合,您可能需要重新考虑您的设计。要生成游戏对象层级的许多实例,[集合工厂](/manuals/collection-factory)更适合。
 
 输入
-: 要让集合里的游戏对象获得输入信息, 首先要确保集合代理所在的游戏对象获得了输入焦点. 当游戏对象收到输入消息时, 这些消息将传播到该对象的组件也就是集合代理中去. 输入动作通过集合代理下发到其载入的集合里.
+: 如果您在加载的集合中有需要输入操作的对象,您需要确保包含集合代理的游戏对象获取输入。当游戏对象接收到输入消息时,这些消息会传播到该对象的组件,即集合代理。输入操作通过代理发送到加载的集合中。

+ 46 - 47
docs/zh/manuals/components.md

@@ -1,6 +1,6 @@
 ---
 title: 游戏对象组件
-brief: 本教程提供了游戏对象组件概览及其使用方法.
+brief: 本手册提供了组件概览及其使用方法.
 ---
 
 # 组件
@@ -9,99 +9,98 @@ brief: 本教程提供了游戏对象组件概览及其使用方法.
 
 ## 组件类型
 
-Defold 提供以下组件类型:
+Defold 支持以下组件类型:
 
-* [Collection factory](/manuals/collection-factory) - 创建集合实例
-* [Collection proxy](/manuals/collection-proxy) - 加载卸载集合
+* [Collection factory](/manuals/collection-factory) - 生成集合
+* [Collection proxy](/manuals/collection-proxy) - 加载卸载集合
 * [Collision object](/manuals/physics) - 2D 和 3D 物理
-* [Camera](/manuals/camera) - 修改游戏世界的视口和映射
-* [Factory](/manuals/factory) - 创建游戏对象实例
+* [Camera](/manuals/camera) - 更改游戏世界的视口和投影
+* [Factory](/manuals/factory) - 生成游戏对象
 * [GUI](/manuals/gui) - 渲染图形用户界面
-* [Label](/manuals/label) - 渲染文本
-* [Mesh](/manuals/mesh) - 显示3D网格 (同时具有实时创建和维护功能)
-* [Model](/manuals/model) 显示3D模型 (可以带动画)
-* [Particle FX](/manuals/particlefx) -  创建粒子
+* [Label](/manuals/label) - 渲染一段文本
+* [Mesh](/manuals/mesh) - 显示3D网格(具有运行时创建和操作功能)
+* [Model](/manuals/model) - 显示3D模型(带有可选动画)
+* [Particle FX](/manuals/particlefx) - 生成粒子
 * [Script](/manuals/script) - 添加游戏逻辑
-* [Sound](/manuals/sound) - 播放音效音乐
-* [Sprite](/manuals/sprite) - 显示2D图像 (可以带逐帧动画)
-* [Tilemap](/manuals/tilemap) - 显示一组瓷砖图
+* [Sound](/manuals/sound) - 播放声音或音乐
+* [Sprite](/manuals/sprite) - 显示2D图像(带有可选翻页动画)
+* [Tilemap](/manuals/tilemap) - 显示瓦片网格
 
-其他组件可以通过载入扩展插件的方式导入项目:
+可以通过扩展添加其他组件:
 
-* [Rive model](/extension-rive) - 渲染 Rive 动画
-* [Spine model](/extension-spine) - 渲染 Spine 动画
+* [Rive model](/extension-rive) - 渲染Rive动画
+* [Spine model](/extension-spine) - 渲染Spine动画
 
 
-## 开启关闭组件
+## 启用和禁用组件
 
-游戏对象在创建时其组件是开启的. 如果需要关闭组件可以给组件发送 [`disable`](/ref/go/#disable) 消息:
+游戏对象的组件在游戏对象创建时被启用。如果您希望禁用组件,可以通过向组件发送[`disable`](/ref/go/#disable)消息来完成:
 
 ```lua
--- 把此脚本所在的游戏对象上 id 为 'weapon' 的组件关闭
+-- 禁用与此脚本在同一游戏对象上的id为'weapon'的组件
 msg.post("#weapon", "disable")
 
--- 关闭 'enemy' 游戏对象上 id 为 'shield' 的所有组件
+-- 禁用'enemy'游戏对象上id为'shield'的组件
 msg.post("enemy#shield", "disable")
 
--- 关闭当前游戏对象上的所有组件
+-- 禁用当前游戏对象上的所有组件
 msg.post(".", "disable")
 
--- 关闭 'enemy' 游戏对象上的所有组件
+-- 禁用'enemy'游戏对象上的所有组件
 msg.post("enemy", "disable")
 ```
 
-需要开启组件可以给组件发送 [`enable`](/ref/go/#enable) 消息:
+要再次启用组件,您可以向组件发送[`enable`](/ref/go/#enable)消息:
 
 ```lua
--- 开启 id 为 'weapon' 的组件
+-- 启用id为'weapon'的组件
 msg.post("#weapon", "enable")
 ```
 
 ## 组件属性
 
-Defold 组件属性各不相同.在 [Outline 面板](/manuals/editor/#Outline 面板) 中当前选中的组件属性会显示在编辑器的 [Properties 面板](/manuals/editor/#Properties 面板) 中. 可用组件的详细属性详情请见API教程.
+Defold组件类型都有不同的属性。编辑器中的[属性面板](/manuals/editor/#the-editor-views)将显示[大纲面板](/manuals/editor/#the-editor-views)中当前选定组件的属性。请参考不同组件类型的手册以了解有关可用组件属性的更多信息。
 
-## 位置, 旋转和缩放
+## 组件位置、旋转和缩放
 
-可视组件通常含有位置, 旋转以及缩放属性. 这些属性可以在编辑器里修改但是绝大多数情况下不能在运行时修改 (sprite 和 label 的缩放属性是例外情况).
+可视组件通常具有位置和旋转属性,大多数情况下还具有缩放属性。这些属性可以从编辑器中更改,并且在几乎所有情况下都不能在运行时更改(唯一的例外是精灵和标签组件缩放,可以在运行时更改)。
 
-如果需要在运行时修改组件的而不是组件所在游戏对象的位置, 旋转和缩放. 有个副作用就是游戏对象所有组件都会受影响. 如果你想维护游戏对象上的一个组件而不是多个, 建议将该组件移入另一个游戏对象并作为原来那个游戏对象的子对象.
+如果您需要在运行时更改组件的位置、旋转或缩放,您可以修改组件所属游戏对象的位置、旋转或缩放。这会产生副作用,即游戏对象上的所有组件都会受到影响。如果您希望只操作附加到游戏对象的多个组件中的一个,建议将相关组件移动到单独的游戏对象,并作为该组件原本所属的游戏对象的子游戏对象添加。
 
-## 组件渲染顺序
+## 组件绘制顺序
 
-可视组件的渲染顺序取决于两个方面:
+可视组件的绘制顺序取决于两个方面:
 
-### 渲染脚本的渲染优先级
-每个组件都有 [材质](/manuals/material/) 而且每个材质都有一个或多个标签. 渲染脚本依次定义一系列优先级, 每个优先级匹配一个或多个材质标签. 渲染脚本在 *update()* 函数里 [按优先级依次渲染](/manuals/render/#渲染优先级) , 匹配优先级标签的组件会被显示出来. 默认渲染脚本先绘制 sprites 和 tilemaps, 再渲染粒子特效, 二者都使用世界坐标系. 最后渲染脚本会在屏幕坐标系中渲染 GUI 组件.
+### 渲染脚本谓词
+每个组件都被分配一个[材质](/manuals/material/),每个材质有一个或多个标签。渲染脚本反过来定义多个谓词,每个谓词匹配一个或多个材质标签。渲染脚本[谓词在渲染脚本的*update()*函数中逐个绘制](/manuals/render/#render-predicates),匹配每个谓词中定义的标签的组件将被绘制。默认渲染脚本首先在一个通道中绘制精灵和瓦片地图,然后在另一个通道中绘制粒子效果,两者都在世界空间中。然后渲染脚本将继续在屏幕空间中的单独通道中绘制GUI组件。
 
 ### 组件z值
-所有游戏对象都使用一个 vector3 作为其在 3D 空间中的位置. 如果是 2D 游戏, 则 X 和 Y 表示其在 "横向" 和 "纵向" 轴上的位置, 而 Z 值表示其在 "深度" 轴上的位置. 使用Z值可以操控游戏对象之间的层叠关系: Z 值是 1 的总是显示在 Z 值是 0 的对象上面. 默认情况下, Defold 使用 Z 值范围是 -1 到 1:
+所有游戏对象和组件都使用vector3对象表示的位置定位在3D空间中。当您以2D查看游戏的图形内容时,X和Y值确定对象在"宽度"和"高度"轴上的位置,而Z位置确定对象在"深度"轴上的位置。Z位置允许您控制重叠对象的可见性:Z值为1的精灵将出现在Z位置0的精灵前面。默认情况下,Defold使用允许Z值在-1和1之间的坐标系:
 
 ![model](images/graphics/z-order.png)
 
-匹配某个优先级的组件在一起渲染, 它们之间的渲染顺序取决于组件的 z 值. 组件的最终z值是由组件的z值, 游戏对象和其父级游戏对象的z值之和.
+匹配[渲染谓词](/manuals/render/#render-predicates)的组件一起绘制,它们绘制的顺序取决于组件的最终z值。组件的最终z值是组件本身的z值、它所属的游戏对象的z值以及任何父游戏对象的z值之和。
 
 ::: sidenote
-各个 GUI 组件的渲染顺序 **不是** 由 GUI 组件的z值决定的. GUI 组件的渲染顺序由 [gui.set_render_order()](/ref/gui/#gui.set_render_order:order) 函数控制.
+多个GUI组件的绘制顺序**不是**由GUI组件的z值决定的。GUI组件绘制顺序由[gui.set_render_order()](/ref/gui/#gui.set_render_order:order)函数控制。
 :::
 
-例如: 两个游戏对象 A 和 B. B 是 A 的子集. B 有一个sprite组件.
+示例:两个游戏对象A和B。B是A的子对象。B有一个精灵组件。
 
-| 元素      | z值     |
-|----------|---------|
-| A        | 2       |
-| B        | 1       |
-| B#sprite | 0.5     |
+| 内容     | Z值 |
+|----------|-----|
+| A        | 2   |
+| B        | 1   |
+| B#sprite | 0.5 |
 
 ![](images/graphics/component-hierarchy.png)
 
-在上述定义中 B 的sprite组件最终z值是 2 + 1 + 0.5 = 3.5.
+使用上述层次结构,B上精灵组件的最终z值为2 + 1 + 0.5 = 3.5。
 
-::: sidenote
-如果两个组件 z 值相同则可能造成两个组件来回穿梭闪烁或者不同平台顺序不同的结果.
+::: important
+如果两个组件具有完全相同的z值,则顺序是未定义的,您可能会遇到组件来回闪烁或组件在一个平台上以一种顺序渲染而在另一个平台上以另一种顺序渲染的情况。
 
-渲染脚本为 z 值定义了极近端和极远端平面. z值在此范围之外的组件不会被渲染. 默认范围是 -1 到 1 但是 [可以任意修改](/manuals/render/#默认视口映射).
-Z 值得极近与极远坐标范围是 -1 到 1 的话, 需要很高的数值精度. 在处理 3D 资源时, 可能需要在你的自定义渲染脚本中修改极近和极远的坐标范围. 详情请见 [渲染教程](/manuals/render/).
+渲染脚本为z值定义了近裁剪面和远裁剪面。任何z值超出此范围的组件都不会被渲染。默认范围是-1到1,但[可以轻松更改](/manuals/render/#default-view-projection)。当近和远限制为-1和1时,Z值的数值精度非常高。在处理3D资源时,您可能需要在自定义渲染脚本中更改默认投影的近和远限制。有关更多信息,请参见[渲染手册](/manuals/render/)。
 :::
 
-:[组件最大数配置](../shared/component-max-count-optimizations.md)
+:[组件最大数量优化](../shared/component-max-count-optimizations.md)

+ 234 - 0
docs/zh/manuals/compute.md

@@ -0,0 +1,234 @@
+---
+title: Defold 计算着色器手册
+brief: 本手册解释了如何使用计算程序、着色器常量和采样器。
+---
+
+# 计算程序
+
+::: sidenote
+Defold 中的计算着色器支持目前处于*技术预览*状态。
+这意味着某些功能尚不完善,并且 API 将来可能会发生变化。
+:::
+
+计算着色器是在 GPU 上执行通用计算的强大工具。它们允许您利用 GPU 的并行处理能力来执行物理模拟、图像处理等任务。计算着色器对存储在缓冲区或纹理中的数据进行操作,在许多 GPU 线程上并行执行操作。这种并行性使得计算着色器在密集计算方面非常强大。
+
+* 有关渲染管线的更多信息,请参阅[渲染文档](/manuals/render)。
+* 有关着色器程序的深入解释,请参阅[着色器文档](/manuals/shader)。
+
+## 我可以用计算着色器做什么?
+
+由于计算着色器旨在用于通用计算,因此您可以用它们做的事情实际上没有限制。以下是计算着色器通常用于的一些示例:
+
+图像处理
+  - 图像过滤:应用模糊、边缘检测、锐化滤镜等。
+  - 色彩分级:调整图像的色彩空间。
+
+物理
+  - 粒子系统:模拟大量粒子以产生烟雾、火焰和流体动力学等效果。
+  - 软体物理:模拟可变形物体,如布料和果冻。
+  - 剔除:遮挡剔除、视锥体剔除
+
+程序化生成
+  - 地形生成:使用噪声函数创建详细地形。
+  - 植被和树叶:创建程序化生成的植物和树木。
+
+渲染效果
+  - 全局光照:通过模拟光线在场景中反弹的方式来模拟逼真的照明。
+  - 体素化:从网格数据创建 3D 体素网格。
+
+## 计算着色器是如何工作的?
+
+在高层次上,计算着色器通过将一个任务划分为许多可以同时执行的小任务来工作。这是通过`工作组`和`调用`的概念实现的:
+
+工作组
+: 计算着色器在`工作组`的网格上运行。每个工作组包含固定数量的调用(或线程)。工作组的大小和调用的数量在着色器代码中定义。
+
+调用
+: 每个调用(或线程)执行计算着色器程序。工作组内的调用可以通过共享内存共享数据,允许它们之间进行有效的通信和同步。
+
+GPU 通过在多个工作组上并行启动许多调用来执行计算着色器,为适合的任务提供强大的计算能力。
+
+## 创建计算程序
+
+要创建计算程序,在*资源*浏览器中<kbd>右键单击</kbd>目标文件夹,然后选择<kbd>新建... ▸ 计算</kbd>。(您也可以从菜单中选择<kbd>文件 ▸ 新建...</kbd>,然后选择<kbd>计算</kbd>)。命名新的计算文件并按<kbd>确定</kbd>。
+
+![计算文件](images/compute/compute_file.png)
+
+新的计算将在*计算编辑器*中打开。
+
+![计算编辑器](images/compute/compute.png)
+
+计算文件包含以下信息:
+
+计算程序
+: 要使用的计算着色器程序文件(*`.cp`*)。该着色器操作"抽象工作项",这意味着输入和输出数据类型没有固定定义。程序员需要定义计算着色器应该产生什么。
+
+常量
+: 将传递给计算着色器程序的统一变量。有关可用常量的列表,请参见下文。
+
+采样器
+: 您可以选择在材质文件中配置特定的采样器。添加采样器,根据着色器程序中使用的名称命名它,并根据您的喜好设置包装和过滤设置。
+
+
+## 在 Defold 中使用计算程序
+
+与材质不同,计算程序不分配给任何组件,也不属于正常渲染流程的一部分。计算程序必须在渲染脚本中`调度`才能执行任何工作。然而,在调度之前,您需要确保渲染脚本有对计算程序的引用。目前,渲染脚本了解计算程序的唯一方法是将其添加到包含对渲染脚本引用的 .render 文件中:
+
+![计算渲染文件](images/compute/compute_render_file.png)
+
+要使用计算程序,首先需要将其绑定到渲染上下文。这与材质的绑定方式相同:
+
+```lua
+render.set_compute("my_compute")
+-- 在此处执行计算工作,调用 render.set_compute() 解除绑定
+render.set_compute()
+```
+
+虽然计算常量将在程序调度时自动应用,但无法从编辑器中将任何输入或输出资源(纹理、缓冲区等)绑定到计算程序。相反,这必须通过渲染脚本完成:
+
+```lua
+render.enable_texture("blur_render_target", "tex_blur")
+render.enable_texture(self.storage_texture, "tex_storage")
+```
+
+要在您决定的工作空间中运行程序,您需要调度该程序:
+
+```lua
+render.dispatch_compute(128, 128, 1)
+-- dispatch_compute 也接受一个选项表作为最后一个参数
+-- 您可以使用此参数表将渲染常量传递给调度调用
+local constants = render.constant_buffer()
+constants.tint = vmath.vector4(1, 1, 1, 1)
+render.dispatch_compute(32, 32, 32, {constants = constants})
+```
+
+### 从计算程序写入数据
+
+目前,从计算程序生成任何类型的输出只能通过`存储纹理`完成。存储纹理类似于"常规纹理",只是它们支持更多功能和可配置性。顾名思义,存储纹理可以用作通用缓冲区,您可以从计算程序中读取和写入数据。然后,您可以将同一缓冲区绑定到不同的着色器程序以进行读取。
+
+要在 Defold 中创建存储纹理,您需要从常规的 .script 文件执行此操作。渲染脚本没有此功能,因为动态纹理需要通过仅在常规 .script 文件中可用的资源 API 创建。
+
+```lua
+-- 在 .script 文件中:
+function init(self)
+    -- 像往常一样创建纹理资源,但添加"storage"标志
+    -- 以便它可以用作计算程序的后备存储
+    local t_backing = resource.create_texture("/my_backing_texture.texturec", {
+        type   = resource.TEXTURE_TYPE_IMAGE_2D,
+        width  = 128,
+        height = 128,
+        format = resource.TEXTURE_FORMAT_RGBA32F,
+        flags  = resource.TEXTURE_USAGE_FLAG_STORAGE + resource.TEXTURE_USAGE_FLAG_SAMPLE,
+    })
+
+    -- 从资源中获取纹理句柄
+    local t_backing_handle = resource.get_texture_info(t_backing).handle
+
+    -- 通知渲染器有关后备纹理的信息,以便它可以通过 render.enable_texture 绑定
+    msg.post("@render:", "set_backing_texture", { handle = t_backing_handle })
+end
+```
+
+## 将所有内容整合在一起
+
+### 着色器程序
+
+```glsl
+// compute.cp
+#version 450
+
+layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+
+// 指定输入资源
+uniform vec4 color;
+uniform sampler2D texture_in;
+
+// 指定输出图像
+layout(rgba32f) uniform image2D texture_out;
+
+void main()
+{
+    // 这不是一个特别有趣的着色器,但它演示了
+    // 如何从纹理和常量缓冲区读取并写入存储纹理
+
+    ivec2 tex_coord   = ivec2(gl_GlobalInvocationID.xy);
+    vec4 output_value = vec4(0.0, 0.0, 0.0, 1.0);
+    vec2 tex_coord_uv = vec2(float(tex_coord.x)/(gl_NumWorkGroups.x), float(tex_coord.y)/(gl_NumWorkGroups.y));
+    vec4 input_value = texture(texture_in, tex_coord_uv);
+    output_value.rgb = input_value.rgb * color.rgb;
+
+    // 将输出值写入存储纹理
+    imageStore(texture_out, tex_coord, output_value);
+}
+```
+
+### 脚本组件
+```lua
+-- 在 .script 文件中
+
+-- 这里我们指定稍后将绑定到
+-- 计算程序的输入纹理。我们可以将此纹理分配给模型组件,
+-- 或在渲染脚本中将其启用到渲染上下文。
+go.property("texture_in", resource.texture())
+
+function init(self)
+    -- 像往常一样创建纹理资源,但添加"storage"标志
+    -- 以便它可以用作计算程序的后备存储
+    local t_backing = resource.create_texture("/my_backing_texture.texturec", {
+        type   = resource.TEXTURE_TYPE_IMAGE_2D,
+        width  = 128,
+        height = 128,
+        format = resource.TEXTURE_FORMAT_RGBA32F,
+        flags  = resource.TEXTURE_USAGE_FLAG_STORAGE + resource.TEXTURE_USAGE_FLAG_SAMPLE,
+    })
+
+    local textures = {
+        texture_in = resource.get_texture_info(self.texture_in).handle,
+        texture_out = resource.get_texture_info(t_backing).handle
+    }
+
+    -- 通知渲染器有关输入和输出纹理的信息
+    msg.post("@render:", "set_backing_texture", textures)
+end
+```
+
+### 渲染脚本
+```lua
+-- 响应消息"set_backing_texture"
+-- 为计算程序设置后备纹理
+function on_message(self, message_id, message)
+    if message_id == hash("set_backing_texture") then
+        self.texture_in = message.texture_in
+        self.texture_out = message.texture_out
+    end
+end
+
+function update(self)
+    render.set_compute("compute")
+    -- 我们可以将纹理绑定到特定的命名常量
+    render.enable_texture(self.texture_in, "texture_in")
+    render.enable_texture(self.texture_out, "texture_out")
+    render.set_constant("color", vmath.vector4(0.5, 0.5, 0.5, 1.0))
+    -- 调度计算程序的次数与我们拥有的像素数一样多。
+    -- 这构成了我们的"工作组"。着色器将被调用
+    -- 128 x 128 x 1 次,或每个像素一次。
+    render.dispatch_compute(128, 128, 1)
+    -- 当我们完成计算程序后,需要解除绑定
+    render.set_compute()
+end
+```
+
+## 兼容性
+
+Defold 目前支持以下图形适配器中的计算着色器:
+
+- Vulkan
+- Metal(通过 MoltenVK)
+- OpenGL 4.3+
+- OpenGL ES 3.1+
+
+::: sidenote
+目前无法检查运行中的客户端是否支持计算着色器。
+这意味着如果图形适配器是基于 OpenGL 或 OpenGL ES 的,则无法保证客户端支持运行计算着色器。
+Vulkan 和 Metal 从 1.0 版本开始支持计算着色器。要使用 Vulkan,您需要创建自定义清单并选择 Vulkan 作为后端。
+:::

+ 33 - 30
docs/zh/manuals/debugging-game-and-system-logs.md

@@ -1,59 +1,59 @@
 ---
 title: 调试 - 游戏和系统日志
-brief: 本教程介绍了获取游戏和系统日志的方法.
+brief: 本手册解释了如何读取游戏和系统日志。
 ---
 
 # 游戏和系统日志
 
-游戏日志保存了引擎的所有输出, 包括原生扩展和脚本代码上的输出. 用 [print()](/ref/stable/base/#print:...) 和 [pprint()](/ref/stable/builtins/?q=pprint#pprint:v) 函数就能在日志里留下游戏输出. 可以使用原生扩展 [dmLog](/ref/stable/dmLog/) 下的函数读写日志文件. 各种文本阅读编辑器都能打开日志文件.
+游戏日志显示了引擎、原生扩展和游戏逻辑的所有输出。您可以从脚本和Lua模块中使用[print()](/ref/stable/base/#print:...)和[pprint()](/ref/stable/builtins/?q=pprint#pprint:v)命令在游戏日志中显示信息。您可以使用[`dmLog`命名空间](/ref/stable/dmLog/)中的函数从原生扩展写入游戏日志。游戏日志可以从编辑器、终端窗口、使用平台特定工具或从日志文件中读取。
 
-系统日志是由操作系统提供的, 也许会对调试游戏有所帮助. 系统日志可以记录应用崩溃时的调用堆栈和内存不足等信息.
+系统日志由操作系统生成,它可以提供帮助您定位问题的附加信息。系统日志可以包含崩溃的堆栈跟踪和低内存警告。
 
-::: sidenote
-游戏日志只会在 debug 模式的编译版本中出现. 发布版本会去掉所有日志输出.
+::: important
+游戏日志只会在调试构建中显示信息。在发布构建中,日志将完全为空。
 :::
 
-## 用编辑器查看游戏日志
+## 从编辑器读取游戏日志
 
-当在编辑器本地或者连接了 [mobile 开发版应用](/manuals/dev-app) 运行游戏时, 所有日志输出都能做编辑器控制台看到:
+当您从编辑器本地运行游戏或连接到[移动开发应用](/manuals/dev-app)时,所有输出将显示在编辑器的控制台窗格中:
 
 ![Editor 2](images/editor/editor2_overview.png)
 
-## 用控制台查看游戏日志
+## 从终端读取游戏日志
 
-当使用控制台启动游戏时, 日志文件也会打印在当前控制台上. 在 Windows 和 Linux 控制台上直接打游戏可执行文件名即可. 在 macOS 控制台上要打 .app 文件里面的游戏引擎名:
+当您从终端运行Defold游戏时,日志将显示在终端窗口本身中。在Windows和Linux上,您在终端中键入可执行文件的名称来启动游戏。在macOS上,您需要从.app文件内启动引擎:
 
 ```
-$ > ./mygame.app/Contenst/MacOS/mygame
+$ > ./mygame.app/Contents/MacOS/mygame
 ```
 
-## 不同平台的日志读取
+## 使用平台特定工具读取游戏和系统日志
 
 ### HTML5
 
-绝大多数浏览器都提供了显示日志输出的控制台.
+可以使用大多数浏览器提供的开发者工具读取日志。
 
 * [Chrome](https://developers.google.com/web/tools/chrome-devtools/console) - 菜单 > 更多工具 > 开发者工具
-* [Firefox](https://developer.mozilla.org/en-US/docs/Tools/Browser_Console) - 工具 > 网络开发者 > 网络控制台
+* [Firefox](https://developer.mozilla.org/en-US/docs/Tools/Browser_Console) - 工具 > Web开发者 > Web控制台
 * [Edge](https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide/console)
 * [Safari](https://support.apple.com/guide/safari-developer/log-messages-with-the-console-dev4e7dedc90/mac) - 开发 > 显示JavaScript控制台
 
 ### Android
 
-可以使用 Android Debug Bridge (ADB) 工具来查看游戏和系统日志.
+您可以使用Android调试桥(ADB)工具查看游戏和系统日志。
 
 :[Android ADB](../shared/android-adb.md)
 
-  工具安装好之后, 通过 USB 连接你的设备, 启动控制台, 输入:
+安装并设置好后,通过USB连接设备,打开终端并运行:
 
 ```txt
 $ cd <path_to_android_sdk>/platform-tools/
 $ adb logcat
 ```
 
-设备会把所有日志信息打印在当前控制台上, 包含游戏输出信息.
+设备随后会将所有输出转储到当前终端,以及来自游戏的任何打印信息。
 
-要想只查看 Defold 输出的日志信息, 可以这么输入:
+如果您只想查看Defold应用程序输出,请使用此命令:
 
 ```txt
 $ cd <path_to_android_sdk>/platform-tools/
@@ -63,7 +63,7 @@ $ adb logcat -s defold
 I/defold  ( 6210): INFO:DLIB: SSDP started (ssdp://192.168.0.97:58089, http://0.0.0.0:38637)
 I/defold  ( 6210): INFO:ENGINE: Defold Engine 1.2.50 (8d1b912)
 I/defold  ( 6210): INFO:ENGINE: Loading data from:
-I/defold  ( 6210): INFO:ENGINE: Initialised sound device 'default'
+I/defold  ( 6210): INFO:ENGINE: Initialized sound device 'default'
 I/defold  ( 6210):
 D/defold  ( 6210): DEBUG:SCRIPT: Hello there, log!
 ...
@@ -71,33 +71,36 @@ D/defold  ( 6210): DEBUG:SCRIPT: Hello there, log!
 
 ### iOS
 
-可以使用 [控制台工具](https://support.apple.com/guide/console/welcome/mac) 读取游戏和系统日志. 可以使用 LLDB 调试器连接设备上运行的游戏. 调试前确保设备上存有该应用的 “Apple Developer Provisioning Profile”. 从编辑器的打包对话框那里提供档案文件 (只能在 macOS 平台上打包 iOS 应用).
+您有多种选择可以在iOS上读取游戏和系统日志:
 
-需要一个叫做 [ios-deploy](https://github.com/phonegap/ios-deploy) 的工具才能进行调试. 命令如下:
+1. 您可以使用[控制台工具](https://support.apple.com/guide/console/welcome/mac)读取游戏和系统日志。
+2. 您可以使用LLDB调试器附加到设备上运行的游戏。要调试游戏,它需要使用包含您要调试的设备的"Apple Developer Provisioning Profile"进行签名。从编辑器打包游戏,并在打包对话框中提供配置文件(iOS打包仅在macOS上可用)。
+
+要启动游戏并附加调试器,您需要一个名为[ios-deploy](https://github.com/phonegap/ios-deploy)的工具。通过在终端中运行以下命令来安装和调试您的游戏:
 
 ```txt
-ios-deploy --debug --bundle <path_to_game.app> # 注意: 不是 .ipa 文件
+$ ios-deploy --debug --bundle <path_to_game.app> # 注意: 不是 .ipa 文件
 ```
 
-它会把应用安装到设备上, 启动应用并且把 LLDB 调试器连接到应用上. 如果不熟悉 LLDB, 请参考 [LLDB 基础教程](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/gdb_to_lldb_transition_guide/document/lldb-basics.html).
+这将在您的设备上安装应用程序,启动它并自动将LLDB调试器附加到它。如果您是LLDB的新手,请阅读[LLDB入门](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/gdb_to_lldb_transition_guide/document/lldb-basics.html)
 
 
-## 从日志文件读取日志信息
+## 从日志文件读取游戏日志
 
-如果你在 *game.project* 文件里打开了 *Write Log* 项, 所有游戏输出都会被记录到硬盘上, 保存为 "`log.txt`" 文件. 下面介绍了从设备上获取日志文件的方法:
+如果您在*game.project*中启用*Write Log*设置,任何游戏输出都将写入磁盘,到一个名为"`log.txt`"的文件中。以下是在设备上运行游戏时如何提取文件的方法:
 
 iOS
-: 把设备连接到安装有 macOS 和 Xcode 的电脑上.
+: 将设备连接到安装了macOS和Xcode的计算机上。
 
-  启动 Xcode 选择 <kbd>Window ▸ Devices and Simulators</kbd>.
+  打开Xcode并转到<kbd>Window ▸ Devices and Simulators</kbd>。
 
-  在列表中选择你的设备, 然后在 *Installed Apps* 列表中选择你的游戏应用.
+  在列表中选择您的设备,然后在*Installed Apps*列表中选择相关的应用程序。
 
-  点击列表下方的齿轮图标选择 <kbd>Download Container...</kbd>.
+  单击列表下方的齿轮图标并选择<kbd>Download Container...</kbd>。
 
   ![download container](images/debugging/download_container.png)
 
-  容器被下载解压之后就可以在 *Finder* 中看到了. 右键单击容器选择 <kbd>Show Package Content</kbd>. 找到 "`log.txt`", 一般位于 "`AppData/Documents/`".
+  容器提取后,它将显示在*Finder*中。右键单击容器并选择<kbd>Show Package Content</kbd>。找到文件"`log.txt`",它应该位于"`AppData/Documents/`"中。
 
 Android
-: "`log.txt`" 的获取取决于操作系统版本和制造商. 这里有一个简单的 [步骤教程](https://stackoverflow.com/a/48077004/129360).
+: 提取"`log.txt`"的能力取决于操作系统版本和制造商。这里有一个简短的简单的[逐步指南](https://stackoverflow.com/a/48077004/]129360)。

+ 48 - 48
docs/zh/manuals/debugging-game-logic.md

@@ -1,139 +1,139 @@
 ---
 title: Defold 中的调试
-brief: 本教程介绍了 Defold 中自带的调试功能.
+brief: 本手册解释了 Defold 中提供的调试功能。
 ---
 
 # 调试游戏逻辑
 
-Defold 内置集成式 Lua 调试器及检视工具. 加上内置的 [分析工具](/manuals/profiling) 构成强大工具集帮你快速找到逻辑错误和性能问题.
+Defold 包含一个带有检查功能的集成 Lua 调试器。与内置的[分析工具](/manuals/profiling)一起,它是一个强大的工具,可以帮助您找到游戏逻辑中错误的原因或帮助分析性能问题。
 
-## 打印输出与可视调试
+## 打印和可视化调试
 
-Defold 最基础的调试功能是 [控制台打印输出](http://en.wikipedia.org/wiki/Debugging#Techniques). 使用 `print()` 或 [`pprint()`](/ref/builtins#pprint) 来检查变量值或者逻辑流程. 如果有个游戏对象不正常, 只需要将包含调试代码的脚本组件拖上去就行了. 打印输出函数会把信息发送到编辑器的 *控制台* 与 [游戏日志](/manuals/debugging-game-and-system-logs) 中.
+在 Defold 中调试游戏的最简单方法是使用[打印调试](http://en.wikipedia.org/wiki/Debugging#Techniques)。使用 `print()` 或 [`pprint()`](/ref/builtins#pprint) 语句来观察变量或指示执行流程。如果一个没有脚本的游戏对象表现异常,您可以只附加一个脚本,其唯一目的是调试。使用任何打印函数都会在编辑器的*控制台*视图和[游戏日志](/manuals/debugging-game-and-system-logs)中打印。
 
-更进一步来说, 引擎有绘制调试信息的功能, 可以显示文字和画线. 用此功能需要向 `@render` 接口发送消息:
+除了打印之外,引擎还可以在屏幕上绘制调试文本和直线。这是通过向 `@render` 套接字发布消息来完成的:
 
 ```lua
--- 把变量 "my_val" 画在屏幕上
+-- 在屏幕上用调试文本绘制 "my_val" 的值
 msg.post("@render:", "draw_text", { text = "My value: " .. my_val, position = vmath.vector3(200, 200, 0) })
 
--- 画出带颜色的文字
+-- 在屏幕上绘制彩色文本
 local color_green = vmath.vector4(0, 1, 0, 1)
 msg.post("@render:", "draw_debug_text", { text = "Custom color", position = vmath.vector3(200, 180, 0), color = color_green })
 
--- 在主角和敌人之间画一条线
+-- 在屏幕上绘制玩家和敌人之间的调试线
 local start_p = go.get_position("player")
 local end_p = go.get_position("enemy")
 local color_red = vmath.vector4(1, 0, 0, 1)
 msg.post("@render:", "draw_line", { start_point = start_p, end_point = end_p, color = color_red })
 ```
 
-调试绘制与普通的渲染处于同一个渲染管线之上.
+可视化调试消息向渲染管线添加数据,并作为常规渲染管线的一部分进行绘制。
 
-* `"draw_line"` 实际是是使用渲染脚本的 `render.draw_debug3d()` 函数进行绘制的.
-* `"draw_text"` 使用的是 `/builtins/fonts/debug/always_on_top.font` 字体和 `/builtins/fonts/debug/always_on_top_font.material` 材质.
-* `"draw_debug_text"` 与 `"draw_text"` 类似, 只是可以自定义文字颜色.
+* `"draw_line"` 添加使用渲染脚本中的 `render.draw_debug3d()` 函数渲染的数据。
+* `"draw_text"` 使用 `/builtins/fonts/debug/always_on_top.font` 字体渲染,该字体使用 `/builtins/fonts/debug/always_on_top_font.material` 材质。
+* `"draw_debug_text"` 与 `"draw_text"` 相同,但它以自定义颜色渲染。
 
-注意一般调试信息都需要实时更新所以把它们放在 `update()` 函数中是个好主意.
+请注意,您可能希望每帧更新此数据,因此在 `update()` 函数中发布这些消息是个好主意。
 
-## Running the debugger
+## 运行调试器
 
-一种办法是通过 <kbd>Debug ▸ Run with Debugger</kbd> 运行游戏并且自动接入调试器, 另一种是通过 <kbd>Debug ▸ Attach Debugger</kbd> 把调试器接入正在运行中的游戏上.
+要运行调试器,选择 <kbd>Debug ▸ Start/Attach</kbd>,这将以附加的调试器启动游戏或将调试器附加到已经运行的游戏上。
 
 ![overview](images/debugging/overview.png)
 
-调试器接入后, 就可以使用控制台上的调试控制按钮, 或者使用 <kbd>Debug</kbd> 菜单了:
+一旦调试器附加,您就可以通过控制台中的调试器控制按钮或通过 <kbd>Debug</kbd> 菜单控制游戏的执行:
 
 Break
 : ![pause](images/debugging/pause.svg){width=60px .left}
-  立即断下游戏. 游戏于此点暂停. 此时可以观察游戏状态, 逐步运行, 或者运行到下一个断点. 断点会在代码编辑器上标识出来:
+  立即中断游戏执行。游戏将在其当前点中断。您现在可以检查游戏状态,逐步推进游戏,或继续运行直到下一个断点。当前执行点在代码编辑器中标记:
 
   ![script](images/debugging/script.png)
 
 Continue
 : ![play](images/debugging/play.svg){width=60px .left}
-  继续运行游戏. 直到按下暂停键或者遇到断点. 如果遇到断点停下, 运行点会在代码编辑器的断点标识之上标识出来:
+  继续运行游戏。游戏代码将继续运行,直到您按下暂停或执行遇到您设置的断点。如果执行在设置的断点处中断,则执行点在代码编辑器中断点标记上方标记:
 
   ![break](images/debugging/break.png)
 
 Stop
 : ![stop](images/debugging/stop.svg){width=60px .left}
-  停止调试. 立即停止调试, 断开调试器, 关闭游戏.
+  停止调试器。按下此按钮将立即停止调试器,将其从游戏中断开并终止正在运行的游戏。
 
 Step Over
 : ![step over](images/debugging/step_over.svg){width=60px .left}
-  步越. 步进时如果运行到某个 Lua 函数, 步越 _不会进入这个函数_ 而是执行它然后停在函数下一行上. 图中, 如果用户按下 "step over", 调试器会执行代码直至调用 `nextspawn()` 函数下面的 `end` 位置处:
+  将程序执行推进一个步骤。如果执行涉及运行另一个 Lua 函数,执行_不会进入该函数_,而是继续运行并停止在函数调用下方的下一行。在此示例中,如果用户按下"step over",调试器将执行代码并停止在调用 `nextspawn()` 函数的行下方的 `end` 语句处:
 
   ![step](images/debugging/step.png)
 
 ::: sidenote
-一行Lua代码不一定就是一句Lua表达式. 调试器按表达式步进, 也就是说有可能出现一行多个表达式的情况就要多按几下步进才会运行到下一行.
+一行 Lua 代码并不对应单个表达式。在调试器中步进是一次推进一个表达式,这意味着目前您可能需要多次按下步进按钮才能推进到下一行。
 :::
 
 Step Into
 : ![step in](images/debugging/step_in.svg){width=60px .left}
-  步入. 步进时如果运行到某个 Lua 函数, 步入 _会进入这个函数_. 一个函数调用会在调用堆栈上增加一项. 可以在堆栈列表上点选来查看各函数入口及其所有变量信息. 图中, 用户步入了 `nextspawn()` 函数:
+  将程序执行推进一个步骤。如果执行涉及运行另一个 Lua 函数,执行_将进入该函数_。调用该函数会在调用堆栈中添加一个条目。您可以单击调用堆栈列表中的每个条目来查看该闭包中的入口点和所有变量的内容。在这里,用户已经进入了 `nextspawn()` 函数:
 
   ![step into](images/debugging/step_into.png)
 
 Step Out
 : ![step out](images/debugging/step_out.svg){width=60px .left}
-  步出. 运行游戏直到函数出口. 如果步入了一个函数, 按 "step out" 按钮能运行代码到函数返回位置.
+  继续执行直到从当前函数返回。如果您已经将执行步入一个函数,按下"step out"按钮将继续执行直到函数返回。
 
-设置/清除断点
-: 可以在代码中随意设置断点. 接入调试器的游戏运行时, 会在断点处暂停, 等待你的下一步交互.
+设置清除断点
+: 您可以在 Lua 代码中设置任意数量的断点。当游戏在附加了调试器的情况下运行时,它将在遇到的下一个断点处停止执行,并等待您的进一步交互。
 
   ![add breakpoint](images/debugging/add_breakpoint.png)
 
-  设置/清除断点, 可以在代码编辑器里行号右边右键点击. 还可以从菜单中选择 <kbd>Edit ▸ Toggle Breakpoint</kbd>.
+  要设置或清除断点,请在代码编辑器中行号右侧的列中单击。您也可以从菜单中选择 <kbd>Edit ▸ Toggle Breakpoint</kbd>。
 
 设置条件断点
-: 可以设置需要计算条件为真才触发的断点. 条件可以读取随着代码执行当前行的本地变量.
+: 您可以将断点配置为包含需要评估为 true 才能触发断点的条件。该条件可以访问代码执行期间在该行可用的局部变量。
 
   ![edit breakpoint](images/debugging/edit_breakpoint.png)
 
-  要编辑断电条件, 右键点击代码编辑器行号的右边的列, 或者从菜单栏点选 <kbd>Edit ▸ Edit Breakpoint</kbd>.
+  要编辑断点条件,请在代码编辑器中行号右侧的列中右键单击,或从菜单中选择 <kbd>Edit ▸ Edit Breakpoint</kbd>。
 
-执行Lua表达式
-: 调试器停在断点上时, 可以直接使用包含有当前上下文的 Lua 运行时. 在控制台底部输入表达式后按 <kbd>回车键</kbd> 来运行:
+评估 Lua 表达式
+: 在调试器附加且游戏在断点处停止的情况下,可以使用带有当前上下文的 Lua 运行时。在控制台底部键入 Lua 表达式并按 <kbd>Enter</kbd> 来评估它们:
 
   ![console](images/debugging/console.png)
 
-  目前不支持用表达式来修改变量.
+  目前无法通过评估器修改变量。
 
-断开调试器
-: 通过选择 <kbd>Debug ▸ Detach Debugger</kbd> 可以把调试器从游戏上断开. 游戏会继续运行.
+分离调试器
+: 选择 <kbd>Debug ▸ Detach Debugger</kbd> 将调试器从游戏中分离。它将立即继续运行。
 
 ## Lua 调试库
 
-Lua 包含一个有用的调试库, 帮你查看 Lua 环境的底层. 详情请见: http://www.lua.org/pil/contents.html#23.
+Lua 附带一个在某些情况下有用的调试库,特别是如果您需要检查 Lua 环境的内部。您可以在 [Lua 手册中关于调试库的章节](http://www.lua.org/pil/contents.html#23) 中找到更多相关信息。
 
-## 调试步骤
+## 调试检查清单
 
-如果发现错误或者bug, 建议进行如下调试:
+如果您遇到错误或您的游戏行为不符合预期,这里有一个调试检查清单:
 
-1. 检查控制台看看输出什么报错没有.
+1. 检查控制台输出并验证没有运行时错误。
 
-2. 在适当地方加入 `print` 语句证明这段代码运行到了没有.
+2. 向代码中添加 `print` 语句以验证代码确实在运行。
 
-3. 看看编辑器各种设置是否配置正确. 代码加到游戏对象上了吗? 输入得到焦点了吗? 输入消息监听对了吗? 材质上有着色程序吗? 等等.
+3. 如果代码没有运行,请检查您是否已在编辑器中完成了代码运行所需的正确设置。脚本是否添加到正确的游戏对象?您的脚本是否获取了输入焦点?输入触发器是否正确?着色器代码是否添加到材质?等等。
 
-4. 如果某些代码取决于变量的值 (比如if语句), 使用 `print` 或者调试器看看那些变量值对不对.
+4. 如果您的代码依赖于变量的值(例如在 if 语句中),要么在使用或检查这些变量的位置 `print` 这些值,要么使用调试器检查它们。
 
-有的 bug 藏得很深, 调试起来很费时, 需要一丝一丝地捋, 逐步缩小可能出错的范围最终消灭错误源头. 这种情况下建议使用 "二分法":
+有时查找错误可能是一个困难和耗时的过程,需要您逐位检查代码,检查所有内容并缩小有问题的代码范围并消除错误源。这最好通过称为"分而治之"的方法来完成:
 
-1. 线确定哪一半代码一定包含着错误.
-2. 继续二分二分, 缩小范围.
-3. 最终找到并消灭错误.
+1. 确定哪一半(或更少)的代码必须包含错误。
+2. 再次确定那一半中的哪一半必须包含错误。
+3. 继续缩小必须导致错误的代码范围,直到找到它为止。
 
-祝你调试愉快!
+祝您调试愉快!
 
-## 物理引擎调试
+## 调试物理问题
 
-如果使用物理系统过程中发现错误请开启物理调试. 在 *game.project* 文件的 *Physics* 部分, 勾选 *Debug* 项:
+如果您在物理方面遇到问题,碰撞没有按预期工作,建议启用物理调试。在 *game.project* 文件的 *Physics* 部分中勾选 *Debug* 复选框:
 
 ![physics debug setting](images/debugging/physics_debug_setting.png)
 
-这样 Defold 就会把所有物理形状和碰撞接触点绘制到屏幕上:
+当此复选框启用时,Defold 将绘制所有碰撞形状和碰撞接触点:
 
 ![physics debug visualisation](images/debugging/physics_debug_visualisation.png)

+ 27 - 24
docs/zh/manuals/debugging-native-code-android.md

@@ -1,20 +1,20 @@
 ---
 title: Android 平台调试
-brief: 本教程介绍了在使用 Android Studio 调试游戏的方法.
+brief: 本手册描述了如何使用 Android Studio 调试构建版本。
 ---
 
 # Android 平台调试
 
-下面介绍了如何使用 [Android Studio](https://developer.android.com/studio/), 即 Google 的 Android 操作系统的官方 IDE, 来调试游戏的方法.
+这里我们描述如何使用 [Android Studio](https://developer.android.com/studio/)(Google 的 Android 操作系统的官方 IDE)来调试构建版本。
 
 
 ## Android Studio
 
-* 在 *game.project* 中设置 `android.debuggable`
+* 通过在 *game.project* 中设置 `android.debuggable` 选项来准备捆绑包
 
 	![android.debuggable](images/extensions/debugging/android/game_project_debuggable.png)
 
-* 在 debug 模式下打包游戏
+* 在调试模式下将应用程序捆绑到您选择的文件夹中
 
 	![bundle_android](images/extensions/debugging/android/bundle_android.png)
 
@@ -24,60 +24,63 @@ brief: 本教程介绍了在使用 Android Studio 调试游戏的方法.
 
 	![debug_apk](images/extensions/debugging/android/android_profile_or_debug.png)
 
-* 选择刚刚输出的apk文件
+* 选择您刚刚创建的 apk 捆绑包
 
 	![select_apk](images/extensions/debugging/android/android_select_apk.png)
 
-* 选择主 `.so` 文件, 确保里面含有调试信息
+* 选择主要的 `.so` 文件,并确保它具有调试符号
 
 	![select_so](images/extensions/debugging/android/android_missing_symbols.png)
 
-* 没有的话可以上传完整 `.so` 文件. (文件大约 20mb)
+* 如果没有,上传一个未剥离的 `.so` 文件。(大小约为 20mb)
 
-* 路径映射帮助建立从编译 (在云端) 到本地文件夹的文件对应关系.
+* 路径映射帮助您重新映射从可执行文件构建位置(在云端)到本地驱动器上的实际文件夹的各个路径。
 
-* 选择 .so 文件, 添加路径映射
+* 选择 .so 文件,然后向您的本地驱动器添加映射
 
 	![path_mapping1](images/extensions/debugging/android/path_mappings_android.png)
 
 	![path_mapping2](images/extensions/debugging/android/path_mappings_android2.png)
 
-* 要是动过引擎源码, 也要对引擎代码添加路径映射
+* 如果您有权访问引擎源代码,也为其添加路径映射。
 
-* 注意一定要获取与你所用版本完全一致的引擎版本
+* 确保检出您当前正在调试的版本
 
 	defold$ git checkout 1.2.148
 
-* 点击 `Apply changes`
+*  `Apply changes`
 
-* 这时路径映射已经生效
+* 您现在应该在项目中看到映射的源代码
 
 	![source](images/extensions/debugging/android/source_mappings_android.png)
 
-* 加断点
+* 加断点
 
 	![breakpoint](images/extensions/debugging/android/breakpoint_android.png)
 
-* 点击 `Run` -> `Debug "Appname"` 然后运行断点处的程序
+* 按 `Run` -> `Debug "Appname"` 并调用您打算中断进入的代码
 
 	![breakpoint](images/extensions/debugging/android/callstack_variables_android.png)
 
-* 步进可用, 变量和调用堆栈一目了然
+* 您现在可以在调用堆栈中步进以及检查变量
 
 
-## 注意
+## 注意事项
 
-### 原生扩展 job 文件夹
+### 原生扩展作业文件夹
 
-目前, 开发流程有点麻烦. 因为job文件夹名是随机的, 每次编译都不一样.
+目前,工作流程对开发来说有点麻烦。这是因为作业文件夹名称对于每个构建都是随机的,使得每次构建的路径映射都无效。
 
-但是还是有办法使用的.
+然而,它对于调试会话工作得很好。
 
-路径映射保存于 Android Studio 项目的 <project>.iml 文件中.
+路径映射存储在 Android Studio 项目的项目 `.iml` 文件中。
 
-运行下列命令就能得到job文件夹名
+可以从可执行文件获取作业文件夹
 
-	$ arm-linux-androideabi-readelf --string-dump=.debug_str build/armv7-android/libdmengine.so | grep /job
+```sh
+$ arm-linux-androideabi-readelf --string-dump=.debug_str build/armv7-android/libdmengine.so | grep /job
+```
+
+作业文件夹的命名类似于 `job1298751322870374150`,每次都有不同的随机数。
 
-类似 `job1298751322870374150` 这样的名字, 后面的数字每次编译都不相同.
 

+ 71 - 52
docs/zh/manuals/debugging-native-code-ios.md

@@ -1,136 +1,155 @@
 ---
 title: 在 iOS/macOS 中调试
-brief: 本教程介绍了如何使用 Xcode 进行调试.
+brief: 本手册描述了如何使用 Xcode 调试构建版本。
 ---
 
 # 在 iOS/macOS 中调试
 
-这里我们介绍如何使用 [Xcode](https://developer.apple.com/Xcode/), Apple的 macOS 和 iOS 首选开发环境来调试应用.
+这里我们描述如何使用 [Xcode](https://developer.apple.com/xcode/)(Apple 的 macOS 和 iOS 首选 IDE)来调试构建版本。
 
 ## Xcode
 
-* 使用 bob, 加上 `--with-symbols` 选项打包应用 ([更多详情](/manuals/debugging-native-code/#symbolicate-a-callstack)):
+* 使用 bob,通过 `--with-symbols` 选项打包应用 ([更多信息](/manuals/debugging-native-code/#symbolicate-a-callstack)):
 
-		$ cd myproject
-		$ wget http://d.defold.com/archive/<sha1>/bob/bob.jar
-		$ java -jar bob.jar --platform armv7-darwin build --with-symbols --variant debug --archive bundle -bo build/ios -mp <app>.mobileprovision --identity "iPhone Developer: Your Name (ID)"
+```sh
+$ cd myproject
+$ wget http://d.defold.com/archive/<sha1>/bob/bob.jar
+$ java -jar bob.jar --platform armv7-darwin build --with-symbols --variant debug --archive bundle -bo build/ios -mp <app>.mobileprovision --identity "iPhone Developer: Your Name (ID)"
+```
 
-* 安装应用, 可以通过 `Xcode`, `iTunes` 或者 [ios-deploy](https://github.com/ios-control/ios-deploy)
+* 安装应用,可以通过 `Xcode`、`iTunes` 或 [ios-deploy](https://github.com/ios-control/ios-deploy)
 
-		$ ios-deploy -b <AppName>.ipa
+```sh
+$ ios-deploy -b <AppName>.ipa
+```
 
-* 得到 `.dSYM` 文件夹 (即调试 symbols)
+* 获取 `.dSYM` 文件夹(即调试符号)
 
-	* 如果没使用原生扩展, 可以从 [d.defold.com](http://d.defold.com) 下载 `.dSYM` 文件
+	* 如果没有使用原生扩展,可以从 [d.defold.com](http://d.defold.com) 下载 `.dSYM` 文件
 
-	* 如果使用了原生扩展, 可以使用 [bob.jar](https://www.defold.com/manuals/bob/) 生成 `.dSYM` 文件夹. 只需要 building (不需要 archive 和 bundling):
+	* 如果您正在使用原生扩展,那么在使用 [bob.jar](https://www.defold.com/manuals/bob/) 构建时会生成 `.dSYM` 文件夹。只需要构建(不需要打包或捆绑):
 
-			$ cd myproject
-			$ unzip .internal/cache/arm64-ios/build.zip
-			$ mv dmengine.dSYM <AppName>.dSYM
-			$ mv <AppName>.dSYM/Contents/Resources/DWARF/dmengine <AppName>.dSYM/Contents/Resources/DWARF/<AppName>
+```sh
+$ cd myproject
+$ unzip .internal/cache/arm64-ios/build.zip
+$ mv dmengine.dSYM <AppName>.dSYM
+$ mv <AppName>.dSYM/Contents/Resources/DWARF/dmengine <AppName>.dSYM/Contents/Resources/DWARF/<AppName>
+```
 
 
 ### 创建项目
 
-要正确的调试, 我们需要一个项目, 以及一个代码映射(source map).
-这次项目不是用来编译的, 只是调试举例.
+要正确调试,我们需要有一个项目和映射的源代码。
+我们不是使用这个项目来构建东西,只是用于调试。
 
-*新建 Xcode 项目, 选择 `Game` 模板
+* 创建新的 Xcode 项目,选择 `Game` 模板
 
 	![project_template](images/extensions/debugging/ios/project_template.png)
 
-* 指定一个名字 (例如 `debug`) 并且使用默认设置
+* 选择一个名称(例如 `debug`)和默认设置
 
-* 选择一个存项目的目录
+* 选择一个文件夹来保存项目
 
-* 为应用加入代码文件
+* 将您的代码添加到应用中
 
 	![add_files](images/extensions/debugging/ios/add_files.png)
 
-* 确保 "Copy items if needed" 未选中.
+* 确保 "Copy items if needed" 未被选中。
 
 	![add_source](images/extensions/debugging/ios/add_source.png)
 
-* 结果是这样
+* 这是最终结果
 
 	![added_source](images/extensions/debugging/ios/added_source.png)
 
 
-* 关闭 `Build` 步骤
+* 禁用 `Build` 步骤
 
 	![edit_scheme](images/extensions/debugging/ios/edit_scheme.png)
 
 	![disable_build](images/extensions/debugging/ios/disable_build.png)
 
-* 设置 `Deployment target` 版本
+* 设置 `Deployment target` 版本,使其大于您设备的 iOS 版本
 
 	![deployment_version](images/extensions/debugging/ios/deployment_version.png)
 
-* 设置目标设备
+* 选择目标设备
 
 	![select_device](images/extensions/debugging/ios/select_device.png)
 
 
 ### 启动调试器
 
-调试应用有如下方法
+您有几种选项来调试应用
 
-1. 可以使用 `Debug` -> `Attach to process...` 然后选择要调试应用
+1. 选择 `Debug` -> `Attach to process...` 并从那里选择应用
 
-1. 也可以选择 `Attach to process by PID or Process name`
+2. 或者选择 `Attach to process by PID or Process name`
 
 	![select_device](images/extensions/debugging/ios/attach_to_process_name.png)
 
-1. 从设备上启动应用
+3. 在设备上启动应用
 
-1. 在 `Edit Scheme` 中加入 <AppName>.app 作为可运行文件夹
+4. 在 `Edit Scheme` 中将 <AppName>.app 文件夹添加为可执行文件
 
-### 调试 symbols
+### 调试符号
 
-**要使用 lldb, 运行必须先暂停**
+**要使用 lldb,执行必须暂停**
 
-* 把 `.dSYM` 目录加入到 lldb 中
+* 将 `.dSYM` 路径添加到 lldb
 
-		(lldb) add-dsym <PathTo.dSYM>
+```
+(lldb) add-dsym <PathTo.dSYM>
+```
 
 	![add_dsym](images/extensions/debugging/ios/add_dsym.png)
 
-* 确认 `lldb` 成功读取 symbols
+* 验证 `lldb` 是否成功读取了符号
 
-		(lldb) image list <AppName>
+```
+(lldb) image list <AppName>
+```
 
 ### 路径映射
 
-* 加入引擎路径 (根据你的安装目录自行调整)
+* 添加引擎源代码(根据您的需求进行相应更改)
 
-		(lldb) settings set target.source-map /Users/builder/ci/builds/engine-ios-64-master/build /Users/mathiaswesterdahl/work/defold
-		(lldb) settings append target.source-map /private/var/folders/m5/bcw7ykhd6vq9lwjzq1mkp8j00000gn/T/job4836347589046353012/upload/videoplayer/src /Users/mathiaswesterdahl/work/projects/extension-videoplayer-native/videoplayer/src
+```
+(lldb) settings set target.source-map /Users/builder/ci/builds/engine-ios-64-master/build /Users/mathiaswesterdahl/work/defold
+(lldb) settings append target.source-map /private/var/folders/m5/bcw7ykhd6vq9lwjzq1mkp8j00000gn/T/job4836347589046353012/upload/videoplayer/src /Users/mathiaswesterdahl/work/projects/extension-videoplayer-native/videoplayer/src
+```
 
-	* 从可运行文件夹里可以得到 job 文件夹.
-	job 文件夹命名类似这样 `job1298751322870374150`, 每次都是随机数字.
+* 可以从可执行文件获取作业文件夹。作业文件夹命名为 `job1298751322870374150`,每次都有随机数。
 
-			$ dsymutil -dump-debug-map <executable> 2>&1 >/dev/null | grep /job
+```sh
+$ dsymutil -dump-debug-map <executable> 2>&1 >/dev/null | grep /job
+```
 
-* 验证路径映射
+* 验证源代码映射
 
-		(lldb) settings show target.source-map
+```
+(lldb) settings show target.source-map
+```
 
-可以使用如下命令确定 symbol 的源代码文件
+您可以使用以下命令检查符号源自哪个源文件
 
-	(lldb) image lookup -va <SymbolName>
+```
+(lldb) image lookup -va <SymbolName>
+```
 
 
 ### 断点
 
-* 从 project 视图打开一个文件, 然后设置断点
+* 在项目视图中打开一个文件,并设置断点
 
 	![breakpoint](images/extensions/debugging/ios/breakpoint.png)
 
-## 注意
+## 注意事项
 
-### 检查二进制文件 UUID
+### 检查二进制文件 UUID
 
-为了让调试器接受 `.dSYM` 文件夹, UUID 需要与可运行文件的 UUID 相匹配. 你可以这样检查 UUID:
+为了让调试器接受 `.dSYM` 文件夹,UUID 需要与正在调试的可执行文件的 UUID 匹配。您可以像这样检查 UUID:
 
-	$ dwarfdump -u <PathToBinary>
+```sh
+$ dwarfdump -u <PathToBinary>
+```

+ 68 - 52
docs/zh/manuals/debugging-native-code.md

@@ -1,23 +1,23 @@
 ---
 title: Defold 中的原生代码调试
-brief: 本教程介绍了在 Defold 中调试原生代码的方法.
+brief: 本手册解释了如何在 Defold 中调试原生代码。
 ---
 
 # 原生代码调试
 
-Defold 几经测试鲜有崩溃情况出现. 但是崩溃这种事谁能保证永远避免, 尤其是游戏中还使用了原生扩展代码的情况下. 要是游戏崩溃或者原生代码出错请从下面几方面入手检查:
+Defold 经过充分测试,在正常情况下应该很少崩溃。然而,无法保证它永远不会崩溃,特别是当您的游戏使用原生扩展时。如果您遇到崩溃或原生代码行为不符合预期的问题,有几种不同的解决方法:
 
-* 使用调试器调试代码
-* 使用 print 函数检查代码
+* 使用调试器逐步执行代码
+* 使用打印调试
 * 分析崩溃日志
-* 调用堆栈代码文件映射
+* 符号化调用堆栈
 
 
 ## 使用调试器
 
-首先推荐使用 `调试器`. 使用它步进代码, 设置 `断点` 最重要的是游戏崩溃时会自动暂停.
+最常见的方法是通过 `调试器` 运行代码。它允许您逐步执行代码,设置 `断点`,如果发生崩溃,它将停止执行。
 
-不同平台调试器有很多.
+每个平台都有几种调试器。
 
 * Visual studio - Windows
 * VSCode - Windows, macOS, Linux
@@ -27,39 +27,39 @@ Defold 几经测试鲜有崩溃情况出现. 但是崩溃这种事谁能保证
 * lldb / gdb - macOS, Linux, (Windows)
 * ios-deploy - macOS
 
-每个工具可以调试的应用如下:
+每个工具可以调试特定平台:
 
-* Visual studio - Windows + platforms supporting gdbserver (比如 Linux/Android)
-* VSCode - Windows, macOS (lldb), Linux (lldb/gdb) + platforms supporting gdbserver
-* Xcode -  macOS, iOS ([详见](/manuals/debugging-native-code-ios))
-* Android Studio - Android ([详见](/manuals/debugging-native-code-android))
+* Visual studio - Windows + 支持 gdbserver 的平台(例如 Linux/Android)
+* VSCode - Windows, macOS (lldb), Linux (lldb/gdb) + 支持 gdbserver 的平台
+* Xcode -  macOS, iOS ([了解更多](/manuals/debugging-native-code-ios))
+* Android Studio - Android ([了解更多](/manuals/debugging-native-code-android))
 * WinDBG - Windows
 * lldb/gdb - macOS, Linux, (iOS)
-* ios-deploy - iOS (via lldb)
+* ios-deploy - iOS (通过 lldb)
 
 
-## 使用 print 函数
+## 使用打印调试
 
-调试最简单的方法就是使用 [print 函数](http://en.wikipedia.org/wiki/Debugging#Techniques). 位于 [dmLog 命名空间](/ref/stable/dmLog/) 下的 print 函数可以用来检查变量值或者用来检查程序执行流程. 它可以在 *控制台* 视图和 [游戏日志](/manuals/debugging-game-and-system-logs) 中输出数据.
+调试原生代码的最简单方法是使用 [打印调试](http://en.wikipedia.org/wiki/Debugging#Techniques)。使用 [`dmLog` 命名空间](/ref/stable/dmLog/) 中的函数来观察变量或指示执行流程。使用任何日志函数都会在编辑器的 *控制台* 视图和 [游戏日志](/manuals/debugging-game-and-system-logs) 中打印输出。
 
 
-## 崩溃日志分析
+## 分析崩溃日志
 
-崩溃时, Defold 引擎保存了一个 `_crash` 日志文件. 其中包含了系统信息与崩溃信息. 其存放位置参考 [游戏日志输出](/manuals/debugging-game-and-system-logs) (不同设备, 系统, 位置不同).
+如果 Defold 引擎发生硬崩溃,它会保存一个 `_crash` 文件。崩溃文件将包含有关系统以及崩溃的信息。[游戏日志输出](/manuals/debugging-game-and-system-logs) 将写入崩溃文件所在的位置(它根据操作系统、设备和应用程序而变化)。
 
-可以使用 [崩溃模块](https://www.defold.com/ref/crash/) 帮助分析这个文件. 推荐你阅读, 收集信息, 打印信息到控制台, 然后把信息发送到 [第三方分析服务](/tags/stars/analytics/) 上去.
+可以使用 [崩溃模块](https://www.defold.com/ref/crash/) 在后续会话中读取此文件。建议您读取文件,收集信息,将其打印到控制台,然后将其发送到支持收集崩溃日志的 [分析服务](/tags/stars/analytics/)。
 
 ::: important
-在 Windows 上还有个 `_crash.dmp` 文件被创建. 这个文件在调试崩溃时很有用.
+在 Windows 上,还会生成一个 `_crash.dmp` 文件。此文件在调试崩溃时很有用。
 :::
 
-### 从设备获取崩溃日志
+### 从设备获取崩溃日志
 
-手机上的崩溃日志可以下载到本地以便查看.
+如果崩溃发生在移动设备上,您可以选择将崩溃文件下载到您自己的计算机并在本地解析它。
 
 #### Android
 
-如果应用是 [可调式的](/manuals/project-settings/#Android), 就可以使用 [Android Debug Bridge (ADB) 工具](https://developer.android.com/studio/command-line/adb.html) 和 `adb shell` 命令得到崩溃日志:
+如果应用是 [可调试的](/manuals/project-settings/#android),您可以使用 [Android Debug Bridge (ADB) 工具](https://developer.android.com/studio/command-line/adb.html) 和 `adb shell` 命令获取崩溃日志:
 
 ```
 $ adb shell "run-as com.defold.example sh -c 'cat /data/data/com.defold.example/files/_crash'" > ./_crash
@@ -67,80 +67,96 @@ $ adb shell "run-as com.defold.example sh -c 'cat /data/data/com.defold.example/
 
 #### iOS
 
-在 iTunes 里, 可以下载 app 容器.
+在 iTunes 中,您可以查看/下载应用程序容器。
 
-在 `Xcode -> Devices` 窗口中也能获取到崩溃日志.
+在 `Xcode -> Devices` 窗口中,您也可以选择崩溃日志。
 
 
-## 调用堆栈代码文件映射
+## 符号化调用堆栈
 
-从 `_crash` 文件或 [日志文件](/manuals/debugging-game-and-system-logs), 都可以进行代码文件映射. 即把调用堆栈里的每个地址映射到文件名和代码行, 利于寻找代码的问题.
+如果您从 `_crash` 文件或 [日志文件](/manuals/debugging-game-and-system-logs) 获取调用堆栈,您可以对其进行符号化。这意味着将调用堆栈中的每个地址转换为文件名和行号,这反过来有助于找出根本原因。
 
-注意引擎版本要选择正确. 不然映射会错乱. 使用 [bob](https://www.defold.com/manuals/bob/) 编译时命令行加入 [--with-symbols](https://www.defold.com/manuals/bob/) 或者在编辑器打包对话框里点选 "Generate debug symbols":
+重要的是,您必须将正确的引擎与调用堆栈匹配,否则很可能会让您调试错误的内容!使用 [`--with-symbols`](https://www.defold.com/manuals/bob/) 标志与 [bob](https://www.defold.com/manuals/bob/) 捆绑,或者从编辑器的捆绑对话框中选中 "Generate debug symbols" 复选框:
 
-* iOS - 在 `build/arm64-ios` 下的 `dmengine.dSYM.zip` 中包含有 iOS 编译用 debug symbols.
-* macOS - 在 `build/x86_64-macos` 下的 `dmengine.dSYM.zip` 中包含有 macOS 编译用 debug symbols.
-* Android - 在打包输出目录 `projecttitle.apk.symbols/lib/` 下包含有各架构编译用 debug symbols.
-* Linux - 可执行文件本身包含 debug symbols.
-* Windows - 在 `build/x86_64-win32` 下的 `dmengine.pdb` 中包含有 Windows 编译用 debug symbols.
-* HTML5 - 在 `build/js-web` 或 `build/wasm-web` 下的 `dmengine.js.symbols` 中包含有 HTML5 编译用 debug symbols.
+* iOS - `build/arm64-ios` 中的 `dmengine.dSYM.zip` 文件夹包含 iOS 构建的调试符号。
+* macOS - `build/x86_64-macos` 中的 `dmengine.dSYM.zip` 文件夹包含 macOS 构建的调试符号。
+* Android - `projecttitle.apk.symbols/lib/` 捆绑输出文件夹包含目标架构的调试符号。
+* Linux - 可执行文件包含调试符号。
+* Windows - `build/x86_64-win32` 中的 `dmengine.pdb` 文件包含 Windows 构建的调试符号。
+* HTML5 - `build/js-web` 或 `build/wasm-web` 中的 `dmengine.js.symbols` 文件包含 HTML5 构建的调试符号。
 
 
 ::: important
-对于游戏的每个发布版本一定要保留一套对应的调试数据. 不然的话原生扩展上线以后出错误就没法调试! 为了方便查看调用堆栈, 也要保存好对应的游戏引擎.
+非常重要的一点是,您必须为您发布的每个公共版本保存调试符号,并且您知道调试符号属于哪个版本。如果您没有调试符号,您将无法调试任何原生崩溃!此外,您应该保留引擎的未剥离版本。这样可以最好地对调用堆栈进行符号化。
 :::
 
 
-### 把 symbols 上传到 Google Play
-可以 [上传 debug symbols 到 Google Play](https://developer.android.com/studio/build/shrink-code#android_gradle_plugin_version_40_or_earlier_and_other_build_systems) 以便让 Google Play 上的崩溃日志显示可读的调用堆栈. 详情请见 [原生代码调试教程](/manuals/debugging-native-code).
+### 将符号上传到 Google Play
+可以 [将调试符号上传到 Google Play](https://developer.android.com/studio/build/shrink-code#android_gradle_plugin_version_40_or_earlier_and_other_build_systems),以便在 Google Play 中记录的任何崩溃都将显示符号化的调用堆栈。将 `projecttitle.apk.symbols/lib/` 捆绑输出文件夹的内容压缩。该文件夹包含一个或多个具有架构名称的子文件夹,如 `arm64-v8a` 和 `armeabi-v7a`。
 
 
-### Android调用堆栈映射
+### 符号化 Android 调用堆栈
 
-1. 从编译文件夹下找到引擎文件
+1. 从您的构建文件夹中获取引擎
 
+```sh
 	$ ls <project>/build/<platform>/[lib]dmengine[.exe|.so]
+```
 
-1. 解压引擎:
+2. 解压到一个文件夹:
 
+```sh
 	$ unzip dmengine.apk -d dmengine_1_2_105
+```
 
-1. 找到地址
+3. 查找调用堆栈地址
 
-	例如下面这个文件
+	例如,在未符号化的调用堆栈中,它可能看起来像这样
 
 	`#00 pc 00257224 libmy_game_name.so`
 
-	其中 *00257224* 是地址
+	其中 *`00257224`* 是地址
 
-1. 映射地址
+4. 解析地址
 
+```sh
     $ arm-linux-androideabi-addr2line -C -f -e dmengine_1_2_105/lib/armeabi-v7a/libdmengine.so _address_
+```
 
-注意: 要是从 [Android 日志](/manuals/debugging-game-and-system-logs) 获取的调用堆栈数据, 可能需要使用 [ndk-stack](https://developer.android.com/ndk/guides/ndk-stack.html) 进行地址解析
+注意:如果您从 [Android 日志](/manuals/debugging-game-and-system-logs) 获取堆栈跟踪,您可能可以使用 [ndk-stack](https://developer.android.com/ndk/guides/ndk-stack.html) 对其进行符号化
 
-### iOS 调用堆栈映射
+### 符号化 iOS 调用堆栈
 
-1. 如果使用了原生扩展, 服务器会为你提供映射数据 (.dSYM) 文件 (使用 bob.jar 连同 `--with-symbols` 参数)
+1. 如果您正在使用原生扩展,服务器可以为您提供符号(.dSYM)(将 `--with-symbols` 传递给 bob.jar)
 
+```sh
 	$ unzip <project>/build/arm64-darwin/build.zip
-	# 文件会被解压到 Contents/Resources/DWARF/dmengine
+	# 它将产生一个 Contents/Resources/DWARF/dmengine
+```
 
-1. 如果没用原生扩展, 直接下载映射文件:
+2. 如果您没有使用原生扩展,下载原始符号:
 
+```sh
 	$ wget http://d.defold.com/archive/<sha1>/engine/arm64-darwin/dmengine.dSYM
+```
 
-1. 地址映射
+3. 使用加载地址进行符号化
 
-	不能直接使用堆栈里的地址 (比如载入地址 0x0)
+	出于某种原因,简单地放入调用堆栈中的地址不起作用(即加载地址 0x0)
 
+```sh
 		$ atos -arch arm64 -o Contents/Resources/DWARF/dmengine 0x1492c4
+```
 
-	# 也不能作为参数加入载入地址
+	# 直接指定加载地址也不起作用
 
+```sh
 		$ atos -arch arm64 -o MyApp.dSYM/Contents/Resources/DWARF/MyApp -l0x100000000 0x1492c4
+```
 
-	二者相加才可以:
+	将加载地址添加到地址中起作用:
 
+```sh
 		$ atos -arch arm64 -o MyApp.dSYM/Contents/Resources/DWARF/MyApp 0x1001492c4
 		dmCrash::OnCrash(int) (in MyApp) (backtrace_execinfo.cpp:27)
+```

+ 4 - 4
docs/zh/manuals/debugging.md

@@ -1,11 +1,11 @@
 ---
 title: Defold 调试
-brief: 本教程介绍了 Defold 的内置调试工具.
+brief: 本手册解释了 Defold 中提供的调试功能。
 ---
 
 # 调试
 
-Defold 内置集成式 Lua 调试器与检视工具. 加上内置的 [分析工具](/manuals/profiling) 一起提供了强大的游戏调试除错性能分析功能. 万一游戏崩溃了 Defold 还能提供游戏引擎崩溃日志.
+Defold 包含一个带有检查功能的集成式 Lua 调试器。与内置的 [分析工具](/manuals/profiling) 相结合,它是一个强大的工具,可以帮助您找出游戏逻辑中错误的原因或帮助分析性能问题。在引擎本身崩溃的罕见情况下,Defold 还提供崩溃日志。
 
-* 参考 [调试游戏逻辑](/manuals/debugging-game-logic).
-* 参考 [调试原生代码](/manuals/debugging-native-code).
+* 了解有关 [调试游戏逻辑](/manuals/debugging-game-logic) 的更多信息。
+* 了解有关 [调试原生代码](/manuals/debugging-native-code) 的更多信息。

+ 17 - 17
docs/zh/manuals/design.md

@@ -1,24 +1,24 @@
 ---
-title: Defold 设计理念
-brief: Defold 设计幕后理念
+title: Defold 设计
+brief: Defold 设计背后的理念
 ---
 
-# Defold 的设计理念
+# Defold 的设计
 
-Defold 为以下目的而创建:
+Defold 是为以下目标而创建的:
 
-- 为游戏团队提供专业的迭代开发平台.
-- 简单明了, 提供可视化解决方案和游戏常用功能与开发流程.
-- 提供极轻量级的游戏开发平台.
-- 提供高性能运行环境.
-- 真正跨平台.
+- 成为一个完整的、专业的、交钥匙式的游戏团队生产平台。
+- 简单明了,为常见的游戏开发架构和工作流程问题提供明确的解决方案。
+- 成为一个极快的开发平台,非常适合迭代式游戏开发。
+- 在运行时具有高性能。
+- 真正的多平台。
 
-Defold编辑器与引擎就是为了实现上述目的而精心打造的. 如果你从其他平台转来, 可能会有点不习惯, 比如:
+编辑器和引擎的设计经过精心打造,以实现这些目标。如果您有其他平台的经验,我们的一些设计决策可能与您习惯的不同,例如:
 
-- 资源树与各种命名需要静态指定. 开始可能麻烦, 随着项目深入你就会觉得很方便.
-- 我们鼓励简单封装的实体间互相传递消息.
-- 没有面向对象的思想.
-- API都是异步的.
-- 渲染流程是可程式化可自定义的.
-- 所有资源文件都是直白文本文件, 为了最大化适应 Git merge , 也为了方便用外部工具编辑.
-- 资源可以实时修改然后在运行中的游戏里热重载, 这样特别方便开发迭代和做测试.
+- 我们要求静态声明资源树和所有命名。这需要您付出一些初始努力,但从长远来看,极大地帮助了开发过程。
+- 我们鼓励简单封装实体之间的消息传递。
+- 没有面向对象的继承。
+- 我们的 API 是异步的。
+- 渲染管道是由代码驱动的,并且完全可定制。
+- 我们所有的资源文件都是简单的纯文本格式,针对 Git 合并以及使用外部工具导入和处理进行了最佳结构化。
+- 资源可以被更改并热重载到正在运行的游戏中,从而实现极快的迭代和实验。

+ 35 - 35
docs/zh/manuals/dev-app.md

@@ -1,67 +1,67 @@
 ---
-title: 在设备上运行开发用app
-brief: 本教程介绍了如何在设备上安装开发用app以方便开发流程.
+title: 在设备上运行开发
+brief: 本手册解释了如何在设备上放置开发应用,以便在设备上进行迭代开发。
 ---
 
-# 移动开发用app
+# 移动开发
 
-开发用app 让你可以通过wifi把内容推送到设备上. 这样进行修改测试的时候就不用反复打包安装了. 只需要在设备上安装开发用app, 打开app然后在编辑器里选择设备作为推送目标即可.
+开发应用允许您通过wifi将内容推送到它。这将大大减少迭代时间,因为您不必在每次希望测试更改时都进行打包和安装。您在设备上安装开发应用,启动应用,然后从编辑器中选择设备作为构建目标。
 
-## 安装开发用app
+## 安装开发
 
-Debug 模式下编译的任何 iOS 或 Android 应用都可以作为开发用app. 事实上, 我们推荐这么做因为开发用app包含正确的项目配置而且拥有和开发时使用的相同的 [原生扩展](/manuals/extensions/).
+任何以Debug模式打包的iOS或Android应用程序都可以作为开发应用。事实上,这是推荐的解决方案,因为开发应用将具有正确的项目设置,并使用与您正在处理的项目相同的[原生扩展](/manuals/extensions/)。
 
-从 Defold 1.4.0 版本开始可以给项目打空的 debug 包. 使用这个选项可以创建带原生扩展的应用版本, 适合于教程里提到的开发迭代.
+从Defold 1.4.0开始,可以打包项目的Debug变体而不包含任何内容。使用此选项创建带有原生扩展的应用程序版本,适用于本手册中描述的迭代开发。
 
 ![content less bundle](images/dev-app/contentless-bundle.png)
 
-### Installing on iOS
+### 在iOS上安装
 
-依照 [iOS 教程介绍的步骤](/manuals/ios/#creating-an-ios-application-bundle) 打包 iOS 应用. 记得 variant 要选择 Debug!
+按照[iOS手册中的说明](/manuals/ios/#creating-an-ios-application-bundle)为iOS打包。确保选择Debug作为变体!
 
-### Installing on Android
+### 在Android上安装
 
-依照 [Android 教程介绍的步骤](https://defold.com/manuals/android/#creating-an-android-application-bundle) 打包 Android 应用.
+按照[Android手册中的说明](https://defold.com/manuals/android/#creating-an-android-application-bundle)为Android打包。
 
-## 启动游戏
+## 启动您的游戏
 
-要在设备上启动游戏, 应用与编辑器之间需要互联, 可以使用 wifi 也可以使用 USB 线缆 (见下文).
+要在设备上启动游戏,开发应用和编辑器必须能够通过相同的wifi网络或使用USB(见下文)进行连接。
 
-1. 确保编辑器处于运行中.
-2. 在设备上启动开发用app.
-3. 在编辑器的 <kbd>Project ▸ Targets</kbd> 中选择设备.
-4. 选择 <kbd>Project ▸ Build</kbd> 运行游戏. 如果用网络连接的话可能需要等一小会儿.
-5. 游戏运行时, 就可以照常使用 [热重载](/manuals/hot-reload/) 功能了.
+1. 确保编辑器已启动并正在运行。
+2. 在设备上启动开发应用。
+3. 在编辑器中的<kbd>Project ▸ Targets</kbd>下选择您的设备。
+4. 选择<kbd>Project ▸ Build</kbd>来运行游戏。游戏启动可能需要一段时间,因为游戏内容通过网络流式传输到设备。
+5. 游戏运行时,您可以照常使用[热重载](/manuals/hot-reload/)。
 
-### 在 Windows 上使用 USB 连接 iOS 设备
+### 在Windows上使用USB连接iOS设备
 
-要在 Windows 上使用 USB 连接运行于 iOS 设备上的app, 首先 [安装 iTunes](https://www.apple.com/lae/itunes/download/). 安装完之后还需从iOS设备的设置菜单里 [开启 Personal Hotspot](https://support.apple.com/en-us/HT204023). 如果跳出 "Trust This Computer?" 则选择 Trust. 这样设备就会出现在 <kbd>Project ▸ Targets</kbd> 列表中了.
+在Windows上通过USB连接到运行在iOS设备上的开发应用时,首先需要[安装iTunes](https://www.apple.com/lae/itunes/download/)。安装iTunes后,您还需要从设置菜单中[在iOS设备上启用个人热点](https://support.apple.com/en-us/HT204023)。如果您看到提示点击"Trust This Computer?"的警报,请点击Trust。当开发应用运行时,设备现在应该会显示在<kbd>Project ▸ Targets</kbd>下。
 
-### 在 Linux 上使用 USB 连接 iOS 设备
+### 在Linux上使用USB连接iOS设备
 
-Linux 上同样开启 Personal Hotspot 然后 "Trust This Computer".
+在Linux上,当使用USB连接时,您需要从设置菜单中在设备上启用个人热点。如果您看到提示点击"Trust This Computer?"的警报,请点击Trust。当开发应用运行时,设备现在应该会显示在<kbd>Project ▸ Targets</kbd>下。
 
-### 在 macOS 上使用 USB 连接 iOS 设备
+### 在macOS上使用USB连接iOS设备
 
-当设备与 macOS 通过 USB 连线时, 新版本 iOS 能自动开启连接,  <kbd>Project ▸ Targets</kbd> 会自动显示出设备.
+在较新的iOS版本上,当在macOS上使用USB连接时,设备会自动在设备和计算机之间打开一个新的以太网接口。当开发应用运行时,设备应该会显示在<kbd>Project ▸ Targets</kbd>下。
 
-老iOS设备还是同样开启 Personal Hotspot 然后 "Trust This Computer".
+在较旧的iOS版本上,当在macOS上使用USB连接时,您需要从设置菜单中在设备上启用个人热点。如果您看到提示点击"Trust This Computer?"的警报,请点击Trust。当开发应用运行时,设备现在应该会显示在<kbd>Project ▸ Targets</kbd>下。
 
-### 在 macOS 上使用 USB 连接 Android 设备
+### 在macOS上使用USB连接Android设备
 
-当设备处于 USB 共享模式时,  可以通过 USB 连接设备与 macOS. 在 macOS 上需要安装 [HoRNDIS](https://joshuawise.com/horndis#available_versions) 这类的第三方驱动程序. 当 HoRNDIS 安装好后还需要在 Security & Privacy 设置里允许其运行. 设备上开启 USB 共享模式后就会出现在 <kbd>Project ▸ Targets</kbd> 列表中了.
+在macOS上,当设备处于USB网络共享模式时,可以通过USB连接到运行在Android设备上的开发应用。在macOS上,您需要安装第三方驱动程序,如[HoRNDIS](https://joshuawise.com/horndis#available_versions)。安装HoRNDIS后,您还需要通过安全性与隐私设置允许它运行。一旦启用USB网络共享,当开发应用运行时,设备将显示在<kbd>Project ▸ Targets</kbd>下。
 
-### 在 Windows  Linux 上使用 USB 连接 Android 设备
+### 在Windows或Linux上使用USB连接Android设备
 
-同样在设备上开启 USB 共享模式后就会出现在 <kbd>Project ▸ Targets</kbd> 列表中了.
+在Windows和Linux上,当设备处于USB网络共享模式时,可以通过USB连接到运行在Android设备上的开发应用。一旦启用USB网络共享,当开发应用运行时,设备将显示在<kbd>Project ▸ Targets</kbd>下。
 
 ## 故障排除
 
-无法下载应用
-: 确保你的设备 UDID 包含在手机应用签名 provisioning 中.
+无法下载应用程序
+: 确保您的设备UDID包含在用于签署应用程序的移动配置中。
 
-Targets 菜单没有设备
-: 确保设备于计算机处于相同 wifi 网络之下. 确保使用 Debug 模式编译开发用app.
+您的设备没有出现在Targets菜单中
+: 确保您的设备连接到与计算机相同的wifi网络。确保开发应用是以Debug模式构建的。
 
-弹出消息说版本不匹配
-: 这是由于更新了编辑器没更新应用. 用新编辑器重新编译安装应用即可.
+游戏没有启动,并显示有关版本不匹配的消息
+: 当您将编辑器升级到最新版本时会发生这种情况。您需要构建并安装新版本。

+ 55 - 27
docs/zh/manuals/editor-preferences.md

@@ -1,68 +1,80 @@
 ---
-title: 编辑器配置
-brief: 可以通过设置窗口修改编辑器配置.
+title: 编辑器首选项
+brief: 您可以从首选项窗口修改编辑器的设置。
 ---
 
-# 编辑器配置
+# 编辑器首选项
 
-可以通过设置窗口修改编辑器配置. 选择菜单栏 <kbd>File -> Preferences</kbd> 即可打开设置窗口.
+您可以从首选项窗口修改编辑器的设置。首选项窗口通过 <kbd>File -> Preferences</kbd> 菜单打开。
 
-## General
+## 通用
 
 ![](images/editor/preferences_general.png)
 
 Load External Changes on App Focus
-: 当编辑器获得焦点时扫描外部文件改变.
+: 当编辑器获得焦点时启用外部更改扫描。
 
 Open Bundle Target Folder
-: 打包结束后自动打开输出文件夹.
+: 启用打包过程完成后打开目标包文件夹。
 
 Enable Texture Compression
-: 开启编译 [纹理压缩](/manuals/texture-profiles).
+: 为编辑器进行的所有构建启用[纹理压缩](/manuals/texture-profiles)。
 
 Escape Quits Game
-: 用 <kbd>Esc</kbd> 键关闭正在运行的编译好的游戏.
+: 使用 <kbd>Esc</kbd> 键关闭正在运行的游戏构建。
 
 Track Active Tab in Asset Browser
-: 在 *编辑器* 面板编辑的文件自动在资源浏览器 (也叫 *Asset* 面板) 中选中.
+: 在*编辑器*面板中选定标签页中编辑的文件将在资源浏览器(也称为*资源*面板)中被选中。
 
-Path to custom keymap
-: [自定义快捷键](/manuals/editor-keyboard-shortcuts) 配置文件的绝对路径.
+Lint Code on Build
+: 构建项目时启用[代码检查](/manuals/writing-code/#linting-configuration)。此选项默认启用,但如果大型项目的代码检查耗时过长,可以禁用。
 
+Engine Arguments
+: 当编辑器构建和运行时,将传递给dmengine可执行文件的参数。
+每行使用一个参数。例如:
+```
+--config=bootstrap.main_collection=/my dir/1.collectionc
+--verbose
+--graphics-adapter=vulkan
+```
 
-## Code
+
+## 代码
 
 ![](images/editor/preferences_code.png)
 
 Custom Editor
-: 自定义编辑器的绝对路径. 在 macOS 上应指向 .app 内的可执行程序 (比如 `/Applications/Atom.app/Contents/MacOS/Atom`).
+: 外部编辑器的绝对路径。在macOS上,它应该是.app内部可执行文件的路径(例如 `/Applications/Atom.app/Contents/MacOS/Atom`)。
 
 Open File
-: 自定义编辑器开启时要打开的文件的表达式. 其中 `{file}` 在开启时会被真实文件名代替.
+: 自定义编辑器用于指定要打开哪个文件的模式。模式 `{file}` 将被要打开的文件名替换。
 
 Open File at Line
-: 自定义编辑器开启时要打开的文件以及指定光标放置的行数. 表达式 `{file}` 在开启时会被真是文件名代替, 而 `{line}` 被行号代替.
+: 自定义编辑器用于指定要打开哪个文件以及在哪个行号打开的模式。模式 `{file}` 将被要打开的文件名替换,`{line}` 将被行号替换。
 
 Code editor font
-: 代码编辑器里要使用的系统上已安装的字体名称.
+: 在代码编辑器中使用的系统安装字体名称。
+
+Zoom on Scroll
+: 在代码编辑器中滚动时按住Cmd/Ctrl按钮是否更改字体大小。
 
 
-### 使用 Visual Studio Code 打开脚本文件
+### 在Visual Studio Code中打开脚本文件
 
 ![](images/editor/preferences_vscode.png)
 
-要从 Defold 编辑器里直接用 Visual Studio Code 打开脚本文件, 必须配置下列可执行文件地址:
+要从Defold编辑器直接在Visual Studio Code中打开脚本文件,必须通过指定可执行文件的路径来设置以下设置:
 
 - MacOS: `/Applications/Visual Studio Code.app/Contents/MacOS/Electron`
 - Linux: `/usr/bin/code`
 - Windows: `C:\Program Files\Microsoft VS Code\Code.exe`
 
- 配置打开指定文件和指定行号的参数:
+设置这些参数以打开特定文件和行:
 
-- 打开文件: `. {file}`
-- 打开到行: `. -g {file}:{line}`
+- Open File: `. {file}`
+- Open File at Line: `. -g {file}:{line}`
 
-其中 `.` 符号代表打开整个项目, 而不是指定文件.
+这里的 `.` 字符是必需的,用于打开整个工作区,而不是单个文件。
 
 
 ## 扩展
@@ -70,17 +82,33 @@ Code editor font
 ![](images/editor/preferences_extensions.png)
 
 Build Server
-: 编译包含 [原生扩展](/manuals/extensions) 项目时使用的编译服务器的 URL. 可以在编译服务器的请求 URL 中加入用户名和验证令牌. 使用格式举例: `username:[email protected]`. 在使用用户自己的编译服务器并开启认证时, 任天堂 Switch 编译需要这种用户认证 ([更多信息详见编译服务器文档](https://github.com/defold/extender/blob/dev/README_SECURITY.md)). 其中用户名和密码可以用系统环境变量 `DM_EXTENDER_USERNAME` 和 `DM_EXTENDER_PASSWORD` 来设置.
+: 构建包含[原生扩展](/manuals/extensions)的项目时使用的构建服务器的URL。可以向URL添加用户名和访问令牌以进行构建服务器的身份验证访问。使用以下表示法指定用户名和访问令牌:`username:[email protected]`。Nintendo Switch构建以及运行启用了身份验证的自己的构建服务器实例时需要身份验证访问([请参阅构建服务器文档](https://github.com/defold/extender/blob/dev/README_SECURITY.md)了解更多信息)。用户名和密码也可以设置为系统环境变量`DM_EXTENDER_USERNAME`和`DM_EXTENDER_PASSWORD`。
+
+Build Server Username
+: 用于身份验证的用户名。
+
+Build Server Password
+: 用于身份验证的密码,将加密存储在首选项文件中。
 
 Build Server Headers
-: 编译原生扩展时向服务器发送的额外的 header. 在使用 CloudFlare 服务或类似服务编译扩展时是很必要的.
+: 构建原生扩展时发送到构建服务器的额外标头。对于使用CloudFlare服务或类似服务的扩展器很重要。
 
 ## 工具
 
 ![](images/editor/preferences_tools.png)
 
 ADB path
-: 配置 [ADB](https://developer.android.com/tools/adb) 命令行工具的路径. 如果系统中安装了 ADB, 则 Defold 编辑器会使用它来安装和运行 Android APK 包到指定设备. 默认情况下, 编辑器会检查 ADB 是否安装在了默认位置, 如果需要手动指定路径则需配置该选项.
+: 安装在此系统上的[ADB](https://developer.android.com/tools/adb)命令行工具的路径。如果系统上安装了ADB,Defold编辑器将使用它将打包的Android APK安装并运行到连接的Android设备上。默认情况下,编辑器检查ADB是否安装在已知位置,因此只有当ADB安装在自定义位置时才需要指定路径。
 
 ios-deploy path
-: 配置 [ios-deploy](https://github.com/ios-control/ios-deploy) 命令行工具的路径 (仅适用于 macOS). 与 ADB 路径类似, Defold 编辑器会使用该工具安装和运行 iOS 包到连接好的 iPhone 上. 默认情况下, 编辑器会检查 ios-deploy 是否安装在了默认位置, 如果需要手动指定路径则需配置该选项.
+: 安装在此系统上的[ios-deploy](https://github.com/ios-control/ios-deploy)命令行工具的路径(仅与macOS相关)。与ADB路径类似,Defold编辑器将使用此工具将打包的iOS应用程序安装并运行到连接的iPhone上。默认情况下,编辑器检查ios-deploy是否安装在已知位置,因此只有当您使用自定义安装的ios-deploy时才需要指定路径。
+
+## 键映射
+
+![](images/editor/preferences_keymap.png)
+
+您可以配置编辑器快捷键,既可以添加自定义快捷键,也可以删除内置快捷键。在快捷键表格中的单个命令上使用上下文菜单来编辑快捷键,或双击/按<kbd>Enter</kbd>打开新的快捷键弹出窗口。
+
+一些快捷键可能有警告:它们使用橙色显示。将鼠标悬停在快捷键上以查看警告。典型警告包括:
+- 可输入快捷键:所选快捷键可在文本输入中输入。确保该命令在代码编辑/文本输入上下文中处于关闭状态。
+- 冲突:同一快捷键分配给多个不同的命令。确保在调用快捷键时最多启用一个命令,否则编辑器将以未定义的方式执行分配的命令之一。

+ 370 - 0
docs/zh/manuals/editor-scripts-ui.md

@@ -0,0 +1,370 @@
+---
+title: "编辑器脚本:UI"
+brief: 本手册解释了如何使用Lua在编辑器中创建UI元素
+---
+
+# 编辑器脚本和UI
+
+本手册解释了如何使用用Lua编写的编辑器脚本在编辑器中创建交互式UI元素。要开始使用编辑器脚本,请参阅[编辑器脚本手册](/manuals/editor-scripts)。您可以找到完整的编辑器API参考[这里](/ref/stable/editor-lua/)。目前,只能创建交互式对话框,尽管我们希望将来将UI脚本支持扩展到编辑器的其余部分。
+
+## Hello world
+
+所有与UI相关的功能都存在于`editor.ui`模块中。这是一个带有自定义UI的编辑器脚本的最简单示例,可以帮助您入门:
+```lua
+local M = {}
+
+function M.get_commands()
+    return {
+        {
+            label = "Do with confirmation",
+            locations = {"View"},
+            run = function()
+                local result = editor.ui.show_dialog(editor.ui.dialog({
+                    title = "Perform action?",
+                    buttons = {
+                        editor.ui.dialog_button({
+                            text = "Cancel",
+                            cancel = true,
+                            result = false
+                        }),
+                        editor.ui.dialog_button({
+                            text = "Perform",
+                            default = true,
+                            result = true
+                        })
+                    }
+                }))
+                print('Perform action:', result)
+            end
+        }
+    }
+end
+
+return M
+
+```
+
+此代码片段定义了一个**View → Do with confirmation**命令。当您执行它时,您将看到以下对话框:
+
+![Hello world dialog](images/editor_scripts/perform_action_dialog.png)
+
+最后,在按<kbd>Enter</kbd>(或点击`Perform`按钮)后,您将在编辑器控制台中看到以下行:
+```
+Perform action:	true
+```
+
+## 基本概念
+
+### 组件
+
+编辑器提供了各种UI**组件**,可以组合这些组件来创建所需的UI。按照惯例,所有组件都使用一个称为**props**的表进行配置。组件本身不是表,而是编辑器用于创建UI的**不可变用户数据**。
+
+### Props
+
+**Props**是定义组件输入的表。Props应被视为不可变的:原地修改props表不会导致组件重新渲染,但使用不同的表会。当组件实例接收到与前一个表浅不相等的props表时,UI会更新。
+
+### 对齐
+
+当组件在UI中被分配一些边界时,它将消耗整个空间,但这并不意味着组件的可见部分会拉伸。相反,可见部分将占据它所需的空间,然后它将在分配的边界内对齐。因此,大多数内置组件定义了`alignment`属性。
+
+例如,考虑这个标签组件:
+```lua
+editor.ui.label({
+    text = "Hello",
+    alignment = editor.ui.ALIGNMENT.RIGHT
+})
+```
+可见部分是`Hello`文本,它在分配的组件边界内对齐:
+
+![Alignment](images/editor_scripts/alignment.png)
+
+## 内置组件
+
+编辑器定义了各种可以一起使用来构建UI的内置组件。组件大致可以分为3类:布局、数据展示和输入。
+
+### 布局组件
+
+布局组件用于将其他组件彼此相邻放置。主要的布局组件是**`horizontal`**、**`vertical`**和**`grid`**。这些组件还定义了**padding**和**spacing**等属性,其中padding是从分配边界边缘到内容的空白空间,而spacing是子组件之间的空白空间:
+
+![Padding and Spacing](images/editor_scripts/padding_and_spacing.png)
+
+编辑器定义了`small`、`medium`和`large`padding和spacing常量。当涉及到spacing时,`small`用于单个UI元素的不同子元素之间的间距,`medium`用于单个UI元素之间的间距,而`large`是元素组之间的间距。默认spacing是`medium`。`large`的padding值表示从窗口边缘到内容的padding,`medium`是从重要UI元素边缘的padding,而`small`是上下文菜单和工具提示等小UI元素边缘的padding(尚未实现)。
+
+**`horizontal`**容器将其子组件一个接一个地水平放置,始终使每个子组件的高度填充可用空间。默认情况下,每个子组件的宽度保持最小,但可以通过在子组件上将`grow`属性设置为`true`来使其占用尽可能多的空间。
+
+**`vertical`**容器与水平容器类似,但是轴切换了。
+
+最后,**`grid`**是一个容器组件,将其子组件布置在2D网格中,就像表格一样。网格中的`grow`设置适用于行或列,因此它不是在子组件上设置,而是在列配置表上设置。此外,网格中的子组件可以配置为使用`row_span`和`column_span`属性跨越多行或多列。网格对于创建多输入表单很有用:
+```lua
+editor.ui.grid({
+    padding = editor.ui.PADDING.LARGE, -- 在对话框边缘添加padding
+    columns = {{}, {grow = true}}, -- 使第2列增长
+    children = {
+        {
+            editor.ui.label({ 
+                text = "Level Name",
+                alignment = editor.ui.ALIGNMENT.RIGHT
+            }),
+            editor.ui.string_field({})
+        },
+        {
+            editor.ui.label({ 
+                text = "Author",
+                alignment = editor.ui.ALIGNMENT.RIGHT
+            }),
+            editor.ui.string_field({})
+        }
+    }
+})
+```
+上面的代码将产生以下对话框表单:
+
+![New Level Dialog](images/editor_scripts/new_level_dialog.png)
+
+### 数据展示组件
+
+编辑器定义了4个数据展示组件:
+- **`label`** — 文本标签,旨在与表单输入一起使用。
+- **`icon`** — 图标;目前,它只能用于呈现一小组预定义图标,但我们打算将来允许更多图标。
+- **`heading`** — 文本元素,旨在呈现例如表单或对话框中的标题行文本。`editor.ui.HEADING_STYLE`枚举定义了各种标题样式,包括HTML的`H1`-`H6`标题,以及编辑器特定的`DIALOG`和`FORM`。
+- **`paragraph`** — 文本元素,旨在呈现一段文本。与`label`的主要区别是段落支持自动换行:如果分配的边界在水平方向上太小,文本将换行,如果无法适应视图,可能会用`"..."`缩短。
+
+### 输入组件
+
+输入组件是为用户与UI交互而设计的。所有输入组件都支持`enabled`属性来控制交互是否启用,并定义各种回调属性,在交互时通知编辑器脚本。
+
+如果您创建静态UI,只需定义简单修改局部变量的回调就足够了。对于动态UI和更高级的交互,请参阅[响应式](#reactivity)。
+
+例如,可以像这样创建一个简单的静态新建文件对话框:
+```lua
+-- 初始文件名,将被对话框替换
+local file_name = ""
+local create_file = editor.ui.show_dialog(editor.ui.dialog({
+    title = "Create New File",
+    content = editor.ui.horizontal({
+        padding = editor.ui.PADDING.LARGE,
+        spacing = editor.ui.SPACING.MEDIUM,
+        children = {
+            editor.ui.label({
+                text = "New File Name",
+                alignment = editor.ui.ALIGNMENT.CENTER
+            }),
+            editor.ui.string_field({
+                grow = true,
+                text = file_name,
+                -- 输入回调:
+                on_value_changed = function(new_text)
+                    file_name = new_text
+                end
+            })
+        }
+    }),
+    buttons = {
+        editor.ui.dialog_button({ text = "Cancel", cancel = true, result = false }),
+        editor.ui.dialog_button({ text = "Create File", default = true, result = true })
+    }
+}))
+if create_file then
+    print("create", file_name)
+end
+```
+这是内置输入组件的列表:
+- **`string_field`**、**`integer_field`**和**`number_field`**是单行文本字段的变体,允许编辑字符串、整数和数字。
+- **`select_box`**用于通过下拉控件从预定义的选项数组中选择一个选项。
+- **`check_box`**是一个带有`on_value_changed`回调的布尔输入字段
+- **`button`**带有在按钮按下时调用的`on_press`回调。
+- **`external_file_field`**是一个用于选择计算机上文件路径的组件。它由一个文本字段和一个打开文件选择对话框的按钮组成。
+- **`resource_field`**是一个用于选择项目中资源的组件。
+
+除按钮外的所有组件都允许设置一个`issue`属性,显示与组件相关的问题(`editor.ui.ISSUE_SEVERITY.ERROR`或`editor.ui.ISSUE_SEVERITY.WARNING`),例如:
+```lua
+issue = {severity = editor.ui.ISSUE_SEVERITY.WARNING, message = "This value is deprecated"}
+```
+当指定issue时,它会改变输入组件的外观,并添加带有问题消息的工具提示。
+
+这是所有输入及其问题变体的演示:
+
+![Inputs](images/editor_scripts/inputs_demo.png)
+
+### 对话框相关组件
+
+要显示对话框,您需要使用`editor.ui.show_dialog`函数。它需要一个**`dialog`**组件,该组件定义了Defold对话框的主要结构:`title`、`header`、`content`和`buttons`。对话框组件有点特殊:您不能将其用作另一个组件的子组件,因为它代表一个窗口,而不是UI元素。`header`和`content`是常规组件。
+
+对话框按钮也很特殊:它们是使用**`dialog_button`**组件创建的。与常规按钮不同,对话框按钮没有`on_pressed`回调。相反,它们定义了一个`result`属性,该属性将在对话框关闭时由`editor.ui.show_dialog`函数返回。对话框按钮还定义了`cancel`和`default`布尔属性:带有`cancel`属性的按钮在用户按<kbd>Escape</kbd>或使用OS关闭按钮关闭对话框时触发,而`default`按钮在用户按<kbd>Enter</kbd>时触发。对话框按钮可以同时将`cancel`和`default`属性设置为`true`。
+
+### 实用组件
+
+此外,编辑器还定义了一些实用组件:
+- **`separator`**是一条细线,用于分隔内容块
+- **`scroll`**是一个包装组件,当包装的组件不适合分配的空间时显示滚动条
+
+## 响应式
+
+由于组件是**不可变用户数据**,因此在创建后无法更改它们。那么如何使UI随时间变化呢?答案是:**响应式组件**。
+
+::: sidenote
+编辑器脚本UI的灵感来自[React](https://react.dev/)库,因此了解响应式UI和React hooks将有所帮助。
+:::
+
+在最简单的术语中,响应式组件是一个带有Lua函数的组件,该函数接收数据(props)并返回视图(另一个组件)。响应式组件函数可以使用**hooks**:`editor.ui`模块中的特殊函数,为您的组件添加响应式功能。按照惯例,所有hooks的名称都以`use_`开头。
+
+要创建响应式组件,请使用`editor.ui.component()`函数。
+
+让我们看这个示例——一个新建文件对话框,只有当输入的文件名不为空时才允许创建文件:
+
+```lua
+-- 1. dialog是一个响应式组件
+local dialog = editor.ui.component(function(props)
+    -- 2. 组件定义了一个本地状态(文件名),默认为空字符串
+    local name, set_name = editor.ui.use_state("")
+
+    return editor.ui.dialog({ 
+        title = props.title,
+        content = editor.ui.vertical({
+            padding = editor.ui.PADDING.LARGE,
+            children = { 
+                editor.ui.string_field({ 
+                    value = name,
+                    -- 3. 输入+Enter更新本地状态
+                    on_value_changed = set_name 
+                }) 
+            }
+        }),
+        buttons = {
+            editor.ui.dialog_button({ 
+                text = "Cancel", 
+                cancel = true 
+            }),
+            editor.ui.dialog_button({ 
+                text = "Create File",
+                -- 4. 当名称存在时启用创建
+                enabled = name ~= "",
+                default = true,
+                -- 5. 结果是名称
+                result = name
+            })
+        }
+    })
+end)
+
+-- 6. show_dialog将返回非空文件名或在取消时返回nil
+local file_name = editor.ui.show_dialog(dialog({ title = "New File Name" }))
+if file_name then 
+    print("create " .. file_name)
+else
+    print("cancelled")
+end
+```
+
+当您执行运行此代码的菜单命令时,编辑器将显示一个在开始时禁用`"Create File"`对话框的对话框,但是当您输入名称并按<kbd>Enter</kbd>时,它将变为启用状态:
+
+![New File Dialog](images/editor_scripts/reactive_new_file_dialog.png)
+
+那么,它是如何工作的呢?在第一次渲染时,`use_state` hook创建一个与组件关联的本地状态,并返回它以及状态的setter。当调用setter函数时,它会安排组件重新渲染。在随后的重新渲染中,组件函数再次被调用,`use_state`返回更新的状态。然后,组件函数返回的新视图组件与旧组件进行差异比较,并在检测到更改的地方更新UI。
+
+这种响应式方法大大简化了构建交互式UI并使其保持同步:而不是在用户输入时显式更新所有受影响的UI组件,视图被定义为输入(props和本地状态)的纯函数,编辑器自己处理所有更新。
+
+### 响应式规则
+
+编辑器期望响应式函数组件表现良好才能正常工作:
+
+1. 组件函数必须是纯函数。不保证何时或多久调用一次组件函数。所有副作用都应该在渲染之外,例如在回调中
+2. Props和本地状态必须是不可变的。不要改变props。如果您的本地状态是一个表,不要原地修改它,而是在状态需要更改时创建一个新表并将其传递给setter。
+3. 组件函数必须在每次调用时以相同的顺序调用相同的hooks。不要在循环中、条件块中、提前返回后等调用hooks。最佳实践是在组件函数的开头调用hooks,在任何其他代码之前。
+4. 只从组件函数调用hooks。Hooks在响应式组件的上下文中工作,因此只允许在组件函数中(或由组件函数直接调用的另一个函数中)调用它们。
+
+### Hooks
+
+::: sidenote
+如果您熟悉[React](https://react.dev/),您会注意到编辑器中的hooks在hook依赖项方面具有稍微不同的语义。
+:::
+
+编辑器定义了2个hooks:**`use_memo`**和**`use_state`**。
+
+### **`use_state`**
+
+本地状态可以通过两种方式创建:使用默认值或使用初始化器函数:
+```lua
+-- 默认值
+local enabled, set_enabled = editor.ui.use_state(true)
+-- 初始化器函数+参数
+local id, set_id = editor.ui.use_state(string.lower, props.name)
+```
+类似地,可以使用新值或更新器函数调用setter:
+```lua
+-- 更新器函数
+local function increment_by(n, by)
+    return n + by
+end
+
+local counter = editor.ui.component(function(props)
+    local count, set_count = editor.ui.use_state(0)
+    
+    return editor.ui.horizontal({
+        spacing = editor.ui.SPACING.SMALL,
+        children = {
+            editor.ui.label({
+                text = tostring(count),
+                alignment = editor.ui.ALIGNMENT.LEFT,
+                grow = true
+            }),
+            editor.ui.text_button({
+                text = "+1",
+                on_pressed = function() set_count(increment_by, 1) end
+            }),
+            editor.ui.text_button({
+                text = "+5",
+                on_pressed = function() set_count(increment_by, 5) end
+            })
+        }
+    })
+end)
+```
+
+最后,状态可以被**重置**。当`editor.ui.use_state()`的任何参数更改时,状态会重置,使用`==`进行检查。因此,您不能使用字面量表或字面量初始化器函数作为`use_state` hook的参数:这会导致每次重新渲染时状态重置。举例说明:
+```lua
+-- ❌ 错误:字面量表初始化器在每次重新渲染时导致状态重置
+local user, set_user = editor.ui.use_state({ first_name = props.first_name, last_name = props.last_name})
+
+-- ✅ 正确:在组件函数外部使用初始化器函数创建表状态
+local function create_user(first_name, last_name) 
+    return { first_name = first_name, last_name = last_name}
+end
+-- ...稍后,在组件函数中:
+local user, set_user = editor.ui.use_state(create_user, props.first_name, props.last_name)
+
+
+-- ❌ 错误:字面量初始化器函数在每次重新渲染时导致状态重置
+local id, set_id = editor.ui.use_state(function() return string.lower(props.name) end)
+
+-- ✅ 正确:使用引用的初始化器函数创建状态
+local id, set_id = editor.ui.use_state(string.lower, props.name)
+```
+
+### **`use_memo`**
+
+您可以使用`use_memo` hook来提高性能。通常在渲染函数中执行一些计算,例如检查用户输入是否有效。`use_memo` hook可用于检查计算函数的参数是否更改比调用计算函数更便宜的情况。hook将在第一次渲染时调用计算函数,如果`use_memo`的所有参数都未更改,则在随后的重新渲染中重用计算值:
+```lua
+-- 组件函数外的验证函数
+local function validate_password(password)
+    if #password < 8 then
+        return false, "Password must be at least 8 characters long."
+    elseif not password:match("%l") then
+        return false, "Password must include at least one lowercase letter."
+    elseif not password:match("%u") then
+        return false, "Password must include at least one uppercase letter."
+    elseif not password:match("%d") then
+        return false, "Password must include at least one number."
+    else
+        return true, "Password is valid."
+    end
+end
+
+-- ...稍后,在组件函数中
+local username, set_username = editor.ui.use_state('')
+local password, set_password = editor.ui.use_state('')
+local valid, message = editor.ui.use_memo(validate_password, password)
+```
+在这个例子中,密码验证将在每次密码更改时运行(例如在密码字段中输入时),但在用户名更改时不会运行。
+
+`use_memo`的另一个用例是创建然后在输入组件上使用的回调,或者当本地创建的函数用作另一个组件的prop值时——这可以防止不必要的重新渲染。

+ 641 - 118
docs/zh/manuals/editor-scripts.md

@@ -1,26 +1,27 @@
 ---
 title: 编辑器脚本
-brief: 本教程介绍了如何使用 Lua 扩展编辑器功能
+brief: 本手册解释了如何使用 Lua 扩展编辑器功能
 ---
 
 # 编辑器脚本
 
-只需使用: `.editor_script` 扩展名的 Lua 脚本就可以创建自定义菜单项和编辑器生命周期回调. 使用这种方法, 你可以调整编辑器创建适合自己的开发流.
+您可以使用具有特殊扩展名的 Lua 文件创建自定义菜单项和编辑器生命周期钩子:`.editor_script`。使用此系统,您可以调整编辑器以增强您的开发工作流程。
 
-## 编辑器脚本运行环境
+## 编辑器脚本运行
 
-编辑器脚本运行于编辑器中, 在一个Java虚拟机下的Lua虚拟机下运行. 所有脚本共享一个环境, 也就是说它们能彼此访问. 你可以导入Lua模块, 就像 `.script` 文件一样, 但是编辑器内lua运行版本不同, 所以要注意代码兼容性. 编辑器使用 Lua 版本 5.2.x, 具体来说就是 [luaj](https://github.com/luaj/luaj) 运行时, 目前只有这个运行时能运行在Java虚拟机下. 除了这些, 还有一些限制:
-- 没有 `debug` 和 `coroutine` 包;
-- 没有 `os.execute` — 我们在 [actions](#actions) 部分提供了更有效安全的方法;
-- 没有 `os.tmpname` 和 `io.tmpfile` — 目前编辑器可存取文件仅限于项目文件夹内的文件;
-- 目前没有 `os.rename`, 以后可能加入;
-- 没有 `os.exit` 和 `os.setlocale`.
+编辑器脚本在编辑器内部运行,在 Java 虚拟机模拟的 Lua 虚拟机中运行。所有脚本共享同一个环境,这意味着它们可以相互交互。您可以导入 Lua 模块,就像使用 `.script` 文件一样,但编辑器内部运行的 Lua 版本不同,因此请确保您的共享代码是兼容的。编辑器使用 Lua 版本 5.2.x,更具体地说是 [luaj](https://github.com/luaj/luaj) 运行时,这目前是在 JVM 上运行 Lua 的唯一可行解决方案。除此之外,还有一些限制:
+- 没有 `debug` 包;
+- 没有 `os.execute`,尽管我们提供了类似的 `editor.execute()`;
+- 没有 `os.tmpname` 和 `io.tmpfile` — 目前编辑器脚本只能访问项目目录内的文件;
+- 目前没有 `os.rename`,尽管我们希望添加它;
+- 没有 `os.exit` 和 `os.setlocale`。
+- 在编辑器需要脚本立即响应的上下文中,不允许使用一些长时间运行的函数,详见[执行模式](#execution-modes)。
 
-用编辑器脚本定义的编辑器扩展会在打开项目时加载. 获取依赖库时, 扩展会重新加载, 因为依赖库里有可能有扩展脚本存在. 重新加载时, 不会改变当前扩展脚本, 因为此时也许你正在编辑它们. 要完全重新加载, 可以使用 Project → Reload 编辑器命令.
+所有在编辑器脚本中定义的编辑器扩展在您打开项目时都会加载。当您获取库时,扩展会重新加载,因为您依赖的库中可能有新的编辑器脚本。在此重新加载期间,不会获取您自己的编辑器脚本的更改,因为您可能正在更改它们。要同时重新加载它们,您应该运行 **Project → Reload Editor Scripts** 命令。
 
-## `.editor_script` 构成
+## `.editor_script` 构成
 
-每个编辑器脚本需要返回一个模块, 如下:
+每个编辑器脚本都应该返回一个模块,如下所示:
 ```lua
 local M = {}
 
@@ -32,40 +33,64 @@ function M.get_language_servers()
   -- TODO - 定义语言服务器
 end
 
+function M.get_prefs_schema()
+  -- TODO - 定义首选项
+end
+
 return M
 ```
-然后编辑器会收集项目中和共享库里的所有的编辑器脚本, 把它们加载到Lua虚拟机中并在需要的时候调用它们 (详情请见 [commands](#commands) 和 [lifecycle hooks](#lifecycle-hooks) 部分).
+然后编辑器会收集项目和库中定义的所有编辑器脚本,将它们加载到单个 Lua 虚拟机中,并在需要时调用它们(更多内容请参见[命令](#commands)和[生命周期钩子](#lifecycle-hooks)部分)。
 
 ## 编辑器 API
 
-可以使用API中 `editor` 包与编辑器进行交互:
-- `editor.platform` —字符串, 在Windows上是 `"x86_64-win32"`, 在macOS上是 `"x86_64-macos"`, 在Linux上是 `"x86_64-linux"`.
-- `editor.get(node_id, property)` — 得到编辑器里某些节点的值. 编辑器里的节点是可变实体, 比如脚本或者集合文件, 集合中的游戏对象, 作为资源加载的 json 文件, 等等. `node_id` 是由编辑器发往编辑器脚本的一个 userdata. 或者, 可以用资源路径代替节点 id, 比如 `"/main/game.script"`. `property` 是一个字符串. 目前支持以下属性:
-  - `"path"` — 基于项目文件夹对 *resources* 的相对路径 — 资源即代表文件. 有效值举例: `"/main/game.script"`
-  - `"text"` — 可编辑文本资源文件 (比如脚本文件或者 json). 有效值举例: `"function init(self)\nend"`. 注意这里跟用 `io.open()` 读取文件不同, 文本资源可以只编辑不保存, 这些编辑仅在访问 `"text"` 属性时有效.
-  - 在大纲试图做点选操作时, 有些属性可以在属性面板显示出来. 可以显示的属性有:
-    - strings
-    - booleans
-    - numbers
-    - vec2/vec3/vec4
-    - resources
-
-    注意这些属性有的不是只读的, 而且基于上下文有些可能不可用, 所以要在读取之前执行 `editor.can_get`, 设置之前执行 `editor.can_set`. 属性面板里用鼠标悬停在属性名上会显示一个信息提示标明该属性在编辑器脚本里是如何命名的. 资源属性赋值为 `""` 代表 nil 值.
-- `editor.can_get(node_id, property)` — 检查属性是否可读, 确保 `editor.get()` 不会报错
-- `editor.can_set(node_id, property)` — 检查属性是否可写, 确保设置操作不会报错
-- `editor.create_directory(resource_path)` — 新建文件夹, 及其所有父文件夹
-- `editor.delete_directory(resource_path)` — 删除文件夹, 及其所有子文件夹和文件.
-
-## Command
-
-如果编辑器脚本模块定义了 `get_commands` 函数, 它会在扩展重载时被调用, 返回的命令可以在编辑器菜单栏或者资源和大纲视图的右键菜单里使用. 例如:
+您可以使用定义此 API 的 `editor` 包与编辑器进行交互:
+- `editor.platform` — 字符串,Windows 上为 `"x86_64-win32"`,macOS 上为 `"x86_64-macos"`,Linux 上为 `"x86_64-linux"`。
+- `editor.version` — 字符串,Defold 的版本名称,例如 `"1.4.8"`
+- `editor.engine_sha1` — 字符串,Defold 引擎的 SHA1
+- `editor.editor_sha1` — 字符串,Defold 编辑器的 SHA1
+- `editor.get(node_id, property)` — 获取编辑器内某个节点的值。编辑器中的节点是各种实体,例如脚本或集合文件,集合内的游戏对象,作为资源加载的 json 文件等。`node_id` 是由编辑器传递给编辑器脚本的 userdata。或者,您可以使用资源路径代替节点 id,例如 `"/main/game.script"`。`property` 是一个字符串。目前支持以下属性:
+  - `"path"` — *资源* 的项目文件夹文件路径 — 作为文件或目录存在的实体。返回值示例:`"/main/game.script"`
+  - `"children"` — 目录资源的子资源路径列表
+  - `"text"` — 可编辑为文本的资源文本内容(例如脚本文件或 json)。返回值示例:`"function init(self)\nend"`。请注意,这与使用 `io.open()` 读取文件不同,因为您可以在不保存文件的情况下编辑文件,这些编辑仅在访问 `"text"` 属性时可用。
+  - 对于图集:`images`(图集中图像的编辑器节点列表)和 `animations`(动画节点列表)
+  - 对于图集动画:`images`(与图集中的 `images` 相同)
+  - 对于瓦片地图:`layers`(瓦片地图中图层的编辑器节点列表)
+  - 对于瓦片地图图层:`tiles`(瓦片的无限 2D 网格),详见 `tilemap.tiles.*`
+  - 对于粒子效果:`emitters`(发射器编辑器节点列表)和 `modifiers`(修改器编辑器节点列表)
+  - 对于粒子效果发射器:`modifiers`(修改器编辑器节点列表)
+  - 对于碰撞对象:`shapes`(碰撞形状编辑器节点列表)
+  - 对于 GUI 文件:`layers`(图层编辑器节点列表)
+  - 当您在大纲视图中选择某些内容时,属性视图中显示的一些属性。这些类型的大纲属性支持:
+    - `strings`
+    - `booleans`
+    - `numbers`
+    - `vec2`/`vec3`/`vec4`
+    - `resources`
+    - `curves`
+    请注意,其中一些属性可能是只读的,有些在不同上下文中可能不可用,因此您应该在读取它们之前使用 `editor.can_get`,在让编辑器设置它们之前使用 `editor.can_set`。将鼠标悬停在属性视图中的属性名称上,可以看到一个工具提示,其中包含有关该属性在编辑器脚本中如何命名的信息。您可以通过提供 `""` 值将资源属性设置为 `nil`。
+- `editor.can_get(node_id, property)` — 检查您是否可以获取此属性,以便 `editor.get()` 不会抛出错误。
+- `editor.can_set(node_id, property)` — 检查带有此属性的 `editor.tx.set()` 事务步骤不会抛出错误。
+- `editor.create_directory(resource_path)` — 如果目录不存在,则创建目录,以及所有不存在的父目录。
+- `editor.create_resources(resources)` — 创建 1 个或多个资源,可以从模板创建或使用自定义内容创建
+- `editor.delete_directory(resource_path)` — 如果目录存在,则删除目录,以及所有存在的子目录和文件。
+- `editor.execute(cmd, [...args], [options])` — 运行 shell 命令,可选择捕获其输出。
+- `editor.save()` — 将所有未保存的更改持久化到磁盘。
+- `editor.transact(txs)` — 使用 1 个或多个由 `editor.tx.*` 函数创建的事务步骤修改编辑器内存状态。
+- `editor.ui.*` — 各种与 UI 相关的函数,请参见[UI 手册](/manuals/editor-scripts-ui)。
+- `editor.prefs.*` — 与编辑器首选项交互的函数,请参见[首选项](#preferences)。
+
+您可以在[此处](https://defold.com/ref/alpha/editor/)找到完整的编辑器 API 参考。
+
+## 命令
+
+如果编辑器脚本模块定义了函数 `get_commands`,它将在扩展重新加载时被调用,返回的命令将在编辑器的菜单栏或资源和大纲窗格的上下文菜单中可用。例如:
 ```lua
 local M = {}
 
 function M.get_commands()
   return {
     {
-      label = "Remove Comments",
+      label = "删除注释",
       locations = {"Edit", "Assets"},
       query = {
         selection = {type = "resource", cardinality = "one"}
@@ -76,18 +101,13 @@ function M.get_commands()
       end,
       run = function(opts)
         local text = editor.get(opts.selection, "text")
-        return {
-          {
-            action = "set",
-            node_id = opts.selection,
-            property = "text",
-            value = strip_comments(text)
-          }
-        }
+        editor.transact({
+          editor.tx.set(opts.selection, "text", strip_comments(text))
+        })
       end
     },
     {
-      label = "Minify JSON",
+      label = "压缩 JSON",
       locations = {"Assets"},
       query = {
         selection = {type = "resource", cardinality = "one"}
@@ -97,12 +117,7 @@ function M.get_commands()
       end,
       run = function(opts)
         local path = editor.get(opts.selection, "path")
-        return {
-          {
-            action = "shell",
-            command = {"./scripts/minify-json.sh", path:sub(2)}
-          }
-        }
+        editor.execute("./scripts/minify-json.sh", path:sub(2))
       end
     }
   }
@@ -110,66 +125,395 @@ end
 
 return M
 ```
-编辑器需要 `get_commands()` 返回一组 table, 每个 table 描述一个命令. 命令描述由以下部分组成:
+编辑器期望 `get_commands()` 返回一个表数组,每个表描述一个单独的命令。命令描述包括:
+
+- `label`(必需)— 将显示给用户的菜单项上的文本
+- `locations`(必需)— 一个数组,包含 `"Edit"`、`"View"`、`"Project"`、`"Debug"`、`"Assets"`、`"Bundle"`、`"Scene"` 或 `"Outline"` 中的一个或多个,描述了该命令应该可用的位置。`"Edit"`、`"View"`、`"Project"` 和 `"Debug"` 表示顶部的菜单栏,`"Assets"` 表示资源窗格中的上下文菜单,`"Outline"` 表示大纲窗格中的上下文菜单,`"Bundle"` 表示 **Project → Bundle** 子菜单。
+- `query` — 命令向编辑器询问相关信息并定义它操作的数据的一种方式。对于 `query` 表中的每个键,`opts` 表中将有相应的键,`active` 和 `run` 回调将作为参数接收。支持的键:
+  - `selection` 表示此命令在有选择内容时有效,并且它对该选择进行操作。
+    - `type` 是命令感兴趣的所选节点类型,目前允许的类型有:
+      - `"resource"` — 在资源和大纲中,资源是具有相应文件的选定项。在菜单栏(编辑或视图)中,资源是当前打开的文件;
+      - `"outline"` — 可以在大纲中显示的内容。在大纲中它是选定项,在菜单栏中它是当前打开的文件;
+      - `"scene"` — 可以渲染到场景中的内容。
+    - `cardinality` 定义应该有多少个选定项。如果是 `"one"`,传递给命令回调的选择将是单个节点 id。如果是 `"many"`,传递给命令回调的选择将是一个或多个节点 id 的数组。
+  - `argument` — 命令参数。目前,只有 `"Bundle"` 位置中的命令接收参数,当明确选择打包命令时为 `true`,在重新打包时为 `false`。
+- `id` - 命令标识符字符串,例如用于在 `prefs` 中持久化最后使用的打包命令
+- `active` - 一个回调函数,用于检查命令是否处于活动状态,预期返回布尔值。如果 `locations` 包括 `"Assets"`、`"Scene"` 或 `"Outline"`,在显示上下文菜单时将调用 `active`。如果位置包括 `"Edit"` 或 `"View"`,则会在每次用户交互时调用 active,例如键盘输入或鼠标点击,因此请确保 `active` 相对较快。
+- `run` - 当用户选择菜单项时执行的回调函数。
+
+### 使用命令更改编辑器内存状态
+
+在 `run` 处理程序中,您可以查询和更改编辑器的内存状态。查询使用 `editor.get()` 函数完成,您可以在其中询问编辑器有关文件和选择的当前状态(如果使用 `query = {selection = ...}`)。您可以获取脚本文件的 `"text"` 属性,以及属性视图中显示的一些属性 — 将鼠标悬停在属性名称上以查看工具提示,其中包含有关该属性在编辑器脚本中如何命名的信息。更改编辑器状态使用 `editor.transact()` 完成,您可以在其中将 1 个或多个修改捆绑在一个可撤销的步骤中。例如,如果您希望能够重置游戏对象的变换,您可以编写如下命令:
+```lua
+{
+  label = "重置变换",
+  locations = {"Outline"},
+  query = {selection = {type = "outline", cardinality = "one"}},
+  active = function(opts)
+    local node = opts.selection
+    return editor.can_set(node, "position") 
+       and editor.can_set(node, "rotation") 
+       and editor.can_set(node, "scale")
+  end,
+  run = function(opts)
+    local node = opts.selection
+    editor.transact({
+      editor.tx.set(node, "position", {0, 0, 0}),
+      editor.tx.set(node, "rotation", {0, 0, 0}),
+      editor.tx.set(node, "scale", {1, 1, 1})
+    })
+  end
+}
+```
 
-- `label` (必要) — 显示在菜单栏项上的文字
-- `locations` (必要) — 包含 `"Edit"`, `"View"`, `"Assets"` 或者 `"Outline"` 的数组, 描述该命令在哪里生效. `"Edit"` 和 `"View"` 表示菜单栏最高层, `"Assets"` 表示在资源视图右键菜单里, "Outline"` 表示在大纲视图右键菜单里.
-- `query` — 命令向编辑器查询信息并定义被操作数据的地方. 在 `query` 表里的每个键都会一一对应包裹在 `opts` 表里, 作为参数传给 `active` 和 `run` 回调函数. 支持的 key 有:
-  - `selection` 意思是在选择了什么时可用, 操作将作用于被选择的东西上.
-    - `type` 命令能作用于选择节点的类型, 目前支持以下几种:
-      - `"resource"` — 大纲视图或者资源视图里, 被选择资源对应的文件. 在菜单栏 (Edit 或 View), 资源是当前打开了的文件;
-      - `"outline"` — 在大纲视图显示的东西. 在大纲视图被选择的项, 在菜单栏是当前打开了的文件;
-    - `cardinality` 定义备选项的个数. 如果是 `"one"`, 将传给命令回调一个节点 id. 如果是 `"many"`, 将传给命令回调一个数组, 包含一个或多个节点 id.
-- `active` - 检测命令是否可用的回调, 返回布尔值. 如果 `locations` 包含 `"Assets"` 或 `"Outline"`, `active` 会在显示右键菜单时被调用. 如果包含 `"Edit"` 或 `"View"`, 它会在每个用户交互时被调用, 比如按键盘或者点鼠标的时候, 所以 `active` 应该快速执行完毕.
-- `run` - 用户点选菜单项时运行的回调, 返回包含 [actions](#actions) 的数组.
+#### 编辑图集
 
-## Action
+除了读取和写入图集的属性外,您还可以读取和修改图集图像和动画。图集定义了 `images` 和 `animations` 节点列表属性,动画定义了 `images` 节点列表属性:您可以将 `editor.tx.add`、`editor.tx.remove` 和 `editor.tx.clear` 事务步骤与这些属性一起使用。
 
-行为是描述编辑器要做什么的表. 每个行为包含一个 `action` 键. 行为有两种: 可撤销行为和不可撤销行为.
+例如,要向图集添加图像,请在命令的 `run` 处理程序中执行以下代码:
+```lua
+editor.transact({
+    editor.tx.add("/main.atlas", "images", {image="/assets/hero.png"})
+})
+```
+要查找图集中的所有图像集,请执行以下代码:
+```lua
+local all_images = {} ---@type table<string, true>
+-- 首先,收集所有"裸"图像
+local image_nodes = editor.get("/main.atlas", "images")
+for i = 1, #image_nodes do
+    all_images[editor.get(image_nodes[i], "image")] = true
+end
+-- 其次,收集动画中使用的所有图像
+local animation_nodes = editor.get("/main.atlas", "animations")
+for i = 1, #animation_nodes do
+    local animation_image_nodes = editor.get(animation_nodes[i], "images")
+    for j = 1, #animation_image_nodes do
+        all_images[editor.get(animation_image_nodes[j], "image")] = true
+    end
+end
+pprint(all_images)
+-- {
+--     ["/assets/hero.png"] = true,
+--     ["/assets/enemy.png"] = true,
+-- }}
+```
+要替换图集中的所有动画:
+```lua
+editor.transact({
+    editor.tx.clear("/main.atlas", "animations"),
+    editor.tx.add("/main.atlas", "animations", {
+        id = "hero_run",
+        images = {
+            {image = "/assets/hero_run_1.png"},
+            {image = "/assets/hero_run_2.png"},
+            {image = "/assets/hero_run_3.png"},
+            {image = "/assets/hero_run_4.png"}
+        }
+    })
+})
+```
 
-### 可撤销行为
+#### 编辑瓦片源
 
-可撤销行为在执行后可以撤销. 如果一个命令返回了多个可撤销行为, 它们会一起执行, 撤销时也一起被撤销. 应尽量使用可撤销行为. 只是可撤销行为有更多一些限制.
+除了大纲属性外,瓦片源还定义了以下属性:
+- `animations` - 瓦片源的动画节点列表
+- `collision_groups` - 瓦片源的碰撞组节点列表
+- `tile_collision_groups` - 瓦片源中瓦片的碰撞组分配表
 
-目前的可撤销行为有:
-- `"set"` — 设置编辑器里一个节点的属性为指定值. 例如:
-  ```lua
-  {
-    action = "set",
-    node_id = opts.selection,
-    property = "text",
-    value = "current time is " .. os.date()
-  }
-  ```
-  `"set"` 行为有如下键:
-  - `node_id` — 表示节点 id 的 userdata. 或者, 可以用资源路径代替编辑器发来的节点 id, 例如 `"/main/game.script"`;
-  - `property` — 要设置的节点属性, 目前只支持 `"text"`;
-  - `value` — 给节点属性设置的新值. 对于 `"text"` 属性来说该值应该是一个字符串.
+例如,以下是设置瓦片源的方法:
+```lua
+local tilesource = "/game/world.tilesource"
+editor.transact({
+    editor.tx.add(tilesource, "animations", {id = "idle", start_tile = 1, end_tile = 1}),
+    editor.tx.add(tilesource, "animations", {id = "walk", start_tile = 2, end_tile = 6, fps = 10}),
+    editor.tx.add(tilesource, "collision_groups", {id = "player"}),
+    editor.tx.add(tilesource, "collision_groups", {id = "obstacle"}),
+    editor.tx.set(tilesource, "tile_collision_groups", {
+        [1] = "player",
+        [7] = "obstacle",
+        [8] = "obstacle"
+    })
+})
+```
 
-### 不可撤销行为
+#### 编辑瓦片地图
 
-不可撤销行为会清空可撤销历史, 所以要撤销这种行为, 必须使用其他特殊方法, 比如版本控制系统.
+瓦片地图定义了 `layers` 属性,即瓦片地图图层的节点列表。每个图层还定义了 `tiles` 属性,该属性保存此图层上瓦片的无限 2D 网格。这与引擎不同:瓦片没有边界,可以添加到任何位置,包括负坐标。要编辑瓦片,编辑器脚本 API 定义了一个 `tilemap.tiles` 模块,具有以下功能:
+- `tilemap.tiles.new()` 创建一个新的数据结构,用于保存无限的 2D 瓦片网格(在编辑器中,与引擎相反,瓦片地图是无限的,坐标可以是负数)
+- `tilemap.tiles.get_tile(tiles, x, y)` 获取特定坐标处的瓦片索引
+- `tilemap.tiles.get_info(tiles, x, y)` 获取特定坐标处的完整瓦片信息(数据形状与引擎的 `tilemap.get_tile_info` 函数相同)
+- `tilemap.tiles.iterator(tiles)` 创建一个遍历瓦片地图中所有瓦片的迭代器
+- `tilemap.tiles.clear(tiles)` 从瓦片地图中移除所有瓦片
+- `tilemap.tiles.set(tiles, x, y, tile_or_info)` 在特定坐标处设置瓦片
+- `tilemap.tiles.remove(tiles, x, y)` 移除特定坐标处的瓦片
 
-目前可用的不可撤销行为:
-- `"shell"` — 执行一个 shell 脚本. 例如:
-  ```lua
-  {
-    action = "shell",
-    command = {
-      "./scripts/minify-json.sh",
-      editor.get(opts.selection, "path"):sub(2) -- trim leading "/"
-    }
-  }
-  ```
-  `"shell"` 行为要有一个 `command` 键, 它是一组命令连同其参数. 它与 `os.execute` 主要区别在于, 鉴于它是一种潜在危险操作, 编辑器会弹出一个对话框询问用户是否确认进行此操作. 用户允许的每个命令授权都会被记住.
+例如,以下是打印整个瓦片地图内容的方法:
+```lua
+local layers = editor.get("/level.tilemap", "layers")
+for i = 1, #layers do
+    local layer = layers[i]
+    local id = editor.get(layer, "id")
+    local tiles = editor.get(layer, "tiles")
+    print("layer " .. id .. ": {")
+    for x, y, tile in tilemap.tiles.iterator(tiles) do
+        print("  [" .. x .. ", " .. y .. "] = " .. tile)
+    end
+    print("}")
+end
+```
 
-### 行为混用及其副作用
+以下示例显示如何向瓦片地图添加带有瓦片的图层:
+```lua
+local tiles = tilemap.tiles.new()
+tilemap.tiles.set(tiles, 1, 1, 2)
+editor.transact({
+    editor.tx.add("/level.tilemap", "layers", {
+        id = "new_layer",
+        tiles = tiles
+    })
+})
+```
 
-可以混用可撤销行为和不可撤销行为. 行为是依次执行的, 根据执行顺序撤销操作会停在不可撤销行为上.
+#### 编辑粒子效果
 
-除了从函数返回行为, 还可以直接用 `io.open()` 读写文件. 这会触发资源重载并且清空撤销历史记录.
+您可以使用 `modifiers` 和 `emitters` 属性编辑粒子效果。例如,添加带有加速度修改器的圆形发射器的方法如下:
+```lua
+editor.transact({
+    editor.tx.add("/fire.particlefx", "emitters", {
+        type = "emitter-type-circle",
+        modifiers = {
+          {type = "modifier-type-acceleration"}
+        }
+    })
+})
+```
+许多粒子效果属性是曲线或曲线扩展(即曲线 + 一些随机值)。曲线表示为具有非空 `points` 列表的表,其中每个点是具有以下属性的表:
+- `x` - 点的 x 坐标,应从 0 开始,以 1 结束
+- `y` - 点的值
+- `tx`(0 到 1)和 `ty`(-1 到 1)- 点的切线。例如,对于 80 度角,`tx` 应该是 `math.cos(math.rad(80))`,`ty` 应该是 `math.sin(math.rad(80))`。
+曲线扩展还具有 `spread` 数字属性。
+
+例如,为现有发射器设置粒子生命周期 alpha 曲线可能如下所示:
+```lua
+local emitter = editor.get("/fire.particlefx", "emitters")[1]
+editor.transact({
+    editor.tx.set(emitter, "particle_key_alpha", { points = {
+        {x = 0,   y = 0, tx = 0.1, ty = 1}, -- 从 0 开始,快速上升
+        {x = 0.2, y = 1, tx = 1,   ty = 0}, -- 在生命周期的 20% 处达到 1
+        {x = 1,   y = 0, tx = 1,   ty = 0}  -- 缓慢下降到 0
+    }})
+})
+```
+当然,也可以在创建发射器时在表中使用 `particle_key_alpha` 键。此外,您可以使用单个数字来表示"静态"曲线。
+
+#### 编辑碰撞对象
+
+除了默认的大纲属性外,碰撞对象还定义了 `shapes` 节点列表属性。添加新的碰撞形状的方法如下:
+```lua
+editor.transact({
+    editor.tx.add("/hero.collisionobject", "shapes", {
+        type = "shape-type-box" -- 或 "shape-type-sphere", "shape-type-capsule"
+    })
+})
+```
+形状的 `type` 属性在创建期间是必需的,并且在添加形状后不能更改。有 3 种形状类型:
+- `shape-type-box` - 具有 `dimensions` 属性的盒形
+- `shape-type-sphere` - 具有 `diameter` 属性的球形
+- `shape-type-capsule` - 具有 `diameter` 和 `height` 属性的胶囊形
+
+#### 编辑 GUI 文件
+
+除了大纲属性外,GUI 节点还定义了以下属性:
+- `layers` — 图层编辑器节点列表(可重新排序)
+- `materials` — 材质编辑器节点列表
+
+可以使用编辑器的 `layers` 属性编辑 GUI 图层,例如:
+```lua
+editor.transact({
+    editor.tx.add("/main.gui", "layers", {name = "foreground"}),
+    editor.tx.add("/main.gui", "layers", {name = "background"})
+})
+```
+此外,可以重新排序图层:
+```lua
+local fg, bg = table.unpack(editor.get("/main.gui", "layers"))
+editor.transact({
+    editor.tx.reorder("/main.gui", "layers", {bg, fg})
+})
+```
+类似地,使用 `fonts`、`materials`、`textures` 和 `particlefxs` 属性编辑字体、材质、纹理和粒子效果:
+```lua
+editor.transact({
+    editor.tx.add("/main.gui", "fonts", {font = "/main.font"}),
+    editor.tx.add("/main.gui", "materials", {name = "shine", material = "/shine.material"}),
+    editor.tx.add("/main.gui", "particlefxs", {particlefx = "/confetti.material"}),
+    editor.tx.add("/main.gui", "textures", {texture = "/ui.atlas"})
+})
+```
+这些属性不支持重新排序。
+
+最后,您可以使用 `nodes` 列表属性编辑 GUI 节点,例如:
+```lua
+editor.transact({
+    editor.tx.add("/main.gui", "nodes", {
+        type = "gui-node-type-box",
+        position = {20, 20, 20}
+    }),
+    editor.tx.add("/main.gui", "nodes", {
+        type = "gui-node-type-template",
+        template = "/button.gui"
+    }),
+})
+```
+内置节点类型有:
+- `gui-node-type-box`
+- `gui-node-type-particlefx`
+- `gui-node-type-pie`
+- `gui-node-type-template`
+- `gui-node-type-text`
+
+如果您使用spine扩展,还可以使用`gui-node-type-spine`节点类型。
+
+如果GUI文件定义了布局,您可以使用`layout:property`语法从布局中获取和设置值,例如:
+```lua
+local node = editor.get("/main.gui", "nodes")[1]
+
+-- GET:
+local position = editor.get(node, "position")
+pprint(position) -- {20, 20, 20}
+local landscape_position = editor.get(node, "Landscape:position")
+pprint(landscape_position) -- {20, 20, 20}
+
+-- SET:
+editor.transact({
+    editor.tx.set(node, "Landscape:position", {30, 30, 30})
+})
+pprint(editor.get(node, "Landscape:position")) -- {30, 30, 30}
+```
+
+可以使用`editor.tx.reset`重置已设置的布局属性为默认值:
+```lua
+print(editor.can_reset(node, "Landscape:position")) -- true
+editor.transact({
+    editor.tx.reset(node, "Landscape:position")
+})
+```
+
+模板节点树可以被读取,但不能编辑 — 您只能设置模板节点树的节点属性:
+```lua
+local template = editor.get("/main.gui", "nodes")[2]
+print(editor.can_add(template, "nodes")) -- false
+local node_in_template = editor.get(template, "nodes")[1]
+editor.transact({
+    editor.tx.set(node_in_template, "text", "Button text")
+})
+print(editor.can_reset(node_in_template, "text")) -- true (覆盖模板中的值)
+```
+
+#### 编辑游戏对象
+
+可以使用编辑器脚本编辑游戏对象文件的组件。组件有两种类型:引用型和嵌入型。引用型组件使用`component-reference`类型,作为对其他资源的引用,只允许覆盖脚本中定义的go属性。嵌入型组件使用`sprite`、`label`等类型,允许编辑组件类型中定义的所有属性,以及添加子组件(如碰撞对象的形状)。例如,您可以使用以下代码设置游戏对象:
+```lua
+editor.transact({
+    editor.tx.add("/npc.go", "components", {
+        type = "sprite",
+        id = "view"
+    }),
+    editor.tx.add("/npc.go", "components", {
+        type = "collisionobject",
+        id = "collision",
+        shapes = {
+            {
+                type = "shape-type-box",
+                dimensions = {32, 32, 32}
+            }
+        }
+    }),
+    editor.tx.add("/npc.go", "components", {
+        type = "component-reference",
+        path = "/npc.script",
+        id = "controller",
+        __hp = 100 -- 设置脚本中定义的go属性
+    })
+})
+```
+
+#### 编辑集合
+
+可以使用编辑器脚本编辑集合。您可以添加游戏对象(嵌入型或引用型)和集合(引用型)。例如:
+```lua
+local coll = "/char.collection"
+editor.transact({
+    editor.tx.add(coll, "children", {
+        -- 嵌入式游戏对象
+        type = "go",
+        id = "root",
+        children = {
+            {
+                -- 引用型游戏对象
+                type = "go-reference",
+                path = "/char-view.go",
+                id = "view"
+            },
+            {
+                -- 引用型集合
+                type = "collection-reference",
+                path = "/body-attachments.collection",
+                id = "attachments"
+            }
+        },
+        -- 嵌入式游戏对象也可以有组件
+        components = {
+            {
+                type = "collisionobject",
+                id = "collision",
+                shapes = {
+                    {type = "shape-type-box", dimensions = {2.5, 2.5, 2.5}}
+                }
+            },
+            {
+                type = "component-reference",
+                id = "controller",
+                path = "/char.script",
+                __hp = 100 -- 设置脚本中定义的go属性
+            }
+        }
+    })
+})
+```
 
-## Lifecycle hooks
+与编辑器中一样,引用型集合只能添加到被编辑集合的根目录,而游戏对象只能添加到嵌入式或引用型游戏对象,但不能添加到引用型集合或这些引用型集合中的游戏对象。
+
+### 使用 shell 命令
+
+在`run`处理程序中,您可以写入文件(使用`io`模块)并执行shell命令(使用`editor.execute()`命令)。执行shell命令时,可以将shell命令的输出捕获为字符串,然后在代码中使用它。例如,如果您想创建一个格式化JSON的命令,该命令使用全局安装的[`jq`](https://jqlang.github.io/jq/),您可以编写以下命令:
+```lua
+{
+  label = "Format JSON",
+  locations = {"Assets"},
+  query = {selection = {type = "resource", cardinality = "one"}},
+  action = function(opts)
+    local path = editor.get(opts.selection, "path")
+    return path:match(".json$") ~= nil
+  end,
+  run = function(opts)
+    local text = editor.get(opts.selection, "text")
+    local new_text = editor.execute("jq", "-n", "--argjson", "data", text, "$data", {
+      reload_resources = false, -- 不要重新加载资源,因为jq不接触磁盘
+      out = "capture" -- 返回文本输出而不是无输出
+    })
+    editor.transact({ editor.tx.set(opts.selection, "text", new_text) })
+  end
+}
+```
+由于此命令以只读方式调用shell程序(并使用`reload_resources = false`通知编辑器),您可以使此操作可撤销。
+
+::: sidenote
+如果您想将编辑器脚本作为库分发,您可能希望将编辑器平台的二进制程序捆绑在依赖项中。有关如何执行此操作的更多详细信息,请参阅[库中的编辑器脚本](#editor-scripts-in-libraries)。
+:::
+
+## 生命周期钩子
 
 有一个特殊的编辑器脚本文件: `hooks.editor_script`, 位于项目根目录, 就是跟 *game.project* 并存于同一目录. 只有这个编辑器脚本会从编辑器获得生命周期事件. 脚本文件举例:
 ```lua
@@ -177,7 +521,7 @@ local M = {}
 
 function M.on_build_started(opts)
   local file = io.open("assets/build.json", "w")
-  file:write("{\"build_time\": \"".. os.date() .."\"}")
+  file:write('{"build_time": "' .. os.date() .. '"}')
   file:close()
 end
 
@@ -185,9 +529,7 @@ return M
 ```
 我们决定将生命周期事件只发给这个文件, 这里构建事件顺序比加入构建步骤容易度更重要. 命令互相独立, 所以它们在菜单里的次序并不重要, 用户回选择需要的命令来执行. 编译事件也可以发给多个脚本, 但这会产生一个问题: 事件顺序是什么样的? 你可能希望压缩资源后检查校验和... 用单一文件通过每步的函数配置好构建步骤不失为一种解决方案.
 
-生命周期函数可以返回行为或者在项目文件夹的文件里写入数据.
-
-目前的生命周期脚本 `/hooks.editor_script` 可以指定:
+现有的生命周期钩子 `/hooks.editor_script` 可以指定:
 - `on_build_started(opts)` — 游戏开始构建到本地或某远程设备上时执行. 你的更改, 不论是返回行为还是更新文件内容, 都会反应在构建好的游戏中. 在这里抛出错误的话会导致构建终止. `opts` 是包含如下 key 的表:
   - `platform` — `%arch%-%os%` 格式的字符串, 描述了构建的目标平台, 目前其值与 `editor.platform` 中的值相同.
 - `on_build_finished(opts)` — 构建完成时执行, 无论构建成功与否. `opts` 是包含如下 key 的表:
@@ -203,20 +545,11 @@ return M
 
 注意目前生命周期处理脚本只是编辑器特性, 使用 Bob 以命令行编译打包时该脚本不会被执行.
 
-## Editor scripts in libraries
-
-可以为他人发布包含命令的库, 编辑器会自动配置它们. 事件处理脚本除外, 因为它要放在项目根目录, 而库则是解压在子目录里. 这是为了在构建处理时提供更多控制权: 可以在 `.lua` 文件里提供简单的事件处理函数, 库用户则可以在他们的 `/hooks.editor_script` 文件里引入并使用它们.
-
-还要注意虽然依赖库显示在资源视窗里, 它们却不是文件 (而是 zip 包), 所以目前没办法从依赖库里执行 shell 脚本. 如果实在要执行, 需要先用 `editor.get()` 读取脚本, 然后用 `file:write()` 写入脚本文件, 比如写到 `build/editor-scripts/your-extension-name` 目录下.
-
-更简单的办法是使用原生扩展插件系统.
-首先在库目录创建 `ext.manifest` 文件, 然后在 `ext.manifest` 文件所在文件夹里创建 `plugins/bin/${platform}`. 该文件夹下的文件会被自动提取到 `/build/plugins/${extension-path}/plugins/bin/${platform}` 目录下, 可以在编辑器脚本中引用它们.
+## 语言服务器
 
-## Language servers
+编辑器支持 [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) 的子集。虽然我们旨在未来扩展编辑器对 LSP 功能的支持,但目前它只能在编辑的文件中显示诊断(即 lints)并提供补全。
 
-编辑器支持 [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) 的小子集. 我们计划以后全面支持 LSP 特性, 但是目前只支持显示编辑文件的代码审查 (比如 lints).
-
-要定义 language server, 需要设置编辑器脚本的 `get_language_servers` 函数如下:
+要定义语言服务器,您需要像这样编辑编辑器脚本的 `get_language_servers` 函数:
 
 ```lua
 function M.get_language_servers()
@@ -235,9 +568,199 @@ function M.get_language_servers()
   }
 end
 ```
-编辑器会使用指定 `command` 启动 language server, 使用服务器进程的标准输入和输出进行通信.
+编辑器将使用指定的 `command` 启动语言服务器,使用服务器进程的标准输入和输出进行通信。
+
+语言服务器定义表可以指定:
+- `languages`(必需)— 服务器感兴趣的语言列表,如[此处](https://code.visualstudio.com/docs/languages/identifiers#_known-language-identifiers)所定义(文件扩展名也可以工作);
+- `command`(必需)- 命令及其参数的数组
+- `watched_files` - 带有 `pattern` 键(glob)的表数组,将触发服务器的[监视文件更改](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeWatchedFiles)通知。
+
+## HTTP 服务器
+
+每个运行的编辑器实例都有一个正在运行的 HTTP 服务器。可以使用编辑器脚本扩展该服务器。要扩展编辑器 HTTP 服务器,您需要添加 `get_http_server_routes` 编辑器脚本函数 — 它应该返回额外的路由:
+```lua
+print("My route: " .. http.server.url .. "/my-extension")
+
+function M.get_http_server_routes()
+  return {
+    http.server.route("/my-extension", "GET", function(request)
+      return http.server.response(200, "Hello world!")
+    end)
+  }
+end
+```
+重新加载编辑器脚本后,您将在控制台中看到以下输出:`My route: http://0.0.0.0:12345/my-extension`。如果在浏览器中打开此链接,您将看到您的 `"Hello world!"` 消息。
+
+输入的 `request` 参数是一个包含请求信息的简单 Lua 表。它包含诸如 `path`(以 `/` 开头的 URL 路径段)、请求 `method`(例如 `"GET"`)、`headers`(带有小写标题名称的表)以及可选的 `query`(查询字符串)和 `body`(如果路由定义了如何解释正文)等键。例如,如果您想创建一个接受 JSON 正文的路由,可以使用 `"json"` 转换器参数定义它:
+```lua
+http.server.route("/my-extension/echo-request", "POST", "json", function(request)
+  return http.server.json_response(request)
+end)
+```
+您可以使用 `curl` 和 `jq` 在命令行中测试此端点:
+```sh
+curl 'http://0.0.0.0:12345/my-extension/echo-request?q=1' -X POST --data '{"input": "json"}' | jq
+{
+  "path": "/my-extension/echo-request",
+  "method": "POST",
+  "query": "q=1",
+  "headers": {
+    "host": "0.0.0.0:12345",
+    "content-type": "application/x-www-form-urlencoded",
+    "accept": "*/*",
+    "user-agent": "curl/8.7.1",
+    "content-length": "17"
+  },
+  "body": {
+    "input": "json"
+  }
+}
+```
+路由路径支持可以从请求路径中提取并作为请求的一部分提供给处理函数的模式,例如:
+```lua
+http.server.route("/my-extension/setting/{category}.{key}", function(request)
+  return http.server.response(200, tostring(editor.get("/game.project", request.category .. "." .. request.key)))
+end)
+```
+现在,如果您打开例如 `http://0.0.0.0:12345/my-extension/setting/project.title`,您将看到从 `/game.project` 文件中获取的游戏标题。
+
+除了单段路径模式外,您还可以使用 `{*name}` 语法匹配 URL 路径的其余部分。例如,这是一个简单的文件服务器端点,它从项目根目录提供文件:
+```lua
+http.server.route("/my-extension/files/{*file}", function(request)
+  local attrs = editor.external_file_attributes(request.file)
+  if attrs.is_file then
+    return http.server.external_file_response(request.file)
+  else
+    return 404
+  end
+end)
+```
+现在,在浏览器中打开例如 `http://0.0.0.0:12345/my-extension/files/main/main.collection` 将显示 `main/main.collection` 文件的内容。
+
+## 库中的编辑器脚本
+
+您可以发布包含命令的库供他人使用,编辑器会自动获取这些命令。另一方面,钩子不能自动获取,因为它们必须定义在项目根目录的文件中,而库只公开子文件夹。这是为了在构建过程中提供更多控制:您仍然可以在 `.lua` 文件中创建生命周期钩子作为简单函数,以便库的用户可以在他们的 `/hooks.editor_script` 中 require 并使用它们。
+
+还要注意,尽管依赖项显示在资源视图中,但它们并不作为文件存在(它们是 zip 存档中的条目)。可以使编辑器从依赖项中提取一些文件到 `build/plugins/` 文件夹中。为此,您需要在库文件夹中创建 `ext.manifest` 文件,然后在 `ext.manifest` 文件所在的同一文件夹中创建 `plugins/bin/${platform}` 文件夹。该文件夹中的文件将自动提取到 `/build/plugins/${extension-path}/plugins/bin/${platform}` 文件夹,因此您的编辑器脚本可以引用它们。
+
+## 首选项
+
+编辑器脚本可以定义和使用首选项 — 存储在用户计算机上的持久化、未提交的数据。这些首选项具有三个关键特性:
+- 类型化:每个首选项都有一个模式定义,包括数据类型和其他元数据,如默认值
+- 作用域:首选项的作用域可以是每个项目或每个用户
+- 嵌套:每个首选项键是一个点分隔的字符串,其中第一个路径段标识一个编辑器脚本,其余部分
+
+所有首选项必须通过定义其模式来注册:
+```lua
+function M.get_prefs_schema()
+  return {
+    ["my_json_formatter.jq_path"] = editor.prefs.schema.string(),
+    ["my_json_formatter.indent.size"] = editor.prefs.schema.integer({default = 2, scope = editor.prefs.SCOPE.PROJECT}),
+    ["my_json_formatter.indent.type"] = editor.prefs.schema.enum({values = {"spaces", "tabs"}, scope = editor.prefs.SCOPE.PROJECT}),
+  }
+end
+```
+重新加载此类编辑器脚本后,编辑器将注册此模式。然后编辑器脚本可以获取和设置首选项,例如:
+```lua
+-- 获取特定首选项
+editor.prefs.get("my_json_formatter.indent.type")
+-- 返回: "spaces"
+
+-- 获取整个首选项组
+editor.prefs.get("my_json_formatter")
+-- 返回:
+-- {
+--   jq_path = "",
+--   indent = {
+--     size = 2,
+--     type = "spaces"
+--   }
+-- }
+
+-- 一次设置多个嵌套首选项
+editor.prefs.set("my_json_formatter.indent", {
+    type = "tabs",
+    size = 1
+})
+```
+
+## 执行模式
+
+编辑器脚本运行时使用两种执行模式,这些模式对编辑器脚本基本上是透明的:**即时**和**长时间运行**。 
+
+**即时**模式用于编辑器需要尽快从脚本接收响应的情况。例如,菜单命令的 `active` 回调在即时模式下执行,因为这些检查是在编辑器 UI 线程上响应与编辑器的用户交互而执行的,并且应该在同一帧内更新 UI。 
+
+**长时间运行**模式用于编辑器不需要脚本即时响应的情况。例如,菜单命令的 `run` 回调在**长时间运行**模式下执行,允许脚本有更多时间来完成其工作。
+
+编辑器脚本可以使用的一些函数可能需要很长时间才能运行。例如,`editor.execute("git", "status", {reload_resources=false, out="capture"})` 在足够大的项目上可能需要长达一秒钟的时间。为了保持编辑器的响应性和性能,在编辑器需要即时响应的情况下,不允许使用可能耗时的函数。尝试在即时上下文中使用此类函数将导致错误:`Cannot use long-running editor function in immediate context`。要解决此错误,请避免在即时上下文中使用此类函数。
+
+以下函数被认为是长时间运行的,不能在即时模式下使用:
+- `editor.create_directory()`、`editor.create_resources()`、`editor.delete_directory()`、`editor.save()`、`os.remove()` 和 `file:write()`:这些函数修改磁盘上的文件,导致编辑器将其内存中的资源树与磁盘状态同步,这在大型项目中可能需要几秒钟。
+- `editor.execute()`:执行 shell 命令可能需要不可预测的时间。
+- `editor.transact()`:对广泛引用的节点的大型事务可能需要数百毫秒,这对于 UI 响应性来说太慢了。
+
+以下代码执行上下文使用即时模式:
+- 菜单命令的 `active` 回调:编辑器需要在同一 UI 帧内从脚本接收响应。
+- 编辑器脚本的顶层:我们不期望重新加载编辑器脚本的行为有任何副作用。
+
+## 操作
+
+::: sidenote
+以前,编辑器以阻塞方式与 Lua VM 交互,因此编辑器脚本有一个硬性要求,即不能阻塞,因为某些交互必须从编辑器 UI 线程完成。因此,例如没有 `editor.execute()` 和 `editor.transact()`。执行脚本和更改编辑器状态是通过从钩子和命令 `run` 处理程序返回一个 "actions" 数组来触发的。
+
+现在编辑器以非阻塞方式与 Lua VM 交互,因此不再需要这些操作:使用像 `editor.execute()` 这样的函数更方便、简洁和强大。这些操作现在已**弃用**,尽管我们没有计划删除它们。
+:::
+
+编辑器可以从命令的 `run` 函数或 `/hooks.editor_script` 的钩子函数返回一个操作数组。然后这些操作将由编辑器执行。
+
+操作是描述编辑器应该做什么的表。每个操作都有一个 `action` 键。操作有两种类型:可撤销和不可撤销。
+
+### 可撤销操作
+
+::: sidenote
+优先使用 `editor.transact()`。
+:::
+
+可撤销操作在执行后可以撤销。如果一个命令返回多个可撤销操作,它们将一起执行,并一起撤销。如果可以,您应该使用可撤销操作。它们的缺点是它们更受限制。
+
+现有的可撤销操作:
+- `"set"` — 将编辑器中节点的属性设置为某个值。例如:
+  ```lua
+  {
+    action = "set",
+    node_id = opts.selection,
+    property = "text",
+    value = "current time is " .. os.date()
+  }
+  ```
+  `"set"` 操作需要以下键:
+  - `node_id` — 节点 id userdata。或者,您可以在这里使用资源路径代替从编辑器接收的节点 id,例如 `"/main/game.script"`;
+  - `property` — 要设置的节点属性,例如 `"text"`;
+  - `value` — 属性的新值。对于 `"text"` 属性,它应该是一个字符串。
+
+### 不可撤销操作
+
+::: sidenote
+优先使用 `editor.execute()`。
+:::
+
+不可撤销操作会清除撤销历史记录,因此如果您想撤销此类操作,您将不得不使用其他方法,例如版本控制。
+
+现有的不可撤销操作:
+- `"shell"` — 执行 shell 脚本。例如:
+  ```lua
+  {
+    action = "shell",
+    command = {
+      "./scripts/minify-json.sh",
+      editor.get(opts.selection, "path"):sub(2) -- trim leading "/"
+    }
+  }
+  ```
+  `"shell"` 操作需要 `command` 键,它是命令及其参数的数组。
+
+### 操作混用及其副作用
+
+您可以混合使用可撤销和不可撤销操作。操作是按顺序执行的,因此根据操作的顺序,您将失去撤销该命令部分操作的能力。
 
-Language server 定义表可以指定:
-- `languages` (必要) — 服务器支持的语言列表, 详见 [这里](https://code.visualstudio.com/docs/languages/identifiers#_known-language-identifiers) (支持文件扩展名);
-- `command` (必要) - 命令及其参数列表
-- `watched_files` - 一组带有 `pattern` 键 (a glob) 的表, 用来激活服务器的 [监视文件更改](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeWatchedFiles) 通知功能.
+除了从期望它们的函数返回操作外,您可以直接使用 `io.open()` 读写文件。这将触发资源重载,从而清除撤销历史记录。

+ 12 - 12
docs/zh/manuals/editor-styling.md

@@ -1,11 +1,11 @@
 ---
 title: 编辑器风格
-brief: 您可以使用自定义 stylesheet 修改编辑器配色, 文本及其他可视元素.
+brief: 您可以使用自定义样式表修改编辑器的颜色、字体排版及其他视觉元素。
 ---
 
 # 编辑器风格
 
-您可以使用自定义 stylesheet 修改编辑器配色, 文本及其他可视元素:
+您可以使用自定义样式表修改编辑器的颜色、字体排版及其他视觉元素:
 
 * 在用户目录下创建文件夹并命名为 `.defold`.
    * Windows 路径 `C:\Users\**Your Username**\.defold`
@@ -13,7 +13,7 @@ brief: 您可以使用自定义 stylesheet 修改编辑器配色, 文本及其
    * Linux 路径 `~/.defold`
  *  在 `.defold` 目录下创建一个 `editor.css` 文件.
 
-编辑器启动时会加载您的自定义 stylesheet 作为优先默认风格. 编辑器使用 JavaFX 编写用户界面所以 stylesheets 几乎等价于浏览器里支持的网页 CSS 文件. 官方默认的 stylesheets 保存于 [GitHub 上](https://github.com/defold/defold/tree/editor-dev/editor/styling/stylesheets/base).
+编辑器启动时会加载您的自定义样式表并将其应用在默认样式之上。编辑器使用 JavaFX 编写用户界面,所以样式表几乎等价于浏览器中用于网页的 CSS 文件。官方默认的样式表保存于 [GitHub 上](https://github.com/defold/defold/tree/editor-dev/editor/styling/stylesheets/base)
 
 ## 修改颜色
 
@@ -43,13 +43,13 @@ brief: 您可以使用自定义 stylesheet 修改编辑器配色, 文本及其
   and so on...
 ```
 
-基本配色主题分为三大部分 (分为深色浅色两种方案):
+基本配色主题分为三大部分(分为深色和浅色两种方案):
 
-* Background color - 面板, 窗口, 对话框的背景颜色
-* Component color - 按钮, 卷动条手柄, 文字描边颜色
-* Text color - 文和图标颜色
+* Background color - 面板、窗口、对话框的背景颜色
+* Component color - 按钮、滚动条手柄、文本框边框颜色
+* Text color - 文和图标颜色
 
-默认情况下, 如果在系统用户目录下的 `.defold` 文件夹下提供自定义 `editor.css` stylesheet:
+作为一个例子,如果您在用户主目录下的`.defold`文件夹中的自定义`editor.css`样式表中添加以下内容:
 
 ```
 * {
@@ -68,7 +68,7 @@ brief: 您可以使用自定义 stylesheet 修改编辑器配色, 文本及其
 
 ## 修改字体
 
-编辑器使用两种字体: 代码编写和单行距文本(报错文字)用 `Dejavu Sans Mono`, 其他 UI 用 `Source Sans Pro`. 文字定义主要保存在 [`_typography.scss`](https://github.com/defold/defold/blob/editor-dev/editor/styling/stylesheets/base/_typography.scss) 中, 如下所示:
+编辑器使用两种字体:代码编写和等宽文本(错误信息)使用`Dejavu Sans Mono`,其他UI使用`Source Sans Pro`。字体定义主要保存在[`_typography.scss`](https://github.com/defold/defold/blob/editor-dev/editor/styling/stylesheets/base/_typography.scss)中,如下所示:
 
 ```
 @font-face {
@@ -97,7 +97,7 @@ Text.strong {
 and so on...
 ```
 
-主要字体定义在树形结构根部以便于调整修改. 将如下 `editor.css` 应用后:
+主要字体定义在根元素中,这使得在大多数地方替换字体变得相当容易。将以下内容添加到您的`editor.css`中:
 
 ```
 @import url('https://fonts.googleapis.com/css2?family=Architects+Daughter&display=swap');
@@ -107,11 +107,11 @@ and so on...
 }
 ```
 
-则您的编辑器文本会如下图所示:
+您的编辑器字体将会如下图所示:
 
 ![](images/editor/editor-styling-fonts.png)
 
-使用本地字体代替网络字体也是可以的:
+也可以使用本地字体而不是网络字体:
 
 ```
 @font-face {

+ 13 - 13
docs/zh/manuals/editor-templates.md

@@ -1,23 +1,23 @@
 ---
-title: 项目模板
-brief: 在编辑器新建项目窗口中可以加入自定义模板.
+title: 编辑器模板
+brief: 您可以在新建项目窗口中添加自己的自定义项目模板。
 ---
 
-# 项目模板
+# 编辑器模板
 
-在编辑器新建项目窗口中可以加入自定义模板.:
+您可以在新建项目窗口中添加自己的自定义项目模板:
 
 ![custom project templates](images/editor/custom_project_templates.png)
 
-要在窗口中添加自定义项目模板页需要在系统用户目录的 `.defold` 文件夹下加入 `welcome.edn` 文件:
+为了添加一个或多个带有自定义项目模板的新标签页,您需要在用户主目录的 `.defold` 文件夹中添加一个 `welcome.edn` 文件:
 
-* 找到系统用户目录下 `.defold`文件夹的位置:
-  * Windows `C:\Users\**Your Username**\.defold`
-  * macOS `/Users/**Your Username**/.defold`
-  * Linux `~/.defold`
-* 在 `.defold` 文件夹下新建 `welcome.edn` 文件.
+* 在您的用户主目录中创建一个名为 `.defold` 的文件夹。
+  * 在 Windows 上:`C:\Users\**您的用户名**\.defold`
+  * 在 macOS 上:`/Users/**您的用户名**/.defold`
+  * Linux 上:`~/.defold`
+* 在 `.defold` 文件夹中创建一个 `welcome.edn` 文件。
 
-`welcome.edn` 文件使用的是可扩展数据注解格式. 例如:
+`welcome.edn` 文件使用可扩展数据表示法(Extensible Data Notation)格式。示例:
 
 ```
 {:new-project
@@ -39,8 +39,8 @@ brief: 在编辑器新建项目窗口中可以加入自定义模板.
 }
 ```
 
-这样就建立好了如上图的模板列表.
+这将创建如上截图所示的模板列表。
 
 ::: sidenote
-模板图片只能使用 [编辑器自带的图片](https://github.com/defold/defold/tree/dev/editor/resources/welcome/images).
+您只能使用[随编辑器一起提供的模板图片](https://github.com/defold/defold/tree/dev/editor/resources/welcome/images)。
 :::

+ 100 - 82
docs/zh/manuals/editor.md

@@ -1,172 +1,190 @@
 ---
 title: 编辑器概述
-brief: 本教程介绍了 Defold 编辑器的外观和用法, 以及切换导航方法.
+brief: 本手册提供了 Defold 编辑器的外观和工作方式的概述,以及如何在其中导航。
 ---
 
 # 编辑器概述
 
-编辑器在布局排版, 切换导航上设计得尽量让游戏开发更有效率. 编辑各个视图里的文件时都会有适当的编辑器自动弹出以方便使用.
+编辑器允许您以高效的方式浏览和操作游戏项目中的所有文件。编辑文件会调出合适的编辑器,并在单独的视图中显示文件的所有相关信息。
 
-## 打开编辑器
+## 启动编辑器
 
-打开 Defold 编辑器, 首先呈现的是一个项目选择和新建窗口. 通过点选上面的按钮可以:
+当您运行 Defold 编辑器时,会看到一个项目选择和创建界面。点击选择您想要执行的操作:
 
 Home
-: 显示最近编辑的项目以便快速打开. 这是默认视图.
+: 点击显示您最近打开的项目,以便您可以快速访问它们。这是默认视图。
 
 New Project
-: 创建新的项目, 然后会让你 (从 *Template* 窗口) 选择是否需要基于模板创建新项目, 还可以选择是否要参考 (*Tutorial* 窗口) 里的教程, 或者学习 (*Sample* 窗口) 里的示例项目.
+: 如果您想创建一个新的 Defold 项目,请点击此选项,然后选择您是否希望基于基本模板创建项目(来自 *来自模板* 标签页),是否想要按照教程操作(*来自教程* 标签页),或者尝试其中一个示例项目(*来自示例* 标签页)。
 
   ![new project](images/editor/new_project.png)
 
-  新建项目完成后所有项目文件都保存在了本地硬盘上.
+  当您创建一个新项目时,它会存储在您的本地驱动器上,您所做的任何编辑都会在本地保存。
 
-详情请见 [项目设立教程](https://www.defold.com/manuals/project-setup/).
+您可以在[项目设置手册](https://www.defold.com/manuals/project-setup/)中了解有关不同选项的更多信息。
 
 ## 编辑器面板
 
-Defold 编辑器被划分为许多面板, 或称视图, 以展示和编辑数据.
+Defold 编辑器被分为一组面板或视图,用于显示特定信息。
 
 ![Editor 2](images/editor/editor2_overview.png)
 
 *Assets* 面板
-: 展示项目的所有文件. 点选和滚动鼠标滚轮可以在面板上滑动. 在这个视图上可以做的操作有:
+: 列出作为项目一部分的所有文件。点击和滚动来导航列表。所有面向文件的操作都可以在此视图中进行:
 
-   - <kbd>双击</kbd> 文件会根据文件类型启动相应的编辑器打开文件.
-   - <kbd>拖放</kbd> 文件可以向项目中添加资源或者移动资源到想要的位置.
-   - <kbd>右键单击</kbd> 会弹出 _上下文菜单_ , 可以用来进行新建文件/文件夹, 重命名, 删除, 查看文件依赖等操作.
+   - <kbd>双击</kbd>文件在该文件类型的编辑器中打开它。
+   - <kbd>拖放</kbd>从磁盘上的其他位置将文件添加到项目中,或将文件和文件夹移动到项目中的新位置。
+   - <kbd>右键单击</kbd>打开_上下文菜单_,您可以从中创建新文件或文件夹、重命名、删除、跟踪文件依赖关系等。
 
-*Editor* 面板
+### 编辑器面板
+中心视图显示当前打开的文件在该文件类型的编辑器中。所有可视化编辑器都允许您更改摄像机视图:
 
-: 中间的视图显示当前打开的文件. 所有可视视图都可以进行如下操作:
+- 平移:<kbd>Alt + 鼠标左键</kbd>。
+- 缩放:<kbd>Alt + 右键</kbd>(三键鼠标)或 <kbd>Ctrl + 鼠标键</kbd>(单键鼠标)。如果您的鼠标有滚轮,可以使用它来缩放。
+- 3D旋转:<kbd>Ctrl + 鼠标左键</kbd>。
 
-- 平移: <kbd>Alt + 鼠标左键</kbd>.
-- 缩放: <kbd>Alt + 鼠标右键</kbd> 或者使用鼠标滚轮.
-- 旋转: <kbd>Ctrl + 鼠标左键</kbd>.
-
-场景视图右上角的工具栏里也有这些功能按钮: *平移*, *旋转* 和 *缩放*, 以及 *摄像机透视* 和 *可见性过滤*.
+在场景视图的右上角有一个工具栏,您可以在其中找到对象操作工具:*移动*、*旋转*和*缩放*,以及*2D模式*、*摄像机透视*和*可见性过滤器*。
 
 ![toolbar](images/editor/toolbar.png)
 
-*Outline* 面板
-: 这个视图以一个树形结构展示当前打开文件的内容. 大纲树的内容与场景视图内容是一一对应的, 可以方便操作:
-   - <kbd>单击</kbd> 选中一个物体. 按住 <kbd>Shift</kbd> 或 <kbd>Option</kbd> 键可以进行多选.
-   - <kbd>拖放</kbd> 移动物体. 在集合里把一个游戏对象拖放到另一个游戏对象上可以建立父子关系.
-   - <kbd>右键单击</kbd> 弹出 _上下文菜单_ 以便进行添加, 删除选中的物体等操作.
+### 大纲面板
+
+此视图显示当前正在编辑的文件内容,但以分层树结构形式展示。大纲反映了编辑器视图,并允许您对项目执行操作:
+   - <kbd>单击</kbd>选择一个项目。按住<kbd>Shift</kbd>或<kbd>Option</kbd>键可以扩展选择。
+   - <kbd>拖放</kbd>移动项目。将游戏对象拖放到集合中的另一个游戏对象上可以使其成为子对象。
+   - <kbd>右键单击</kbd>打开_上下文菜单_,您可以从中添加项目、删除选中的项目等。
+
+可以通过单击列表中元素右侧的小眼睛图标来切换游戏对象和可视化组件的可见性(Defold 1.9.8及更新版本)。
+
+![toolbar](images/editor/outline.png)
 
-*Properties* 面板
-: 这个视图显示出当前选中物体的属性, 比如位置, 旋转, 动画等等.
+### Properties面板
 
-*Tools* 面板
-: 这个视图分为几个组. *Console* 组显示游戏输出和报错信息. 旁边是显示 *编译错误*, *查找结果* 和编辑粒子曲线数据时用到的 *曲线编辑器*. 同时工具面板也负责与调试器进行交互.
+此视图显示与当前所选项目相关联的属性,如位置、旋转、动画等。
 
-*Changed Files* 面板
-: 如果你的项目使用 Git 做版本控制, 这个视图会列出项目中被修改, 添加或者删除的文件. 同步机制会把你的本地项目文件与 Git 托管项目进行同步, 这种机制方便团队合作开发, 而且云端备份可以保证项目不易损坏丢失. 关于 Git 详见 [版本控制教程](/manuals/version-control/). 相关操作:
+### Tools面板
+此视图有几个标签。*控制台* 标签显示游戏运行时产生的任何错误输出或您有意打印的内容。控制台旁边是包含 *构建错误*、*搜索结果* 和 *曲线编辑器* 的标签,后者用于在粒子编辑器中编辑曲线。Tools 面板还用于与集成调试器交互。
 
-   - <kbd>双击</kbd> 文件显示版本区别窗口. 同样, 编辑器会根据文件类型选择合适的显示窗口.
-   - <kbd>右键点击</kbd> 文件弹出的上下文菜单中, 可以进行显示版本区别窗口, 回退文件的更改, 打开文件系统浏览器显示文件位置等操作.
+### Changed Files面板
 
-## 同时编辑
+如果您的项目使用分布式版本控制系统Git,此视图将列出项目中已更改、添加或删除的任何文件。通过定期同步项目,您可以使本地副本与存储在项目Git仓库中的内容保持同步,这样您可以在团队内协作,并且在发生灾难时不会丢失您的工作。您可以在我们的[版本控制手册](/manuals/version-control/)中了解更多关于Git的信息。一些面向文件的操作可以在此视图中执行:
 
-如果同时打开了多个文件, 编辑器视图上方就会出现多个标签. 要想两个视图对照着同时进行编辑工作. <kbd>右键点击</kbd> 想要移动的视图标签, 然后选择 <kbd>Move to Other Tab Pane</kbd>.
+   - <kbd>双击</kbd>文件打开文件的差异视图。编辑器会在适合的编辑器中打开文件,就像在资源视图中一样。
+   - <kbd>右键单击</kbd>文件打开弹出菜单,您可以从中打开差异视图、恢复对文件所做的所有更改、在文件系统中查找文件等。
+
+## 并排编辑
+
+如果同时打开了多个文件, 编辑器视图上方就会出现多个标签. 可以并排打开2个编辑器视图。<kbd>右键单击</kbd>想要移动的编辑器标签并选择<kbd>移动到另一个标签面板</kbd>。
 
 ![2 panes](images/editor/2-panes.png)
 
-使用视图标签还可以让两个视图交换位置或者把多个面板合为一组.
+您还可以使用标签菜单交换两个面板的位置并将它们合并为单个面板。
 
 ## 场景编辑器
 
-双击集合文件或者游戏对象文件就会打开 *场景编辑器*:
+双击集合或游戏对象文件会打开*场景编辑器*:
 
 ![Select object](images/editor/select.png)
 
-选择物体
-: 在主视图中点选可以选中单个物体. 框选可以选中绿色方框套住的多个物体. 被选中的物体则在 *大纲* 视图中被高亮显示.
+### 选择对象
+点击主窗口中的对象来选择它们。编辑器视图中围绕对象的矩形将高亮显示为绿色,以指示选择了哪个项目。所选对象也在*大纲*视图中高亮显示。
 
-  大纲中还可以:
+  您还可以通过以下方式选择对象:
 
-  - <kbd>点击左键拖拉</kbd> 框选中多个物体.
-  - <kbd>单击</kbd> 选中单个物体.
+  - <kbd>单击并拖动</kbd>以选择选择区域内的所有对象。
+  - <kbd>单击</kbd>大纲视图中的对象。
 
-  按住 <kbd>Shift</kbd> 或 <kbd>⌘</kbd> (Mac) / <kbd>Ctrl</kbd> (Win/Linux) 键可以在已选中物体的基础上增选物体.
+  按住<kbd>Shift</kbd>或<kbd>⌘</kbd>(Mac)/<kbd>Ctrl</kbd>(Win/Linux)键的同时单击以扩展选择。
 
-移动工具
-: ![Move tool](images/editor/icon_move.png){.left}
-  使用 *移动工具* 来移动物体. 移动工具位于场景编辑器右上角的工具栏内, 快捷键是 <kbd>W</kbd>.
+### 移动工具
+![Move tool](images/editor/icon_move.png){.left}
+要移动对象,请使用*移动工具*。您可以在场景编辑器右上角的工具栏中找到它,或按<kbd>W</kbd>键。
 
-  ![Move object](images/editor/move.png)
+![Move object](images/editor/move.png)
 
-  被选中的物体会显示出坐标轴 (方块和箭头). 拖拽绿方块可以在屏幕空间内任意移动这个物体, 拖拽箭头则是让这个物体在 X, Y 或 Z 轴上进行移动. 拖拽别的方块则可以让这个物体在 X-Y 平面上 (在3D视图中可见) 移动或者在 X-Z , Y-Z 平面上移动.
+所选对象显示一组操纵器(方块和箭头)。单击并拖动绿色中心方块手柄可在屏幕空间中自由移动对象,单击并拖动箭头可沿X、Y或Z轴移动对象。还有一些方形手柄用于在X-Y平面中移动对象,以及(如果在3D中旋转相机可见)用于在X-Z和Y-Z平面中移动对象。
 
-旋转工具
-: ![Rotate tool](images/editor/icon_rotate.png){.left}
-  使用 *旋转工具* 来旋转物体. 旋转工具位于场景编辑器右上角的工具栏内, 快捷键是 <kbd>E</kbd>.
+### 旋转工具
+![Rotate tool](images/editor/icon_rotate.png){.left}
+要旋转对象,请通过在工具栏中选择它或按<kbd>E</kbd>键来使用*旋转工具*。
 
-  ![Move object](images/editor/rotate.png)
+![Move object](images/editor/rotate.png)
 
-  旋转工具的坐标轴显示为圆形. 拖拽橙色的圆可以在屏幕空间内任意旋转这个物体, 可以沿着 X, Y 和 Z 轴旋转. 因为 X 和 Y 轴的位置关系, 在2D视图上仅显示为穿过物体的两条线.
+该工具由四个圆形操纵器组成。一个橙色操纵器在屏幕空间中旋转对象,以及围绕X、Y和Z轴中的每一个旋转的操纵器。由于视图垂直于X轴和Y轴,因此圆仅显示为穿过对象的两条线。
 
-缩放工具
-: ![Scale tool](images/editor/icon_scale.png){.left}
-  使用 *缩放工具* 来缩放物体. 缩放工具位于场景编辑器右上角的工具栏内, 快捷键是 <kbd>R</kbd>.
+### 缩放工具
+![Scale tool](images/editor/icon_scale.png){.left}
+要缩放对象,请通过在工具栏中选择它或按<kbd>R</kbd>键来使用*缩放工具*。
 
-  ![Scale object](images/editor/scale.png)
+![Scale object](images/editor/scale.png)
 
-  缩放工具坐标轴显示为一组方块. 拖拽中间的方块可以将物体等比缩放 (包括Z轴). 同样也可以沿着 X, Y 和 Z 轴方向, 以及 X-Y , X-Z 和 Y-Z 平面上进行缩放.
+该工具由一组方形手柄组成。中心一个在所有轴(包括Z)中均匀缩放对象。每个X、Y和Z轴还有一个手柄用于缩放,以及一个用于在X-Y平面、X-Z平面和Y-Z平面中缩放的手柄。
 
-可见性过滤
-: 各种组件类型的可视性开关, 包括边界框和基准线.
+### 可见性过滤
+切换各种组件类型以及边界框和指南的可见性。
 
-  ![Visibility filters](images/editor/visibilityfilters.png)
+![Visibility filters](images/editor/visibilityfilters.png)
 
+## 创建新的项目文件
 
-## 新建文件
+要创建新的资源文件,可以选择<kbd>文件 ▸ 新建...</kbd>,然后从菜单中选择文件类型,或者使用上下文菜单:
 
-新建资源文件有两种方法, 通过点选菜单栏 <kbd>File ▸ New...</kbd> 按钮, 或者使用上下文菜单:
-
-在 *资源* 浏览器目标位置 <kbd>右键单击</kbd> , 选择 <kbd>New... ▸ [file type]</kbd> 按钮:
+在*资源*浏览器中的目标位置<kbd>右键单击</kbd>,然后选择<kbd>新建... ▸ [文件类型]</kbd>:
 
 ![create file](images/editor/create_file.png)
 
-为新文件取一个有意义的名字. 完整文件名包括类型扩展名会显示在 *路径* 对话框内:
+为新文件键入合适的名称。包含文件类型后缀的完整文件名显示在对话框的*路径*下:
 
 ![create file name](images/editor/create_file_name.png)
 
-## 向项目添加资源文件
+可以为每个项目指定自定义模板。为此,请在项目根目录中创建一个名为`templates`的新文件夹,并添加名为`default.*`的新文件,并带有所需的扩展名,例如`/templates/default.gui`或`/templates/default.script`。此外,如果在这些文件中使用了`{{NAME}}`标记,它将被文件创建窗口中指定的文件名替换。
+
+## 导入文件到项目
 
-要向项目添加资源 (图片, 声音, 模型等) 文件, 只需把文件拖放到 *资源* 浏览器里适当的位置上. 这样做实际上是把文件系统中的资源文件 _拷贝_ 到项目中来. 详情请见 [导入资源教程](/manuals/importing-assets/).
+要向项目添加资源文件(图像、声音、模型等),只需将它们拖放到*资源*浏览器中的正确位置。这将在项目文件结构的选定位置创建文件的副本。阅读更多关于[如何在手册中导入资源](/manuals/importing-assets/)的信息。
 
 ![Import files](images/editor/import.png)
 
-## 编辑器更新
+## 更新编辑器
 
-编辑器自动检查更新. 检测到新版本的话就会在编辑器右下角或者项目选择视图里显示出来. 点击即可自动更新.
+编辑器将自动检查更新。当检测到更新时,它将在编辑器窗口的右下角和项目选择屏幕上显示。按可用更新链接将下载并更新编辑器。
 
 ![Update from project selection](images/editor/update-project-selection.png)
 
 ![Update from editor](images/editor/update-main.png)
 
-## 配置
+## 首选项
 
-可以 [通过设置窗口](/manuals/editor-preferences) 修改编辑器配置.
-
-## 键盘快捷键
-
-键盘快捷键及自定义方法详见 [键盘快捷键教程](/manuals/editor-keyboard-shortcuts).
+您可以从[首选项窗口](/manuals/editor-preferences)修改编辑器的设置。
 
 ## 编辑器日志
-使用编辑器时如果遇到了麻烦可以 [向我们汇报](/manuals/getting-help/#获得帮助), 并且连同编辑器日志一起上报. 编辑器日志存放路径如下:
+如果您在使用编辑器时遇到问题并需要[报告问题](/manuals/getting-help/#getting-help),最好提供编辑器本身的日志文件。编辑器日志文件可以在以下位置找到:
 
-  * Windows: `C:\Users\ **Your Username** \AppData\Local\Defold`
-  * macOS: `/Users/ **Your Username** /Library/Application Support/` 或 `~/Library/Application Support/Defold`
-  * Linux: `~/.Defold`
+  * Windows: `C:\Users\ **您的用户名** \AppData\Local\Defold`
+  * macOS: `/Users/ **您的用户名** /Library/Application Support/` 或 `~/Library/Application Support/Defold`
+  * Linux: `$XDG_STATE_HOME/Defold` 或 `~/.local/state/Defold`
 
-如果用命令行启动编辑器那么日志会显示在控制台上. 例如从 macOS 终端启动 Defold 编辑器:
+如果编辑器是从终端/命令提示符启动的,您也可以在编辑器运行时访问编辑器日志。要从终端在macOS上启动编辑器:
 
 ```
 $ > ./path/to/Defold.app/Contents/MacOS/Defold
 ```
 
+## 编辑器服务器
+
+当编辑器打开项目时,它会在随机端口上启动Web服务器。该服务器可用于从其他应用程序与编辑器交互。从1.11.0版本开始,端口被写入`.internal/editor.port`文件中。
+
+此外,从1.11.0版本开始,编辑器可执行文件有一个命令行选项`--port`(或`-p`),允许在启动时指定端口,例如:
+```shell
+# 在Windows上
+.\Defold.exe --port 8181
+
+# 在Linux上:
+./Defold --port 8181
+
+# 在macOS上:
+./Defold.app/Contents/MacOS/Defold --port 8181
+```
 
-## 常見問題
+## 常见问题
 :[Editor FAQ](../shared/editor-faq.md)

+ 46 - 0
docs/zh/manuals/extender-docker-images.md

@@ -0,0 +1,46 @@
+---
+title: 可用的Docker镜像
+brief: 文档描述了可用的Docker镜像和使用它们的Defold版本
+---
+
+# 可用的Docker镜像
+以下是公共注册表中所有可用的Docker镜像列表。这些镜像可用于在不再支持旧SDK的环境中运行Extender。
+
+|SDK               |镜像标签                                                                                                 |平台名称(在Extender配置中) |使用该镜像的Defold版本 |
+|------------------|---------------------------------------------------------------------------------------------------------|-----------------------------|-----------------------|
+|Linux latest      |`europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-linux-env:latest`         |`linux-latest`               |所有Defold版本          |
+|Android NDK25     |`europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-android-ndk25-env:latest` |`android-ndk25`              |从1.4.3开始             |
+|Emscripten 2.0.11 |`europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-emsdk-2011-env:latest`    |`emsdk-2011`                 |直到1.7.0              |
+|Emscripten 3.1.55 |`europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-emsdk-3155-env:latest`    |`emsdk-3155`                 |[1.8.0-1.9.3]          |
+|Emscripten 3.1.65 |`europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-emsdk-3165-env:latest`    |`emsdk-3165`                 |从1.9.4开始             |
+|Winsdk 2019       |`europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-winsdk-2019-env:latest`   |`winsdk-2019`                |直到1.6.1              |
+|Winsdk 2022       |`europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-winsdk-2022-env:latest`   |`winsdk-2022`                |从1.6.2开始             |
+
+# 如何使用旧的Docker镜像
+要使用旧环境,您应该按照以下步骤操作:
+1. 修改Extender存储库中的`docker-compose.yml`文件[链接](https://github.com/defold/extender/blob/dev/server/docker/docker-compose.yml)。需要添加一个带有必要Docker镜像的服务定义。例如,如果我们想使用包含Emscripten 2.0.11的Docker镜像,我们需要添加以下服务定义:
+    ```yml
+    emscripten_2011-dev:
+        image: europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-emsdk-2011-env:latest
+        extends:
+        file: common-services.yml
+        service: remote_builder
+        profiles:
+        - all
+        - web
+        networks:
+        default:
+            aliases:
+            - emsdk-2011
+    ```
+    重要字段包括:
+    * **profiles** - 触发服务启动的配置文件列表。配置文件名称通过`--profile <profile_name>`参数传递给`docker compose`命令。
+    * **networks** - Docker容器应使用的网络列表。运行Extender使用名为`default`的网络。重要的是设置服务网络别名(它将在后续的Extender配置中使用)。
+2. 在[`application-local-dev-app.yml`](https://github.com/defold/extender/blob/dev/server/configs/application-local-dev-app.yml)的`extender.remote-builder.platforms`部分添加远程构建器的定义。在我们的示例中,它将如下所示:
+    ```yml
+        emsdk-2011:
+            url: http://emsdk-2011:9000
+            instanceId: emsdk-2011
+    ```
+    URL应采用以下格式:`http://<service_network_alias>:9000`,其中`service_network_alias` - 来自步骤1的网络别名。9000 - Extender的标准端口(如果您使用自定义Extender配置,可能会有所不同)。
+3. 按照[如何使用预配置构件运行本地Extender](/manuals/extender-local-setup#how-to-run-local-extender-with-preconfigured-artifacts)中的描述运行本地Extender。

+ 133 - 0
docs/zh/manuals/extender-local-setup.md

@@ -0,0 +1,133 @@
+---
+title: 设置本地构建服务器
+brief: 本手册描述如何设置和运行本地构建服务器
+---
+
+# 构建服务器本地设置
+
+运行本地构建服务器(也称为'Extender')有两种方式:
+1. 使用预配置构件运行本地构建服务器。
+2. 使用本地构建的构件运行本地构建服务器。
+
+## 如何使用预配置构件运行本地Extender
+
+在运行本地云构建器之前,您需要安装以下软件:
+
+* [Docker](https://www.docker.com/) - Docker是一组平台即服务产品,使用操作系统级虚拟化来交付称为容器的软件包。要在本地开发机器上运行云构建器,您需要安装[Docker Desktop](https://www.docker.com/products/docker-desktop/)
+* Google Cloud CLI - Google Cloud CLI是一组用于创建和管理Google Cloud资源的工具。这些工具可以[直接从Google安装](https://cloud.google.com/sdk/docs/install)或从包管理器(如Brew、Chocolatey或Snap)安装。
+* 您还需要一个Google账户来下载包含平台特定构建服务器的容器。
+
+安装上述软件后,请按照以下步骤安装和运行Defold云构建器:
+
+**Windows用户注意**:使用git bash终端执行以下命令。
+
+1. __授权Google Cloud并创建应用程序默认凭据__ - 下载Docker容器镜像时,您需要拥有Google账户,以便我们可以监控并确保公共容器注册表的公平使用,并暂时暂停过度下载镜像的账户。
+
+   ```sh
+   gcloud auth login
+   ```
+2. __配置Docker使用工件注册表__ - 需要将Docker配置为使用`gcloud`作为凭据助手,以便从`europe-west1-docker.pkg.dev`的公共容器注册表下载容器镜像。
+
+   ```sh
+   gcloud auth configure-docker europe-west1-docker.pkg.dev
+   ```
+3. __验证Docker和Google Cloud是否配置正确__ - 通过拉取所有构建服务器容器镜像使用的基础镜像,验证Docker和Google Cloud是否设置成功。在运行以下命令之前,请确保Docker Desktop正在运行:
+   ```sh
+   docker pull --platform linux/amd64 europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-base-env:latest
+   ```
+4. __克隆Extender仓库__ - 正确设置Docker和Google Cloud后,我们几乎可以启动服务器了。在启动服务器之前,我们需要克隆包含构建服务器的Git仓库:
+   ```sh
+   git clone https://github.com/defold/extender.git
+   cd extender
+   ```
+5. __下载预构建的jar文件__ - 下一步是下载预构建的服务器(`extender.jar`)和清单合并工具(`manifestmergetool.jar`):
+   ```sh
+    TMP_DIR=$(pwd)/server/_tmp
+    APPLICATION_DIR=$(pwd)/server/app
+    # 设置必要的Extender和清单合并工具版本
+    # 版本可以在Github发布页面找到 https://github.com/defold/extender/releases
+    # 或者您可以拉取最新版本(见下面的代码示例)
+    EXTENDER_VERSION=2.6.5
+    MANIFESTMERGETOOL_VERSION=1.3.0
+    echo "将预构建的jar文件下载到 ${APPLICATION_DIR}"
+    rm -rf ${TMP_DIR}
+    mkdir -p ${TMP_DIR}
+    rm -rf ${APPLICATION_DIR}
+    mkdir -p ${APPLICATION_DIR}
+
+    gcloud artifacts files download \
+    --project=extender-426409 \
+    --location=europe-west1 \
+    --repository=extender-maven \
+    --destination=${TMP_DIR} \
+    com/defold/extender/server/${EXTENDER_VERSION}/server-${EXTENDER_VERSION}.jar
+
+    gcloud artifacts files download \
+    --project=extender-426409 \
+    --location=europe-west1 \
+    --repository=extender-maven \
+    --destination=${TMP_DIR} \
+    com/defold/extender/manifestmergetool/${MANIFESTMERGETOOL_VERSION}/manifestmergetool-${MANIFESTMERGETOOL_VERSION}.jar
+
+    cp ${TMP_DIR}/$(ls ${TMP_DIR} | grep server-${EXTENDER_VERSION}.jar) ${APPLICATION_DIR}/extender.jar
+    cp ${TMP_DIR}/$(ls ${TMP_DIR} | grep manifestmergetool-${MANIFESTMERGETOOL_VERSION}.jar) ${APPLICATION_DIR}/manifestmergetool.jar
+   ```
+6. __启动服务器__ - 现在我们可以通过运行docker compose主命令来启动服务器:
+```sh
+docker compose -p extender -f server/docker/docker-compose.yml --profile <profile> up
+```
+其中*profile*可以是:
+* **all** - 为每个平台运行远程实例
+* **android** - 运行前端实例 + 用于构建Android版本的远程实例
+* **web** - 运行前端实例 + 用于构建Web版本的远程实例
+* **linux** - 运行前端实例 + 用于构建Linux版本的远程实例
+* **windows** - 运行前端实例 + 用于构建Windows版本的远程实例
+* **consoles** - 运行前端实例 + 用于构建Nintendo Switch/PS4/PS5版本的远程实例
+* **nintendo** - 运行前端实例 + 用于构建Nintendo Switch版本的远程实例
+* **playstation** - 运行前端实例 + 用于构建PS4/PS5版本的远程实例
+* **metrics** - 运行VictoriaMetrics + Grafana作为指标后端和可视化工具
+有关`docker compose`参数的更多信息,请参见 https://docs.docker.com/reference/cli/docker/compose/。
+
+当docker compose启动后,您可以在编辑器的首选项中使用**http://localhost:9000**作为构建服务器地址,或者如果您使用Bob构建项目,则作为`--build-server`值。
+
+可以将多个配置文件传递给命令行。例如:
+```sh
+docker compose -p extender -f server/docker/docker-compose.yml --profile android --profile web --profile windows up
+```
+上面的示例运行前端、Android、Web、Windows实例。
+
+要停止服务 - 如果docker compose以非分离模式运行,请按Ctrl+C,或者
+```sh
+docker compose -p extender down
+```
+如果docker compose是以分离模式运行的(例如,向`docker compose up`命令传递了'-d'标志)。
+
+如果您想拉取最新版本的jar文件,可以使用以下命令确定最新版本
+```sh
+    EXTENDER_VERSION=$(gcloud artifacts versions list \
+        --project=extender-426409 \
+        --location=europe-west1 \
+        --repository=extender-maven \
+        --package="com.defold.extender:server" \
+        --sort-by="~createTime" \
+        --limit=1 \
+        --format="value(name)")
+
+    MANIFESTMERGETOOL_VERSION=$(gcloud artifacts versions list \
+        --project=extender-426409 \
+        --location=europe-west1 \
+        --repository=extender-maven \
+        --package="com.defold.extender:manifestmergetool" \
+        --sort-by="~createTime" \
+        --limit=1 \
+        --format="value(name)")
+```
+
+### 那么macOS和iOS呢?
+
+macOS和iOS的构建是在真实的Apple硬件上完成的,使用在独立模式下运行的构建服务器,而不使用Docker。而是在机器上直接安装XCode、Java和其他必需的工具,构建服务器作为普通的Java进程运行。您可以在[GitHub上的构建服务器文档](https://github.com/defold/extender?tab=readme-ov-file#running-as-a-stand-alone-server-on-macos)中了解如何设置它。
+
+
+## 如何使用本地构建的构件运行本地Extender
+
+请遵循[GitHub上Extender仓库中的说明](https://github.com/defold/extender)来手动构建和运行本地构建服务器。

+ 64 - 66
docs/zh/manuals/extension-facebook.md

@@ -1,139 +1,137 @@
 ---
-title: Defold Facebook 教程
-brief: 本教程介绍了如何在 Defold 游戏中设置和整合 Facebook 功能.
+title: Defold Facebook 扩展
+brief: 本手册介绍了如何在 Defold 游戏中设置和整合 Facebook 功能.
 ---
 
 API 文档位于 [这里](https://defold.github.io/extension-facebook/).
 
-## 注册成为 Facebook 开发者
 # Facebook
 
-Facebook API 作为 [原生扩展](/manuals/extensions/) 提供. 此扩展使得 iOS, Android 和 HTML5 游戏可以使用 Facebook 的在线交互功能. Defold Facebook 扩展对于 iOS, Android 和 HTML5 (基于 Facebook Canvas) 不同平台封装了同一的 Facebook API 函数库. 要在游戏中使用 Facebook 在线交互功能, 首先需要有一个 Facebook 账户.
+Facebook API 作为 [原生扩展](/manuals/extensions/) 提供. 此扩展使得 iOSAndroid 和 HTML5 游戏可以使用 Facebook 的在线交互功能. Defold Facebook 扩展对于 iOS、Android 和 HTML5(基于 Facebook Canvas)不同平台封装了统一的 Facebook API 函数库. 要在游戏中使用 Facebook 在线交互功能,首先需要有一个 Facebook 账户.
 
 ## 安装扩展
 
-要使用 Facebook 扩展, 需要在 *game.project* 文件中设置依赖. 最新稳定版的 URL 是:
+要使用 Facebook 扩展,需要在 *game.project* 文件中设置依赖. 最新稳定版的 URL 是:
 ```
 https://github.com/defold/extension-facebook/archive/master.zip
 ```
 
-推荐使用 [指定版本](https://github.com/defold/extension-facebook/releases) 的zip包链接作为依赖.
+推荐使用 [指定版本](https://github.com/defold/extension-facebook/releases) 的 zip 包链接作为依赖。
 
-Facebook API 文档位于 [fb扩展主页](https://defold.github.io/extension-facebook/).
+Facebook API 文档位于 [fb 扩展主页](https://defold.github.io/extension-facebook/)
 
-## 注册为 Facebook 开发者
+## 注册为 Facebook 开发者
 
-开发 Facebook 应用首先要注册成为 Facebook 开发者. 这样你的 Defold 游戏就能与 Facebook 应用交互了.
+开发 Facebook 应用首先要注册成为 Facebook 开发者。这样你的 Defold 游戏就能与 Facebook 应用交互了。
 
 * 访问 [Facebook 开发者网站](https://developers.facebook.com) 进行注册
-* 登入你的 Facebook 账户.
-* 注册激活你的开发者身份.
+* 登入你的 Facebook 账户
+* 注册激活你的开发者身份
 
-![Register as a developer](images/facebook/register_dev.png)
-![ developer](images/facebook/register_verify.png)
+![注册成为开发者](images/facebook/register_dev.png)
+![验证开发者身份](images/facebook/register_verify.png)
 
 ## 创建 Facebook 应用
 
-下一步要创建一个 Facebook 应用. 右上角 <kbd>My Apps</kbd> 菜单列出了你的应用, 以及 <kbd>Add a New App</kbd> 按钮.
+下一步要创建一个 Facebook 应用。右上角 <kbd>My Apps</kbd> 菜单列出了你的应用,以及 <kbd>Add a New App</kbd> 按钮。
 
-![Add new app](images/facebook/add_new_app_menu.png)
+![添加新应用](images/facebook/add_new_app_menu.png)
 
-然后是选择目标平台界面. 点击 *basic setup* 可以略过引导界面.
+然后是选择目标平台界面。点击 *basic setup* 可以略过引导界面。
 
 ::: sidenote
-引导界面里绝大多数内容与开发 Defold 游戏无关. 而且, 一般不需要自己修改 *Info.plist* 或者 *AndroidManifest.xml* 文件. Defold 会自动完成.
+引导界面里绝大多数内容与开发 Defold 游戏无关。而且,一般不需要自己修改 *Info.plist* 或者 *AndroidManifest.xml* 文件。Defold 会自动完成。
 :::
 
-![Add new app platform](images/facebook/add_new_app_platform.png)
+![添加新应用平台](images/facebook/add_new_app_platform.png)
 
-在 dashboard 里可以随意添加, 删除应用或者更改平台设置. 接下来需要设置 *Display Name*, *Namespace* 和 *Category*. 这些也都可以在 dashboard 里设置. 设置完后, Facebook 会给你的应用创建唯一id. *App ID* 是不可修改的.
+在 dashboard 里可以随意添加、删除应用或者更改平台设置。接下来需要设置 *Display Name*、*Namespace* 和 *Category*。这些也都可以在 dashboard 里设置。设置完后,Facebook 会给你的应用创建唯一 ID。*App ID* 是不可修改的。
 
-![New app id](images/facebook/new_app_id.png)
+![新应用 ID](images/facebook/new_app_id.png)
 
-![App dashboard settings](images/facebook/add_platform.png)
+![应用仪表板设置](images/facebook/add_platform.png)
 
-点击 *Settings* 面板. 这里显示了 *App ID*. 你要在 Defold 游戏的 [项目设置](/manuals/project-settings) 里输入这个id. 从 *资源面板* 里打开 *game.project* 文件, 滚动到 *Facebook* 部分, 在 `Appid` 这里填入 *App ID*.
+点击 *Settings* 面板。这里显示了 *App ID*。你要在 Defold 游戏的 [项目设置](/manuals/project-settings) 里输入这个 ID。从 *资源面板* 里打开 *game.project* 文件,滚动到 *Facebook* 部分,在 `Appid` 这里填入 *App ID*。
 
-现在回到 Facebook 网站的 *Settings* 页面, 点击 *+ Add Platform* 来为应用设置目标平台. 针对每个平台都有不同的设置.
+现在回到 Facebook 网站的 *Settings* 页面,点击 *+ Add Platform* 来为应用设置目标平台。针对每个平台都有不同的设置。
 
-![Select platform](images/facebook/select_platform.png)
+![选择平台](images/facebook/select_platform.png)
 
 ## iOS
 
-iOS 平台需要填写和 *game.project* 里一样的 `bundle_identifier`.
+iOS 平台需要填写和 *game.project* 里一样的 `bundle_identifier`
 
-![iOS settings](images/facebook/settings_ios.png)
+![iOS 设置](images/facebook/settings_ios.png)
 
 ## Android
 
-Android 平台需要填写 *Google Play Package Name*, 也就是 *game.project* 里的 *package* id. 还要在 *Key Hashes* 里填入证书的 Hashes. 可以使用 openssl 从 *certificate.pem* 文件生成 Hashes:
+Android 平台需要填写 *Google Play Package Name*,也就是 *game.project* 里的 *package* ID。还要在 *Key Hashes* 里填入证书的 Hashes。可以使用 openssl 从 *certificate.pem* 文件生成 Hashes:
 
 ```sh
 $ cat certificate.pem | openssl x509 -outform der | openssl sha1 -binary | openssl base64
 ```
 
-(关于签名文件详细信息参见 [制作 keystore](/manuals/android/#制作 keystore).)
+(关于签名文件详细信息参见 [制作 keystore](/manuals/android/#制作 keystore)。)
 
-![Android settings](images/facebook/settings_android.png)
+![Android 设置](images/facebook/settings_android.png)
 
 ## Facebook Canvas
 
-对于 HTML5 游戏, 过程略有不同. Facebook 需要直接在线访问你的游戏内容. 两个办法:
+对于 HTML5 游戏,过程略有不同。Facebook 需要直接在线访问你的游戏内容。两个办法:
 
-![Facebook Canvas settings](images/facebook/settings_canvas.png)
+![Facebook Canvas 设置](images/facebook/settings_canvas.png)
 
-1. 使用 Facebook 的 *Simple Application Hosting*. 点击 *Yes* 使用在线托管. 选择 *uploaded assets* 打开托管资源管理器.
+1. 使用 Facebook 的 *Simple Application Hosting*。点击 *Yes* 使用在线托管。选择 *uploaded assets* 打开托管资源管理器。
 
-    ![Simple hosting](images/facebook/simple_hosting.png)
+    ![简单托管](images/facebook/simple_hosting.png)
 
-    托管类型选择 "HTML5 Bundle":
+    托管类型选择 "HTML5 Bundle"
 
-    ![HTML5 bundle](images/facebook/html5_bundle.png)
+    ![HTML5 ](images/facebook/html5_bundle.png)
 
-    把你的 HTML5 游戏包压缩为一个 .7z 或者 .zip 包上传至 Facebook. 点击 *Push to production* 即可在线发布.
+    把你的 HTML5 游戏包压缩为一个 .7z 或者 .zip 包上传至 Facebook。点击 *Push to production* 即可在线发布。
 
-2. 另一个办法就是把你的 HTML5 游戏包托管到你自己选择的服务器上通过 HTTPS 访问. *Secure Canvas URL* 这里填写你的游戏地址.
+2. 另一个办法就是把你的 HTML5 游戏包托管到你自己选择的服务器上通过 HTTPS 访问。*Secure Canvas URL* 这里填写你的游戏地址。
 
-至此 Facebook 就能通过 *Canvas Page* 发布你的游戏了.
+至此 Facebook 就能通过 *Canvas Page* 发布你的游戏了
 
 ## 小测试
 
-可以通过创建一个小测试来看看扩展工作是否顺利.
+可以通过创建一个小测试来看看扩展工作是否顺利
 
-1. 新建游戏对象然后在上面添加一个脚本.
-2. 脚本里加入如下代码 (需要 Facebook 扩展 v.2 版及以上):
+1. 新建游戏对象然后在上面添加一个脚本
+2. 脚本里加入如下代码(需要 Facebook 扩展 v.2 版及以上):
 
 ```lua
 local function get_me_callback(self, id, response)
-    -- The response table includes all the response data
+    -- 响应表包含所有响应数据
     pprint(response)
 end
 
 local function fb_login(self, data)
     if data.status == facebook.STATE_OPEN then
-        -- Logged in ok. Let's try reading some "me" data through the
-        -- HTTP graph API.
+        -- 登录成功。让我们尝试通过 HTTP graph API 读取一些 "me" 数据。
         local token = facebook.access_token()
         local url = "https://graph.facebook.com/me/?access_token=" .. token
         http.request(url, "GET", get_me_callback)
     elseif data.status == facebook.STATE_CLOSED_LOGIN_FAILED then
-        -- Do something to indicate that login failed
+        -- 执行一些操作以指示登录失败
     end
     if data.error then
-        -- An error occurred
+        -- 发生错误
     else
-        -- No error
+        -- 没有错误
     end
 end
 
 function init(self)
-    -- Log in with read permissions.
+    -- 使用读取权限登录。
     local permissions = { "public_profile", "email" }
     facebook.login_with_permissions(permissions, facebook.AUDIENCE_EVERYONE, fb_login)
 end
 ```
 
-直接运行, 控制台输出大概这样:
+直接运行,控制台输出大概这样:
 
 ```txt
 DEBUG:SCRIPT:
@@ -158,53 +156,53 @@ DEBUG:SCRIPT:
 }
 ```
 
-* 完整的 Defold Facebook API 文档在 [这里](https://defold.github.io/extension-facebook/).
-* Facebook Graph API 在这里: https://developers.facebook.com/docs/graph-api
+* 完整的 Defold Facebook API 文档在 [这里](https://defold.github.io/extension-facebook/)
+* Facebook Graph API 在这里https://developers.facebook.com/docs/graph-api
 
 
 ## Facebook Analytics
 
-Facebook Analytics 可以对游戏相关信息汇总统计并提供适当建议, 比如开启游戏人数, 付款频率和其他各种信息.
+Facebook Analytics 可以对游戏相关信息汇总统计并提供适当建议,比如开启游戏人数、付款频率和其他各种信息。
 
 ### 配置
 
-使用 Facebook Analytics 之前你得创建好 Facebook 应用. 然后就是把分析功能整合进去:
+使用 Facebook Analytics 之前你得创建好 Facebook 应用。然后就是把分析功能整合进去:
 
-![Add Facebook Analytics](images/facebook/add_facebook_analytics.png)
+![添加 Facebook Analytics](images/facebook/add_facebook_analytics.png)
 
-分析功能也有很多配置选项. 详情请见:
+分析功能也有很多配置选项。详情请见:
 
-![Add Facebook Analytics](images/facebook/facebook_analytics_settings.png)
+![Facebook Analytics 设置](images/facebook/facebook_analytics_settings.png)
 
 ### 使用
 
-分析功能配置好之后就可以通过发布分析事件来进行信息统计了:
+分析功能配置好之后就可以通过发布分析事件来进行信息统计了
 
 ```lua
 function init(self)
-    -- post a spent credits event
+    -- 发布消费积分事件
     local params = { [facebook.PARAM_LEVEL] = 30, [facebook.PARAM_NUM_ITEMS] = 2 }
     facebook.post_event(facebook.EVENT_SPENT_CREDITS, 25, params)
 
-    -- post a custom event
+    -- 发布自定义事件
     local level = 19
     local params = { kills = 23, gold = 4, xp = 890 }
     facebook.post_event("level_completed", level, params)
 end
 ```
 
-各种事件和参数详情请见 [Facebook 扩展 API 文档](https://defold.github.io/extension-facebook/). 这些应该与 Facebook 的 [标准事件](https://developers.facebook.com/docs/analytics/send_data/events#standard) 和 [参数](https://developers.facebook.com/docs/analytics/send_data/events#parameter) 文档相一致.
+各种事件和参数详情请见 [Facebook 扩展 API 文档](https://defold.github.io/extension-facebook/)这些应该与 Facebook 的 [标准事件](https://developers.facebook.com/docs/analytics/send_data/events#standard) 和 [参数](https://developers.facebook.com/docs/analytics/send_data/events#parameter) 文档相一致
 
-除了分析统计事件, Defold 使用 Facebook SDK 时也会自动产生一些事件, 比如装机次数启动次数之类的. 详情请见 Facebook 的 [自动日志事件](https://developers.facebook.com/docs/analytics/send_data/events#autologged) 文档.
+除了分析统计事件,Defold 使用 Facebook SDK 时也会自动产生一些事件,比如装机次数、启动次数之类的。详情请见 Facebook 的 [自动日志事件](https://developers.facebook.com/docs/analytics/send_data/events#autologged) 文档
 
-事件汇总后会在 Facebook Analytics dashboard 中显示出来, 点击 *View Analytics* 按钮查看分析信息:
+事件汇总后会在 Facebook Analytics dashboard 中显示出来,点击 *View Analytics* 按钮查看分析信息:
 
-![Add Facebook Analytics](images/facebook/facebook_analytics_open_dashboard.png)
+![打开 Facebook Analytics](images/facebook/facebook_analytics_open_dashboard.png)
 
-通过页面里 *Events* 选项可以看到各种事件:
+通过页面里 *Events* 选项可以看到各种事件
 
-![Add Facebook Analytics](images/facebook/facebook_analytics_show_events.png)
+![显示事件](images/facebook/facebook_analytics_show_events.png)
 
 ### Facebook 的事件分享
 
-你可以选择是否向 Facebook 分享你的事件数据. 通过 [`enable_event_usage()`](https://defold.github.io/extension-facebook/#enable_event_usage) 和 [`disable_event_usage()`](https://defold.github.io/extension-facebook/#disable_event_usage) 函数控制. 默认不分享.
+你可以选择是否向 Facebook 分享你的事件数据通过 [`enable_event_usage()`](https://defold.github.io/extension-facebook/#enable_event_usage) 和 [`disable_event_usage()`](https://defold.github.io/extension-facebook/#disable_event_usage) 函数控制。默认不分享。

+ 21 - 21
docs/zh/manuals/extension-fbinstant.md

@@ -1,39 +1,39 @@
 ---
 title: Facebook Instant Games
-brief: 本教程介绍了如何使用 Defold 创建 Facebook Instant Games.
+brief: 本手册介绍了如何使用 Defold 创建 Facebook Instant Games。
 ---
 
 # Facebook Instant Games
 
-Instant Games 可以让玩家在 Facebook 平台上随时玩到游戏的新方式. 基于 HTML5 技术, 可以让玩家直接从新闻Feed或者聊天消息中打开游戏, 同时支持桌面和移动设备.
+Instant Games 可以让玩家在 Facebook 平台上随时玩到游戏的新方式。基于 HTML5 技术,可以让玩家直接从新闻 Feed 或者聊天消息中打开游戏,同时支持桌面和移动设备。
 
 ![InstantGames](images/instant-games/instantgames.png)
 
 ## 发布 Instant Games
 
-在把你的 Defold 游戏发布到 Facebook 之前, 需要对游戏项目进行一些设定:
+在把你的 Defold 游戏发布到 Facebook 之前,需要对游戏项目进行一些设定:
 
-1. 在 [Facebook App Dashboard](https://developers.facebook.com/apps) 里创建 Instant Games 应用. 详情请见 [Instant Games 入门指南](https://developers.facebook.com/docs/games/instant-games/getting-started/game-setup).
+1. 在 [Facebook App Dashboard](https://developers.facebook.com/apps) 里创建 Instant Games 应用详情请见 [Instant Games 入门指南](https://developers.facebook.com/docs/games/instant-games/getting-started/game-setup)
 
-2. 在你的 *game.project* 文件中添加 Instant Games 扩展依赖. 即把 "https://github.com/defold/extension-fbinstant/archive/master.zip" 添加到 *Dependencies* 属性中.
+2. 在你的 *game.project* 文件中添加 Instant Games 扩展依赖即把 "https://github.com/defold/extension-fbinstant/archive/master.zip" 添加到 *Dependencies* 属性中
 
-   ![Project settings](images/instant-games/game_project.png)
+   ![项目设置](images/instant-games/game_project.png)
 
-3. 确保在你打包游戏生成的 "index.html" 文件包含了 Instant Games SDK.
+3. 确保在你打包游戏生成的 "index.html" 文件包含了 Instant Games SDK
 
    ```html
    <script src="https://connect.facebook.net/en_US/fbinstant.6.3.js"></script>
    ```
 
-   关于打包设置详情请见 [HTML5 教程](/manuals/html5/#自定义HTML5打包).
+   关于打包设置详情请见 [HTML5 教程](/manuals/html5/#自定义HTML5打包)
 
-4. 都准备好之后, 打包 HTML5 游戏并上传至 Facebook.
+4. 都准备好之后,打包 HTML5 游戏并上传至 Facebook。
 
 ## API 使用
 
-Instant Games 扩展使用命名空间 `fbinstant.*` , 用 Lua API 对 Javascript SDK 进行了封装. 此扩展基本上是从 Javascript SDK 到 Lua API 一一对应的.
+Instant Games 扩展使用命名空间 `fbinstant.*`,用 Lua API 对 Javascript SDK 进行了封装。此扩展基本上是从 Javascript SDK 到 Lua API 一一对应的。
 
-比如, 看以下 Javascript 代码:
+比如,看以下 Javascript 代码:
 
 ```javascript
 FBInstant.initializeAsync().then(function() {
@@ -44,7 +44,7 @@ FBInstant.initializeAsync().then(function() {
 });
 ```
 
-相应的 Lua 代码是这样的:
+相应的 Lua 代码是这样的
 
 ```lua
 fbinstant.initialize(function(self, success)
@@ -55,31 +55,31 @@ fbinstant.initialize(function(self, success)
 end)
 ```
 
-关于如何在Defold中使用 Instant Games SDK 详情请见 [API documentation](https://github.com/defold/extension-fbinstant/blob/master/README.md).
+关于如何在 Defold 中使用 Instant Games SDK 详情请见 [API 文档](https://github.com/defold/extension-fbinstant/blob/master/README.md)。
 
 ## 示例游戏
 
-有个 Defold 游戏 "Tic Tac Toe" 的 Instant Games 版本在 [官方 GitHub 代码库](https://github.com/defold/extension-fbinstant) 提供了完整的源码和素材. 可以作为学习资料或者素材来使用.
+有个 Defold 游戏 "Tic Tac Toe" 的 Instant Games 版本在 [官方 GitHub 代码库](https://github.com/defold/extension-fbinstant) 提供了完整的源码和素材。可以作为学习资料或者素材来使用。
 
 ![Tic Tac Toe](images/instant-games/tictactoe.png)
 
 ## 减小包体
 
-Facebook Instant Games [最佳实践](https://developers.facebook.com/docs/games/instant-games/best-practices) 建议游戏首次载入时间不得超过5秒. 这对 Defold 来说有点勉强, 好在还有一些方法能减小游戏体积:
+Facebook Instant Games [最佳实践](https://developers.facebook.com/docs/games/instant-games/best-practices) 建议游戏首次载入时间不得超过 5 秒。这对 Defold 来说有点勉强,好在还有一些方法能减小游戏体积:
 
 去掉未使用引擎特性
-: HTML5 版的标准 Defold 引擎用gzip压缩后小于 1.2MB, 但是可以通过去掉不必要的引擎特效来达到减少包体的效果. 在 "app.manifest" 文件中可以指定去掉引擎哪方面特性, 此文件在 *game.project* 文件的 [Native Extension 部分](/manuals/project-settings/#Native extension) 引用.
+: HTML5 版的标准 Defold 引擎用 gzip 压缩后小于 1.2MB,但是可以通过去掉不必要的引擎特效来达到减少包体的效果。在 "app.manifest" 文件中可以指定去掉引擎哪方面特性,此文件在 *game.project* 文件的 [Native Extension 部分](/manuals/project-settings/#Native extension) 引用
 
-  此功能尚处于测试阶段且没有说明文档. 这里: https://forum.defold.com/t/stripping-appmanifest-maker/16059 有一个可以自动生成 app.manifests 文件的工具.
+  此功能尚处于测试阶段且没有说明文档。这里:https://forum.defold.com/t/stripping-appmanifest-maker/16059 有一个可以自动生成 app.manifests 文件的工具
 
 使用纹理压缩
-: 纹理压缩是有效减少包体和内存占用的方法. 关于纹理压缩详情请见 [Texture Profiles 教程](/manuals/texture-profiles/).
+: 纹理压缩是有效减少包体和内存占用的方法。关于纹理压缩详情请见 [Texture Profiles 教程](/manuals/texture-profiles/)。
 
 减少启动所需资源按需下载
-: 许多游戏把内容分成各个关卡或者各个篇章. 这种类型的游戏可以把内容放到玩家玩到的时候再下载.
+: 许多游戏把内容分成各个关卡或者各个篇章。这种类型的游戏可以把内容放到玩家玩到的时候再下载。
 
-这种把内容分块, 保存到服务器上然后按需下载并缓存的方法可以有效减少 Instant Game 包体. 这种方法由 Defold 的 [热更新](/manuals/live-update/) 系统提供支持.
+这种把内容分块,保存到服务器上然后按需下载并缓存的方法可以有效减少 Instant Game 包体。这种方法由 Defold 的 [热更新](/manuals/live-update/) 系统提供支持。
 
 ## 已知问题
 
-关于 HTML5 和 Instant Games 的已知问题详见 [HTML5 教程已知问题部分](/manuals/html5/#已知问题和局限性).
+关于 HTML5 和 Instant Games 的已知问题详见 [HTML5 教程已知问题部分](/manuals/html5/#已知问题和局限性)

+ 29 - 29
docs/zh/manuals/extension-googleplayinstant.md

@@ -1,31 +1,31 @@
 ---
 title: Google Play Instant
-brief: 本教程介绍了使用 Defold 创建 Google Play Instant 游戏的方法.
+brief: 本手册介绍了使用 Defold 创建 Google Play Instant 游戏的方法。
 ---
 
 # Google Play Instant
 
-Google Play Instant 可以让 Android 6.0+ 的设备运行无需安装的原生应用.
+Google Play Instant 可以让 Android 6.0+ 的设备运行无需安装的原生应用
 
 
-![GooglePlayInstant](images/gpi/gpi-try-now.png)
+![Google Play Instant](images/gpi/gpi-try-now.png)
 
 ## 发布流程
 
-如果想让游戏作为 Google Play Instant 发布, 需要修改项目配置:
+如果想让游戏作为 Google Play Instant 发布,需要修改项目配置:
 
-1. 自定义 `AndroidManifest.xml` 文件加入 `<manifest>` 属性:
+1. 自定义 `AndroidManifest.xml` 文件加入 `<manifest>` 属性
 
 ```lua
 xmlns:dist="http://schemas.android.com/apk/distribution"
 android:targetSandboxVersion="2"
 ```
-后面紧跟描述项:
+后面紧跟描述项
 ```lua
 <dist:module dist:instant="true" />
 ```
 
-结果 AndroidManifest.xml 类似这样:
+结果 AndroidManifest.xml 类似这样
 
 ```lua
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
@@ -38,32 +38,32 @@ android:targetSandboxVersion="2"
       <dist:module dist:instant="true" />
 ```
 
-2. 在 “game.project” 文件里添加 Google Instant Apps 扩展. 加入 “https://github.com/defold/extension-instantapp/archive/master.zip” 地址依赖或者指定 [特定版本](https://github.com/defold/extension-instantapp/releases) 的依赖.
+2. 在 "game.project" 文件里添加 Google Instant Apps 扩展。加入 "https://github.com/defold/extension-instantapp/archive/master.zip" 地址依赖或者指定 [特定版本](https://github.com/defold/extension-instantapp/releases) 的依赖
 
-![Project settings](images/gpi/game_project.png)
+![项目设置](images/gpi/game_project.png)
 
-3. 下载库文件: Project->Fetch Libraries
-4. 打包 `aab` Project->Bundle->Android Application
+3. 下载库文件Project->Fetch Libraries
+4. 打包 `aab`Project->Bundle->Android Application
 5. 上传 `aab` 至 Google Play Console 作为 Android Instant App 发布
 
 ### 版本号
-注意 [关于版本号的建议](https://developer.android.com/topic/google-play-instant/getting-started/game-instant-app#version-codes): Instant 游戏版本号要小于可安装游戏的版本号.
+注意 [关于版本号的建议](https://developer.android.com/topic/google-play-instant/getting-started/game-instant-app#version-codes):Instant 游戏版本号要小于可安装游戏的版本号。
 
-![Project settings](images/gpi/version_code.png)
+![项目设置](images/gpi/version_code.png)
 
 ### android:targetSandboxVersion="2"
 
-如果在可安装主游戏里设置 `android:targetSandboxVersion="2"` 就可以像 instant 游戏一样访问数据 (比如存取同一个文件). 但是这样一来主游戏程序就可能会受到一些限制. 详情请见 [官方文档](https://developer.android.com/guide/topics/manifest/manifest-element#targetSandboxVersion).
+如果在可安装主游戏里设置 `android:targetSandboxVersion="2"` 就可以像 instant 游戏一样访问数据(比如存取同一个文件)。但是这样一来主游戏程序就可能会受到一些限制。详情请见 [官方文档](https://developer.android.com/guide/topics/manifest/manifest-element#targetSandboxVersion)
 ::: sidenote
-游戏一旦安装, 它的目标沙箱值只能增加. 要想降级, 只能把游戏删除再覆盖安装 manifest 属性里目标沙箱值较小的版本.
+游戏一旦安装,它的目标沙箱值只能增加。要想降级,只能把游戏删除再覆盖安装 manifest 属性里目标沙箱值较小的版本。
 :::
-即使在可安装游戏和 instant 游戏里的 `android:targetSandboxVersion` 设置了不同的值, 仍然可以使用 `instantapp.set_cookie()` 和 `instantapp.get_cookie()` 来进行游戏版本间通信.
+即使在可安装游戏和 instant 游戏里的 `android:targetSandboxVersion` 设置了不同的值仍然可以使用 `instantapp.set_cookie()` 和 `instantapp.get_cookie()` 来进行游戏版本间通信
 
 ## API 使用
 
-Google Play Instant 扩展使用 `instantapp.*` 命名空间封装了 Java [PackageManagerCompat 方法](https://developers.google.com/android/reference/com/google/android/gms/instantapps/PackageManagerCompat) API 供 Lua 使用.
+Google Play Instant 扩展使用 `instantapp.*` 命名空间封装了 Java [PackageManagerCompat 方法](https://developers.google.com/android/reference/com/google/android/gms/instantapps/PackageManagerCompat) API 供 Lua 使用
 
-如果你要制作跨平台游戏最好在使用前检查 `instantapp` 模块是否存在, 因为它只存在于安卓游戏包中:
+如果你要制作跨平台游戏最好在使用前检查 `instantapp` 模块是否存在,因为它只存在于安卓游戏包中:
 ```lua
 if instantapp then
   -- 调用 instantapp 方法
@@ -84,33 +84,33 @@ else
 end
 ```
 
-关于在 Defold 里使用 Google Instant API 的详细信息请见 [API 文档](https://github.com/defold/extension-instantapp/blob/master/README.md).
+关于在 Defold 里使用 Google Instant API 的详细信息请见 [API 文档](https://github.com/defold/extension-instantapp/blob/master/README.md)
 
 ## 限制
-遵循 [Google Play Instant Technical Requirements](https://developer.android.com/topic/google-play-instant/game-tech-requirements) `apk` 大小不得大于 15 MB. 游戏大小优化详见 [这里](extension-fbinstant/#reducing-bundle-size).
+遵循 [Google Play Instant Technical Requirements](https://developer.android.com/topic/google-play-instant/game-tech-requirements) `apk` 大小不得大于 15 MB。游戏大小优化详见 [这里](extension-fbinstant/#reducing-bundle-size)。
 
 ## 测试
-![Testing Instant game](images/gpi/start_instant.png)
+![测试 Instant 游戏](images/gpi/start_instant.png)
 
-1. 下载 Android SDK 工具:
+1. 下载 Android SDK 工具
 - macOS: https://dl.google.com/android/repository/tools_r25.2.3-macosx.zip
 - Windows: https://dl.google.com/android/repository/tools_r25.2.3-windows.zip
 - Linux: https://dl.google.com/android/repository/tools_r25.2.3-linux.zip
-2. 解压拷贝 `tools` 文件夹到 `android-sdk` 文件夹.
-3. 安卓编译工具:
+2. 解压拷贝 `tools` 文件夹到 `android-sdk` 文件夹
+3. 安卓编译工具
 ```console
-./android-sdk/tools/bin/sdkmanager --verbose “build-tools;25.0.3”
+./android-sdk/tools/bin/sdkmanager --verbose "build-tools;25.0.3"
 ```
-4. 安装 `extra-google-instantapps` 工具:
+4. 安装 `extra-google-instantapps` 工具
 ```console
 sh ./android-sdk/tools/android update sdk --no-ui --all --filter extra-google-instantapps
 ```
-5. 在设备上作为 Instant 游戏加载 `apk` 文件:
+5. 在设备上作为 Instant 游戏加载 `apk` 文件
 ```console
 android-sdk/extras/google/instantapps/ia run path_to_your_game.apk
 ```
 
-前4步可以合并为一个脚本:
+前4步可以合并为一个脚本
 ```console
 mkdir ~/android
 cd ~/android
@@ -125,4 +125,4 @@ mv tools android-sdk/tools
 sh ./android-sdk/tools/android update sdk --no-ui --all --filter extra-google-instantapps
 ```
 
-设备调试详情请见 [调试教程](/manuals/debugging/#_debugging_on_mobile_devices).
+设备调试详情请见 [调试教程](/manuals/debugging/#_debugging_on_mobile_devices)

+ 5 - 5
docs/zh/manuals/extension-gpgs.md

@@ -1,21 +1,21 @@
 ---
 title: Defold 中的 Google Play Game 服务
-brief: 本教程介绍了配置使用 Google Play Game 服务的方法
+brief: 本手册介绍了配置使用 Google Play Game 服务的方法
 ---
 
 # Google Play Game Services
 
-[Google Play Game Services](https://developers.google.com/games/services) 可以给你的安卓游戏增加用户认证, 云存储, 成就系统, 排行榜等各种功能. Google Play Game 服务在 Defold 中作为一个 [原生扩展](/manuals/extensions/).
+[Google Play Game Services](https://developers.google.com/games/services) 可以给你的安卓游戏增加用户认证、云存储、成就系统、排行榜等各种功能。Google Play Game 服务在 Defold 中作为一个 [原生扩展](/manuals/extensions/)。
 
 ## 安装扩展
 
-要使用 Google Play Game 服务扩展你需要在 *game.project* 文件中加入依赖. 最新稳定版地址:
+要使用 Google Play Game 服务扩展你需要在 *game.project* 文件中加入依赖。最新稳定版地址:
 ```
 https://github.com/defold/extension-gpgs/archive/master.zip
 ```
 
-推荐使用发布页的zip链接 [指定某个版本](https://github.com/defold/extension-gpgs/releases).
+推荐使用发布页的zip链接 [指定某个版本](https://github.com/defold/extension-gpgs/releases)
 
 ## 使用扩展
 
-使用的介绍以及 API 文档位于 [GitHub 扩展项目网页](https://defold.github.io/extension-gpgs/).
+使用的介绍以及 API 文档位于 [GitHub 扩展项目网页](https://defold.github.io/extension-gpgs/)

+ 56 - 57
docs/zh/manuals/extension-iap.md

@@ -1,14 +1,14 @@
 ---
 title: Defold 中的内支付
-brief: 应用内支付 (也称内购买) 允许用户付费以获得额外的内容或功能. 本教程介绍了相关功能的 Defold API.
+brief: 应用内支付(也称内购买)允许用户付费以获得额外的内容或功能。本手册介绍了相关功能的 Defold API。
 ---
 
 # 应用内支付
 
 Defold 提供了方便的 iOS Appstore "in-app purchases" 和 Google Play 及 Amazon "in-app billing" 系统接口. Facebook Canvas 的 "game payments" 用于 Facebook Canvas 游戏. 这些服务能让你销售:
 
-* 标准应用内支付 (一次性购买) 的消耗品和非消耗品
-* 订阅 (自动循环购买)
+* 标准应用内支付(一次性购买)的消耗品和非消耗品
+* 订阅(自动循环购买)
 
 ::: sidenote
 目前 Defold 接口可以与 Apple 的 Storekit 完整交互. 对于 Google Play 和 Facebook Canvas, 接口是一致的, 这有助于代码跨平台. 但是不同平台需要的流程有所不同. 而且注意目前没有针对 macOS 系统上 Mac Appstore 的支付接口.
@@ -16,83 +16,83 @@ Defold 提供了方便的 iOS Appstore "in-app purchases" 和 Google Play 及 Am
 
 关于 Apple, Google, Amazon 和 Facebook 的详细文档参考:
 
-* [In-App Purchase Programming Guide](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Introduction.html).
-* [Google Play In-app Billing documentation](http://developer.android.com/google/play/billing/index.html).
-* [Amazon In-app Purchase documentation](https://developer.amazon.com/public/apis/earn/in-app-purchasing).
-* [Facebook game payments documentation](https://developers.facebook.com/docs/payments).
+* [In-App Purchase Programming Guide](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Introduction.html)
+* [Google Play In-app Billing documentation](http://developer.android.com/google/play/billing/index.html)
+* [Amazon In-app Purchase documentation](https://developer.amazon.com/public/apis/earn/in-app-purchasing)
+* [Facebook game payments documentation](https://developers.facebook.com/docs/payments)
 
 ## 安装扩展
 
-首先要在 *game.project* 文件中加入内支付扩展依赖. 最新稳定版本地址如下:
+首先要在 *game.project* 文件中加入内支付扩展依赖。最新稳定版本地址如下:
 ```
 https://github.com/defold/extension-iap/archive/master.zip
 ```
 
-推荐使用 [正式发布版](https://github.com/defold/extension-iap/releases) 的zip连接作为依赖引用.
+推荐使用 [正式发布版](https://github.com/defold/extension-iap/releases) 的 zip 连接作为依赖引用。
 
-其 API 文档详见 [扩展项目首页](https://defold.github.io/extension-iap/).
+其 API 文档详见 [扩展项目首页](https://defold.github.io/extension-iap/)
 
 
 ## 使用静态报告测试 Google Play Billing
 
-Android 建议使用 Google Play 的静态报告来实现 IAP. 这样在正式发布之前就可以确保内支付工作正常. 测试用静态报告包括4个ID:
+Android 建议使用 Google Play 的静态报告来实现 IAP。这样在正式发布之前就可以确保内支付工作正常。测试用静态报告包括 4 个 ID:
 
 `android.test.purchased`
-: Google Play 报告模拟支付完成. 此报告包含一个 JSON 字符串, 内含模拟支付信息 (比如模拟用户ID等).
+: Google Play 报告模拟支付完成。此报告包含一个 JSON 字符串,内含模拟支付信息(比如模拟用户 ID 等)。
 
 `android.test.canceled`
-: Google Play 报告模拟支付取消. 这种情况可能因为付款时出现错误, 比如信用卡无效, 或者用户付款前订单被取消.
+: Google Play 报告模拟支付取消。这种情况可能因为付款时出现错误,比如信用卡无效,或者用户付款前订单被取消。
 
 `android.test.refunded`
-: Google Play 报告模拟退款完成.
+: Google Play 报告模拟退款完成
 
 `android.test.item_unavailable`
-: Google Play 报告app可购买物品列表里找不到用户购买的项目.
+: Google Play 报告 app 可购买物品列表里找不到用户购买的项目
 
 ## 内支付准备流程
 
-iOS 和 Android 内支付的准备流程差不多:
+iOS 和 Android 内支付的准备流程差不多
 
-1. 注册为 Apple 或 Google Play 开发者.
-2. 为目标平台进行项目配置. 参考 [iOS 开发教程](/manuals/ios) 与 [Android 开发教程](/manuals/android).
-3. 为应用商店进行测试配置:
+1. 注册为 Apple 或 Google Play 开发者
+2. 为目标平台进行项目配置。参考 [iOS 开发教程](/manuals/ios) 与 [Android 开发教程](/manuals/android)。
+3. 为应用商店进行测试配置
 
-    - Android 上, 使用 [Google Play Developer Console](https://play.google.com/apps/publish/).
-    - iOS 上, 使用 [iTunes Connect](https://itunesconnect.apple.com/). 注意你的 App ID (于 https://developer.apple.com 上的 "成员中心" 配置) 要开启 "In-App Purchase" 选项.
+    - Android 上,使用 [Google Play Developer Console](https://play.google.com/apps/publish/)。
+    - iOS 上,使用 [iTunes Connect](https://itunesconnect.apple.com/)。注意你的 App ID(于 https://developer.apple.com 上的 "成员中心" 配置)要开启 "In-App Purchase" 选项。
 
     ![iTunes Connect and Google Play Dev Console](images/iap/itunes_connect_google_play.png)
 
-4. 对于 Google Play, 你需要 _上传并发布_ 测试版 *.apk* 文件. 对于 iTunes Connect, 直到应用审批之前你 _不用上传_ 应用文件给 iTunes Connect. 加入上传了未完成的应用文件给 iTunes Connect, Apple 会拒绝该应用.
+4. 对于 Google Play,你需要 _上传并发布_ 测试版 *.apk* 文件。对于 iTunes Connect,直到应用审批之前你 _不用上传_ 应用文件给 iTunes Connect。加入上传了未完成的应用文件给 iTunes Connect,Apple 会拒绝该应用。
 
-5. 设置应用内消费品.
+5. 设置应用内消费品
 
     ![iTunes 消费品](images/iap/itunes_products.png)
 
     ![Google Play 消费品](images/iap/google_play_products.png)
 
-6. 设置测试用账户.
-    - 在 iTunes Connect 页面 *用户与规则* 中可以设置专门用于 _沙盒环境_ 的模拟支付用户. 要给应用做开发者证书签名然后在测试设备上登录 Appstore 沙盒账户进行测试.
-    - 在 Google Play Developer Console 上, 选择 *设置 > 账户详情* 的 License Testing 部分设置测试用户 email. 多个 email 用逗号分隔. 然后测试者可以登录并购买消费品而不会真的扣款.
-    - 在 Google Play 上, 还需要为测试者们建立 Google Group. Google 使用组来管理应用测试组成员. 在 *Alpha Testing* 页面的 *Manage list of testers* 设置测试者 Google Group. 应用上线前必须通过 Alpha 测试.
+6. 设置测试用账户
+    - 在 iTunes Connect 页面 *用户与规则* 中可以设置专门用于 _沙盒环境_ 的模拟支付用户要给应用做开发者证书签名然后在测试设备上登录 Appstore 沙盒账户进行测试
+    - 在 Google Play Developer Console 上,选择 *设置 > 账户详情* 的 License Testing 部分设置测试用户 email。多个 email 用逗号分隔。然后测试者可以登录并购买消费品而不会真的扣款。
+    - 在 Google Play 上,还需要为测试者们建立 Google Group。Google 使用组来管理应用测试组成员。在 *Alpha Testing* 页面的 *Manage list of testers* 设置测试者 Google Group。应用上线前必须通过 Alpha 测试。
 
 ![Alpha testers](images/iap/alpha_testers.png)
 
-Facebook 内支付准备流程:
+Facebook 内支付准备流程
 
-1. 注册为 Facebook 开发者. 登录 [Facebook for developers](https://developers.facebook.com/), 在 "My Apps" 下 "Register as a developer", 完成注册步骤.
-2. Facebook 要求支持同步和异步两种支付方式. 详情请见 [Payment overview](https://developers.facebook.com/docs/payments/overview)
-3. 建立应用托管和回调服务器:
-    * 建立托管应用的加密 canvas 地址. 详情请见 [Games on Facebook](https://developers.facebook.com/docs/games/gamesonfacebook/hosting).
-    * 建立回调服务器. 详情请见 [Setting up your callback server](https://developers.facebook.com/docs/payments/realtimeupdates#yourcallbackserver).
-4. 配置应用. 详情请见 [Facebook Developer Dashboard](https://developers.facebook.com/quickstarts/?platform=canvas).
-5. 加入测试用户. 在应用面板的 "Canvas Payments" 部分进行设置.
-6. 建立应用消费品. 详情请见 [Defining products](https://developers.facebook.com/docs/payments/implementation-guide/defining-products/).
+1. 注册为 Facebook 开发者。登录 [Facebook for developers](https://developers.facebook.com/),在 "My Apps" 下 "Register as a developer",完成注册步骤。
+2. Facebook 要求支持同步和异步两种支付方式详情请见 [Payment overview](https://developers.facebook.com/docs/payments/overview)
+3. 建立应用托管和回调服务器
+    * 建立托管应用的加密 canvas 地址详情请见 [Games on Facebook](https://developers.facebook.com/docs/games/gamesonfacebook/hosting)
+    * 建立回调服务器详情请见 [Setting up your callback server](https://developers.facebook.com/docs/payments/realtimeupdates#yourcallbackserver)
+4. 配置应用详情请见 [Facebook Developer Dashboard](https://developers.facebook.com/quickstarts/?platform=canvas)
+5. 加入测试用户。在应用面板的 "Canvas Payments" 部分进行设置。
+6. 建立应用消费品详情请见 [Defining products](https://developers.facebook.com/docs/payments/implementation-guide/defining-products/)
 
 ## 异步的内支付 API
 
-内支付 API 是异步的, 也就是说应用发送信息给服务器, 然后能继续运行. 等到从服务器传回的信息时, 一个 _回调_ 函数会被调用, 从中可以根据回调数据进行各种处理工作.
+内支付 API 是异步的,也就是说应用发送信息给服务器,然后能继续运行。等到从服务器传回的信息时,一个 _回调_ 函数会被调用,从中可以根据回调数据进行各种处理工作。
 
-获得消费品列表:
+获得消费品列表
 
 ```lua
 local COINS_ID = "com.defold.examples.coins"
@@ -113,12 +113,12 @@ local function product_list(self, products, error)
 end
 
 function init(self)
-    -- 初始化消费品列表 (对于 Google Play 来说一次能获取 20 个)
+    -- 初始化消费品列表(对于 Google Play 来说一次能获取 20 个)
     iap.list({ COINS_ID, LOGO_ID }, product_list)
 end
 ```
 
-对于正式交易, 首先要注册交易结果监听器, 然后在玩家购买时调用内支付函数:
+对于正式交易,首先要注册交易结果监听器,然后在玩家购买时调用内支付函数:
 
 ```lua
 local function iap_listener(self, transaction, error)
@@ -141,7 +141,7 @@ end
 
 function on_message(self, message_id, message, sender)
     ...
-    -- 注册内支付结果监听器.
+    -- 注册内支付结果监听器
     iap.set_listener(iap_listener)
     -- 买一个金币...
     iap.buy(COINS_ID)
@@ -149,7 +149,7 @@ function on_message(self, message_id, message, sender)
 end
 ```
 
-操作系统会自动弹出支付界面. 要是处于测试/沙盒环境下, 界面中会明确标明.
+操作系统会自动弹出支付界面。要是处于测试/沙盒环境下,界面中会明确标明。
 
 ![Confirm purchase](images/iap/ios_confirm_purchase.png)
 
@@ -159,44 +159,43 @@ end
 
 ## 实时付款
 
-大多数付款系统都是实时的. 支付完成时应用会收到一个消息, TRANS_STATE_PURCHASED. 这是交易的最终状态, 表明对于这笔交易不会再有其他消息了.
+大多数付款系统都是实时的。支付完成时应用会收到一个消息,TRANS_STATE_PURCHASED。这是交易的最终状态,表明对于这笔交易不会再有其他消息了。
 
 ## 非实时付款
 
-有的付款系统需要非实时的支持. 也就是说你的应用只在付款开始时收到一个消息. 为了验证付款完成与否, 需要你的服务器 (或者客户端) 与付款系统进行更多的交流.
-这种情况下支付完成时应用会收到一个 TRANS_STATE_UNVERIFIED 消息 (而不是 TRANS_STATE_PURCHASED). 这也是交易的最终状态, 表明对于这笔交易不会再有其他消息了.
+有的付款系统需要非实时的支持。也就是说你的应用只在付款开始时收到一个消息。为了验证付款完成与否,需要你的服务器(或者客户端)与付款系统进行更多的交流。
+这种情况下支付完成时应用会收到一个 TRANS_STATE_UNVERIFIED 消息(而不是 TRANS_STATE_PURCHASED)。这也是交易的最终状态,表明对于这笔交易不会再有其他消息了。
 
 ## 购买交付
 
-玩家购买消费品之后, 应用有义务告知玩家支付已完成 (比如服务器验证支付成功之后).
-内支付支持 auto-completion, 也就是自动产生支付完成的消息 (默认设置). 也可以在项目配置里关闭 auto-completion. 支付完成时手动调用 `iap.finish()`, 来产生完成消息.
+玩家购买消费品之后,应用有义务告知玩家支付已完成(比如服务器验证支付成功之后)。
+内支付支持 auto-completion,也就是自动产生支付完成的消息(默认设置)。也可以在项目配置里关闭 auto-completion。支付完成时手动调用 `iap.finish()`,来产生完成消息。
 
 ### 消耗品与非消耗品
-Google Play 应用商店只支持消耗品. 必须使用非消耗品的话就关闭 auto-completion 并且不要调用完成函数. 这样在 `iap.set_listener()` 被调用时, 消费品购买总是保持着购买中的状态.
+Google Play 应用商店只支持消耗品。必须使用非消耗品的话就关闭 auto-completion 并且不要调用完成函数。这样在 `iap.set_listener()` 被调用时,消费品购买总是保持着购买中的状态。
 
-Apple App Store 支持非消耗品, 也就是说购买完成时才向玩家提供消费品交付. 这种情况下 auto-completion 可以开启也可以关闭 (比如你需要自己验证支付成功) 之后调用 `iap.finish()`.
+Apple App Store 支持非消耗品,也就是说购买完成时才向玩家提供消费品交付。这种情况下 auto-completion 可以开启也可以关闭(比如你需要自己验证支付成功)之后调用 `iap.finish()`。
 
 ## 支付收据
 
-收据是一堆加密数据, 可以把它发送给 App Store 来验证付款是否真正完成. 这是用开发者服务器验证付款必须使用的东西.
+收据是一堆加密数据,可以把它发送给 App Store 来验证付款是否真正完成。这是用开发者服务器验证付款必须使用的东西。
 
 ## 除错
-
 Android `iap.list()` 返回 "failed to fetch product"
-: 你需要上传 *.apk* 文件到 Google Play Developer Console 的 alpha 或者 beta 频道. 还要注意确保你的设配上 _日期和时间_ 是正确的.
+: 你需要上传 *.apk* 文件到 Google Play Developer Console 的 alpha 或者 beta 频道。还要注意确保你的设配上 _日期和时间_ 是正确的。
 
 Android (Google Play) `iap.list()` 只返回 20 个消费品
-: Google 有 [每次请求返回最多 20 个消费品的限制](https://github.com/googlesamples/android-play-billing/blob/master/TrivialDrive/app/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl#L62). 可以多次调用 `iap.list()` 然后合并返回结果以实现20个以上的消费品列表.
+: Google 有 [每次请求返回最多 20 个消费品的限制](https://github.com/googlesamples/android-play-billing/blob/master/TrivialDrive/app/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl#L62)。可以多次调用 `iap.list()` 然后合并返回结果以实现 20 个以上的消费品列表。
 
 iOS `iap.list()` 返回空值
-: 确保你的账户是 iOS 付款应用账户, 并且签署好一切所需文件. 没有经过认证的话, 你的 iOS 应用内支付 (甚至测试支付) 操作不会正确执行.
+: 确保你的账户是 iOS 付款应用账户,并且签署好一切所需文件。没有经过认证的话,你的 iOS 应用内支付(甚至测试支付)操作不会正确执行。
 
-  检查 "Member Center" 上的应用ID是否开启了 in-app purchases  (检查 "Member Center" 里 "Certificates, Identifiers & Profiles" 的 "Enabled Services:" 项) 并且该应用 (或者调试版应用) 已用供应商档案进行了签名而且签名没过期.
+  检查 "Member Center" 上的应用 ID 是否开启了 in-app purchases(检查 "Member Center" 里 "Certificates, Identifiers & Profiles" 的 "Enabled Services:" 项)并且该应用(或者调试版应用)已用供应商档案进行了签名而且签名没过期。
 
-  内支付消费品信息传到沙盒环境需要几小时时间, 请耐心等待.
+  内支付消费品信息传到沙盒环境需要几小时时间,请耐心等待。
 
 iOS `iap.list()` 产生错误日志 "Unexpected callback set"
-: `iap.list()` 调用不可以嵌套. 从 `iap.list()` 调用 `iap.list()` 就会产生这个错误日志.
+: `iap.list()` 调用不可以嵌套。从 `iap.list()` 调用 `iap.list()` 就会产生这个错误日志。
 
 在 iOS 上, "price_string" 里有个 '~' 字符
 : '~' 是未找到字体的字符占位符. 调用 `iap.list()` 返回的数据使用 _不间断空白_ (`\u00a0`) 分割价格和货币符号并填充 "price_string" 变量. 使用 GUI 组件渲染的话, 需要在字体 *extra_characters* 属性里设置所需字符. 在 macOS 上按 <kbd>Option + SPACE</kbd> 就是不间断空白. 详情请见 http://en.wikipedia.org/wiki/Non-breaking_space.

+ 34 - 34
docs/zh/manuals/extension-push.md

@@ -1,29 +1,29 @@
 ---
 title: Defold 的 iOS 和 Android 推送通知
-brief: 本教程介绍了如何配置和实现游戏中的本地和远程 iOS 与 Android 平台的推送通知.
+brief: 本手册介绍了如何配置和实现游戏中的本地和远程 iOS 与 Android 平台的推送通知。
 ---
 
 # 推送通知
 
-推送通知作为 [原生扩展](/manuals/extensions/) 在 iOS 和 Android 设备上用来给玩家提示修改和更新之类的信息. iOS 和 Android 实现方法基本一样但是也有一些平台相关的东西需要注意.
+推送通知作为 [原生扩展](/manuals/extensions/) 在 iOS 和 Android 设备上用来给玩家提示修改和更新之类的信息。iOS 和 Android 实现方法基本一样但是也有一些平台相关的东西需要注意。
 
-推送通知为了找到从服务器到目标设备的通路, 需要得到应用的一些信息. 最复杂的部分包括用于校验客户端接收通知的合法性的应用安全信息. 还需要用于 Apple 或者 Google 校验你发送通知合法性的服务器安全信息. 最后, 推送通知的时候, 你需要知道到用户设备的唯一路径. 为此你需要指定设备的唯一 token (用来分辨用户).
+推送通知为了找到从服务器到目标设备的通路,需要得到应用的一些信息。最复杂的部分包括用于校验客户端接收通知的合法性的应用安全信息。还需要用于 Apple 或者 Google 校验你发送通知合法性的服务器安全信息。最后,推送通知的时候,你需要知道到用户设备的唯一路径。为此你需要指定设备的唯一 token(用来分辨用户)。
 
 ## 安装扩展
 
-使用之前要在 *game.project* 文件里配置扩展依赖. 最新稳定版依赖的 URL 是:
+使用之前要在 *game.project* 文件里配置扩展依赖。最新稳定版依赖的 URL 是:
 
 ```
 https://github.com/defold/extension-push/archive/master.zip
 ```
 
-推荐使用 [指定版本](https://github.com/defold/extension-push/releases) 的zip包链接作为依赖.
+推荐使用 [指定版本](https://github.com/defold/extension-push/releases) 的 zip 包链接作为依赖。
 
 ```
 https://github.com/defold/extension-firebase-core/archive/master.zip
 ```
 
-API 文档在 [推送通知扩展项目](https://defold.github.io/extension-push/) 页上.
+API 文档在 [推送通知扩展项目](https://defold.github.io/extension-push/) 页上
 
 ## iOS 配置
 
@@ -31,13 +31,13 @@ API 文档在 [推送通知扩展项目](https://defold.github.io/extension-push
 为了更好地使用 Apple Push Notification 服务, 最好先熟读 [Apple 的官方文档](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html).
 :::
 
-iOS 上, 推送通知需要做以下准备:
+iOS 上,推送通知需要做以下准备:
 
-* 要为 App ID 开启推送通知.
-* 需要包含此 App ID 的应用提供商档案.
-* 还需要一个 SSL 证书用来把数据从消息服务应用发送到 Apple 服务器.
+* 要为 App ID 开启推送通知
+* 需要包含此 App ID 的应用提供商档案
+* 还需要一个 SSL 证书用来把数据从消息服务应用发送到 Apple 服务器
 
-准备就绪后登录到 [Apple 开发者中心](https://developer.apple.com/membercenter). 找到 AppID 打开通知推送服务.
+准备就绪后登录到 [Apple 开发者中心](https://developer.apple.com/membercenter)。找到 AppID 打开通知推送服务。
 
 ![AppID push notifications](images/push/push_ios_app_id.png)
 
@@ -45,20 +45,20 @@ iOS 上, 推送通知需要做以下准备:
 
 ![APN SSL certificate](images/push/push_ios_certificate.png)
 
-从你的服务器往通知推送服务器发送数据时需要这个证书. 开发调试时, 可以先在本地安装这个证书然后运行 [APNS-Pusher](https://github.com/KnuffApp/APNS-Pusher) 或者 [NWPusher](https://github.com/noodlewerk/NWPusher) 之类的测试工具.
+从你的服务器往通知推送服务器发送数据时需要这个证书。开发调试时,可以先在本地安装这个证书然后运行 [APNS-Pusher](https://github.com/KnuffApp/APNS-Pusher) 或者 [NWPusher](https://github.com/noodlewerk/NWPusher) 之类的测试工具
 
-记得创建包含要推送通知 AppID 的供应商档案, 并且在档案中设置好开发设备. 可以在 "Member Center" 页面或者 Xcode 中进行这些操作.
+记得创建包含要推送通知 AppID 的供应商档案,并且在档案中设置好开发设备。可以在 "Member Center" 页面或者 Xcode 中进行这些操作。
 
 ![Provisioning profile](images/push/push_ios_provisioning_profile.png)
 
-注意 Apple 的沙盒服务器可能需要一段时间更新信息, 通知推送功能也许不能马上使用. 要有耐心.
+注意 Apple 的沙盒服务器可能需要一段时间更新信息,通知推送功能也许不能马上使用。要有耐心。
 
 推送通知测试代码如下:
 
 <a name="above-code"></a>
 ```lua
 local function push_listener(self, payload, origin)
-    -- 通知到达这里.
+    -- 通知到达这里
     pprint(payload)
 end
 
@@ -80,7 +80,7 @@ function on_message(self, message_id, message)
                 for i = 1,#token do
                     t = t .. string.format("%02x", string.byte(token, i))
                 end
-                -- 打印设备token
+                -- 打印设备 token
                 print(t)
             else
                 -- 错误
@@ -91,7 +91,7 @@ function on_message(self, message_id, message)
     elseif message_id == hash("push_android") then
         push.register(nil, function (self, token, error)
             if token then
-                -- 打印设备token
+                -- 打印设备 token
                 print(token)
             else
                 -- 错误
@@ -103,17 +103,17 @@ function on_message(self, message_id, message)
 end
 ```
 
-如果一切顺利通知监听器会被注册然后打印出设备的 token:
+如果一切顺利通知监听器会被注册然后打印出设备的 token
 
 ```txt
 DEBUG:SCRIPT: 1f8ba7869b84b10df69a07aa623cd7f55f62bca22cef61b51fedac643ec61ad8
 ```
 
-如果运行的是测试应用, 你现在就可以尝试使用设备token和通知服务SSL证书向你的设备推送通知了.
+如果运行的是测试应用,你现在就可以尝试使用设备 token 和通知服务 SSL 证书向你的设备推送通知了。
 
 ![Pusher test](images/push/push_ios_pusher.png)
 
-通知发送之后会被测试应用接收, 进入 `push_listener()` 函数:
+通知发送之后会被测试应用接收,进入 `push_listener()` 函数:
 
 ```txt
 DEBUG:SCRIPT:
@@ -126,11 +126,11 @@ DEBUG:SCRIPT:
 }
 ```
 
-同时 iOS 桌面会提示通知:
+同时 iOS 桌面会提示通知
 
 ![iOS notification](images/push/push_ios_notification.png)
 
-如果要在图标上显示计数角标, 可以使用 `push.set_badge_count()` 函数.
+如果要在图标上显示计数角标,可以使用 `push.set_badge_count()` 函数。
 
 ## Android 配置
 
@@ -138,35 +138,35 @@ DEBUG:SCRIPT:
 建议首先阅读 Firebase Cloud Messaging 服务文档. 文档在这里 https://firebase.google.com/docs/cloud-messaging/
 :::
 
-Android 上, 推送通知需要做以下准备:
+Android 上,推送通知需要做以下准备:
 
-* Firebase CM Sender ID 和应用 ID. 这些id会打包到应用中去.
-* 用于使用 Firebase 服务的服务器 API Key.
+* Firebase CM Sender ID 和应用 ID。这些 id 会打包到应用中去。
+* 用于使用 Firebase 服务的服务器 API Key
 
 ::: sidenote
-如果你的应用使用了 Google Cloud Messaging 平台, 现在需要导入 Firebase Cloud Messaging 平台中. 把应用从 Google dashboard 导入到 Firebase 即可. 导入后 *sender id* 保持不变, 你的 *game.project* 文件需要更新使用 `Firebase Application ID` (见下文).
+如果你的应用使用了 Google Cloud Messaging 平台,现在需要导入 Firebase Cloud Messaging 平台中。把应用从 Google dashboard 导入到 Firebase 即可。导入后 *sender id* 保持不变,你的 *game.project* 文件需要更新使用 `Firebase Application ID`(见下文)。
 :::
 
-基本配置很简单. 登录 [https://console.firebase.google.com](https://console.firebase.google.com), 选择或者新建应用. 然后进入 *Grow* 的 *Cloud Messaging* 页面.
+基本配置很简单。登录 [https://console.firebase.google.com](https://console.firebase.google.com),选择或者新建应用。然后进入 *Grow* 的 *Cloud Messaging* 页面。
 
 ![Adding Cloud Messaging to a Firebase project](images/push/push_fcm_add_cm.png)
 
-点击 Android 图标开始配置通知推送.
+点击 Android 图标开始配置通知推送
 
 
 ![Configure Cloud Messaging for Android](images/push/push_fcm_configure_android.png)
 
-根据提示, 输入 Defold 游戏项目使用的包名.
+根据提示,输入 Defold 游戏项目使用的包名。
 
 ![Android cloud services info](images/push/push_fcm_register.png)
 
-下载 `google-services.json`, 我们需要这个文件里面的一些信息.
+下载 `google-services.json`,我们需要这个文件里面的一些信息。
 
 ![Google Cloud Messaging sender ID](images/push/push_fcm_download_json.png)
 
-下面两步可以跳过, *Add Firebase SDK* 和 *Run your app to verify installation*. SDK 已打包进 Defold, 无需手动添加.
+下面两步可以跳过,*Add Firebase SDK* 和 *Run your app to verify installation*。SDK 已打包进 Defold,无需手动添加。
 
-用文本编辑器打开 `google-services.json` 文件, 找到 *`project_number`* 和 *`mobilesdk_app_id`*. 把这俩id考入 *game.project* 文件, 对应 *android* 部分, `Gcm Sender Id` (`project_number`) 和 `Fcm Application Id` (`mobilesdk_app_id`).
+用文本编辑器打开 `google-services.json` 文件,找到 *`project_number`* 和 *`mobilesdk_app_id`*。把这俩 id 考入 *game.project* 文件,对应 *android* 部分,`Gcm Sender Id`(`project_number`)和 `Fcm Application Id`(`mobilesdk_app_id`)。
 
 ```
 {
@@ -189,13 +189,13 @@ Android 上, 推送通知需要做以下准备:
 
 ![Settings applied to game.project](images/push/push_fcm_game_project.png)
 
-至此客户端准备就绪. [上面测试ios时用的代码](#above-code) 对 Android 同样有效. 运行并记录设备 token.
+至此客户端准备就绪。[上面测试 ios 时用的代码](#above-code) 对 Android 同样有效。运行并记录设备 token。
 
 ```txt
 DEBUG:SCRIPT: APA91bHkcKm0QHAMUCEQ_Dlpq2gzset6vh0cz46kDDV6230C5rFivyWZMCxGXcjxRDKg1PK4z1kWg3xnUVqSDiO_4_RiG8b8HeYJfaoW1ho4ukWYXjq5RE0Sy-JTyrhqRusUP_BxRTcE
 ```
 
-发送通知之前需要一个 Firebase 服务认证 key. 这个 key 位于 Firebase dashboard 的 *Settings* 的 *Cloud Messaging* 页面中.
+发送通知之前需要一个 Firebase 服务认证 key。这个 key 位于 Firebase dashboard 的 *Settings* 的 *Cloud Messaging* 页面中。
 
 ![Server Key location](images/push/push_fcm_server_key.png)
 

+ 2 - 2
docs/zh/manuals/extension-websocket.md

@@ -1,7 +1,7 @@
 ---
 title: WebSocket 连接
-brief: 本教程介绍了 websocket 连接的使用方法.
+brief: 本手册介绍了 WebSocket 连接的使用方法。
 ---
 ## WebSocket 连接
 
-Defold 没有内置 WebSocket 连接功能. 建议使用 [Defold-WebSocket 扩展程序](https://github.com/britzl/defold-websocket) 实现该功能.
+Defold 没有内置 WebSocket 连接功能建议使用 [Defold-WebSocket 扩展程序](https://github.com/britzl/defold-websocket) 实现该功能

+ 72 - 72
docs/zh/manuals/extension-webview.md

@@ -1,99 +1,99 @@
 ---
 title: Defold 的 WebViews
-brief: WebViews 可以在你的手机上显示一个网页层. 同时支持在后台运行用户定义的js代码. 本教程介绍了 Defold 的官方 WebView 扩展, API 和功能.
+brief: WebViews 可以在你的手机上显示一个网页层。同时支持在后台运行用户定义的 js 代码。本手册介绍了 Defold 的官方 WebView 扩展、API 和功能。
 ---
 
 # WebViews
-WebView 提供了一套特殊的 API 用来在手机上显示一个网页层. 首先让我们来实现一个简单的 webview.
-然后我们会讨论如何使用一套简单的控制按钮控制这个 webview.
+WebView 提供了一套特殊的 API 用来在手机上显示一个网页层。首先让我们来实现一个简单的 webview。
+然后我们会讨论如何使用一套简单的控制按钮控制这个 webview
 
 ## 安装扩展
 
-在你的 *game.project* 文件中设置 webview 依赖.
-最新版本位于如下 URL:
+在你的 *game.project* 文件中设置 webview 依赖
+最新版本位于如下 URL
 ```
 https://github.com/defold/extension-webview/archive/master.zip
 ```
 
-API文档位于 [扩展首页](https://defold.github.io/extension-webview/).
+API 文档位于 [扩展首页](https://defold.github.io/extension-webview/)
 
 ## 打开 webview
-使用 `webview.create` 就能创建一个网页层, 并且返回一个唯一id. 下文中我们把这个 ID 称为 `webview_id`,
-多个 `webview` 之间进行交互时会用到这个id. 也就是说创建和维护多个 webview 是可行的.
+使用 `webview.create` 就能创建一个网页层,并且返回一个唯一 id。下文中我们把这个 ID 称为 `webview_id`,
+多个 `webview` 之间进行交互时会用到这个 id。也就是说创建和维护多个 webview 是可行的。
 
-`webview.create` 带着一个函数参数, 待会儿我们再来仔细看看这个回调, 现在先给它留空.
+`webview.create` 带着一个函数参数,待会儿我们再来仔细看看这个回调,现在先给它留空。
 ```lua
 local webview_id = webview.create(function()
         -- 目前无代码
     end)
 ```
-默认状况下新建的 webview 都是不可见的, 因为它还没有加载任何内容. 其主要功能就是显示网页, 现在就来加载个超酷的网页吧!
+默认状况下新建的 webview 都是不可见的,因为它还没有加载任何内容。其主要功能就是显示网页,现在就来加载个超酷的网页吧!
 
-调用 `webview.open` 函数, 第一个参数就是上文的那个 `webview_id`, 第二个参数是要打开的URL.
+调用 `webview.open` 函数,第一个参数就是上文的那个 `webview_id`,第二个参数是要打开的 URL。
 
 ```lua
 local request_id = webview.open(webview_id, "http://www.defold.com") --广告无处不在
 ```
 
-这个函数返回网页请求的id, 这个id我们稍后也会用到.
+这个函数返回网页请求的 id,这个 id 我们稍后也会用到。
 
-如果一切顺利你将看到神奇的网页占满了屏幕, 就是 Defold 官方首页.
+如果一切顺利你将看到神奇的网页占满了屏幕,就是 Defold 官方首页。
 
 ::: sidenote
-要在 iOS 里访问的网页必须遵循在 `Info.plist` 文件中的 `NSAppTransportSecurity` 里面设置好的键值对.
+要在 iOS 里访问的网页必须遵循在 `Info.plist` 文件中的 `NSAppTransportSecurity` 里面设置好的键值对
 ```
 <key>NSAllowsArbitraryLoads</key>
 <true/>
 ```
 
-开发的时候可以随便设置, 但是发布到 App Store 之后就只能通过使用 `NSExceptionDomains` 键代替. 这有点超出本教程讨论范围,
-详情可以参考 [Apple 开发者文档](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW35).
+开发的时候可以随便设置,但是发布到 App Store 之后就只能通过使用 `NSExceptionDomains` 键代替。这有点超出本手册讨论范围,
+详情可以参考 [Apple 开发者文档](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW35)
 :::
 
 ## 回调函数
-顺利打开网页固然是好, 但要是 URL 无效或者出现其他不可预知的问题时要给用户显示错误信息怎么办? 或者要在用户离开网页时做些什么该怎么办?
-幸运的是 webview 扩展程序具备了报错, 导航, 载入成功等等事件回调功能. 只需在调用 `webview.create` 时传入回调函数作为参数即可.
+顺利打开网页固然是好但要是 URL 无效或者出现其他不可预知的问题时要给用户显示错误信息怎么办?或者要在用户离开网页时做些什么该怎么办?
+幸运的是 webview 扩展程序具备了报错、导航、载入成功等等事件回调功能。只需在调用 `webview.create` 时传入回调函数作为参数即可。
 
-回调函数特征如下:
+回调函数特征如下
 ```lua
 function callback(self, webview_id, request_id, type, data)
 ```
 
-* **`self`** - 回调函数所处的脚本引用.
-* **`webview_id`** - 回调函数可以做到多个webview共用, 这个参数引用的是回调事件发生的那个webview的id.
-* **`request_id`** - 同样 `webview.open` 也可以共用一个回调回调函数, 这个参数引用的是回调事件发生的那个载入请求的id.
-* **`type`** - 事件的类型, 枚举类型, 下文 *回调类型* 章节会详细探讨.
-* **`data`** - 不同时间连带的各种数据信息.
+* **`self`** - 回调函数所处的脚本引用
+* **`webview_id`** - 回调函数可以做到多个 webview 共用,这个参数引用的是回调事件发生的那个 webview 的 id。
+* **`request_id`** - 同样 `webview.open` 也可以共用一个回调回调函数,这个参数引用的是回调事件发生的那个载入请求的 id。
+* **`type`** - 事件的类型,枚举类型,下文 *回调类型* 章节会详细探讨。
+* **`data`** - 不同时间连带的各种数据信息
 
 #### 回调类型
 回调的 `type` 参数可以被设置为以下枚举之一:
 
-* **`webview.CALLBACK_RESULT_URL_LOADING`** - 在 webview 内导航时, 载入事件被触发. 调用 `webview.open` 或者
-用户点击页面上的超级链接都会造成事件触发. 事件的处理结果决定了载入请求是否被允许. 如果返回 `false` 则载入终止, 其他值则是允许载入.
-被允许的链接也会记录在回调函数 `data` 表的 `url` 项里.
-* **`webview.CALLBACK_RESULT_URL_ERROR`** 和 **`webview.CALLBACK_RESULT_EVAL_ERROR`** -一旦载入出错, 或者
-执行JavaScript脚本出错 (下文 *运行JavaScript脚本* 章节会详细探讨), 错误事件就会被触发. `data` 表的 `result` 项用一个字符串记录了错误的详细内容.
-* **`webview.CALLBACK_RESULT_URL_OK`** 和 **`webview.CALLBACK_RESULT_EVAL_OK`** - 一旦载入成功, 或者执行JavaScript脚本成功,
-OK事件就会被触发. 对于成功执行的JavaScript程序, 其执行结果会被保存在 `data` 表的 `result` 项之中.
+* **`webview.CALLBACK_RESULT_URL_LOADING`** - 在 webview 内导航时,载入事件被触发。调用 `webview.open` 或者
+用户点击页面上的超级链接都会造成事件触发。事件的处理结果决定了载入请求是否被允许。如果返回 `false` 则载入终止,其他值则是允许载入。
+被允许的链接也会记录在回调函数 `data` 表的 `url` 项里
+* **`webview.CALLBACK_RESULT_URL_ERROR`** 和 **`webview.CALLBACK_RESULT_EVAL_ERROR`** - 一旦载入出错,或者
+执行 JavaScript 脚本出错(下文 *运行 JavaScript 脚本* 章节会详细探讨),错误事件就会被触发。`data` 表的 `result` 项用一个字符串记录了错误的详细内容。
+* **`webview.CALLBACK_RESULT_URL_OK`** 和 **`webview.CALLBACK_RESULT_EVAL_OK`** - 一旦载入成功,或者执行 JavaScript 脚本成功,
+OK 事件就会被触发。对于成功执行的 JavaScript 程序,其执行结果会被保存在 `data` 表的 `result` 项之中。
 
-事件触发介绍完了, 现在我们来看一个复杂点的例子.
+事件触发介绍完了,现在我们来看一个复杂点的例子。
 
-比如我们要向玩家展示一个反馈页面, 玩家通过一个 HTML 表格发送反馈意见. 我们要在载入不成功的时候要提示友好的错误信息并关闭webview而不是把白屏留给玩家.
-接下来我们尽量不让玩家离开这个反馈页面.
+比如我们要向玩家展示一个反馈页面,玩家通过一个 HTML 表格发送反馈意见。我们要在载入不成功的时候要提示友好的错误信息并关闭 webview 而不是把白屏留给玩家。
+接下来我们尽量不让玩家离开这个反馈页面
 
-升级版的 `webview.create` 调用和回调被设计成下面这样:
+升级版的 `webview.create` 调用和回调被设计成下面这样
 ```lua
 local player_feedback_url = "https://example.com/my_game_name/customer_feedback"
 
 local function webview_callback(self, webview_id, request_id, type, data)
     if type == webview.CALLBACK_RESULT_URL_ERROR then
-        -- 遇到错误!
-        -- 关闭 webview 然后显示提示文本!
+        -- 遇到错误
+        -- 关闭 webview 然后显示提示文本
         webview.destroy(webview_id)
         label.set_text("#label", "Player feedback not available at this moment.")
 
     elseif type == webview.CALLBACK_RESULT_URL_LOADING then
-        -- 不让玩家离开这个页面.
+        -- 不让玩家离开这个页面
         if data.url ~= player_feedback_url then
             return false
         end
@@ -104,23 +104,23 @@ local feedback_webview = webview.create(webview_callback)
 webview.open(feedback_webview, player_feedback_url)
 ```
 
-一个反馈页面展示就完成了. 网页自己做, 打开后大概像这个样子:
+一个反馈页面展示就完成了。网页自己做,打开后大概像这个样子:
 
 ![Player feedback web page](images/webview/webview_player_feedback1.png)
 
-注意: 我们的例子里有一个指向 google.com 的超级链接, 目的是试试玩家点别的链接出不出的去. --牛虻
+注意:我们的例子里有一个指向 google.com 的超级链接,目的是试试玩家点别的链接出不出的去。——牛虻
 
-强制反馈功能完成! 但是怎么提交反馈呢? 也许玩家不想提交反馈呢, 怎么返回游戏? 再说, 全屏的网页真的合适吗? 后面的游戏界面全都被挡住了啊!
-我们会在下文的 *运行 JavaScript 脚本* 和 *可视定位控制面板* 章节继续探讨.
+强制反馈功能完成!但是怎么提交反馈呢?也许玩家不想提交反馈呢,怎么返回游戏?再说,全屏的网页真的合适吗?后面的游戏界面全都被挡住了啊!
+我们会在下文的 *运行 JavaScript 脚本* 和 *可视定位控制面板* 章节继续探讨
 
 ## 载入展示自己的 HTML 网页
-继续深入探讨之前, 我们来动手做一个可以用来交互的 HTML 简单网页.
+继续深入探讨之前,我们来动手做一个可以用来交互的 HTML 简单网页。
 
-通过调用 `webview.open_raw` 函数我们可以让webview直接解析加载 HTML 文件源码. 这样即使没有服务器, 网络环境恶劣的情况下, 都可以载入我们的网页.
+通过调用 `webview.open_raw` 函数我们可以让 webview 直接解析加载 HTML 文件源码。这样即使没有服务器,网络环境恶劣的情况下,都可以载入我们的网页。
 
-`webview.open_raw` 的第一个参数和 `webview.open` 一样是 `webview_id`. 第二个参数换成网页源代码引用.
+`webview.open_raw` 的第一个参数和 `webview.open` 一样是 `webview_id`。第二个参数换成网页源代码引用。
 
-下面来看一个把网页代码直接写在脚本里的例子:
+下面来看一个把网页代码直接写在脚本里的例子
 ```lua
 local feedback_html = [[
 <html>
@@ -155,14 +155,14 @@ local webview_id = webview.create(webview_callback)
 webview.open_raw(webview_id, feedback_html)
 ```
 
-效果与前面的示例类似, 不同的是这次我们可以随时任意修改网页代码.
-**注意:** 本例中 `webview_callback` 函数与前例类似故忽略.
+效果与前面的示例类似,不同的是这次我们可以随时任意修改网页代码。
+**注意:** 本例中 `webview_callback` 函数与前例类似故忽略。
 
-众所周知一个 HTML 源码包含所有代码和资源是不明智的, 最好把 JavaScript 和 CSS 等资源分门别类保存为文件, 这种情况下
-可以使用 [`sys.load_resource`](https://www.defold.com/ref/sys/#sys.load_resource:filename) 进行资源文件的预加载.
-而且这样做还有一个好处就是可以随时打开网页浏览器查看网页效果.
+众所周知一个 HTML 源码包含所有代码和资源是不明智的,最好把 JavaScript 和 CSS 等资源分门别类保存为文件,这种情况下
+可以使用 [`sys.load_resource`](https://www.defold.com/ref/sys/#sys.load_resource:filename) 进行资源文件的预加载
+而且这样做还有一个好处就是可以随时打开网页浏览器查看网页效果
 
-新建一个文件夹 (`custom_resources`) 和一个 HTML 文件 (`feedback.html`). 然后用 `feedback_html` 变量引用这些资源.
+新建一个文件夹(`custom_resources`)和一个 HTML 文件(`feedback.html`)。然后用 `feedback_html` 变量引用这些资源。
 
 ```lua
 local feedback_html = sys.load_resource("/custom_resources/feedback.html")
@@ -171,48 +171,48 @@ webview.open_raw(webview_id, feedback_html)
 ```
 
 ## 可视性和位置控制
-现在来解决网页占据全屏问题.
+现在来解决网页占据全屏问题
 
-为了更方便的互动, 我们要把网页放在游戏屏幕上半部分. 可以使用 `webview.set_position` 函数设置webview的位置和宽高.
-设置 `-1` 代表在这个轴向上占据全部屏幕.
+为了更方便的互动,我们要把网页放在游戏屏幕上半部分。可以使用 `webview.set_position` 函数设置 webview 的位置和宽高。
+设置 `-1` 代表在这个轴向上占据全部屏幕
 
 ```lua
 local webview_id = webview.create(webview_callback)
--- 位置: 屏幕左上角 (0, 0)
--- 尺寸: 全屏款, 500像素高
+-- 位置屏幕左上角 (0, 0)
+-- 尺寸:全屏宽,500 像素高
 webview.set_position(webview_id, 0, 0, -1, 500)
 ```
 
 ![Resized feedback page](images/webview/webview_player_feedback2.png)
 
-遇到性能不理想的设备, 网页从加载到显示可能会白屏很长时间. 这个体验很不好, 所以加载完成之前我们先把webview隐藏起来. 同时我们还要提示玩家资源正在加载.
+遇到性能不理想的设备,网页从加载到显示可能会白屏很长时间。这个体验很不好,所以加载完成之前我们先把 webview 隐藏起来。同时我们还要提示玩家资源正在加载。
 
-这里用到 `webview.open_raw` (`webview.open` 同样) 的第三个参数, 传入一个表, 然后设置 `hidden` 键为 `true`.
-默认是 `false`, 代表像前面示例那样一调用加载就可见.
+这里用到 `webview.open_raw`(`webview.open` 同样)的第三个参数,传入一个表,然后设置 `hidden` 键为 `true`。
+默认是 `false`,代表像前面示例那样一调用加载就可见。
 
 ```lua
 webview.open_raw(webview_id, feedback_html, {hidden = true})
 ```
 
-等到 `webview.CALLBACK_RESULT_URL_OK` 事件触发说明资源加载完毕. 这时就可以显示webview了, 调用 `webview.set_visible` 函数即可.
+等到 `webview.CALLBACK_RESULT_URL_OK` 事件触发说明资源加载完毕。这时就可以显示 webview 了,调用 `webview.set_visible` 函数即可。
 
-升级版的回调函数如下:
+升级版的回调函数如下
 ```lua
 local function webview_callback(self, webview_id, request_id, type, data)
     if type == webview.CALLBACK_RESULT_URL_OK then
-        -- 顺利完成加载, 显示webview!
+        -- 顺利完成加载,显示 webview!
         webview.set_visible(webview_id, 1)
     elseif type == webview.CALLBACK_RESULT_URL_ERROR then
         -- ...
 ```
 
 ## 运行 JavaScript 脚本
-现在来解决关闭webview的事.
+现在来解决关闭 webview 的事。
 
-前例中已经出现过, 遇到错误事件触发时, 调用了 `webview.destroy` 函数. 但是没有错误就没法把握关闭webview的时机.
-幸好引擎提供了从 Lua 到webview里运行的 JavaScript 程序的交互功能. 这样我们就能关注webview里js变量的变化.
+前例中已经出现过,遇到错误事件触发时,调用了 `webview.destroy` 函数。但是没有错误就没法把握关闭 webview 的时机。
+幸好引擎提供了从 Lua 到 webview 里运行的 JavaScript 程序的交互功能。这样我们就能关注 webview 里 js 变量的变化。
 
-当玩家按下网页上的一个按钮时, 运行一段程序, 改变一个变量.
+当玩家按下网页上的一个按钮时,运行一段程序,改变一个变量。
 ```js
 var shouldClose = false;
 function closeWebview() {
@@ -226,10 +226,10 @@ function submitFeedback() {
 
 ```
 
-不论玩家按了 "提交反馈" 还是 "取消反馈" 按钮, 程序都会把 `shouldClose` 变量设置为 true.
+不论玩家按了 "提交反馈" 还是 "取消反馈" 按钮,程序都会把 `shouldClose` 变量设置为 true。
 
-在 Lua 脚本里我们只要发现 `shouldClose` 变为 true 了, 就知道该调用 `webview.destroy` 了.
-正好有个好地方来关注这个变量, 就是在每帧都会被调用的 `update` 函数里.
+在 Lua 脚本里我们只要发现 `shouldClose` 变为 true 了,就知道该调用 `webview.destroy` 了。
+正好有个好地方来关注这个变量,就是在每帧都会被调用的 `update` 函数里。
 
 ```lua
 function update(self, dt)
@@ -239,7 +239,7 @@ function update(self, dt)
 end
 ```
 
-注意这里 `webview.eval` 返回的并不是 JavaScript 的运行结果, 而是 *运行请求id*. 我们首先要确定回调函数的请求id, 这个函数里传入的 `data.result` 才是真正的 JavaScript 运行结果.
+注意这里 `webview.eval` 返回的并不是 JavaScript 的运行结果,而是 *运行请求 id*。我们首先要确定回调函数的请求 id,这个函数里传入的 `data.result` 才是真正的 JavaScript 运行结果。
 
 ```lua
 local function webview_callback(self, webview_id, request_id, type, data)
@@ -256,4 +256,4 @@ local function webview_callback(self, webview_id, request_id, type, data)
         -- ...
 ```
 
-这样一来玩家在点击按钮之后就能返回继续游戏了!
+这样一来玩家在点击按钮之后就能返回继续游戏了

+ 79 - 77
docs/zh/manuals/extensions-best-practices.md

@@ -1,124 +1,126 @@
 ---
 title: 原生扩展 - 最佳实践
-brief: 本教程介绍了开发原生扩展的最佳实践.
+brief: 本手册介绍了开发原生扩展的最佳实践。
 ---
 
 # 最佳实践
 
-编写跨平台代码可能很困难, 但是通过一些方法可以更易于开发与维护. 本教程列举了 Defold 与跨平台原生代码共同工作的 API 和方法.
+编写跨平台代码可能很困难,但是通过一些方法可以更易于开发与维护这样的代码。
 
-## Defold 代码
+## 项目结构
 
-在 Defold 引擎中我们很少使用 C++ 代码. 事实上, 大多数是 C-like 代码. 除了少数容器类外, 我们去掉了模板, 因为模板会增加编译时间和包体大小.
+创建扩展时,有几件事可以帮助开发和维护它。
 
-### C++ 版本
+### Lua API
 
-Defold 源码使用默认 C++ 版本编译.
+应该只有一个 Lua API,并且只有一个实现。这使得在所有平台上具有相同的行为变得更加容易。
 
-我们不用最新的 C++ 版本及特性. 主要因为默认版本对于游戏引擎足够用了. 追寻最新 C++ 版本特性相当耗费时间.
+如果相关平台不支持该扩展,建议根本不注册 Lua 模块。这样你可以通过检查 nil 来检测支持:
 
-这也有助于向扩展开发者提供稳定 ABI. 而且使用最新 C++ 特性的话很可能会在不同平台上造成编译问题.
+```lua
+    if myextension ~= nil then
+        myextension.do_something()
+    end
+```
 
-### 标准模板库 - STL
+### 文件夹结构
 
-Defold 引擎不支持 STL 代码, 除了某些算法和数学库 (std::sort, std::upper_bound 等), 但是你的扩展里可以使用 STL.
+以下文件夹结构经常用于扩展:
 
-再次注意 ABI 的不兼容性可能使你使用其他扩展或者第三方库造成困难.
+```
+    /root
+        /input
+        /main                            -- 实际示例项目的所有文件
+            /...
+        /myextension                     -- 扩展的实际根文件夹
+            ext.manifest
+            /include                     -- 外部包含,其他扩展使用
+            /libs
+                /<platform>              -- 所有支持平台的外部库
+            /src
+                myextension.cpp          -- 扩展的 Lua api 和扩展生命周期函数
+                                            还包含你的 Lua api 函数的通用实现。
+                myextension_private.h    -- 每个平台将实现的内部 api(即 `myextension_Init` 等)
+                myextension.mm           -- 如果 iOS/macOS 需要原生调用。为 iOS/macOS 实现 `myextension_Init` 等
+                myextension_android.cpp  -- 如果 Android 需要 JNI 调用。为 Android 实现 `myextension_Init` 等
+                /java
+                    /<platform>          -- Android 需要的任何 java 文件
+            /res                         -- 平台需要的任何资源
+            /external
+                README.md                -- 关于如何构建或打包任何外部库的说明/脚本
+        /bundleres                       -- 应该打包的资源(参见 game.project 和 [bundle_resources 设置](/manuals/project-settings/#project))
+            /<platform>
+        game.project
+        game.appmanifest                 -- 任何额外的应用配置信息
+```
 
-去掉 (重模板化的) STL 库, 还能减少编译时间, 更重要的是, 减小应用体积.
+注意,`myextension.mm` 和 `myextension_android.cpp` 只有在为该平台进行特定的原生调用时才需要。
 
-#### 字符串
+#### 平台文件夹
 
-在 Defold 引擎中, 我们使用 `const char*` 代替了 `std::string`.
+在某些地方,平台架构被用作文件夹名称,以了解在编译/捆绑应用程序时使用哪些文件。这些形式如下:
 
-`std::string` 使得 C++ 不同版本混合编译造成困难: 原因是 ABI 不匹配.
-所以我们选择使用 `const char*` 及相关工具函数代替.
+    <architecture>-<platform>
 
-### 函数隐藏
+当前列表是:
 
-本地函数尽量使用 `static` 关键字定义. 这样便于编译器优化, 提高性能减小应用体积.
+    arm64-ios, armv7-ios, x86_64-ios, arm64-android, armv7-android, x86_64-linux, x86_64-osx, x86_64-win32, x86-win32
 
-## 第三方库
+因此,例如,将平台特定的库放在:
 
-当我们选用第三方库时 (不管由什么语言编写), 至少需要考虑这些事情:
+    /libs
+        /arm64-ios
+                            /libFoo.a
+        /arm64-android
+                            /libFoo.a
 
-* 功能 - 这个库满足你的功能要求了吗?
-* 性能 - 运行时是否需要消耗大量性能?
-* 体积 - 会给包体增大多少体积?是否在可接受范围内?
-* 依赖 - 是否依赖其他库?
-* 支持 - 这个库是个什么样的状态? 是否有许多bug? 是否还在维护?
-* 证书 - 是否可以合法使用?
+## 编写原生代码
 
+在 Defold 源码中,C++ 的使用非常有限,大多数代码非常类似于 C。除了少数容器类外,几乎没有模板,因为模板会增加编译时间和可执行文件大小。
 
-## 开源依赖
+### C++ 版本
 
-确定你能访问你的依赖库. 比如说在 GitHub 上托管的库, 随时可能被移除, 突然改变开发方向或者改变拥有者维护者. 如果你fork了这个库就能减少这些变化带来的损失.
+Defold 源码是使用每个编译器的默认 C++ 版本构建的。Defold 源码本身使用的 C++ 版本不高于 C++98。虽然可以使用更高版本来构建扩展,但更高版本可能带来 ABI 变化。这可能会使得无法在引擎或[资源门户](/assets)中将一个扩展与其他扩展一起使用。
 
-库代码是直接注入你的游戏中的, 所以需要保证它在满足你的要求的前提下不会在后台做什么小动作!
+Defold 源码避免使用 C++ 的最新功能或版本。主要是因为在构建游戏引擎时不需要新功能,而且追踪 C++ 的最新功能是一项耗时的任务,真正掌握这些功能需要大量宝贵时间。
 
+这对扩展开发者还有一个额外的好处,即 Defold 维护了稳定的 ABI。还值得指出的是,使用最新的 C++ 功能可能会由于不同平台的支持程度不同而阻止代码在不同平台上编译。
 
-## 项目结构
+### 无 C++ 异常
 
-当你创建扩展, 开发和维护时是有些技巧的.
+Defold 在引擎中不使用任何异常。游戏引擎通常避免使用异常,因为数据(大部分)在开发期间就已知。移除对 C++ 异常的支持可以减小可执行文件大小并提高运行时性能。
 
-### Lua api
+### 标准模板库 - STL
 
-应该只有一个 Lua api, 只有一个实现方法. 这样有助于在所有平台上保持一致的表现.
+由于 Defold 引擎不使用任何 STL 代码,除了一些算法和数学函数(`std::sort`、`std::upper_bound` 等),在你的扩展中使用 STL 可能是可行的。
 
-如果某平台不支持这个扩展, 建议不要注册 Lua 模块.
-这样就可以通过检查非 nil 来判断对扩展的支持性:
+再次记住,当你的扩展与其他扩展或第三方库一起使用时,ABI 不兼容性可能会阻碍你。
 
-    if myextension ~= nil then
-        myextension.do_something()
-    end
+避免使用(重度模板化的)STL 库,也可以改善我们的构建时间,更重要的是,减少可执行文件大小。
 
-### 文件夹结构
+#### 字符串
 
-这是我们开发扩展使用的常用结构.
+在 Defold 引擎中,使用 `const char*` 而不是 `std::string`。使用 `std::string` 是在混合不同版本的 C++ 或编译器版本时的常见陷阱,因为它可能导致 ABI 不匹配。使用 `const char*` 和一些辅助函数可以避免这种情况。
 
-    /root
-        /input
-        /main                            -- 示例项目根目录
-            /...
-        /myextension                     -- 扩展根目录
-            ext.manifest
-            /include                     -- 其他扩展使用的外部包含
-            /libs
-                /<platform>              -- 各个平台使用的外部包含
-            /src
-                myextension.cpp          -- 扩展的 Lua api 及其生命周期函数
-                                            还包含 Lua api 功能的通用实现方法.
-                myextension_private.h    -- 每个平台需要实现的内部 api (也就是 `myextension_Init` 之类的功能)
-                myextension.mm           -- 如果需要调用 iOS/macOS 原生功能. 就要为 iOS/macOS 实现 `myextension_Init` 之类的功能 
-                myextension_android.cpp  -- 如果需要调用 Android 的JNI. 就要为 Android 实现 `myextension_Init` 之类的功能
-                /java
-                    /<platform>          -- Android 需要的java文件
-            /res                         -- 平台需要的资源文件
-            /external
-                README.md                -- 扩展相关编译打包的说明/脚本
-        /bundleres                       -- 需要打包的资源 (参见 game.project 以及 [bundle_resources 设置](/manuals/project-settings/#Project))
-            /<platform>
-        game.project
-        game.appmanifest                 -- 其他应用设置
+### 使函数隐藏
 
+如果可能,在编译单元本地函数上使用 `static` 关键字。这让编译器可以进行一些优化,既可以提高性能,也可以减少可执行文件大小。
 
-注意 `myextension.mm` 和 `myextension_android.cpp` 只在调用平台特定原生功能时使用.
+## 第三方库
 
-#### 平台文件夹
+当选择要使用的第三方库时(无论语言),请考虑以下几点:
 
-在某些地方, 需要针对架构平台命名文件夹, 以便应用编译/打包时使用正确的文件.
-结构是这样的:
+* 功能 - 它是否解决了你遇到的特定问题?
+* 性能 - 它是否会在运行时带来性能成本?
+* 库大小 - 最终可执行文件会增大多少?这是否可接受?
+* 依赖 - 它是否需要额外的库?
+* 支持 - 库的状态如何?它是否有很多未解决的问题?它是否仍在维护?
+* 许可证 - 是否可以在这个项目中使用?
 
-    <architecture>-<platform>
+## 开源依赖
 
-目前支持的有:
+始终确保你可以访问你的依赖项。例如,如果你依赖于 GitHub 上的某些内容,没有什么可以阻止该存储库被删除,或者突然改变方向或所有权。你可以通过分叉存储库并使用你的分叉而不是上游项目来减轻这种风险。
 
-    arm64-ios, armv7-ios, x86_64-ios, arm64-android, armv7-android, x86_64-linux, x86_64-osx, x86_64-win32, x86-win32
+记住,库中的代码将被注入到你的游戏中,所以确保库做了它应该做的事情,而不是其他事情!
 
-比如, 这么放置平台相关库:
 
-    /libs
-        /arm64-ios
-                            /libFoo.a
-        /arm64-android
-                            /libFoo.a

+ 13 - 13
docs/zh/manuals/extensions-build-variants.md

@@ -1,29 +1,29 @@
 ---
 title: 原生扩展 - Build variants
-brief: 本教程介绍了 Defold 能创建的各种 Build variants 以及它们如何与原生扩展和引擎交互.
+brief: 本手册介绍了 Defold 能创建的各种 Build variants 以及它们如何与原生扩展和引擎交互。
 ---
 
 :[Build Variants](../shared/build-variants.md)
 
 ## App Manifest
 
-不但可以为引擎加入原生扩展功能, 还可以从引擎中剔除一些部分. 比如你不需要物理引擎, 就可以从应用中去除. 关于如何去除引擎功能参见 [应用清单教程](/manuals/app-manifest).
+不但可以为引擎加入原生扩展功能,还可以从引擎中剔除一些部分。比如你不需要物理引擎,就可以从应用中去除。关于如何去除引擎功能参见[应用清单手册](/manuals/app-manifest)。
 
 ### 上下文组合
 
-实际上 app manifest 有着与 extension manifest 相同的结构和语法. 这使我们能够在最终编译时为每个平台混合上下文配置.
+实际上 app manifest 有着与 extension manifest 相同的结构和语法。这使我们能够在最终编译时为每个平台混合上下文配置。
 
-而且, Defold 自身, 有其基础 build manifest (`build.yml`). 编译每个扩展时, 这些文件做如下混合:
+而且,Defold 自身,有其基础 build manifest(`build.yml`)。编译每个扩展时,这些文件做如下混合:
 
 	manifest = merge(game.appmanifest, ext.manifest, build.yml)
 
-用户可以覆盖引擎和每个扩展的默认行为. 而且, 对于最终链接阶段, 我们混合了 app manifest 与 defold manifest:
+用户可以覆盖引擎和每个扩展的默认行为。而且,对于最终链接阶段,我们混合了 app manifest 与 defold manifest:
 
 	manifest = merge(game.appmanifest, build.yml)
 
 ### 语法
 
-这是一个参考示例:
+这是一个参考示例
 
 ```yml
 platforms:
@@ -88,15 +88,15 @@ platforms:
 
 #### 白名单
 
-对于所有关键字, 我们提供白名单过滤. 这样可以避免非法路径处理和访问编译上载文件夹之外的文件.
+对于所有关键字,我们提供白名单过滤。这样可以避免非法路径处理和访问编译上载文件夹之外的文件。
 
 #### linkFlags
 
-可以在这里添加指定平台的编译标志.
+可以在这里添加指定平台的编译标志
 
 #### libs
 
-此标志仅在需要添加平台或者 Defold SDK 里的库时使用. 应用的扩展库是自动添加的, 不应在这里添加. 下面是从引擎中剔除 3D 物理的例子:
+此标志仅在需要添加平台或者 Defold SDK 里的库时使用。应用的扩展库是自动添加的,不应在这里添加。下面是从引擎中剔除 3D 物理的例子:
 
     x86_64-linux:
         context:
@@ -107,7 +107,7 @@ platforms:
 
 #### Exclude flags
 
-此标志用于剔除平台上下文已经预先定义的东西. 下面是从引擎中剔除 Facebook 扩展的例子 (注意 `(.*)` 是帮助去掉正确元素而使用的正则表达式).
+此标志用于剔除平台上下文已经预先定义的东西。下面是从引擎中剔除 Facebook 扩展的例子(注意 `(.*)` 是帮助去掉正确元素而使用的正则表达式)。
 
     armv7-android:
         context:
@@ -117,8 +117,8 @@ platforms:
             libs: []
             linkFlags: []
 
-#### 所有 flags, libraries, symbols 在哪?
+#### 所有 flags、libraries、symbols 在哪?
 
-与其在这里列举我们不然努力把 manifest 的编辑功能加入编辑器, 让用户使用更方便.
+与其在这里列举,我们不如努力把 manifest 的编辑功能加入编辑器,让用户使用更方便。
 
-与此同时, [Manifestation](https://britzl.github.io/manifestation/) 工具也会持续更新.
+与此同时,[Manifestation](https://britzl.github.io/manifestation/) 工具也会持续更新。

+ 26 - 0
docs/zh/manuals/extensions-cocoapods.md

@@ -0,0 +1,26 @@
+---
+title: 在 iOS 和 macOS 构建中使用 CocoaPods 依赖
+brief: 本手册介绍了如何在 iOS 和 macOS 构建中使用 CocoaPods 解析依赖。
+---
+
+# CocoaPods
+
+[CocoaPods](https://cocoapods.org/) 是 Swift 和 Objective-C Cocoa 项目的依赖管理器。CocoaPods 通常用于管理和集成 Xcode 项目中的依赖。Defold 在为 iOS 和 macOS 构建时不使用 Xcode,但它仍然使用 Cocoapods 在构建服务器上解析依赖。
+
+## 解析依赖
+
+原生扩展可以在 `manifests/ios` 和 `manifests/osx` 文件夹中包含 `Podfile` 文件来指定扩展依赖。例如:
+
+```
+platform :ios '11.0'
+
+pod 'FirebaseCore', '10.22.0'
+pod 'FirebaseInstallations', '10.22.0'
+```
+
+构建服务器将收集所有扩展中的 `Podfile` 文件,并使用这些文件解析所有依赖,并在构建原生代码时包含它们。
+
+示例:
+
+* [Firebase](https://github.com/defold/extension-firebase/blob/master/firebase/manifests/ios/Podfile)
+* [Facebook](https://github.com/defold/extension-facebook/blob/master/facebook/manifests/ios/Podfile)

+ 2 - 2
docs/zh/manuals/extensions-debugging-android.md

@@ -1,6 +1,6 @@
 ---
 title: Android调试
-brief: 本教程介绍了如何调试运行在 Android 设备上的应用.
+brief: 本手册介绍了如何调试运行在 Android 设备上的构建.
 ---
 
-教程移动至 [调试 Android 原生代码](/manuals/debugging-native-code-android)
+已移至 [调试 Android 原生代码](/manuals/debugging-native-code-android)

+ 2 - 2
docs/zh/manuals/extensions-debugging-ios.md

@@ -1,6 +1,6 @@
 ---
 title: 在 iOS/macOS 中调试
-brief: 本教程介绍了如何使用 Xcode 进行调试.
+brief: 本手册介绍了如何使用 Xcode 调试构建.
 ---
 
-本教程移至 [调试 iOS 原生代码](/manuals/debugging-native-code-ios).
+已移至 [调试 iOS 原生代码](/manuals/debugging-native-code-ios).

+ 2 - 2
docs/zh/manuals/extensions-debugging.md

@@ -1,6 +1,6 @@
 ---
 title: 调试原生扩展
-brief: 本教程介绍了一些调试包含原生扩展程序应用的方法.
+brief: 本手册介绍了一些调试包含原生扩展的应用的方法.
 ---
 
-详见 [调试原生代码教程](/manuals/debugging-native-code).
+请参阅[调试原生代码手册](/manuals/debugging-native-code).

+ 3 - 35
docs/zh/manuals/extensions-defold-sdk.md

@@ -1,11 +1,11 @@
 ---
 title: 原生扩展 - Defold SDK
-brief: 本教程介绍了创建原生扩展时如何使用 Defold SDK.
+brief: 本手册介绍了创建原生扩展时如何使用 Defold SDK。
 ---
 
 # Defold SDK
 
-Defold SDK 包含了应用运行的原生平台底层接口与高层Lua逻辑接口来实现原生扩展的功能.
+Defold SDK 包含了声明原生扩展所需的功能,以及与应用运行的原生平台底层接口和创建游戏逻辑的高层Lua层进行交互的功能。
 
 ## 用法
 
@@ -13,37 +13,5 @@ Defold SDK 包含了应用运行的原生平台底层接口与高层Lua逻辑接
 
     #include <dmsdk/sdk.h>
 
-可用的SDK功能都在 [API文档](/ref/dmExtension/) 里写明了. SDK包含以下命名空间和功能:
-
-* [Align](/ref/dmAlign/) - 公共宏. 用来保证编译器兼容
-* [Array](/ref/dmArray/) - 具有边界检测的模板化数组.
-* [Buffer](/ref/dmBuffer/) - 数据缓存功能是不同平台互相交流的主要途径. [Lua API](/ref/buffer/) 同样具有缓存功能.
-* [Condition Variable](/ref/dmConditionVariable/) - 条件变量.
-* [ConfigFile](/ref/dmConfigFile/) - 配置文件的存取功能. 配置文件是 *game.project* 文件的编译后版本.
-* [Connection Pool](/ref/dmConnectionPool/) - Socket连接池功能.
-* [Crypt](/ref/dmCrypt/) - 加密功能.
-* [DNS](/ref/dmDNS/) - DNS功能.
-* [Engine](/ref/dmEngine/) - 引擎用于处理配置文件, 内部web服务器, 游戏对象等核心功能.
-* [Extension](/ref/dmExtension/) - 创建和控制引擎原生扩展库功能.
-* [Game Object](/ref/dmGameObject/) - 游戏对象管理功能.
-* [Graphics](/ref/dmGraphics/) - 平台相关的原生图像功能.
-* [Hash](/ref/dmHash/) - 哈希功能.
-* [HID](/ref/dmHid/) - 通用程序化输入功能.
-* [HTTP Client](/ref/dmHttpClient/) - HTTP客户端交互功能.
-* [Json](/ref/dmJson/) - 平台无关的json文件解析器.
-* [Log](/ref/dmLog/) - 日志功能.
-* [Math](/ref/dmMath/) - 数学库.
-* [Mutex](/ref/dmMutex/) - 平台无关的互斥锁同步基础功能.
-* [SSL Socket](/ref/dmSSLSocket/) - 加密socket功能.
-* [Script](/ref/dmScript/) - 内置脚本运行环境.
-* [Socket](/ref/dmSocket/) - 非加密socket功能.
-* [String Functions](/ref/dmStringFunc/) - 字符串管理功能.
-* [Thread](/ref/dmThread/) - 线程创建功能.
-* [Time](/ref/dmTime/) - 时间与计时功能.
-* [URI](/ref/dmURI/) - URI管理功能.
-* [Web Server](/ref/dmWebServer/) - 基于`dmHttpServer`的高级单线程web服务器.
-* [Shared Library](/ref/sharedlibrary/) - 共享库导入导出功能.
-* [Sony vector Math Library](../assets/Vector_Math_Library-Overview.pdf) - Sony 矢量计算库 主要为了3D图像和3D, 4D矢量运算, 矩阵运算和四元运算.
-
-如果需要 `dmsdk/sdk.h` 头文件请到 [Defold 官方 Github 库](https://github.com/defold/defold/blob/dev/engine/sdk/src/dmsdk/sdk.h) 查询, 这里有 [各种命名空间的头文件](https://github.com/defold/defold/tree/dev/engine/dlib/src/dmsdk/dlib).
+可用的SDK功能和命名空间在我们的 [API参考文档](/ref/overview_cpp) 中有详细说明。Defold SDK头文件作为单独的 `defoldsdk_headers.zip` 压缩包包含在每个Defold [GitHub发布版本](https://github.com/defold/defold/releases)中。你可以在你选择的编辑器中使用这些头文件进行代码补全。
 

+ 15 - 15
docs/zh/manuals/extensions-details.md

@@ -1,19 +1,19 @@
 ---
 title: 原生扩展 - 详述
-brief: 本教程介绍了有关编译系统用来编译原生扩展的一些细节.
+brief: 本手册介绍了有关编译系统用来编译原生扩展的一些细节.
 ---
 
-# Defold 编译
+# Defold 编译系统
 
-为了让你的扩展整合更加方便, 我们这里列举了一些编译相关的细节.
+为了让你的扩展整合更加方便,我们这里列举了一些编译相关的细节。
 
-在创建 Defold 引擎扩展的时候, 要考虑一些事情. 对于更全面的如何开发跨平台原生代码以及扩展/Lua API的使用, 请参考 [原生扩展 - 最佳实践](/manuals/extensions-best-practices)
+在创建 Defold 引擎扩展的时候,要考虑一些事情。对于更全面的如何开发跨平台原生代码以及扩展/Lua API的使用,请参考 [原生扩展 - 最佳实践](/manuals/extensions-best-practices)
 
 ## C++ 版本
 
-在引擎里我们用的都是不会高于C++98的版本. 你在开发扩展时可能使用了更高的版本, 注意高版本可能会引入 ABI 的变化. 这可能导致你无法在引擎或者asset store里使用你的扩展.
+在引擎里我们用的都是不会高于C++98的版本。你在开发扩展时可能使用了更高的版本,注意高版本可能会引入 ABI 的变化。这可能导致你无法在引擎或者资源商店里使用你的扩展。
 
-要记住创建代码库 (比如扩展)时, 最好选择最具兼容性的版本.
+要记住创建代码库(比如扩展)时,最好选择最具兼容性的版本。
 
 ## 工具链
 
@@ -34,22 +34,22 @@ brief: 本教程介绍了有关编译系统用来编译原生扩展的一些细
 * Win32: `Microsoft Visual Studio 2022` (`clang 17` on build server)
 * iOS/macOS: `apple-clang` (`clang 17` on build server)
 
-对于 iOS/macOS, 我们分别使用了 `-miphoneos-version-min=11.0` 和 `-mmacosx-version-min=10.13` 参数.
+对于 iOS/macOS,我们分别使用了 `-miphoneos-version-min=11.0` 和 `-mmacosx-version-min=10.13` 参数。
 
-由于我们不指定 C++ 版本, 所以各个编译器都使用了默认设置.
+由于我们不指定 C++ 版本,所以各个编译器都使用了默认设置。
 
 ## Win32 + Clang
 
-近来的版本能够在Windows上使用clang.
-这使得我们编译服务器运行更快速, 同时打包更精简.
+近来的版本能够在Windows上使用clang
+这使得我们编译服务器运行更快速,同时打包更精简。
 
 ## 静态链接
 
-自定义引擎使用静态链接进行编译.
-主要原因时 iOS 版本 < 8 时, app store 不支持运行一个 .ipa 里的多个可执行程序.
+自定义引擎使用静态链接进行编译
+主要原因是 iOS 版本 < 8 时,应用商店不支持运行一个 .ipa 里的多个可执行程序。
 
 ## 没有 C++ Exceptions
 
-在引擎里我们不使用任何C++ Exceptions.
-游戏引擎基本用不到, 因为 (大多数) 游戏数据在引擎开发时是未知的.
-移除 C++ exceptions 支持能够减小包体提升运行效率.
+在引擎里我们不使用任何C++ Exceptions
+游戏引擎基本用不到,因为(大多数)游戏数据在引擎开发时是未知的。
+移除 C++ exceptions 支持能够减小包体提升运行效率

+ 75 - 0
docs/zh/manuals/extensions-ext-manifests.md

@@ -0,0 +1,75 @@
+---
+title: 原生扩展 - 扩展清单
+brief: 本手册描述了扩展清单及其与应用清单和引擎清单的关联方式。
+---
+
+# 扩展、应用和引擎清单文件
+
+扩展清单是一个配置文件,包含用于构建单个扩展的标志和定义。此配置与应用级配置和Defold引擎本身的基础级配置相结合。
+
+## 应用清单
+
+应用清单(文件扩展名`.appmanifest`)是关于如何在构建服务器上构建游戏的应用级配置。应用清单允许您移除引擎中不使用的部分。如果您不需要物理引擎,可以从可执行文件中移除它以减小其大小。了解如何排除未使用的功能,请参阅[应用清单手册](/manuals/app-manifest)。
+
+## 引擎清单
+
+Defold引擎有一个构建清单(`build.yml`),它包含在引擎和Defold SDK的每个版本中。该清单控制使用哪些SDK版本,运行哪些编译器、链接器和其他工具,以及向这些工具传递哪些默认构建和链接标志。该清单可以在GitHub上的share/extender/build_input.yml中找到[在GitHub上](https://github.com/defold/defold/blob/dev/share/extender/build_input.yml)。
+
+## 扩展清单
+
+另一方面,扩展清单(`ext.manifest`)是专门针对扩展的配置文件。扩展清单控制扩展的源代码如何编译和链接,以及包含哪些额外的库。
+
+这三种不同的清单文件都共享相同的语法,以便它们可以合并并完全控制扩展和游戏的构建方式。
+
+对于每个构建的扩展,清单按以下方式合并:
+
+	manifest = merge(game.appmanifest, ext.manifest, build.yml)
+
+这允许用户覆盖引擎的默认行为以及每个扩展的行为。而且,在最终的链接阶段,我们将应用清单与defold清单合并:
+
+	manifest = merge(game.appmanifest, build.yml)
+
+
+### ext.manifest文件
+
+除了扩展名称外,清单文件还可以包含特定于平台的编译标志、链接标志、库和框架。如果*ext.manifest*文件不包含"platforms"部分,或者列表中缺少某个平台,您为其打包的平台仍将构建,但不会设置任何额外的标志。
+
+以下是一个示例:
+
+```yaml
+name: "AdExtension"
+
+platforms:
+    arm64-ios:
+        context:
+            frameworks: ["CoreGraphics", "CFNetwork", "GLKit", "CoreMotion", "MessageUI", "MediaPlayer", "StoreKit", "MobileCoreServices", "AdSupport", "AudioToolbox", "AVFoundation", "CoreGraphics", "CoreMedia", "CoreMotion", "CoreTelephony", "CoreVideo", "Foundation", "GLKit", "JavaScriptCore", "MediaPlayer", "MessageUI", "MobileCoreServices", "OpenGLES", "SafariServices", "StoreKit", "SystemConfiguration", "UIKit", "WebKit"]
+            flags:      ["-stdlib=libc++"]
+            linkFlags:  ["-ObjC"]
+            libs:       ["z", "c++", "sqlite3"]
+            defines:    ["MY_DEFINE"]
+
+    armv7-ios:
+        context:
+            frameworks: ["CoreGraphics", "CFNetwork", "GLKit", "CoreMotion", "MessageUI", "MediaPlayer", "StoreKit", "MobileCoreServices", "AdSupport", "AudioToolbox", "AVFoundation", "CoreGraphics", "CoreMedia", "CoreMotion", "CoreTelephony", "CoreVideo", "Foundation", "GLKit", "JavaScriptCore", "MediaPlayer", "MessageUI", "MobileCoreServices", "OpenGLES", "SafariServices", "StoreKit", "SystemConfiguration", "UIKit", "WebKit"]
+            flags:      ["-stdlib=libc++"]
+            linkFlags:  ["-ObjC"]
+            libs:       ["z", "c++", "sqlite3"]
+            defines:    ["MY_DEFINE"]
+```
+
+#### 允许的键
+
+特定于平台的编译标志允许的键有:
+
+* `frameworks` - 构建时要包含的Apple框架(iOS和macOS)
+* `weakFrameworks` - 构建时可选包含的Apple框架(iOS和macOS)
+* `flags` - 应传递给编译器的标志
+* `linkFlags` - 应传递给链接器的标志
+* `libs` - 链接时要包含的额外库
+* `defines` - 构建时要设置的定义
+* `aaptExtraPackages` - 应生成的额外包名(Android)
+* `aaptExcludePackages` - 要排除的包的正则表达式(或确切名称)(Android)
+* `aaptExcludeResourceDirs` - 要排除的资源目录的正则表达式(或确切名称)(Android)
+* `excludeLibs`, `excludeJars`, `excludeSymbols` - 这些标志用于移除平台上下文中先前定义的内容。
+
+对于所有关键字,我们应用白名单过滤器。这是为了避免非法路径处理和访问构建上传文件夹之外的文件。

+ 30 - 0
docs/zh/manuals/extensions-gradle.md

@@ -0,0 +1,30 @@
+---
+title: 在Android构建中使用Gradle依赖
+brief: 本手册解释了如何在Android构建中使用Gradle解析依赖项。
+---
+
+# Android的Gradle
+
+与Android应用程序的典型构建方式不同,Defold在整个构建过程中不使用[Gradle](https://gradle.org/)。相反,Defold在本地构建中直接使用Android命令行工具,如`aapt2`和`bundletool`,仅在构建服务器上解析依赖项时利用Gradle。
+
+## 解析依赖项
+
+原生扩展可以在`manifests/android`文件夹中包含一个`build.gradle`文件来指定扩展依赖项。示例:
+
+```
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    implementation 'com.google.firebase:firebase-installations:17.2.0'
+    implementation 'com.google.android.gms:play-services-base:18.2.0'
+}
+```
+
+构建服务器将收集所有扩展中的`build.gradle`文件,并使用这些文件解析所有依赖项,并在构建原生代码时包含它们。
+
+示例:
+
+* [Firebase](https://github.com/defold/extension-firebase/blob/master/firebase/manifests/android/)build.gradle
+* [Facebook](https://github.com/defold/extension-facebook/blob/master/facebook/manifests/android/build.gradle)

+ 30 - 30
docs/zh/manuals/extensions-manifest-merge-tool.md

@@ -1,19 +1,19 @@
 ---
-title: 原生扩展 - Manifest 混合工具
-brief: 本教程介绍了应用的 manifests 混合是如何工作的
+title: 原生扩展 - 清单合并工具
+brief: 本手册介绍了应用清单的合并工作原理
 ---
 
-# Application manifests
+# 应用清单
 
-一些平台上需要提供 manifests 片段 (或称存根) 来为扩展提供支持.
-可以是部分 `AndroidManifest.xml`, `Info.plist` 或者 `engine_template.html`
+一些平台上需要提供清单片段(或称存根)来为扩展提供支持。
+可以是部分 `AndroidManifest.xml`、`Info.plist` 或者 `engine_template.html`。
 
-从应用基础 manifest 开始, 每个扩展 manifest 存根一个一个的被应用.
-基础 manifest 可以是默认的 (位于 `builtins\manifests\<platforms>\...`), 也可以是由用户自定义的.
+从应用基础清单开始,每个扩展清单存根依次被应用。
+基础清单可以是默认的(位于 `builtins\manifests\<platforms>\...`),也可以是由用户自定义的。
 
 ## 命名和结构
 
-扩展 manifests 必须被放置在适当的指定位置才能生效.
+扩展清单必须被放置在适当的指定位置才能生效。
 
     /myextension
         ext.manifest
@@ -30,12 +30,12 @@ brief: 本教程介绍了应用的 manifests 混合是如何工作的
 
 ## Android
 
-Android 平台提供了 manifest 混合工具 (基于 `ManifestMerger2`), `bob.jar` 中使用此工具混合 Manifest.
-关于 Android manifests 的详细信息, 参见 [官方文档](https://developer.android.com/studio/build/manifest-merge)
+Android 平台提供了清单合并工具(基于 `ManifestMerger2`),`bob.jar` 中使用此工具合并清单。
+关于 Android 清单的详细信息,请参见[官方文档](https://developer.android.com/studio/build/manifest-merge)
 
-::: sidenote
-如果扩展 manifest 中没有设置应用的 `android:targetSdkVersion` , 下列权限会被自动加入:  `WRITE_EXTERNAL_STORAGE`, `READ_PHONE_STATE`, `READ_EXTERNAL_STORAGE`. 详情请见 [此文档](https://developer.android.com/studio/build/manifest-merge#implicit_system_permissions).
-我们推荐这么设置: `<uses-sdk android:targetSdkVersion=“{{android.target_sdk_version}}” />`
+::: important
+如果扩展清单中没有设置应用的 `android:targetSdkVersion`,下列权限会被自动加入:`WRITE_EXTERNAL_STORAGE`、`READ_PHONE_STATE`、`READ_EXTERNAL_STORAGE`。详情请见[此文档](https://developer.android.com/studio/build/manifest-merge#implicit_system_permissions)。
+我们推荐这样设置:`<uses-sdk android:targetSdkVersion="{{android.target_sdk_version}}" />`
 :::
 ### 示例
 
@@ -74,7 +74,7 @@ Android 平台提供了 manifest 混合工具 (基于 `ManifestMerger2`), `bob.j
     </manifest>
 ```
 
-合结果
+合结果
 
 ```xml
     <?xml version='1.0' encoding='utf-8'?>
@@ -107,7 +107,7 @@ Android 平台提供了 manifest 混合工具 (基于 `ManifestMerger2`), `bob.j
 
 ## iOS / macOS
 
-对于 `Info.plist` 我们实现了专用的工具混合列表和字典. 可以在键上指定混合属性 `merge`, `keep` 或 `replace`, 默认是 `merge`.
+对于 `Info.plist`,我们使用自己的实现来合并列表和字典。可以在键上指定合并标记属性 `merge`、`keep` 或 `replace`,默认是 `merge`。
 
 ### 示例
 
@@ -135,11 +135,11 @@ Android 平台提供了 manifest 混合工具 (基于 `ManifestMerger2`), `bob.j
         <key>REAL</key>
         <real>8.0</real>
 
-        <!-- 即使扩展清单里有这个键也要保持该键 -->
+        <!-- 即使扩展清单包含相同的键,也要保留此值 -->
         <key merge='keep'>BASE64</key>
         <data>SEVMTE8gV09STEQ=</data>
 
-        <!-- 如果扩展清单里也有这个键的数组那么所有字典值会与基本数组第一个字典值合并 -->
+        <!-- 如果扩展清单也包含此键的数组,则任何字典值将与基础数组的第一个字典值合并 -->
         <key>Array1</key>
         <array>
             <dict>
@@ -150,7 +150,7 @@ Android 平台提供了 manifest 混合工具 (基于 `ManifestMerger2`), `bob.j
             </dict>
         </array>
 
-        <!-- 不要试图合并这个数组的值, 而应该把扩展清单的值添加到这个数组里去 -->
+        <!-- 不要尝试合并此数组的值,而是应将扩展清单的值添加到数组末尾 -->
         <key merge='keep'>Array2</key>
         <array>
             <dict>
@@ -187,7 +187,7 @@ Android 平台提供了 manifest 混合工具 (基于 `ManifestMerger2`), `bob.j
         <key>INT</key>
         <integer>42</integer>
 
-        <!-- 改写基础清单里已存在的值 -->
+        <!-- 替换基础清单中的现有值 -->
         <key merge='replace'>REAL</key>
         <integer>16.0</integer>
 
@@ -217,13 +217,13 @@ Android 平台提供了 manifest 混合工具 (基于 `ManifestMerger2`), `bob.j
     </plist>
 ```
 
-合结果:
+合结果:
 
 ```xml
     <?xml version='1.0'?>
     <!DOCTYPE plist SYSTEM 'file://localhost/System/Library/DTDs/PropertyList.dtd'>
     <plist version='1.0'>
-        <!-- 嵌套合并基础清单和扩展清单的字典 -->
+        <!-- 基础清单和扩展清单的字典的嵌套合并 -->
         <dict>
             <key>NSAppTransportSecurity</key>
             <dict>
@@ -248,19 +248,19 @@ Android 平台提供了 manifest 混合工具 (基于 `ManifestMerger2`), `bob.j
             <key>INT</key>
             <integer>8</integer>
 
-            <!-- 基础清单的值被改写因为扩展清单的合并标志是 "replace" -->
+            <!-- 基础清单的值被替换,因为扩展清单中的合并标记设置为 "replace" -->
             <key>REAL</key>
             <real>16.0</real>
 
-            <!-- 基础清单的值被使用因为基础清单的合并标志是 "keep" -->
+            <!-- 使用基础清单的值,因为基础清单中的合并标记设置为 "keep" -->
             <key>BASE64</key>
             <data>SEVMTE8gV09STEQ=</data>
 
-            <!-- 扩展清单的值被加入进来因为没有指定合并标志 -->
+            <!-- 添加扩展清单的值,因为没有指定合并标记 -->
             <key>INT</key>
             <integer>42</integer>
 
-            <!-- 数组的字典值被合并因为基础清单默认合并标志是 "merge" -->
+            <!-- 数组的字典值被合并,因为基础清单默认使用 "merge" -->
             <key>Array1</key>
             <array>
                 <dict>
@@ -272,7 +272,7 @@ Android 平台提供了 manifest 混合工具 (基于 `ManifestMerger2`), `bob.j
                 </dict>
             </array>
 
-            <!-- 字典值被加到数组因为基础清单使用了 "keep" -->
+            <!-- 字典值被加到数组因为基础清单使用了 "keep" -->
             <key>Array2</key>
             <array>
                 <dict>
@@ -295,8 +295,8 @@ Android 平台提供了 manifest 混合工具 (基于 `ManifestMerger2`), `bob.j
 
 ## HTML5
 
-对于 html 模板, 我们给各部分命名, 以便混合时相匹配 (比如 "engine-start").
-标签属性可以是 `merge` 或者 `keep`. `merge` 是默认值.
+对于html模板,我们为每个部分命名,以便能够匹配(例如"engine-start")。
+然后可以指定属性 `merge` 或 `keep`。`merge` 是默认值。
 
 ### 示例
 
@@ -335,7 +335,7 @@ Android 平台提供了 manifest 混合工具 (基于 `ManifestMerger2`), `bob.j
     </html>
 ```
 
-合结果
+合结果
 
 ```html
     <!doctype html>
@@ -345,7 +345,7 @@ Android 平台提供了 manifest 混合工具 (基于 `ManifestMerger2`), `bob.j
         <script id='engine-loader' type='text/javascript' src='mydmloader.js'></script>
         <script id='engine-setup' type='text/javascript'>
             function load_engine() {
-                var engineJSdocument.createElement('script');
+                var engineJS = document.createElement('script');
                 engineJS.type = 'text/javascript';
                 engineJS.src = '{{exe-name}}_wasm.js';
                 document.head.appendChild(engineJS);

+ 10 - 10
docs/zh/manuals/extensions-script-api.md

@@ -1,16 +1,16 @@
 ---
-title: 为原生扩展提供编辑器代码提示
-brief: 本教程介绍了如何创建脚本 API 定义, 以便 Defold 编辑器能为用户提供代码提示功能.
+title: 为原生扩展添加编辑器自动补全
+brief: 本手册解释了如何创建脚本API定义,以便Defold编辑器能为扩展用户提供自动补全功能。
 ---
 
-# 原生扩展的代码提示
+# 原生扩展的自动补全
 
-Defold 编辑器为所有 Defold API 功能以及用户引用的Lua模块提供代码提示. 但是编辑器无法为原生扩展暴露的功能. 原生扩展可以在单独一个文件里提供 API 定义来实现代码提示功能.
+Defold编辑器会为所有Defold API函数提供自动补全建议,并会为脚本所需的Lua模块生成建议。然而,编辑器无法自动为原生扩展暴露的功能提供自动补全建议。原生扩展可以在单独的文件中提供API定义,以启用扩展API的自动补全建议。
 
 
-## 创建脚本 API 定义文件
+## 创建脚本API定义
 
-脚本 API 定义文件使用扩展名 `.script_api`. 必须以 [YAML 格式](https://yaml.org/) 与扩展文件放在一起. 一般脚本 API 定义像这样:
+脚本API定义文件的扩展名为`.script_api`。它必须采用[YAML格式](https://yaml.org/)并与扩展文件放在一起。脚本API定义的预期格式为:
 
 ```yml
 - name: 扩展名
@@ -41,14 +41,14 @@ Defold 编辑器为所有 Defold API 功能以及用户引用的Lua模块提供
     ...
 ```
 
-数据类型有 `table, string , boolean, number, function` 几种. 如果一个值有多个类型则这样写 `[type1, type2, type3]`.
+类型可以是`table, string, boolean, number, function`中的任意一种。如果一个值可以有多个类型,则写为`[type1, type2, type3]`。
 ::: sidenote
-目前编辑器里不显示类型. 但是还是鼓励输入类型以便以后编辑器可以显示出来.
+目前编辑器中不显示类型。但仍建议提供类型信息,以便编辑器在支持显示类型信息时可以使用。
 :::
 
-## 例
+## 
 
-实际使用实例参见下面的扩展:
+请参考以下项目获取实际使用示例:
 
 * [Facebook 扩展](https://github.com/defold/extension-facebook/tree/master/facebook/api)
 * [WebView 扩展](https://github.com/defold/extension-webview/blob/master/webview/api/webview.script_api)

+ 66 - 103
docs/zh/manuals/extensions.md

@@ -1,27 +1,27 @@
 ---
-title: 为 Defold 编写原生扩展
-brief: 本教程介绍了给 Defold 游戏引擎编写原生扩展的方法以及云端编译器的用法.
+title: 为Defold编写原生扩展
+brief: 本手册解释了如何为Defold游戏引擎编写原生扩展,以及如何通过零配置云构建器进行编译。
 ---
 
 # 原生扩展
 
-如果需要使用 Lua 本身不提供的功能, 比如第三方软件交互或者底层硬件控制, Defold SDK 接受使用 C, C++, Objective C, Java 以及 Javascript 编写的扩展程序, 语言选取取决于目标发布平台. 原生扩展的常见用法有:
+如果您需要与外部软件或硬件进行底层交互,而Lua无法满足需求,Defold SDK允许您使用C、C++、Objective C、Java或Javascript(取决于目标平台)为引擎编写扩展。原生扩展的典型用例包括:
 
-- 与特定硬件交互, 例如手机摄像头.
-- 与底层软件交互, 例如未提供的底层网络交互要使用 Luasocket 扩展包实现.
-- 高性能计算, 数据处理等.
+- 与特定硬件交互,例如手机摄像头。
+- 与外部底层API交互,例如不允许通过网络API进行交互的广告网络API,而Luasocket本可以用于此类交互。
+- 高性能计算和数据处理。
 
-## 编译服务器
+## 构建服务器
 
-Defold 提供了一个云端服务器编译方案. 游戏项目的各种依赖, 或者直接引用或者通过 [库项目](/manuals/libraries/) 加入, 都会变成项目内容的一部分. 没有必要重新编译特别版引擎然后分发给开发组成员, 任何成员对项目的编译运行使所有成员都能得到嵌入全部所需库的引擎程序.
+Defold通过基于云的构建解决方案,为零配置原生扩展提供了入口点。任何开发并添加到游戏项目中的原生扩展(无论是直接添加还是通过[库项目](/manuals/libraries/)添加),都将成为普通项目内容的一部分。无需构建特殊版本的引擎并分发给团队成员,这一过程会自动处理——任何构建和运行项目的团队成员都将获得一个包含所有原生扩展的项目特定引擎可执行文件。
 
 ![Cloud build](images/extensions/cloud_build.png)
 
-Defold 免费提供云编译服务器, 没有使用限制. 服务器托管于欧洲, 代码上传的 URL 可以在 [编辑器首选项窗口](/manuals/editor-preferences/#extensions) 进行设置, 或者用命令行工具 [bob](/manuals/bob/#usage) 设置 `--build-server` 参数进行指定. 关于云编译服务器及假设私人编译服务器的详情请参考 [GitHub 上的介绍](https://github.com/defold/extender).
+Defold免费提供云构建服务器,没有任何使用限制。服务器托管在欧洲,发送本地代码的URL在[编辑器首选项窗口](/manuals/editor-preferences/#extensions)中配置,或通过[bob](/manuals/bob/#usage)的`--build-server`命令行选项配置。如果您希望设置自己的服务器,请[遵循这些说明](/manuals/extender-local-setup)。
 
-## 项目结构
+## 项目布局
 
-在项目根目录下为扩展程序建立一个文件夹. 这个文件夹将包含扩展程序所需要的一切, 源代码, 外部库和资源文件. 云编译服务器解析这个结构以便分别获取所需要的各种文件.
+要创建新扩展,请在项目根目录中创建一个文件夹。此文件夹将包含与扩展相关的所有设置、源代码、库和资源。扩展构建器会识别文件夹结构并收集任何源文件和库。
 
 ```
  myextension/
@@ -43,43 +43,46 @@ Defold 免费提供云编译服务器, 没有使用限制. 服务器托管于欧
 
 ```
 *ext.manifest*
-: 原生扩展程序文件夹下 _必须_ 包含一个 *ext.manifest* 文件. 这是一个 YAML 格式的文件, 编译服务器通过此文件了解扩展项目结构. 这个文件里至少要包含一项就是原生扩展的名字.
+: 扩展文件夹_必须_包含一个*ext.manifest*文件。此文件是配置文件,包含构建单个扩展时使用的标志和定义。文件格式定义可在[扩展清单手册](https://defold.com/manuals/extensions-ext-manifests/)中找到。
 
 *src*
-: 包含所有源代码.
+: 此文件夹应包含所有源代码文件。
 
 *include*
-: 包含所有外部引用文件(可选).
+: 此可选文件夹包含任何包含文件。
 
 *lib*
-: 包含要用到的所有外部编译好的库. 库文件要根据称为 `platform` 或 `architecure-platform` 的子文件夹分类放置, 也就是说什么平台用什么库.
+: 此可选文件夹包含扩展所依赖的任何已编译库。库文件应放置在按`platform`或`architecture-platform`命名的子文件夹中,具体取决于您的库支持的架构。
 
   :[platforms](../shared/platforms.md)
 
 *manifests*
-: 包含编译过程所需配置文件(可选). 详见下文.
+: 此可选文件夹包含构建或打包过程中使用的其他文件。详情请见下文。
 
 *res*
-: 包含原生扩展所需的一切资源文件(可选). 资源文件要根据称为 `platform` 或 `architecure-platform` 的子文件夹分类放置, 也就是说什么平台用什么资源. 其中 `common` 文件夹包含各种平台的通用资源文件.
+: 此可选文件夹包含扩展所依赖的任何额外资源。资源文件应像"lib"子文件夹一样,放置在按`platform`或`architecture-platform`命名的子文件夹中。还允许使用`common`子文件夹,包含所有平台通用的资源文件。
 
-### Manifest files
+### 清单文件
 
-*manifests* 包含编译时不同平台所需的配置文件. 配置文件要根据称为 `platform` 的子文件夹分类放置:
+扩展的可选*manifests*文件夹包含构建和打包过程中使用的其他文件。文件应放置在按`platform`命名的子文件夹中:
 
-* `android` - 这里存放片段配置文件用以与主配置文件混合 ([就像这里介绍的那样](/manuals/extensions-manifest-merge-tool)). 还可以存放 `build.gradle` 文件及其依赖以便 Gradle 可以解析 ([示例](https://github.com/defold/extension-facebook/blob/master/facebook/manifests/android/build.gradle)). 还能存放0个或多个 ProGuard 代码混淆文件 (试验功能).
-* `ios` - 这里存放片段配置文件用以与主配置文件混合 ([就像这里介绍的那样](/manuals/extensions-manifest-merge-tool)).
-* `osx` - 这里存放片段配置文件用以与主配置文件混合 ([就像这里介绍的那样](/manuals/extensions-manifest-merge-tool)).
-* `web` - 这里存放片段配置文件用以与主配置文件混合 ([就像这里介绍的那样](/manuals/extensions-manifest-merge-tool)).
+* `android` - 此文件夹接受要合并到主应用程序中的清单存根文件([如此处所述](/manuals/extensions-manifest-merge-tool))。
+  * 该文件夹还可以包含一个`build.gradle`文件,其中包含要[由Gradle解析的依赖项](/manuals/extensions-gradle)。
+  * 最后,该文件夹还可以包含零个或多个ProGuard文件(实验性)。
+* `ios` - 此文件夹接受要合并到主应用程序中的清单存根文件([如此处所述](/manuals/extensions-manifest-merge-tool))。
+  * 该文件夹还可以包含一个`Podfile`文件,其中包含要[由Cocoapods解析的依赖项](/manuals/extensions-cocoapods)。
+* `osx` - 此文件夹接受要合并到主应用程序中的清单存根文件([如此处所述](/manuals/extensions-manifest-merge-tool))。
+* `web` - 此文件夹接受要合并到主应用程序中的清单存根文件([如此处所述](/manuals/extensions-manifest-merge-tool))。
 
 
-## 共享原生扩展
+## 共享扩展
 
-原生扩展如同其他资源文件一样也可以共享. 如果库项目包含原生扩展文件夹的话, 它就能作为项目依赖库共享给其他人. 详情请见 [库项目教程](/manuals/libraries/).
+扩展在项目中被视为与其他资产一样,可以以相同方式共享。如果原生扩展文件夹作为库文件夹添加,它可以作为项目依赖项共享给其他人使用。有关更多信息,请参考[库项目手册](/manuals/libraries/)。
 
 
-## 简单示例
+## 一个简单的扩展示例
 
-从头开始做一个简单的原生扩展. 第一步, 创建 *myextension* 文件夹并加入 *ext.manifest* 文件, 文件中包含扩展名 "MyExtension". 注意这个扩展名会作为一个 C++ 变量名填充在 `DM_DECLARE_EXTENSION` 宏的第一个参数位置上 (见下文).
+让我们构建一个非常简单的扩展。首先,我们创建一个新的根文件夹*`myextension`*并添加一个包含扩展名"`MyExtension`"的*`ext.manifest`*文件。请注意,该名称是一个C++符号,必须与`DM_DECLARE_EXTENSION`的第一个参数匹配(见下文)。
 
 ![Manifest](images/extensions/manifest.png)
 
@@ -88,11 +91,11 @@ Defold 免费提供云编译服务器, 没有使用限制. 服务器托管于欧
 name: "MyExtension"
 ```
 
-这个扩展就一个 C++ 文件, *myextension.cpp*, 位于 "src" 文件夹里.
+该扩展由一个 C++ 文件 *`myextension.cpp`* 组成,该文件在 "`src`" 文件夹中创建。
 
 ![C++ file](images/extensions/cppfile.png)
 
-源代码如下:
+扩展源文件包含以下代码:
 
 ```cpp
 // myextension.cpp
@@ -179,11 +182,11 @@ dmExtension::Result FinalizeMyExtension(dmExtension::Params* params)
 DM_DECLARE_EXTENSION(MyExtension, LIB_NAME, AppInitializeMyExtension, AppFinalizeMyExtension, InitializeMyExtension, 0, 0, FinalizeMyExtension)
 ```
 
-注意 `DM_DECLARE_EXTENSION` 宏用来声明扩展程序执行入口. 第一个参数 `symbol` 要与 *ext.manifest* 上的扩展名一致. 本例中没有用到 "update" 或 "on_event" 执行入口, 所以用 `0` 填充了宏的相应参数.
+请注意用于声明扩展代码中各种入口点的宏 `DM_DECLARE_EXTENSION`。第一个参数 `symbol` 必须与 *ext.manifest* 中指定的名称匹配。对于这个简单的示例,不需要任何 "update" 或 "on_event" 入口点,因此在这些位置向宏提供了 `0`。
 
-现在就差编译运行了 (<kbd>Project ▸ Build</kbd>). 带原生扩展的项目会被上传到云编译服务器编译. 如果编译出错, 将会弹出一个包含错误信息的窗口.
+现在只需构建项目(<kbd>Project ▸ Build</kbd>)。这将把扩展上传到扩展构建器,构建器将生成一个包含新扩展的自定义引擎。如果构建器遇到任何错误,将显示一个包含构建错误的对话框。
 
-测试扩展运行, 新建一个游戏对象和一个脚本组件, 再写一些测试代码:
+要测试扩展,创建一个游戏对象并添加一个带有一些测试代码的脚本组件:
 
 ```lua
 local s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -191,97 +194,57 @@ local reverse_s = myextension.reverse(s)
 print(reverse_s) --> ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba
 ```
 
-成功了! 我们从零开始完整地制作了一个扩展程序.
+就是这样!我们已经创建了一个完全可用的原生扩展。
 
 
-## 扩展程序生命周期
+## 扩展生命周期
 
-上面提到了 `DM_DECLARE_EXTENSION` 宏用来声明程序执行入口:
+如上所述,`DM_DECLARE_EXTENSION` 宏用于声明扩展代码中的各种入口点:
 
 `DM_DECLARE_EXTENSION(symbol, name, app_init, app_final, init, update, on_event, final)`
 
-入口对应扩展程序的各种生命周期函数, 运行顺序如下:
+入口点将允许您在扩展生命周期的各个点运行代码:
 
 * 引擎启动
-  * 引擎代码运行
+  * 引擎系统正在启动
   * 扩展 `app_init`
-  * 扩展 `init` - Defold API 初始化. 建议扩展程序从这里开始运行并且暴露给Lua脚本.
-  * 脚本 `init()` 函数调用.
+  * 扩展 `init` - 所有Defold API已初始化。这是扩展生命周期中推荐的创建扩展代码Lua绑定的点。
+  * 脚本初始化 - 脚本文件的 `init()` 函数被调用。
 * 引擎循环
-  * 引擎
+  * 引擎
     * 扩展 `update`
-    * 脚本 `update()` 函数调用.
-  * 引擎事件 (窗口最大/最小化之类的)
+    * 脚本更新 - 脚本文件的 `update()` 函数被调用。
+  * 引擎事件(窗口最小化/最大化等)
     * 扩展 `on_event`
-* 引擎关闭 (或重启)
-  * 脚本 `final()` 函数调用.
+* 引擎关闭(或重启)
+  * 脚本最终 - 脚本文件的 `final()` 函数被调用。
   * 扩展 `final`
   * 扩展 `app_final`
 
-## 预定义的平台标识
+## 已定义的平台标识符
 
-编译器中预定义了如下平台标识:
+构建器在每个相应平台上定义了以下标识符:
 
-* DM_PLATFORM_WINDOWS
-* DM_PLATFORM_OSX
-* DM_PLATFORM_IOS
-* DM_PLATFORM_ANDROID
-* DM_PLATFORM_LINUX
-* DM_PLATFORM_HTML5
+* `DM_PLATFORM_WINDOWS`
+* `DM_PLATFORM_OSX`
+* `DM_PLATFORM_IOS`
+* `DM_PLATFORM_ANDROID`
+* `DM_PLATFORM_LINUX`
+* `DM_PLATFORM_HTML5`
 
-## 编译服务器日志
+## 构建服务器日志
 
-当项目使用了原生扩展, 编译时就会生成编译服务器日志. 编译服务器日志文件 (`log.txt`) 与被编译的项目一起下载到本地, 并保存在项目 build 文件夹的 `.internal/%platform%/build.zip` 文件中.
+当项目使用原生扩展时,构建服务器日志可用。构建服务器日志(`log.txt`)在项目构建时与自定义引擎一起下载,并存储在项目的 `.internal/%platform%/build.zip` 文件中,同时也解压到项目的构建文件夹中。
 
 
-## ext.manifest 文件
+## 扩展示例
 
-除了扩展名称, ext.manifest 文件还可以包含指定平台的编译参数, 链接参数, 外部程序和链接库. 如果 *ext.manifest* 文件不包含 "platforms" 项, 或者找不到对应的平台配置参数, 编译仍会继续, 只是不加各种编译参数.
+* [基础扩展示例](https://github.com/defold/template-native-extension)(本手册中的扩展)
+* [Android扩展示例](https://github.com/defold/extension-android)
+* [HTML5扩展示例](https://github.com/defold/extension-html5)
+* [macOS、iOS和Android videoplayer扩展](https://github.com/defold/extension-videoplayer)
+* [macOS和iOS摄像头扩展](https://github.com/defold/extension-camera)
+* [iOS和Android应用内购买扩展](https://github.com/defold/extension-iap)
+* [iOS和Android Firebase Analytics扩展](https://github.com/defold/extension-firebase-analytics)
 
-Here is an example:
-
-```yaml
-name: "AdExtension"
-
-platforms:
-    arm64-ios:
-        context:
-            frameworks: ["CoreGraphics", "CFNetwork", "GLKit", "CoreMotion", "MessageUI", "MediaPlayer", "StoreKit", "MobileCoreServices", "AdSupport", "AudioToolbox", "AVFoundation", "CoreGraphics", "CoreMedia", "CoreMotion", "CoreTelephony", "CoreVideo", "Foundation", "GLKit", "JavaScriptCore", "MediaPlayer", "MessageUI", "MobileCoreServices", "OpenGLES", "SafariServices", "StoreKit", "SystemConfiguration", "UIKit", "WebKit"]
-            flags:      ["-stdlib=libc++"]
-            linkFlags:  ["-ObjC"]
-            libs:       ["z", "c++", "sqlite3"]
-            defines:    ["MY_DEFINE"]
-
-    armv7-ios:
-        context:
-            frameworks: ["CoreGraphics", "CFNetwork", "GLKit", "CoreMotion", "MessageUI", "MediaPlayer", "StoreKit", "MobileCoreServices", "AdSupport", "AudioToolbox", "AVFoundation", "CoreGraphics", "CoreMedia", "CoreMotion", "CoreTelephony", "CoreVideo", "Foundation", "GLKit", "JavaScriptCore", "MediaPlayer", "MessageUI", "MobileCoreServices", "OpenGLES", "SafariServices", "StoreKit", "SystemConfiguration", "UIKit", "WebKit"]
-            flags:      ["-stdlib=libc++"]
-            linkFlags:  ["-ObjC"]
-            libs:       ["z", "c++", "sqlite3"]
-            defines:    ["MY_DEFINE"]
-```
-
-### 可用参数项
-
-各个平台可用参数项如下:
-
-* `frameworks` - 加入苹果库 (iOS 和 OSX)
-* `flags` - 编译参数
-* `linkFlags` - 链接参数
-* `libs` - 链接库
-* `defines` - 编译预定义
-* `aaptExtraPackages` - 导入外部包 (Android)
-* `aaptExcludePackages` - 排除内部包 (Android)
-* `aaptExcludeResourceDirs` - 排除资源文件夹 (Android)
-
-## 原生扩展举例
-
-* [基础示例](https://github.com/defold/template-native-extension) (本教程所使用的简单示例)
-* [Android 扩展示例](https://github.com/defold/extension-android)
-* [HTML5 扩展示例](https://github.com/defold/extension-html5)
-* [macOS, iOS 和 Android 的 videoplayer 扩展程序](https://github.com/defold/extension-videoplayer)
-* [macOS 和 iOS 的摄像头扩展程序](https://github.com/defold/extension-camera)
-* [iOS 和 Android 的内支付扩展程序](https://github.com/defold/extension-iap)
-* [iOS 和 Android 的 Firebase Analytics 扩展程序](https://github.com/defold/extension-firebase-analytics)
-
-[Defold 资源中心](https://www.defold.com/assets/) 也包含有许多原生扩展项目资源.
+[Defold资产门户](https://www.defold.com/assets/)也包含多个原生扩展。

+ 3 - 3
docs/zh/manuals/facebook.md

@@ -1,6 +1,6 @@
 ---
-title: Defold Facebook 教程
-brief: 本教程介绍了如何在 Defold 游戏中设置和整合 Facebook 功能.
+title: Defold 中的 Facebook
+brief: Defold 中的 Facebook.
 ---
 
-本教程已移至 [这里](/extension-facebook)
+[本手册已移至](/extension-facebook)

+ 64 - 64
docs/zh/manuals/factory.md

@@ -1,13 +1,13 @@
 ---
-title: Factory 组件教程
-brief: 本教程介绍了如何使用工厂组件在游戏运行时创建游戏对象.
+title: Factory 组件手册
+brief: 本手册解释了如何使用工厂组件在运行时动态生成游戏对象.
 ---
 
 # Factory 组件
 
-工厂组件用于在游戏运行时从对象池动态创建游戏对象.
+Factory 组件用于在游戏运行时从对象池中动态生成游戏对象。
 
-工厂组件的 *Prototype* 属性就是动态创建游戏对象的蓝图.
+当您将 Factory 组件添加到游戏对象时,您可以在 *Prototype* 属性中指定工厂应使用哪个游戏对象文件作为原型(在其他引擎中也称为"预制件"或"蓝图")来创建所有新的游戏对象。
 
 ![Factory component](images/factory/factory_collection.png)
 
@@ -25,35 +25,35 @@ factory.create(component, p)
 
 ![Spawned game object](images/factory/factory_spawned.png)
 
-`factory.create()` 有5个参数:
+`factory.create()` 接受5个参数:
 
 `url`
-: 工厂组件的id.
+: 应生成新游戏对象的工厂组件的 ID。
 
 `[position]`
-: (可选) 新创建游戏对象的世界坐标位置. 以 `vector3` 表示. 如果不指定位置, 默认位置是工厂组件游戏对象的位置.
+: (可选)新游戏对象的世界位置。这应该是一个 `vector3`。如果您不指定位置,游戏对象将在工厂组件的位置生成。
 
 `[rotation]`
-: (可选) 新创建游戏对象的世界坐标旋转. 以 `quat` 表示.
+: (可选)新游戏对象的世界旋转。这应该是一个 `quat`。
 
 `[properties]`
-: (可选) 新创建游戏对象的属性初始化 Lua 表. 详情请见 [脚本属性教程](/manuals/script-properties).
+: (可选)一个 Lua 表,包含任何用于初始化游戏对象的脚本属性值。有关脚本属性的信息,请参阅[脚本属性手册](/manuals/script-properties)。
 
 `[scale]`
-: (可选) 新创建游戏对象的等比缩放. 以 `number` (大于 0) 表示. 或者以 `vector3` 表示每个坐标轴上的非等比缩放.
+: (可选)生成的游戏对象的缩放比例。缩放可以表示为一个 `number`(大于0),指定所有轴上的均匀缩放。您也可以提供一个 `vector3`,其中每个组件指定沿相应轴的缩放。
 
-例如:
+例如
 
 ```lua
 -- factory.script
 local p = go.get_position()
 p.y = vmath.lerp(math.random(), min_y, max_y)
 local component = "#star_factory"
--- Spawn with no rotation but double scale.
--- Set the score of the star to 10.
+-- 以无旋转但双倍缩放生成。
+-- 将星星的分数设置为10。
 factory.create(component, p, nil, { score = 10 }, 2.0) -- <1>
 ```
-1. 设置 star 游戏对象的 "score" 属性.
+1. 设置星星游戏对象的"score"属性。
 
 ```lua
 -- star.script
@@ -77,19 +77,19 @@ function on_message(self, message_id, message, sender)
     end
 end
 ```
-1. "score" 脚本属性初始化时要有默认值.
-2. "score" 脚本属性保存在 "self" 中.
+1. "score"脚本属性定义为默认值。
+2. 将"score"脚本属性引用为存储在"self"中的值。
 
 ![Spawned game object with property and scaling](images/factory/factory_spawned2.png)
 
-::: sidenote
-Defold 目前不支持碰撞形状的非等比缩放. 如果赋了非等比值, 比如 `vmath.vector3(1.0, 2.0, 1.0)` 则 sprite 会正确缩放但是碰撞形状不会正确缩放.
+::: important
+Defold 目前不支持碰撞形状的非均匀缩放。如果您提供非均匀缩放值,例如 `vmath.vector3(1.0, 2.0, 1.0)`,精灵将正确缩放,但碰撞形状不会。
 :::
 
 
-## 定位新对象
+## Factory 创建对象的寻址
 
-Defold 的地址定位机制可以在运行时定位任何对象和组件. 关于定位详情请见 [地址定位教程](/manuals/addressing/). 对于工厂新建对象及其组件同样如此. 新建的对象id经常被使用, 比如发送消息时:
+Defold 的寻址机制使得可以访问运行中游戏中的每个对象和组件。[寻址手册](/manuals/addressing/)详细介绍了系统的工作原理。可以对生成的游戏对象及其组件使用相同的寻址机制。通常,使用生成对象的 ID 就足够了,例如在发送消息时:
 
 ```lua
 local function create_hunter(target_id)
@@ -99,11 +99,11 @@ local function create_hunter(target_id)
 end
 ```
 
-::: sidenote
-发给游戏对象而非组件的消息会传遍对象上的所有组件. 一般不会造成问题, 但是处理消息时要明白这一点.
+::: important
+向游戏对象本身而不是特定组件传递消息实际上会将消息发送到所有组件。这通常不是问题,但如果对象有很多组件,最好记住这一点。
 :::
 
-要获取对象上的组件, 比如关闭碰撞或改变Sprite图片该怎么办呢? 使用游戏对象id再加上组件名生成的地址即可.
+但是,如果您需要访问生成的游戏对象上的特定组件,例如禁用碰撞对象或更改精灵图像,该怎么办?解决方案是从游戏对象 ID 和组件 ID 构造一个 URL。
 
 ```lua
 local function create_guard(unarmed)
@@ -118,9 +118,9 @@ local function create_guard(unarmed)
 end
 ```
 
-## 新对象引用和对象父级
+## 跟踪生成的对象和父对象
 
-调用 `factory.create()` 会返回新游戏对象的id, 以便保存其引用. 通常把 id:s 保存到一个表里以便需要时统一删除, 比如重启关卡时:
+当您调用 `factory.create()` 时,您会获得新游戏对象的 ID,允许您存储该 ID 以供将来参考。一个常见的用法是生成对象并将其 ID 添加到表中,以便以后可以一次性删除它们,例如在重置关卡布局时:
 
 ```lua
 -- spawner.script
@@ -128,41 +128,41 @@ self.spawned_coins = {}
 
 ...
 
--- 把新建对象存入 "spawned_coins" 表中.
+-- 生成一个硬币并将其存储在"coins"表中。
 local id = factory.create("#coinfactory", coin_position)
 table.insert(self.spawned_coins, id)
 ```
 
-需要的时候:
+然后稍后:
 
 ```lua
--- coin.script
--- 删除所有 coins.
+-- spawner.script
+-- 删除所有生成的硬币。
 for _, coin_id in ipairs(self.spawned_coins) do
     go.delete(coin_id)
 end
 
--- 或者直接
+-- 或者替代方案
 go.delete(self.spawned_coins)
 ```
 
-另一种常见用法是创建新对象时保存一个引用, 同时新对象也保存脚本的一个引用, 等以后需要时可以给创建脚本发送通知消息:
+另一种常见情况是,您希望生成的对象知道生成它的游戏对象。一个例子是某种只能一次生成一个的自主对象。然后,生成的对象需要在其被删除或停用时通知生成器,以便可以生成另一个:
 
 ```lua
 -- spawner.script
--- 创建 drone 然后设置其引用者为此脚本
+-- 生成一个无人机并将其父级设置为此脚本组件的 URL
 self.spawned_drone = factory.create("#dronefactory", drone_position, nil, { parent = msg.url() })
 
 ...
 
 function on_message(self, message_id, message, sender)
     if message_id == hash("drone_dead") then
-        self.spawed_drone = nil
+        self.spawned_drone = nil
     end
 end
 ```
 
-drone 的脚本:
+生成对象的逻辑:
 
 ```lua
 -- drone.script
@@ -171,77 +171,77 @@ go.property("parent", msg.url())
 ...
 
 function final(self)
-    -- 析构时.
+    -- 我死了。
     msg.post(self.parent, "drone_dead")
 end
 ```
 
-## 工厂资源的动态加载
+## Factory 资源的动态加载
 
-开启工厂属性的 *Load Dynamically*, 工厂资源将会被延迟加载.
+通过勾选工厂属性中的 *Load Dynamically* 复选框,引擎会推迟与工厂关联的资源的加载。
 
 ![Load dynamically](images/factory/load_dynamically.png)
 
-关闭动态加载, 则加载工厂组件时会同时加载其需要的资源以便工厂可以尽快创建新游戏对象.
+如果不勾选该复选框,引擎会在加载工厂组件时加载原型资源,使它们立即可用于生成。
 
-开启动态加载, 有两种用法:
+勾选该复选框后,您有两种使用选项:
 
 同步加载
-: 调用 [`factory.create()`](/ref/factory/#factory.create) 函数创建新对象时. 资源会同步加载, 这意味着游戏可能会卡一下, 加载完成后再创建新对象.
+: 当您想要生成对象时调用 [`factory.create()`](/ref/factory/#factory.create)。这将同步加载资源,可能会导致卡顿,然后生成新实例。
 
   ```lua
   function init(self)
-      -- 工厂父级集合加载时
-      -- 工厂资源不会被加载. 调用 create 函数
-      -- 会把资源进行同步加载.
+      -- 工厂父级集合加载时
+-- 没有工厂资源被加载。在没有调用 load 的情况下调用 create
+-- 将同步创建资源。
       self.go_id = factory.create("#factory")
   end
 
   function final(self)  
-      -- 删掉游戏对象, 资源引用计数减少
-      -- 本例中工厂资源也会被卸载
-      -- 因为工厂组件不包含对资源的引用.
+      -- 删除游戏对象。将减少资源引用计数。
+-- 在这种情况下,资源被删除,因为工厂组件
+-- 不持有引用。
       go.delete(self.go_id)
 
-      -- 因为工厂组件不包含对资源的引用, 所以对工厂调用 unload 没有意义
+      -- 调用 unload 不会执行任何操作,因为工厂不持有引用
       factory.unload("#factory")
   end
   ```
 
 异步加载
-: 调用 [`factory.load()`](/ref/factory/#factory.load) 函数进行资源的异步加载. 资源加载完毕后, 回调用回调函数.
+: 调用 [`factory.load()`](/ref/factory/#factory.load) 显式异步加载资源。当资源准备好生成时,会收到一个回调。
 
   ```lua
   function load_complete(self, url, result)
-      -- 资源加载完成, 可以新建对象
+      -- 加载完成,资源已准备好生成
       self.go_id = factory.create(url)
   end
 
   function init(self)
-      -- 工厂父级集合加载时
-      -- 工厂资源不被加载. 调用 load 函数进行资源异步加载.
+      -- 工厂父级集合加载时
+-- 没有工厂资源被加载。调用 load 将加载资源。
       factory.load("#factory", load_complete)
   end
 
   function final(self)
-      -- 删掉游戏对象, 资源引用计数减少
-      -- 本例中工厂资源不会被卸载
-      -- 因为工厂组件包含对资源的引用.
+      -- 删除游戏对象。将减少资源引用计数。
+-- 在这种情况下,资源不会被删除,因为工厂组件
+-- 仍然持有引用。
       go.delete(self.go_id)
 
-      -- 调用 unload 函数, 工厂对资源引用被释放,
-      -- 这样资源才会被卸载.
+      -- 调用 unload 将减少工厂组件持有的资源引用计数,
+-- 导致资源被销毁。
       factory.unload("#factory")
   end
   ```
 
-## 动态 Prototype
+## 动态原型
 
-factory 组件里有 *Dynamic Prototype* 选项, 点选之后可以在运行时更改 factory 的原型.
+通过勾选工厂属性中的 *Dynamic Prototype* 复选框,可以更改工厂可以创建的 *Prototype*。
 
-![动态 prototype](images/factory/dynamic_prototype.png)
+![Dynamic prototype](images/factory/dynamic_prototype.png)
 
-factory 组件 *Dynamic Prototype* 被点选之后可以使用 `factory.set_prototype()` 函数更改其原型. 例如:
+当 *Dynamic Prototype* 选项被勾选时,工厂组件可以使用 `factory.set_prototype()` 函数更改原型。示例:
 
 ```lua
 factory.unload("#factory") -- 卸载之前的资源
@@ -250,18 +250,18 @@ local enemy_id = factory.create("#factory")
 ```
 
 ::: important
-当 *Dynamic Prototype* 被点选后, 集合组件数目将失去限制, factory 所在的集合将使用 *game.project* 文件指定的默认组件限制数目.
+当设置 *Dynamic Prototype* 选项时,无法优化集合组件计数,拥有集合将使用 *game.project* 文件中的默认组件计数。
 :::
 
 
 ## 实例限制
 
-项目设置 *Collection related settings* 部分 *max_instances* 限制了游戏世界 (启动集合 main.collection 或者通过集合代理加载的集合) 中游戏对象的最大数目. 不论是子编辑器里创建的还是用脚本动态创建的游戏对象综合不得超过这个最大值.
+项目设置 *Collection related settings* 中的 *max_instances* 限制了世界中可以存在的游戏对象实例总数(启动时加载的 main.collection 或通过集合代理加载的任何世界)。世界中存在的所有游戏对象都计入此限制,无论它们是通过编辑器手动放置的还是通过脚本在运行时生成的。
 
 ![Max instances](images/factory/factory_max_instances.png)
 
-如果把 *max_instances* 设置为 1024 然后手动拖放 24 游戏对象到主集合, 那么最多还能创建 1000 个游戏对象. 如果删除一个对象, 就能再创建一个对象.
+如果您将 *max_instances* 设置为 1024 并在主集合中有 24 个手动放置的游戏对象,您可以额外生成 1000 个游戏对象。一旦删除一个游戏对象,您就可以自由生成另一个实例。
 
 ## 游戏对象池
 
-使用游戏对象池提高对象重用性是个好办法. 然而, 游戏引擎已经使用对象池进行游戏对象管理, 用户就不必多此一举了. 不论删除还是创建对象, 都能保证稳定高效.
+将生成的游戏对象保存在池中并重用它们似乎是个好主意。然而,引擎已经在底层进行了对象池化,因此额外的开销只会减慢速度。删除游戏对象并生成新对象既更快又更干净。

+ 122 - 46
docs/zh/manuals/file-access.md

@@ -1,61 +1,137 @@
 ---
 title: 处理文件
-brief: 本教程介绍了保存和加载文件等处理文件的方法.
+brief: 本手册解释了如何保存和加载文件以及执行其他类型的文件操作。
 ---
 
 # 处理文件
-存取文件有很多种方式. 文件的路径和文件类型决定了采取何种方式.
-
-## 文件/文件夹存取函数
-Defold 提供如下函数用以存取文件/文件夹:
-
-* 标准输入输出库 [`io.*` functions](https://defold.com/ref/stable/io/). 用于文件/文件夹存取, 底层高效细致灵活.
-* 操作系统库 [`os.rename()`](https://defold.com/ref/stable/os/#os.rename:oldname-newname) 和 [`os.remove()`](https://defold.com/ref/stable/os/#os.remove:filename) 用于文件改名和删除.
-* 游戏引擎系统库 [`sys.save()`](https://defold.com/ref/stable/sys/#sys.save:filename-table) 和 [`sys.load()`](https://defold.com/ref/stable/sys/#sys.load:filename) 用于存取 Lua 表. 其他 [`sys.*`](https://defold.com/ref/stable/sys/) 下的函数用于不同操作系统文件路径的解析.
-
-## 文件/文件夹位置
-有三个文件/文件夹位置可供游戏应用存取使用:
-
-* 游戏应用所在位置下的文件
-* 游戏应用打包进去的文件
-* 操作系统所管理的文件
-
-### 游戏指定位置的文件处理
-像最高分数, 用户设置和游戏状态等信息建议如此处理. 用 [`sys.get_save_file()`](https://defold.com/ref/stable/sys/#sys.get_save_file:application_id-file_name) 函数得到操作系统指定的文件绝对路径. 然后用 `sys.*`, `io.*` 和 `os.*` 函数处理文件/文件夹 (见上文).
-
-[Check the example showing how to use sys.save() and sys.load()](/examples/file/sys_save_load/).
-
-### 游戏应用打包进去的文件处理
-把文件打包进游戏应用有两种方法:
-
-1. **用户资源文件** - 在 *game.project* 配置文件的 [*Custom Resources* 项](https://defold.com/manuals/project-settings/#custom-resources) 进行设置. 然后可以使用 [`sys.load_resource()`](https://defold.com/ref/sys/#sys.load_resource) 函数进行访问. 注意这些文件实际上并不存在于用户的操作系统之中. 这样打包的文件作为游戏包的一部分只可以使用 `sys.load_resource()` 进行访问.
-
-2. **打包资源文件** - 在 *game.project* 配置文件的 [*Bundle Resources* 项](https://defold.com/manuals/project-settings/#bundle-resources) 进行设置. 然后可以使用 [`sys.get_application_path()`](https://defold.com/ref/stable/sys/#sys.get_application_path:) 得到应用的实际路径. 再基于应用路径得到资源文件的完整路径. 之后就可以使用 `io.*` 和 `os.*` 的功能函数进行访问 (参见上文).
-
- ::: sidenote
- 基于安全考虑浏览器 (及浏览器里运行的 JavaScript 插件) 不允许访问本地文件. 虽然 HTML5 游戏也能运行, 但是只能用浏览器提供的 IndexedDB API 在 "虚拟文件系统" 中存取数据. 也就是说不允许使用 `io.*` 和 `os.*` 下的函数. 但是可以用 `http.request()` 请求在线资源文件.
- :::
+创建和/或访问文件有许多不同的方式。文件路径和访问这些文件的方式根据文件类型和文件位置而有所不同。
+
+## 文件和文件夹访问函数
+Defold 提供了几种不同的函数来处理文件:
+
+* 您可以使用标准的 [`io.*` 函数](https://defold.com/ref/stable/io/)来读写文件。这些函数为您提供了对整个 I/O 过程的非常精细的控制。
+
+```lua
+-- 以二进制模式打开 myfile.txt 进行写入
+-- 失败时返回 nil 和错误消息
+local f, err = io.open("path/to/myfile.txt", "wb")
+if not f then
+	print("打开文件时出错了", err)
+	return
+end
+
+-- 写入文件,刷新到磁盘然后关闭文件
+f:write("Foobar")
+f:flush()
+f:close()
+
+-- 以二进制模式打开 myfile.txt 进行读取
+-- 失败时返回 nil 和错误消息
+local f, err = io.open("path/to/myfile.txt", "rb")
+if not f then
+	print("打开文件时出错了", err)
+	return
+end
+
+-- 将整个文件作为字符串读取
+-- 失败时返回 nil
+local s = f:read("*a")
+if not s then
+	print("读取文件时出错")
+	return
+end
+
+print(s) -- Foobar
+```
+
+* 您可以使用 [`os.rename()`](https://defold.com/ref/stable/os/#os.rename:oldname-newname) 和 [`os.remove()`](https://defold.com/ref/stable/os/#os.remove:filename) 来重命名和删除文件。
+
+* 您可以使用 [`sys.save()`](https://defold.com/ref/stable/sys/#sys.save:filename-table) 和 [`sys.load()`](https://defold.com/ref/stable/sys/#sys.load:filename) 来读写 Lua 表。还有其他 [`sys.*`](https://defold.com/ref/stable/sys/) 函数可以帮助实现平台无关的文件路径解析。
+
+```lua
+-- 获取应用程序"mygame"的文件"highscore"的平台无关路径
+local path = sys.get_save_file("mygame", "highscore")
+
+-- 保存包含一些数据的 Lua 表
+local ok = sys.save(path, { highscore = 100 })
+if not ok then
+	print("保存失败", path)
+	return
+end
+
+-- 加载数据
+local data = sys.load(path)
+print(data.highscore) -- 100
+```
+
+## 文件和文件夹位置
+文件和文件夹位置可以分为三类:
+
+* 由您的应用程序创建的应用程序特定文件
+* 与您的应用程序捆绑在一起的文件和文件夹
+* 由您的应用程序访问的系统特定文件
+
+### 如何保存和加载应用程序特定文件
+当保存和加载应用程序特定文件(如高分、用户设置和游戏状态)时,建议在操作系统提供的专门用于此目的的位置中进行。您可以使用 [`sys.get_save_file()`](https://defold.com/ref/stable/sys/#sys.get_save_file:application_id-file_name) 获取文件的操作系统特定绝对路径。一旦获得绝对路径,您就可以使用 `sys.*`、`io.*` 和 `os.*` 函数(见上文)。
+
+[查看展示如何使用 `sys.save()` 和 `sys.load()` 的示例](/examples/file/sys_save_load/)。
+
+### 如何访问与应用程序捆绑的文件
+您可以使用捆绑资源和自定义资源将文件包含在您的应用程序中。
+
+#### 自定义资源
+:[自定义资源](../shared/custom-resources.md)
+
+```lua
+-- 将关卡数据加载到字符串中
+local data, error = sys.load_resource("/assets/level_data.json")
+-- 将 json 字符串解码为 Lua 表
+if data then
+  local data_table = json.decode(data)
+  pprint(data_table)
+else
+  print(error)
+end
+```
+
+#### 捆绑资源
+:[捆绑资源](../shared/bundle-resources.md)
+
+```lua
+local path = sys.get_application_path()
+local f = io.open(path .. "/mycommonfile.txt", "rb")
+local txt, err = f:read("*a")
+if not txt then
+	print(err)
+	return
+end
+print(txt)
+```
+
+::: important
+出于安全原因,浏览器(以及扩展来说,在浏览器中运行的任何 JavaScript)被阻止访问系统文件。在 Defold 的 HTML5 构建中,文件操作仍然有效,但仅在浏览器中使用 IndexedDB API 的"虚拟文件系统"上有效。这意味着无法使用 `io.*` 或 `os.*` 函数访问捆绑资源。但是,您可以使用 `http.request()` 访问捆绑资源。
+:::
 
 
-#### 用户资源与打包资源对比
+#### 自定义和捆绑资源 - 比较
 
-| 特点              | 用户资源                          | 打包资源                              |
+| 特性              | 自定义资源                          | 捆绑资源                               |
 |-----------------------------|-------------------------------------------|------------------------------------------------|
-| 加载速度               | 快 - 从应用二进制包内加载 | 慢 - 从文件系统中加载          |
-| 加载单个文件的功能          | 无 - 只能加载全部资源                    | 有 - 基于文件的字节读取           |
-| 应用打包后修改资源文件 | 无 - 所有资源保存为一个二进制资源包 | 有 - 文件存储基于文件操作系统    |
-| HTML5 支持               | 有                                       | 有 - 但是这里的访问基于 http 而不是文件 I/O |
+| 加载速度               | 更快 - 从二进制存档加载文件 | 更慢 - 从文件系统加载文件          |
+| 加载部分文件          | 否 - 只能加载整个文件                    | 是 - 从文件读取任意字节           |
+| 捆绑后修改文件 | 否 - 文件存储在二进制存档内 | 是 - 文件存储在本地文件系统上    |
+| HTML5 支持               | 是                                       | 是 - 但通过 http 访问而不是文件 I/O |
 
 
-### 操作系统文件处理
-基于安全考虑操作系统所管理的文件存取被严格限制. 可以使用 [`extension-directiories`](https://defold.com/assets/extensiondirectories/) 原生扩展来存取某些地方的绝对路径 (例如 documents, resource, temp). 然后用 `sys.*`, `io.*` 和 `os.*` 函数处理文件/文件夹 (见上文).
+### 系统文件访问
+出于安全原因,操作系统可能会限制对系统文件的访问。您可以使用 [`extension-directories`](https://defold.com/assets/extensiondirectories/) 原生扩展来获取一些常见系统目录(即文档、资源、临时文件)的绝对路径。一旦获得这些文件的绝对路径,您就可以使用 `io.*` 和 `os.*` 函数来访问文件(见上文)。
 
-::: sidenote
-出于安全考虑浏览器 (连同浏览器里运行的 JavaScript 扩展程序) 不可访问系统文件. Defold 的 HTML5 文件存取程序依然工作, 但只是在浏览器以 IndexedDB API 提供的 "虚拟文件系统" 上. 这意味着 HTML5 应用不能真正存取系统文件.
+::: important
+出于安全原因,浏览器(以及扩展来说,在浏览器中运行的任何 JavaScript)被阻止访问系统文件。在 Defold 的 HTML5 构建中,文件操作仍然有效,但仅在浏览器中使用 IndexedDB API 的"虚拟文件系统"上有效。这意味着在 HTML5 构建中无法访问系统文件。
 :::
 
-## 相关原生扩展
-在 [资源中心](https://defold.com/assets/) 里有些原生扩展能简化文件存取的工作. 例如:
+## 扩展
+[资源门户](https://defold.com/assets/) 包含几个简化文件和文件夹访问的资源。一些示例:
 
-* [Lua File System (LFS)](https://defold.com/assets/luafilesystemlfs/) - 提供操作文件夹, 文件权限之类的功能.
-* [DefSave](https://defold.com/assets/defsave/) - 一个用于保存/加载游戏设置和玩家数据档的模块.
+* [Lua 文件系统 (LFS)](https://defold.com/assets/luafilesystemlfs/) - 用于处理目录、文件权限等的函数
+* [DefSave](https://defold.com/assets/defsave/) - 一个帮助您在会话之间保存/加载配置和玩家数据的模块

+ 87 - 86
docs/zh/manuals/flash.md

@@ -1,45 +1,47 @@
 ---
-title: Flash 开发者 Defold 过渡教程
-brief: 本教程针对 Flash 游戏开发者对比介绍了 Defold 相对应的概念和方法.
+title: Defold for Flash users
+brief: 本指南为 Flash 游戏开发者介绍了 Defold 作为替代方案。它涵盖了 Flash 游戏开发中使用的一些关键概念,并解释了 Defold 中相应的工具和方法。
 ---
 
-# Flash 开发者 Defold 过渡
+# Defold for Flash users
 
-本教程针对 Flash 游戏开发者对比介绍了 Defold 相对应的概念和方法.
+本指南为 Flash 游戏开发者介绍了 Defold 作为替代方案。它涵盖了 Flash 游戏开发中使用的一些关键概念,并解释了 Defold 中相应的工具和方法。
 
 ## 介绍
 
-Flash 上手快门槛低. 新用户开发方便入门, 短时间内就可以开发出简单的游戏. Defold 针对游戏开发提供了类似的易用工具集, 此外还对高端开发者提供了更自由的发挥空间 (比如自己编写渲染脚本).
+Flash 的一些主要优势是易用性和低入门门槛。新用户可以快速学习该程序,并能在有限的时间投入内创建基本游戏。Defold 通过提供一套专门用于游戏设计的工具提供了类似的优势,同时使高级开发者能够为更复杂的需求创建高级解决方案(例如允许开发者编辑默认渲染脚本)。
 
-Flash 用 ActionScript (最新 3.0 版) 写脚本, Defold 用 Lua 写脚本. 本教程不涉及 Lua 和 Actionscript 3.0 编程. [Defold Lua 教程](/manuals/lua) 介绍了 Defold 中的 lua 脚本, [Programming in Lua](https://www.lua.org/pil/) (第一版) 有在线免费版可供学习.
+Flash 游戏使用 ActionScript 编程(3.0 是最新版本),而 Defold 脚本使用 Lua 编写。本指南不会详细比较 Lua 和 Actionscript 3.0。[Defold 手册](/manuals/lua) 提供了 Defold 中 Lua 编程的良好介绍,并引用了非常有用的 [Programming in Lua](https://www.lua.org/pil/)(第一版),该书可在线免费获取。
 
-Jesse Warden 写了一篇 [Actionscript 与 Lua 简要对比](http://jessewarden.com/2011/01/lua-for-actionscript-developers.html) 的文章, 可以先看看这个. 注意 Defold 和 Flash 架构上的不同比起脚本语言的区别更多. Actionscript 和 Flash 是标准的面向对象的架构. Defold 却没有类也没有集成的概念. 它有着叫做 *游戏对象* 的概念, 用来表达视听, 行为和数据. 脚本通过调用 Defold API *函数* 进行逻辑编写. 而且, Defold 推荐使用 *消息* 机制进行对象间的互相通信. 消息机制比函数调用更高级别. 这些概念需要一段时间掌握, 本教程不做讲解.
+Jesse Warden 的一篇文章提供了 [Actionscript 和 Lua 的基本比较](http://jessewarden.com/2011/01/lua-for-actionscript-developers.html),这可以作为一个很好的起点。但请注意,Defold 和 Flash 在构建方式上的差异比语言层面可见的差异更深。Actionscript 和 Flash 在经典意义上是面向对象的,具有类和继承。Defold 没有类,也没有继承。它包含 *游戏对象* 的概念,可以包含视听表示、行为和数据。对游戏对象的操作是通过 Defold API 中可用的 *函数* 完成的。此外,Defold 鼓励使用 *消息* 在对象之间进行通信。消息是比方法调用更高级的构造,并不打算用作方法调用。这些差异很重要,需要一段时间才能适应,但本指南不会详细讨论。
 
-本教程, 主要是寻找 Flash 开发中的关键技术, 然后在 Defold 中找到对应的解决方案. 我们将探讨相似处和区别以及一些注意事项, 让你快速从 Flash 过渡到 Defold.
+相反,本指南探讨了 Flash 游戏开发的一些关键概念,并概述了 Defold 中最接近的等价物。讨论了相似性和差异,以及常见的陷阱,使你能够从 Flash 过渡到 Defold 时快速上手。
 
 ## 影片剪辑和游戏对象
 
-影片剪辑是 Flash 游戏开发的基础组成部分. 每个影片剪辑包含自己的时间轴. Defold 中类似的概念是游戏对象.
+影片剪辑是 Flash 游戏开发的基础组成部分。每个影片剪辑包含自己的时间轴。Defold 中类似的概念是游戏对象。
 
 ![game object and movieclip](images/flash/go_movieclip.png)
 
-不同的是, Defold 游戏对象没有时间轴. 却能包含很多组件. 组件有 sprite, sound, 脚本---等等 (关于组件详情请见 [构成教程](/manuals/building-blocks)). 下图这个游戏对象包含一个 sprite 和一个脚本. 脚本用来控制游戏对象生命周期中的行为:
+不同的是,Defold 游戏对象没有时间轴。却能包含很多组件。组件有 sprite、sound、脚本等等(关于组件详情请见 [构成教程](/manuals/building-blocks))。下图这个游戏对象包含一个 sprite 和一个脚本。脚本用来控制游戏对象生命周期中的行为:
 
 ![script component](images/flash/script_component.png)
 
-影片剪辑可以包含其他影片剪辑, 游戏对象不是 *包含* 其他游戏对象. 但是能够与其他游戏对象建立 *父子* 层级关系, 父子关系的游戏对象可以一起移动, 旋转和缩放.
+影片剪辑可以包含其他影片剪辑,游戏对象不是 *包含* 其他游戏对象。但是能够与其他游戏对象建立 *父子* 层级关系,父子关系的游戏对象可以一起移动、旋转和缩放。
 
 ## Flash 手动创建影片剪辑
 
-Flash 里, 可以从库中往时间轴上拖放影片剪辑以创建实例. 下图中, 舞台上的每个图标都是logo影片剪辑的实例:
+在 Flash 中,影片剪辑可以在 IDE 中手动创建,也可以运行时动态创建。手动创建的影片剪辑需要给实例名,才能在代码里引用。
 
 ![manual movie clips](images/flash/manual_movie_clips.png)
 
-## Defold 手动创建游戏对象
+## Defold手动创建游戏对象
 
-上文说了, Defold 没有时间轴概念. 但是, 集合可以用来管理游戏对象. 集合是容纳游戏对象和其他集合的容器 (或称 prefabs). 最简单的情况, 一个游戏有一个集合. 通常, Defold 游戏包含许多集合, 或者手动指定启动 “main” 集合或者通过 [集合代理](/manuals/collection-proxy) 动态载入集合. 但是 Flash 的 "levels" 或者 "screens" 没有这个能力.
+Defold 中,游戏对象可以在编辑器里手动创建,也可以运行时动态创建。手动创建的游戏对象需要给唯一 id,才能在代码里引用。
 
-下面的例子里, "main" 集合 (看右边, *Outline* 窗口里) 包含3个 "logo" 游戏对象 (看左边, *Assets* 浏览器窗口里):
+集合可以用来管理游戏对象。集合是容纳游戏对象和其他集合的容器(或称 prefabs)。最简单的情况,一个游戏有一个集合。通常,Defold 游戏包含许多集合,或者手动指定启动 “main” 集合或者通过 [集合代理](/manuals/collection-proxy) 动态载入集合。但是 Flash 的 "levels" 或者 "screens" 没有这个能力。
+
+下面的例子里,"main" 集合(看右边,*Outline* 窗口里)包含3个 "logo" 游戏对象(看左边,*Assets* 浏览器窗口里):
 
 ![manual game objects](images/flash/manual_game_objects.png)
 
@@ -100,15 +102,15 @@ local logo_id = factory.create("factories#logo_factory")
 
 URL 是 `factory.create()` 函数的必要参数. 此外, 还有可选参数用以设置位置, 旋转, 缩放, 和其他属性. 工厂组件详情请见 [工厂教程](/manuals/factory). 注意调用 `factory.create()` 可返回被创建游戏对象的id. 可以把这个id放入表中留待以后引用 (Lua 的表相当于其他语言的数组).
 
-## Flash—物体
+## Flash—舞台
 
-Flash 里经常使用时间轴 (下图上半部分) 和舞台 (时间轴下方):
+在 Flash 中,我们熟悉时间轴(下图的上部)和舞台(时间轴下方可见):
 
 ![timeline and stage](images/flash/stage.png)
 
-就像上文提到的影片剪辑容器, 舞台是Flash游戏的顶级容器. 舞台默认有一个子集, 叫 *MainTimeline*. 项目中每个影片剪辑都有子集的时间轴, 可以作为容纳其他组件的容器 (包括可以嵌套影片剪辑).
+如上面影片剪辑部分所讨论的,舞台本质上是 Flash 游戏的顶级容器,在每次导出项目时创建。舞台默认情况下有一个子对象,即 *`MainTimeline`*。项目中生成的每个影片剪辑都有自己的时间轴,并且可以作为其他符号(包括影片剪辑)的容器。
 
-## Defold—集合
+## Defold—collections
 
 Defold 的集合类似于舞台. 引擎启动时集合文件的内容组成了游戏世界. 默认启动集合叫 "main.collection" 但是可以在 *game.project* 项目配置文件里随意更改:
 
@@ -122,31 +124,31 @@ Defold 的集合类似于舞台. 引擎启动时集合文件的内容组成了
 
 ## Flash—时间轴
 
-Flash 时间轴主要用来制作动画, 可以是逐帧动画也可以是形状/运动补间动画. 项目设置定义了全局 FPS (帧每秒) 决定了每帧显示多长时间. 老鸟用户可以随时修改游戏 FPS, 或者为影片剪辑独立设置 FPS.
+Flash 时间轴主要用于动画,使用各种逐帧技术或形状/运动补间。项目的整体 FPS(每秒帧数)设置定义了帧显示的时间长度。高级用户可以修改游戏的整体 FPS,甚至单个影片剪辑的 FPS。
 
-形状补间可以在矢量图的两个状态间进行插值. 这主要针对简单的图形和应用, 比如下例中把方块补间成三角:
+形状补间允许在矢量图形的两个状态之间进行插值。它主要适用于简单的形状和应用,如下例中将正方形补间成三角形所示:
 
 ![timeline](images/flash/timeline.png)
 
-运动补间可以应用于对象属性, 包括大小, 位置和旋转. 下例中这些属性都进行了补间.
+运动补间允许对对象的各种属性进行动画,包括大小、位置和旋转。在下面的例子中,所有列出的属性都被修改了。
 
 ![motion tween](images/flash/tween.png)
 
 ## Defold—属性动画
 
-Defold 不使用矢量图而是使用位图, 所以没有形状补间. 但是运动补间可以使用 [属性动画](/ref/go/#go.animate) 来实现. 通过脚本, 调用 `go.animate()` 函数即可. go.animate() 函数基于各种缓动函数 (可以自定义) , 对属性 (比如颜色, 缩放, 旋转或者位置) 进行从初始值到设定结束值的补间. Defold 引擎内置了许多要 Flash 用户自定义才能实现的 [缓动函数](/manuals/animation/#easing).
+Defold 不使用矢量图而是使用位图,所以没有形状补间。但是运动补间可以使用 [属性动画](/ref/go/#go.animate) 来实现。通过脚本,调用 `go.animate()` 函数即可。go.animate() 函数基于各种缓动函数(可以自定义),对属性(比如颜色、缩放、旋转或者位置)进行从初始值到设定结束值的补间。Defold 引擎内置了许多要 Flash 用户自定义才能实现的 [缓动函数](/manuals/animation/#easing)
 
-Flash 在时间轴上用关键帧做动画, Defold 动画功能之一是用导入的序列图做逐帧动画. 动画基于图集管理. 下例中图集有一个叫做 "run" 的动画. 此动画由一组图片组成:
+Flash 在时间轴上用关键帧做动画,Defold 动画功能之一是用导入的序列图做逐帧动画。动画基于图集管理。下例中图集有一个叫做 "run" 的动画,此动画由一组图片组成:
 
 ![flipbook](images/flash/flipbook.png)
 
-## Flash—深度索引
+## Flash—depth index
 
-在 Flash 里, 显示列表决定显示次序. 每个容器 (比如舞台) 都有一个显示列表. 对象使用 `addChild()` 方法会自动被加入到显示列表顶端, 从 0 开始索引层层递增. 下图中, 有三个 "logo" 影片剪辑的对象:
+在 Flash 中,显示列表决定显示什么以及以什么顺序显示。容器(如舞台)中对象的排序通过索引处理。使用 `addChild()` 方法添加到容器的对象将自动占据索引的顶部位置,从 0 开始,每个额外对象都会递增。在下面的截图中,我们生成了三个 "logo" 影片剪辑的实例:
 
 ![depth index](images/flash/depth_index.png)
 
-图标上标注了其所在显示列表索引位置. 除去 x/y 位置设置, 如下代码会把图标加入到显示列表中:
+显示列表中的位置由每个标志实例旁边的数字指示。忽略处理影片剪辑 x/y 位置的任何代码,上述内容可以如下生成:
 
 ```as
 var logo1:Logo = new Logo();
@@ -158,145 +160,144 @@ addChild(logo2);
 addChild(logo3);
 ```
 
-显示列表索引位置决定了它们的显示层次. 如果交互两个图标的索引, 比如:
+对象是显示在另一个对象之上还是之下,是由它们在显示列表索引中的相对位置决定的。通过交换两个对象的索引位置可以很好地说明这一点,例如:
 
 ```as
 swapChildren(logo2,logo3);
 ```
 
-结果如下 (索引已更新):
+结果将如下所示(索引位置已更新):
 
 ![depth index](images/flash/depth_index_2.png)
 
-## Defold— z 轴位置
+## Defold—z position
 
-Defold 里游戏对象的位置向量包含三部分: x, y, 和 z. 其中 z 轴位置决定了其深度. 在默认 [渲染脚本](/manuals/render) 中, z 轴位置范围是 -1 到 1.
+Defold 使用 z 轴位置控制游戏对象的显示顺序。每个游戏对象的位置向量包含 x、y、z 三个分量,其中 z 值越大,对象越靠前显示。在默认 [渲染脚本](/manuals/render) 中,z 轴有效范围为 -1 到 1。
 
 ::: sidenote
-如果游戏对象的 z 轴位置不在 -1 到 1 的范围内就不会被渲染也就是不可见. Defold 新手经常会因为这个感到困惑, 所以如果发现该显示的东西不显示想想是不是这个原因.
+若游戏对象的 z 值超出 [-1, 1] 范围将不会被渲染(不可见)。这是新手常见困惑点,若对象未显示请优先检查 z 值。
 :::
 
-不同于 Flash 由编辑器决定显示索引 (然后可以使用 *Bring Forward* 和 *Send Backward* 之类的命令修改索引), Defold 可以在编辑器里直接设置游戏对象的 z 轴位置. 下图中, 你会看到 "logo3" 显示在最上层, 其 z 轴位置是 0.2. 其他两个的 z 轴位置是 0.0 和 0.1.
+与 Flash 的深度索引不同,Flash 编辑器只隐含深度索引(并允许使用*Bring Forward*和*Send Backward*等命令修改),而 Defold 可直接在编辑器中设置 z 值。下图示例中,"logo3" 因 z=0.2 显示在最上层,其余两个对象 z 值分别为 0.0 和 0.1:
 
 ![z-order](images/flash/z_order.png)
 
-注意游戏对象 z 轴位置是由其本身 z 轴位置, 连同其所有父级的 z 轴位置共同决定的. 比如, 假设上文图标位于 "logos" 集合中, 该集合又位于 "main" 集合中 (见下图). 如果 "logos" 集合 z 位置是 0.9, 那么这三个图标的 z 位置就会是 0.9, 1.0, 和 1.1. 所以, "logo3" 不会被渲染因为其 z 位置大于 1.
+层级叠加规则:对象的最终 z 值 = 自身 z 值 + 所有父级 z 值之和。例如,若 "logos" 集合(包含三个图标)的 z=0.9,则三个图标的最终 z 值为 0.9、1.0、1.1,此时 "logo3" 因 z=1.1 > 1 而不可见:
 
 ![z-order](images/flash/z_order_outline.png)
 
-z 轴位置可由脚本更改. 如下代码设置了游戏对象的 z 轴位置:
-
+脚本动态修改:
 ```lua
 local pos = go.get_position()
-pos.z  = 0.5
+pos.z = 0.5  -- 设置 z 轴位置
 go.set_position(pos)
 ```
 
-## Flash—hitTestObject 和 hitTestPoint 碰撞检测
+## Flash `hitTestObject` 和 `hitTestPoint` 碰撞检测
 
-Flash 中使用 `hitTestObject()` 方法进行基本碰撞检测. 举个例子, 有两个影片剪辑: "bullet" 和 "bullseye". 见下图. 在 Flash 编辑器选中对象时会显示一个蓝色边框, `hitTestObject()` 方法就是用这样的边框来进行碰撞检测的.
+Flash 中的基本碰撞检测通过使用 `hitTestObject()` 方法实现。在这个例子中,我们有两个影片剪辑:"bullet" 和 "bullseye"。下图中展示了这两个对象。在 Flash 编辑器中选择符号时可见的蓝色边界框,正是驱动 `hitTestObject()` 方法结果的边界框。
 
 ![hit test](images/flash/hittest.png)
 
-如下使用 `hitTestObject()` 进行碰撞检测:
+使用 `hitTestObject()` 进行碰撞检测:
 
 ```as
 bullet.hitTestObject(bullseye);
 ```
 
-这样检测可能会不准确, 比如如下的情况:
+在这种情况下使用边界框并不合适,因为下面的场景会登记为碰撞:
 
 ![hit test bounding box](images/flash/hitboundingbox.png)
 
-除了 `hitTestObject()` 还有 `hitTestPoint()` 方法. 此方法包含一个 `shapeFlag` 参数, 可以提供像素对目标有像素形状的碰撞检测. 如下使用 `hitTestPoint()` 进行碰撞检测:
+除了 `hitTestObject()` 之外,还有 `hitTestPoint()` 方法。这个方法包含一个 `shapeFlag` 参数,允许针对对象的实际像素进行碰撞测试,而不是边界框。使用 `hitTestPoint()` 进行碰撞检测可以如下所示:
 
 ```as
 bullseye.hitTestPoint(bullet.x, bullet.y, true);
 ```
 
-这样通过子弹 x 和 y 坐标 (子弹图片左上角) 对靶子形状进行碰撞检测. 因为 `hitTestPoint()` 是点对形状的碰撞检测, 哪个 (或哪些) 点需要检测是要考虑的关键.
+这一行会检查子弹的 x 和 y 位置(在这种情况下是左上角)与目标形状的碰撞。由于 `hitTestPoint()` 检查的是点与形状的碰撞,因此检查哪个点(或哪些点!)是一个关键考虑。
 
-## Defold—碰撞对象
+## Defold—collision objects
 
-Defold 内含物理引擎可以用于碰撞检测然后使用其上的脚本进行相应. 首先要在游戏对象上面添加碰撞对象组件. 如下图所示, 我们对 "bullet" 游戏对象添加了碰撞对象. 碰撞对象以红色半透明方块表示 (只在编辑器中可见):
+Defold 内含物理引擎可以用于碰撞检测然后使用其上的脚本进行响应。首先要在游戏对象上面添加碰撞对象组件。如下图所示,我们对 "bullet" 游戏对象添加了碰撞对象。碰撞对象以红色半透明方块表示(只在编辑器中可见):
 
 ![collision object](images/flash/collision_object.png)
 
-Defold 包含一个 Box2D 物理引擎的修改版, 可以用来自动模拟真实的碰撞. 本教程使用运 Kinematic 碰撞对象, 因为它的碰撞检测和 Flash 的最接近. 关于动态碰撞详情请见 Defold [物理教程](/manuals/physics).
+Defold 包含一个 Box2D 物理引擎的修改版,可以用来自动模拟真实的碰撞。本教程使用 Kinematic 碰撞对象,因为它的碰撞检测和 Flash 的最接近。关于动态碰撞详情请见 Defold [物理教程](/manuals/physics)。
 
-此碰撞对象包含如下属性:
+此碰撞对象包含如下属性
 
 ![collision object properties](images/flash/collision_object_properties.png)
 
-用一个矩形代表上例中的子弹. 圆形代表靶子进行碰撞检测. 设置类型为 Kinematic 意味着使用脚本进行碰撞处理, 物理引擎默认不是这样 (关于其他类型, 请见 [物理手册](/manuals/physics)). 属性 group 和 mask 分别决定了碰撞对象属于哪个组以及和哪个组相碰撞. 当前设置是 "bullet" 只能与 "target" 碰撞. 要是如下这样:
+用一个矩形代表上例中的子弹。圆形代表靶子进行碰撞检测。设置类型为 Kinematic 意味着使用脚本进行碰撞处理,物理引擎默认不是这样(关于其他类型,请见 [物理手册](/manuals/physics))。属性 group 和 mask 分别决定了碰撞对象属于哪个组以及和哪个组相碰撞。当前设置是 "bullet" 只能与 "target" 碰撞。要是如下这样:
 
 ![collision group/mask](images/flash/collision_groupmask.png)
 
-子弹之间就能相互碰撞了. 我们为靶子设置了如下的碰撞对象:
+子弹之间就能相互碰撞了。我们为靶子设置了如下的碰撞对象:
 
 ![collision object bullet](images/flash/collision_object_bullet.png)
 
-注意 *Group* 属性设置为了 "target" 然后 *Mask* 设置为了 "bullet".
+注意 *Group* 属性设置为了 "target" 然后 *Mask* 设置为了 "bullet"
 
-Flash 里, 需要脚本调用才会进行碰撞检测. Defold 里, 只要碰撞对象开启, 后台就会持续进行碰撞检测. 碰撞发生时, 消息会发送到游戏对象所有组件上 (更确切地说是脚本组件). 有 [碰撞处理和碰撞点处理消息](/manuals/physics/#碰撞消息), 其中包含了处理碰撞所需的各种信息.
+Flash 里,需要脚本调用才会进行碰撞检测。Defold 里,只要碰撞对象开启,后台就会持续进行碰撞检测。碰撞发生时,消息会发送到游戏对象所有组件上(更确切地说是脚本组件)。有 [碰撞处理和碰撞点处理消息](/manuals/physics/#碰撞消息),其中包含了处理碰撞所需的各种信息。
 
-Defold 的碰撞检测比 Flash 的要高级, 毫不费力就能检测复杂形状间的碰撞. 碰撞检测是自动的, 也就是说不需要手动遍历各个对象然后挨个进行碰撞检测. 但是没有 Flash 的 shapeFlag. 但是对于复杂图形可以使用简单图形组合达成. 更复杂的需求下, 还可以使用 [自定义图形](//forum.defold.com/t/does-defold-support-only-three-shapes-for-collision-solved/1985).
+Defold 的碰撞检测比 Flash 的要高级,毫不费力就能检测复杂形状间的碰撞。碰撞检测是自动的,也就是说不需要手动遍历各个对象然后挨个进行碰撞检测。但是没有 Flash 的 `shapeFlag`。但是对于复杂图形可以使用简单图形组合达成。更复杂的需求下,还可以使用 [自定义图形](https://forum.defold.com/t/does-defold-support-only-three-shapes-for-collision-solved/1985)。
 
-## Flash—事件监听
+## Flash—事件处理
 
-事件对象及其监听器用来检测各种事件 (比如说 鼠标点击, 按钮按下, 剪辑加载) 并在反馈里处理行为. 包括许许多多的事件.
+Flash 中,事件处理通过事件监听器来完成。您可以使用 addEventListener() 方法来添加事件监听器。
 
-## Defold—回调函数和消息
+## Defold—call-back functions and messaging
 
-Defold 跟 Flash 比有几个地方差不多. 首先, 每个脚本组件都包含一组特定事件的回调函数. 具体有:
+Defold 中与 Flash 事件处理系统等效的几个方面。首先,每个脚本组件都带有一组检测特定事件的回调函数。这些函数包括:
 
 init
-:   脚本组件初始化时调用. 相当于 Flash 的构造函数.
+:   脚本组件初始化时调用。相当于 Flash 中的构造函数。
 
 final
-:   脚本组件析构时调用 (比如游戏对象被删除时).
+:   脚本组件被销毁时调用(例如,生成的游戏对象被移除)。
 
 update
-:   在每一帧调用. 相当于 Flash 的 `enterFrame`.
+:   每帧调用。相当于 Flash 中的 `enterFrame`。
 
 on_message
-:   当脚本组件收到消息时调用.
+:   脚本组件接收到消息时调用。
 
 on_input
-:   当用户输入 (比如鼠标或键盘) 发送到得到 [输入焦点](/ref/go/#acquire_input_focus) 的游戏对象上时调用, 得到输入焦点的游戏对象会接收并反馈所有输入.
+:   当用户输入(例如鼠标或键盘)发送到具有[输入焦点](/ref/go/#acquire_input_focus)的游戏对象时调用,这意味着该对象接收所有输入并可以对其做出反应。
 
 on_reload
-:   脚本组件重载时调用.
+:   脚本组件重新加载时调用。
 
-这些都是可选回调函数如果不需要可以删除. 关于如何接收输入, 详情请见 [输入教程](/manuals/input). 有一个关于集合代理易用错的地方 - 详情请见输入教程的 [这一章](/manuals/input/#输入调度和 on_input() 函数).
+上面列出的回调函数都是可选的,如果不使用可以删除。有关如何设置输入的详细信息,请参阅[输入手册](/manuals/input)。使用集合代理时会出现一个常见问题 - 请参阅输入手册的[此部分](/manuals/input/#input-dispatch-and-on_input)获取更多信息。
 
-就像碰撞检测部分说的那样, 碰撞事件被发送到相关游戏对象上进行处理. 各个脚本组件的 on_message 回调函数会被调用.
+如碰撞检测部分所述,碰撞事件通过向涉及的游戏对象发送消息来处理。它们各自的脚本组件在其 on_message 回调函数中接收消息。
 
-## Flash—按钮剪辑
+## Flash—按钮符号
 
-Flash 为按钮使用了一种特殊剪辑. 按钮监听到用户交互时使用特殊的事件处理方法 (比如 `click` 和 `buttonDown`) 来运行指定行为. 按钮 "Hit" 部分的图形决定了按钮的可点击区域.
+Flash 使用专用的按钮符号类型。按钮使用特定的事件处理方法(如 `click` 和 `buttonDown`)在检测到用户交互时执行动作。按钮符号中“点击”部分的图形形状决定了按钮的点击区域。
 
 ![button](images/flash/button.png)
 
-## Defold—GUI场景和脚本
+## Defold—GUI 场景和脚本
 
-Defold 没有内置按钮组件, 也不像 Flash 那样使用游戏对象的图形进行方便的点击检测. 使用 [GUI](/manuals/gui) 组件是一个通用方案, 部分因为 Defold GUI 组件的位置不受游戏中摄像机 (如果有使用). GUI API 还包含在 GUI 组件的范围内检测用户输入例如点击和触摸事件的功能.
+Defold 不包含原生按钮组件,也不能像 Flash 中那样轻易地检测对特定游戏对象形状的点击。使用 [GUI](/manuals/gui) 组件是最常见的解决方案,部分原因是 Defold GUI 组件的位置不受游戏内摄像机影响(如果使用的话)。GUI API 还包含检测用户输入(如点击和触摸事件)是否在 GUI 元素边界内的函数。
 
 ## 调试
 
-在 Flash 里, 用 `trace()` 命令帮助调试. 在 Defold 里相应的是 `print()`, 跟使用 `trace()` 方法一样:
+在 Flash 中,您使用 `trace()` 命令来帮助调试。Defold 中的等效函数是 `print()`,它的使用方式与 `trace()` 相同:
 
 ```lua
-print("Hello world!"")
+print("Hello world!")
 ```
 
-可以调用一次 `print()` 函数输出多个变量:
+您可以在一次 `print()` 调用中打印多个变量:
 
 ```lua
 print(score, health, ammo)
 ```
 
-还有一个 `pprint()` 函数 (pretty print), 用于打印表. 此函数能输出表的内容, 包括嵌套表. 看下面的脚本:
+还有一个 `pprint()` 函数(美化打印)用于打印表。这个函数输出表的内容,包括嵌套表。考虑以下脚本:
 
 ```lua
 factions = {"red", "green", "blue"}
@@ -304,13 +305,13 @@ world = {name = "Terra", teams = factions}
 pprint(world)
 ```
 
-这里把表 (`factions`) 嵌入到表 (`world`) 里. 使用普通 `print()` 命令只会输出表的id, 不含内容:
+这里我们将一个表(`factions`)嵌入到另一个表(`world`)中。使用常规的 `print()` 命令只会输出表的 id,而不是其内容:
 
 ```
 DEBUG:SCRIPT: table: 0x7ff95de63ce0
 ```
 
-使用 `pprint()` 函数就能显示出更多内容:
+使用 `pprint()` 函数显示更有用的信息:
 
 ```
 DEBUG:SCRIPT:
@@ -324,32 +325,32 @@ DEBUG:SCRIPT:
 }
 ```
 
-如果游戏使用了碰撞检测, 可以发送如下消息开关物理调试:
+如果您的游戏使用碰撞检测,您可以使用以下消息切换物理调试:
 
 ```lua
 msg.post("@system:", "toggle_physics_debug")
 ```
 
-也可以在项目设置里打开物理调试. 打开物理调试前我们的项目看起来像这样:
+您也可以在项目设置中启用物理调试。在启用物理调试之前,我们的项目看起来像这样:
 
 ![no debug](images/flash/no_debug.png)
 
-打开物理调试显示出项目中的碰撞对象:
+启用物理调试后,项目中的碰撞对象会显示出来:
 
 ![with debug](images/flash/with_debug.png)
 
-当碰撞发生时, 相关碰撞对象会高光显示. 而且, 碰撞向量也会被显示出来:
+当碰撞发生时,相关碰撞对象会高光显示。而且,碰撞向量也会被显示出来:
 
 ![collision](images/flash/collision.png)
 
-最后, 关于检测 CPU 和内存使用情况详情请见 [性能分析教程](/ref/profiler/). 更高级的调试技术, 详情请见 Defold 手册的 [调试部分](/manuals/debugging).
+最后,关于检测 CPU 和内存使用情况详情请见 [性能分析教程](/ref/profiler/)。更高级的调试技术,详情请见 Defold 手册的 [调试部分](/manuals/debugging)。
 
-## 更多参考
+## 从这里开始
 
-- [Defold examples](/examples)
-- [Tutorials](/tutorials)
-- [Manuals](/manuals)
-- [Reference](/ref)
-- [FAQ](/faq)
+- [Defold 示例](/examples)
+- [教程](/tutorials)
+- [手册](/manuals)
+- [参考](/ref/go)
+- [常见问题](/faq/faq)
 
-如果你有疑问, [Defold 论坛](//forum.defold.com) 是一个获取帮助的好地方.
+如果你有问题或遇到困难,[Defold 论坛](//forum.defold.com) 是寻求帮助的好地方。

+ 27 - 27
docs/zh/manuals/flipbook-animation.md

@@ -1,46 +1,46 @@
 ---
-title: Defold 中的逐帧动画
-brief: 本教程介绍了如何在 Defold 中使用逐帧动画.
+title: Defold 中的逐帧动画手册
+brief: 本手册描述了如何在 Defold 中使用逐帧动画.
 ---
 
-# 逐帧动画
+# Flip-book animation
 
-逐帧动画就是由一些列静态图片轮流显示生成的动画. 这种技术类似于老式翻页动画 (详见 http://en.wikipedia.org/wiki/Traditional_animation). 由于每帧的独立性使得这种技术很自由. 但是每帧一张图片会很耗费内存. 相似图片越多动画过渡越平滑同时也带来了巨大的工作量. Defold 逐帧动画使用来自于 [图集](/manuals/atlas), 或者 [瓷砖图源](/manuals/tilesource) 里水平排列的图片.
+逐帧动画由一系列静态图像连续显示组成。这种技术非常类似于传统的赛璐珞动画(参见 http://en.wikipedia.org/wiki/Traditional_animation)。由于每一帧都可以单独操作,该技术提供了无限的可能性。然而,由于每一帧都存储在独特的图像中,内存占用可能会很高。动画的平滑度也取决于每秒显示的图像数量,但增加图像数量通常也会增加工作量。Defold 逐帧动画要么作为添加到[图集](/manuals/atlas)中的单独图像存储,要么作为[瓷砖图源](/manuals/tilesource)存储,所有帧以水平序列排列。
 
   ![Animation sheet](images/animation/animsheet.png){.inline}
   ![Run loop](images/animation/runloop.gif){.inline}
 
 ## 播放逐帧动画
 
-Sprite 和 GUI 方块节点可以用来播放逐帧动画而且可以在运行时进行控制.
+精灵和GUI方块节点可以播放逐帧动画,您可以在运行时对它们进行很好的控制。
 
-Sprites
-: 通过调用 [`sprite.play_flipbook()`](/ref/sprite/?q=play_flipbook#sprite.play_flipbook:url-id-[complete_function]-[play_properties]) 函数播放逐帧动画. 示例见下文.
+精灵
+: 要在运行时运行动画,您可以使用 [`sprite.play_flipbook()`](/ref/sprite/?q=play_flipbook#sprite.play_flipbook:url-id-[complete_function]-[play_properties]) 函数。请参见下面的示例。
 
-GUI 方块节点
-: 通过调用 [`gui.play_flipbook()`](/ref/gui/?q=play_flipbook#gui.play_flipbook:node-animation-[complete_function]-[play_properties]) 函数播放逐帧动画. 示例见下文.
+GUI方块节点
+: 要在运行时运行动画,您可以使用 [`gui.play_flipbook()`](/ref/gui/?q=play_flipbook#gui.play_flipbook:node-animation-[complete_function]-[play_properties]) 函数。请参见下面的示例。
 
 ::: sidenote
-ping-pong 播放模式把动画从第一帧播放到最后一帧再反向播放到 **第二帧** , 而不是第一帧. 这样便于连续播放的衔接.
+ping-pong 播放模式会将动画播放到最后一帧,然后反转顺序并播放回动画的**第二帧**,而不是回到第一帧。这样做是为了使动画链接更容易。
 :::
 
-### Sprite 示例
+### 精灵示例
 
-假设你的游戏有个 "dodge" 功能, 按下指定的键主角就进行闪避动作. 为此你建立了四组动画:
+假设您的游戏有一个"闪避"功能,允许玩家按下特定按钮进行闪避。您已经创建了四个动画来支持此功能的视觉反馈:
 
 "idle"
-: 主角待机的循环动画.
+: 玩家角色待机的循环动画。
 
 "dodge_idle"
-: 主角闪避动作的循环动画.
+: 玩家角色在闪避姿态下待机的循环动画。
 
 "start_dodge"
-: 主角从站立姿态到闪避动作的一次性动画.
+: 一次性过渡动画,将玩家角色从站立状态带到闪避状态。
 
 "stop_dodge"
-: 主角从闪避动作到站立姿态的一次性动画.
+: 一次性过渡动画,将玩家角色从闪避状态带回站立状态。
 
-逻辑代码如下:
+以下脚本提供了逻辑:
 
 ```lua
 
@@ -53,38 +53,38 @@ local function play_idle_animation(self)
 end
 
 function on_input(self, action_id, action)
-    -- "dodge" 是输入动作
+    -- "dodge" 是我们的输入动作
     if action_id == hash("dodge") then
         if action.pressed then
             sprite.play_flipbook("#sprite", hash("start_dodge"), play_idle_animation)
-            -- 记录闪避动作已开始
+            -- 记住我们正在闪避
             self.dodge = true
         elseif action.released then
             sprite.play_flipbook("#sprite", hash("stop_dodge"), play_idle_animation)
-            -- 记录闪避动作完成
+            -- 我们不再闪避了
             self.dodge = false
         end
     end
 end
 ```
 
-### GUI 方块节点示例
+### GUI方块节点示例
 
-给节点选择图片或者动画时, 实际上也同时指定了图片来源 (图集或者瓷砖图源) 以及默认动画. 节点图源是静态的, 但是当前播放的动画是可以在运行时指定的. 静态图片被视作单帧动画, 所以运行时切换图片相当于播放另一个动画:
+当为节点选择动画或图像时,实际上您是在一次性分配图像源(图集或瓷砖图源)和默认动画。图像源在节点中静态设置,但当前要播放的动画可以在运行时更改。静态图像被视为单帧动画,因此在运行时更改图像相当于为节点播放不同的逐帧动画:
 
 ```lua
 function init(self)
     local character_node = gui.get_node("character")
-    -- 新动画/图片播放时
-    -- 节点图源要存在默认动画.
-    gui.play_flipbook(character_node, "jump_left", flipbook_done)
+    -- 这要求节点在与我们正在播放的新动画/图像相同的图集或瓷砖图源中
+    -- 具有默认动画。
+    gui.play_flipbook(character_node, "jump_left")
 end
 ```
 
 
-## 播放完成回调函数
+## 完成回调函数
 
-动画函数 (`sprite.play_flipbook()` 和 `gui.play_flipbook()`) 可以在最后一个参数上传入Lua回调函数. 当动画播放完成时会调用这个函数. 对于循环动画和用 `go.cancel_animations()` 手动取消播放的动画, 不会调用回调函数. 动画播放完成的回调函数里可以发送消息或者继续播放其他动画. 例如:
+`sprite.play_flipbook()` 和 `gui.play_flipbook()` 函数支持一个可选的 Lua 回调函数作为最后一个参数。当动画播放到结束时,将调用此函数。对于循环动画,永远不会调用该函数。回调函数可用于在动画完成时触发事件或将多个动画链接在一起。示例:
 
 ```lua
 local function flipbook_done(self)

+ 154 - 79
docs/zh/manuals/font.md

@@ -1,164 +1,239 @@
 ---
-title: Defold 字体教程
-brief: 本教程介绍了 Defold 如何处理和在游戏中使用字体.
+title: Defold 处理字体手册
+brief: 本手册描述了 Defold 如何处理字体以及如何在游戏中将字体显示在屏幕上。
 ---
 
 # 字体文件
 
-字体用于在 Label 组件和 GUI 文本节点上显示文字. Defold 支持下列字体类型:
+字体用于在标签组件和GUI文本节点上渲染文本。Defold支持多种字体文件格式:
 
 - TrueType
 - OpenType
 - BMFont
 
-字体加入到 Defold 后会被自动转换成可以渲染的纹理. 文字渲染有两种技术, 各自都有优缺点:
+添加到项目中的字体会自动转换为Defold可以渲染的纹理格式。有两种字体渲染技术可用,每种都有其特定的优点和缺点:
 
-- Bitmap
-- Distance field
+- 位图
+- 距离场
 
 ## 创建字体
 
-在 Defold 中, 可以通过菜单栏 <kbd>File ▸ New...</kbd> 然后旋转 <kbd>Font</kbd> 来新建字体. 或者在 *Assets* 浏览器中 <kbd>右键点击</kbd> , 选择 <kbd>New... ▸ Font</kbd>.
+要在Defold中创建字体,请从菜单中选择<kbd>文件 ▸ 新建...</kbd>,然后选择<kbd>字体</kbd>。您也可以在*资源*浏览器中<kbd>右键点击</kbd>一个位置,然后选择<kbd>新建... ▸ 字体</kbd>。
 
 ![New font name](images/font/new_font_name.png)
 
-填写字体名并点击 <kbd>Ok</kbd>. 字体编辑器会自动打开.
+给新字体文件命名并点击<kbd>确定</kbd>。新字体文件现在在编辑器中打开。
 
 ![New font](images/font/new_font.png)
 
-把字体文件拖放到 *Assets* 浏览器中.
+将您想要使用的字体拖放到*资源*浏览器中,并将其放在合适的位置。
 
-设置字体的 *Font* 属性为所需字体文件然后设置其他所需属性.
+将*字体*属性设置为您想要使用的字体文件,并根据需要设置字体属性。
 
 ## 属性
 
-*Font*
-: TTF, OTF 或者 *.fnt* 文件用以生成文字数据.
+*字体*
+: 用于生成字体数据的TTF、OTF或*`.fnt`*文件。
 
-*Material*
-: 渲染文字所用材质. distance field 和 BMFonts 不同格式所需材质不同 (详见下文).
+*材质*
+: 渲染此字体时使用的材质。确保为距离场和BMFonts更改此材质(详见下文)。
 
-*Output Format*
-: 字体生成的纹理格式.
+*输出格式*
+: 生成的字体数据类型。
 
-  - `TYPE_BITMAP` 把 OTF 或 TTF 的文字转换成为可以渲染的位图图表. 颜色通道决定了文字, 描边和阴影的颜色. 对于 *.fnt* 文件, 直接使用里面的位图纹理.
-  - `TYPE_DISTANCE_FIELD` 也是把文字转换成纹理但是要记录每个像素到文字边缘的距离. 详情见下文.
+  - `TYPE_BITMAP` 将导入的OTF或TTF文件转换为字体表纹理,其中位图数据用于渲染文本节点。颜色通道用于编码字体形状、轮廓和阴影。对于*`.fnt`*文件,直接使用源纹理位图。
+  - `TYPE_DISTANCE_FIELD` 导入的字体被转换为字体表纹理,其中像素数据表示的不是屏幕像素,而是到字体边缘的距离。详见下文。
 
-*Render Mode*
-: 文字渲染模式.
+*渲染模式*
+: 用于字形渲染的渲染模式。
 
-  - `MODE_SINGLE_LAYER` 为每个字母渲染一个四边形.
-  - `MODE_MULTI_LAYER` 为文字, 描边和阴影分别渲染一个四边形. 从后往前渲染, 这样能够避免描边太大对前一个字母造成的遮挡. 这种渲染模式可以依照字体资源阴影 X/Y 属性, 准确渲染阴影位置.
+  - `MODE_SINGLE_LAYER` 为每个字符生成一个四边形。
+  - `MODE_MULTI_LAYER` 分别为字形形状、轮廓和阴影生成单独的四边形。层按从后到前的顺序渲染,这可以防止字符在轮廓比字形之间的距离更宽时遮挡先前渲染的字符。此渲染模式还支持通过字体资源中的阴影X/Y属性指定的正确阴影偏移。
 
-*Size*
-: 文字大小单位像素.
+*大小*
+: 字形的目标大小,以像素为单位。
 
-*Antialias*
-: 生成位图时是否抗锯齿. 如果想要像素对齐效果则设置为0.
+*抗锯齿*
+: 字体在烘焙到目标位图时是否应该抗锯齿。如果您想要像素完美的字体渲染,请设置为0。
 
-*Alpha*
-: 文字透明度. 范围 0.0--1.0,  其中 0.0 表示透明 1.0 表示不透明.
+*透明度*
+: 字形的透明度。0.0--1.0,其中0.0表示透明,1.0表示不透明。
 
-*Outline Alpha*
-: 描边透明度. 范围 0.0--1.0.
+*轮廓透明度*
+: 生成的轮廓的透明度。0.0--1.0。
 
-*Outline Width*
-: 描边宽度单位像素. 0 代表无描边.
+*轮廓宽度*
+: 生成的轮廓的宽度,以像素为单位。设置为0表示无轮廓。
 
-*Shadow Alpha*
-: 阴影透明度. 范围 0.0--1.0.
+*阴影透明度*
+: 生成的阴影的透明度。0.0--1.0。
 
 ::: sidenote
-内置文字材质着色器单层多层渲染模式下都支持文字阴影. 如果不需要分层渲染或者阴影渲染, 最好使用 builtins/font-singlelayer.fp 之类的简单版着色器.
+阴影支持由内置字体材质着色器启用,并处理单层和多层渲染模式。如果您不需要分层字体渲染或阴影支持,最好使用更简单的着色器,如*`builtins/font-singlelayer.fp`*。
 :::
 
-*Shadow Blur*
-: 对于位图字体, 此设置代表文字阴影叠加计算次数. 对于 distance field 字体, 此设置代表文字阴影宽度像素数.
+*阴影模糊*
+: 对于位图字体,此设置表示将小模糊核应用于每个字体字形的次数。对于距离场字体,此设置等于模糊的实际像素宽度。
 
-*Shadow X/Y*
-: 阴影水平和垂直偏移. 只在渲染模式为 `MODE_MULTI_LAYER` 时有效.
+*阴影X/Y*
+: 生成的阴影的水平和垂直偏移,以像素为单位。此设置仅在渲染模式设置为`MODE_MULTI_LAYER`时才会影响字形阴影。
 
-*Extra Characters*
-: 默认字体包含 ASCII 字母表字符 (字符码 32-126). 如果需要更多字符, 需要手动在这里输入.
+*字符*
+: 字体中包含哪些字符。默认情况下,此字段包含ASCII可打印字符(字符代码32-126)。您可以从此字段添加或删除字符,以在字体中包含更多或更少的字符。
 
 ::: sidenote
-ASCII 字母表字符包含:
+ASCII可打印字符是:
 space ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ \` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
 :::
 
-*All Chars*
-: 把字体可以显示的所有字符都打包进游戏中来.
+*所有字符*
+: 如果您选中此属性,源文件中所有可用的字形都将包含在输出中。
 
-*Cache Width/Height*
-: 文字缓存大小限制. 渲染文字时, 先从缓存中查找字符. 如果没找到的话, 实际渲染前会先添加进缓存中. 如果缓存太小, 会造成溢出错误 (`ERROR:RENDER: Out of available cache cells! Consider increasing cache_width or cache_height for the font.`).
+*缓存宽度/高度*
+: 限制字形缓存位图的大小。当引擎渲染文本时,它从缓存位图中查找字形。如果它不存在于缓存位图中,它将在渲染之前添加到缓存中。如果缓存位图太小而无法包含引擎被要求渲染的所有字形,则会发出错误信号(`ERROR:RENDER: Out of available cache cells! Consider increasing cache_width or cache_height for the font.`)。
 
-  设置为0代表自动管理缓存大小.
+  如果设置为0,缓存大小将自动设置,最大增长到2048x4096。
 
-## Distance field 字体
+## 距离场字体
 
-Distance field 字体不存储位图像素而是存储像素到纹理边缘的距离. 这样在渲染文字时, 专用的着色器会通过距离数据渲染文字. Distance field 字体往往比位图数据量大, 但是对于尺寸控制更为灵活.
+距离场字体在纹理中存储到字形边缘的距离,而不是位图数据。当引擎渲染字体时,需要特殊的着色器来解释距离数据并使用它来绘制字形。距离场字体比位图字体更消耗资源,但允许更大的尺寸灵活性。
 
 ![Distance field font](images/font/df_font.png)
 
-这种字体要确保 *Material* 属性设置为 *builtins/fonts/font-df.material* (或其他 distance field 数据专用材质) --- 否则的话渲染会不正确.
+确保在创建字体时将字体的*材质*属性更改为*`builtins/fonts/font-df.material`*(或任何其他可以处理距离场数据的材质)---否则字体在渲染到屏幕时将不会使用正确的着色器。
 
-## 位图 BMFont
+## 位图BMFonts
 
-Defold 还支持 "BMFont" 格式字体. 这种字体的字符都是由位图组成的. 而且, *.fnt* 文件保存了字符位置大小间距等信息. (注意 Defold 不支持 Phaser 等其他引擎用的 XML 格式的 *.fnt* 文件格式)
+除了生成的位图外,Defold还支持预烘焙的位图"BMFont"格式字体。这些字体由包含所有字形的PNG字体表组成。此外,*`.fnt`*文件包含有关在表上可以找到每个字形的位置以及大小和字距调整信息的信息。(请注意,Defold不支持Phaser和其他一些工具使用的*`.fnt`*格式的XML版本)
 
-相比其他格式字体 BMFont 并无性能优势, 但是因为基于图片, 颜色阴影效果可以随意添加.
+这些类型的字体与从TrueType或OpenType字体文件生成的位图字体相比没有性能改进,但可以在图像中直接包含任意图形、颜色和阴影。
 
-把 *.fnt* 和 *.png* 文件加入 Defold 项目中. 这些文件要保存在同一文件夹中. 新建字体然后设置 *font* 属性为 *.fnt* 文件. 确保 *output_format* 属性为 `TYPE_BITMAP`. Defold 会直接使用 PNG 文件而不用再生成位图.
+将生成的*`.fnt`*和*`.png`*文件添加到您的Defold项目中。这些文件应该位于同一文件夹中。创建一个新的字体文件,并将*字体*属性设置为*`.fnt`*文件。确保*output_format*设置为`TYPE_BITMAP`。Defold不会生成位图,而是使用PNG中提供的位图。
 
 ::: sidenote
-要使用 BMFont, 需要使用工具软件来生成所需文件. 下面列举一些这样的工具:
+要创建BMFont,您需要使用能够生成适当文件的工具。存在几个选项:
 
-* [Bitmap Font Generator](http://www.angelcode.com/products/bmfont/), AngelCode 开发的 Windows 版软件.
-* [Shoebox](http://renderhjs.net/shoebox/), 免费的基于 Adobe Air 的可运行与 Windows 和 macOS 上的工具.
-* [Hiero](https://github.com/libgdx/libgdx/wiki/Hiero), 基于 Java 的开源软件.
-* [Glyph Designer](https://71squared.com/glyphdesigner), 71 Squared 开发的付费 macOS 应用.
-* [bmGlyph](https://www.bmglyph.com), Sovapps 开发的付费 macOS 应用.
+* [Bitmap Font Generator](http://www.angelcode.com/products/bmfont/),AngelCode提供的仅限Windows的工具。
+* [Shoebox](http://renderhjs.net/shoebox/),免费的基于Adobe Air的应用程序,适用于Windows和macOS。
+* [Hiero](https://libgdx.com/wiki/tools/hiero),基于Java的开源工具。
+* [Glyph Designer](https://71squared.com/glyphdesigner),71 Squared的商业macOS工具。
+* [bmGlyph](https://www.bmglyph.com),Sovapps的商业macOS工具。
 :::
 
 ![BMfont](images/font/bm_font.png)
 
-要使用位图字体, 别忘了将其材质设置为 *builtins/fonts/font-fnt.material*.
+为了使字体正确渲染,不要忘记在创建字体时将材质属性设置为*`builtins/fonts/font-fnt.material`*。
 
-## 举例与最佳实践
+## 伪影和最佳实践
 
-一般来说, 不用缩放的话位图字体最好. 因为渲染速度快.
+通常,当字体在没有缩放的情况下渲染时,位图字体是最好的。它们比距离场字体渲染到屏幕的速度更快。
 
-Distance field 字体适用于需要放大文字的地方. 相对的位图字体放大需要填充更多像素会导致模糊的效果. 下例是字体尺寸 48 像素, 放大 4 倍.
+距离场字体对放大效果非常好。另一方面,位图字体只是像素化图像,随着字体缩放,大小会增加,像素会增长,导致块状伪影。以下是字体大小48像素,放大4倍的示例:
 
 ![Fonts scaled up](images/font/scale_up.png)
 
-位图字体缩小的时候没有什么问题,  GPU 还会帮助抗锯齿. 位图字体颜色保持得比 distance field 字体好. 下例是字体尺寸 48 像素, 缩小到 1/5:
+缩小时,位图纹理可以被GPU很好地有效地缩小和抗锯齿。位图字体比距离场字体更好地保持其颜色。以下是相同示例字体在48像素大小下的放大视图,缩小到原始大小的1/5:
 
 ![Fonts scaled down](images/font/scale_down.png)
 
-Distance field 需要足够多的数据信息才能较好地显示出文字边角部位. 下例是字体尺寸 18  像素, 放大 10 倍. 可以看到边角信息严重不足:
+距离场字体需要渲染到足够大的目标大小,以保存能够表达字体字形曲线的距离信息。这是与上面相同的字体,但在18像素大小下放大10倍。很明显,这太小而无法编码这种字体的形状:
 
 ![Distance field artifacts](images/font/df_artifacts.png)
 
-如果不需要文字阴影和描边, 要将这两种属性设置为0. 否则, 阴影和描边仍然会生成, 造成不必要的内存浪费.
+如果您不需要阴影或轮廓支持,请将它们各自的alpha值设置为零。否则,阴影和轮廓数据仍将生成,占用不必要的内存。
 
-## 字缓存
-Defold 中字体在运行时包含两部分内容, 纹理和字体数据.
+## 字缓存
+Defold中的字体资源在运行时会产生两个东西,一个纹理和字体数据。
 
-* 字体数据是一个字符表, 包含了字符对应的纹理及其字间距信息.
-* 纹理在引擎内部称为 "glyph cache texture" 用以渲染显示文字.
+* 字体数据由字形条目列表组成,每个条目包含一些基本的字距调整信息和该字形的位图数据。
+* 纹理在内部称为"字形缓存纹理",它将在为特定字体渲染文本时使用。
 
-运行时渲染文字的时候, 引擎会首先在文字缓存里查找需要的字符. 找不到的话再往缓存里添加这个字符.
+在运行时渲染文本时,引擎将首先循环遍历要渲染的字形,以检查纹理缓存中有哪些字形可用。字形纹理缓存中缺少的每个字形都将触发从字体数据中存储的位图数据进行纹理上传。
 
-每个字符纹理基于字体基准线排列在缓存中, 以便着色器计算字符纹理本地坐标. 这意味着可以动态实现渐变或者或者纹理混合之类的效果. 引擎通过一个叫做 `texture_size_recip` 的常量将缓存信息暴露给着色器, 这个四元数包含如下信息:
+每个字形根据字体基线在内部放置在缓存中,这使得能够在着色器中计算字形在其相应缓存单元内的局部纹理坐标。这意味着您可以动态实现某些文本效果,如渐变或纹理叠加。引擎通过一个名为`texture_size_recip`的特殊着色器常量将缓存的度量标准暴露给着色器,该常量在向量组件中包含以下信息:
 
-* `texture_size_recip.x` 是缓存宽度倒数
-* `texture_size_recip.y` 是缓存高度倒数
-* `texture_size_recip.z` 是单位宽度与缓存宽度的比
-* `texture_size_recip.w` 是单位高度与缓存高度的比
+* `texture_size_recip.x` 是缓存宽度倒数
+* `texture_size_recip.y` 是缓存高度倒数
+* `texture_size_recip.z` 是缓存单元宽度与缓存宽度的比率
+* `texture_size_recip.w` 是缓存单元高度与缓存高度的比率
 
-例如 - 实现一个渐变渲染的片元着色器, 可以这么写:
+例如 - 要在着色器片段中生成渐变,只需编写:
 
 `float horizontal_gradient = fract(var_texcoord0.y / texture_size_recip.w);`
 
-更多详情请见 [着色器教程](/manuals/shader).
+有关着色器uniform的更多信息,请参阅[着色器手册](/manuals/shader)。
+
+## 运行时生成
+
+可以对SDF类型字体使用运行时生成,当使用TrueType (.ttf)字体时。
+这种方法可以大大减少Defold游戏的下载大小和运行时内存消耗。
+小小的缺点是为每个在运行时生成的字形会有非常小的延迟。
+
+通过设置`font.runtime_generation`在game.project中启用此功能。
+
+::: sidenote
+此功能目前是实验性的,但打算在未来用作默认工作流程。
+:::
+
+::: important
+此设置影响项目中的所有.ttf字体。
+:::
+
+### 预热字形缓存
+
+为了使运行时字体更易于使用,它们支持预热字形缓存。
+这意味着字体将生成字体中列出的*字符*中的字形。
+
+::: sidenote
+如果选择了`所有字符`,将不会有预热,因为这违背了不必同时生成所有字形的目的。
+:::
+
+### 字体脚本
+
+对于运行时字体,可以添加或删除子字体。
+当大字体已被拆分为多个文件用于不同字符集时(例如CJK),这很有用。
+
+::: important
+添加子字体不会自动加载或渲染所有字形。
+:::
+
+```lua
+-- 将范围A-Z添加到.fontc
+local font_hash = hash("/assets/fonts/roboto.fontc")
+local ttf_hash = hash("/assets/fonts/Roboto/Roboto-Bold.ttf")
+local codepoint_min = 0x00000041 -- A
+local codepoint_max = 0x0000005A -- Z
+font.add_source(font_hash, ttf_hash, codepoint_min, codepoint_max)
+```
+
+```lua
+-- 删除关联的ttf资源
+local font_hash = hash("/assets/fonts/roboto.fontc")
+local ttf_hash = hash("/assets/fonts/Roboto/Roboto-Bold.ttf")
+font.remove_source(font_hash, ttf_hash)
+```
+
+要将字形加载到字体中,您需要调用`font.add_glyphs()`。
+这是一个异步操作,一旦完成,就可以安全地继续显示包含字形的任何消息。
+
+```lua
+local function add_glyph_callback(self, id, result, errmsg)
+  if not result then
+    print("Request " .. id .." finished with error:", errmsg)
+  else
+    msg.post(some_url, "show_dialog")
+  end
+end
+
+-- 将字形加载到字体中
+local font_hash = hash("/assets/fonts/roboto.fontc")
+local glyphs = "Some text to be shown!" -- 为了最佳性能,使其成为唯一字形列表
+local request_id = font.add_glyphs(font_hash, ttf_hash, add_glyph_callback)
+```
+
+而且,当不再需要字符时,您可以丢弃该内存:
+```lua
+-- 删除关联的ttf资源
+local font_hash = hash("/assets/fonts/roboto.fontc")
+font.remove_glyphs(font_hash, "All the characters in the set")
+```

+ 50 - 50
docs/zh/manuals/getting-help.md

@@ -1,99 +1,99 @@
 ---
-title: 如何获帮助
-brief: 本教程介绍了使用 Defold 遇到麻烦时该如何寻求帮助.
+title: 如何获帮助
+brief: 本手册介绍了使用Defold遇到问题时如何获取帮助.
 ---
 
-# 获帮助
+# 获帮助
 
-如果你使用 Defold 时遇到了麻烦请联系我们以便解决或绕过问题! 有许多途径可以讨论和汇报问题. 依个人喜好选择:
+如果您在使用Defold时遇到问题,我们希望听到您的反馈,以便我们能够解决问题和/或帮助您解决难题!有多种方式可以讨论和报告问题。请选择最适合您的方式:
 
-## 在论坛里提交问题
+## 在论坛上报告问题
 
-在我们的 [论坛](https://forum.defold.com) 上提交问题是一个好方法. 依据你的问题的类型可以在 [Questions](https://forum.defold.com/c/questions) 或者 [Bugs](https://forum.defold.com/c/bugs) 类目下发帖. 提交问题的时候请尽附加可能多的信息. 记得发问之前在论坛 [搜索](https://forum.defold.com/search) 一下相关内容, 也许论坛上已经存在你的问题的解决方案了.
+在我们的[论坛](https://forum.defold.com)上发布问题是讨论和获取帮助的好方法。根据您遇到的问题类型,在[问题](https://forum.defold.com/c/questions)或[错误](https://forum.defold.com/c/bugs)类别中发帖。记得在提问之前先[搜索](https://forum.defold.com/search)您的问题/问题,因为可能已经有解决方案了。
 
-有多个问题, 就发多张帖子. 不要在一个帖子说发布不相干的问题.
+如果您有多个问题,请创建多个帖子。不要在同一帖子中提出不相关的问题。
 
-### 提供信息
-提问时请提供以下信息:
+### 必需信息
+除非您提供所需信息,否则我们将无法提供支持:
 
-**题**
-简明扼要的标题. 像 "如何让游戏对象延面对方向前进?" 或者 "如何实现 Sprite 渐隐效果?" 就比较好. 像 "我需要 Defold 的帮助!" 或者 "我的游戏不动了!" 就不怎么好.
+**题**
+确保使用简短且描述性的标题。好的标题应该是"如何让游戏对象沿其旋转方向移动?"或"如何让精灵淡出?"。不好的标题是"我需要一些使用Defold的帮助!"或"我的游戏不工作了!"。
 
-* **问题的描述 (必须)**
-问题的简短描述.
+**描述错误(必需)**
+对错误是什么的清晰简洁描述。
 
-* **问题的复现 (必须)**
-复现问题的步骤:
-  1. 进入 '...'
-  2. 点击 '....'
-  3. 滑动到 '....'
-  4. 错误出现
+**复现步骤(必需)**
+复现行为的步骤:
+1. 转到'...'
+2. 点击'....'
+3. 滚动到'....'
+4. 看到错误
 
-* **期望行为 (必须)**
-期望实现的行为的简短描述.
+**预期行为(必需)**
+对您期望发生的事情的清晰简洁描述。
 
-* **Defold 版本 (必须)**
-  - 版本 [例如 1.2.155].
+**Defold版本(必需):**
+  - 版本 [例如 1.2.155]
 
-* **操作平台 (必须)**
-  - 平台: [比如 iOS, Android, Windows, macOS, Linux, HTML5]
-  - 系统: [比如 iOS8.1, Windows 10, High Sierra]
-  - 设备: [比如 iPhone6]
+**平台(必需):**
+ - 平台:[例如 iOS, Android, Windows, macOS, Linux, HTML5]
+ - 操作系统:[例如 iOS8.1, Windows 10, High Sierra]
+ - 设备:[例如 iPhone6]
 
-* **问题复现小项目 (可选)**
-请附加一个可以再现问题的最小项目包. 这可以对别人研究修复问题提供极大帮助.
+**最小复现案例项目(可选):**
+请附加一个可以复现错误的最小项目。这将极大地帮助尝试调查和修复错误的人。
 
-* **日志 (可选)**
-请附带相关 引擎, 编辑器或者云编译服务器的日志. 日志保存在哪请参考 [这里](#日志文件).
+**日志(可选):**
+请提供来自引擎、编辑器或构建服务器的相关日志。了解日志存储位置[请点击这里](#日志文件)。
 
-* **绕过方法 (可选)**
-如果你找到了可以绕过问题的方案, 也请附加上.
+**变通方法(可选):**
+如果有变通方法,请在此处描述。
 
-* **屏幕截图 (可选)**
-如果可以, 附加屏幕截图有助于描述出现的问题.
+**屏幕截图(可选):**
+如果适用,添加屏幕截图以帮助解释您的问题。
 
-* **其他 (可选)**
-还可以加入其他问题相关上下文信息.
+**附加上下文(可选):**
+在此处添加有关问题的任何其他上下文。
 
 
-### 提交代码
-提交代码最好用文本, 别用截图. 文本代码便于查找, 分析错误并提出修改意见. 代码使用 \`\`\` 符号包裹或者行首加4个空格.
+### 分享代码
+当您分享代码时,建议以文本形式分享代码,而不是截图。以文本形式分享代码便于搜索、突出错误以及提出和进行修改。通过用三个\`\`\`包裹代码或用4个空格缩进来分享代码。
 
-举例:
+示例:
 
 \`\`\`
 print("Hello code!")
 \`\`\`
 
-效果:
+结果:
 
 ```
 print("Hello code!")
 ```
 
 
-## 从编辑器里汇报问题
+## 从编辑器报问题
 
-编辑器提供了一个汇报错误的方便的方法. 选择 <kbd>Help->Report Issue</kbd> 菜单项来汇报错误.
+编辑器提供了一种方便的方式来报告问题。从编辑器中选择<kbd>帮助->报告问题</kbd>菜单选项来报告问题。
 
 ![](images/getting_help/report_issue.png)
 
-这样就会在 GitHub 上生成一个错误报告. 请提供 [日志文件](#log-files), 操作系统, 重现方法, 临时绕过错误的方法等信息.
+选择此菜单选项将带您到GitHub上的问题跟踪器。提供[日志文件](#日志文件)、有关您操作系统的信息、复现问题的步骤、可能的变通方法等。
 
 ::: sidenote
-报告之前确保你已经拥有 GitHub 账户.
+您需要GitHub帐户才能以这种方式提交错误报告。
 :::
 
 
-## 在 Discord 上讨论问题
+## 在Discord上讨论问题
 
-如果在使用 Defold 时遇到困难你可以尝试在 [Discord](https://www.defold.com/discord/) 上提出问题. 虽然我们推荐复杂问题应该在论坛上深入讨论. 而且注意 Discord 上不支持错误报告.
+如果您在使用Defold时遇到问题,可以尝试在[Discord](https://www.defold.com/discord/)上提问。但是,我们建议将复杂问题和深入讨论发布在论坛上。另请注意,我们不接受通过Discord提交的错误报告。
 
 
 # 日志文件
 
-游戏引擎, 编辑器和云编译服务器都有日志系统, 这对于定位调试错误十分有利. 报告错误时请务必带上日志文件.
+引擎、编辑器和构建服务器生成日志信息,这在寻求帮助和调试问题时非常有价值。报告问题时始终提供日志文件:
 
 * [引擎日志](/manuals/debugging-game-and-system-logs)
-* [Editor logs](/manuals/editor#editor-logs)
-* [编译服务器日志](/manuals/extensions#build-server-logs)
+* [编辑器日志](/manuals/editor#editor-logs)
+* [构建服务器日志](/manuals/extensions#build-server-logs)

+ 45 - 45
docs/zh/manuals/glossary.md

@@ -1,172 +1,172 @@
 ---
-title: Defold 术语
-brief: 本教程列举了使用 Defold 工作中会遇到的各种专用词汇及其简短的解释.
+title: Defold glossary
+brief: 本手册列出了在Defold工作中遇到的所有内容及其简要描述。
 ---
 
-# Defold 术语
+# Defold glossary
 
-该名词表简要介绍了您在 Defold 中遇到的各种术语.在大多数情况下,您会找到更多相关详细文档的链接.
+本词汇表简要介绍了您在Defold中遇到的所有内容。在大多数情况下,您会找到更多深入文档的链接。
 
 ## Animation set
 
-![Animation set](images/icons/animationset.png){.left} 包含一组动画的 .dae 文件或其他用以读取动画的 .animationset 文件的动画集资源. 如果多个模型文件共享一组动画的话, 可以方便地把 .animationset 文件设置给其他模型. 详情请见 [模型动画教程](/manuals/model-animation/).
+![Animation set](images/icons/animationset.png){.left} 动画集资源包含一组.dae文件或其他.animationset文件,从中读取动画。将一个.animationset文件添加到另一个文件中很方便,如果您在多个模型之间共享部分动画集。有关详细信息,请参阅[模型动画手册](/manuals/model-animation/)。
 
 ## Atlas
 
-![Atlas](images/icons/atlas.png){.left} 图集是为了增加性能减少显存消耗而把许多单张图片合并而成的一张大图. 其中可以包括静态图和逐帧动画序列图. 图集可以被多种组件所共享. 详情请见 [图集教程](/manuals/atlas).
+![Atlas](images/icons/atlas.png){.left} 图集是一组单独的图像,出于性能和内存原因被编译成一张较大的图。它们可以包含静态图像或翻页动画图像序列。图集被各种组件使用,以共享图形资源。有关更多信息,请参阅[图集文档](/manuals/atlas)。
 
 ## Builtins
 
-![Builtins](images/icons/builtins.png){.left} 项目内置文件夹是一个包含必要默认资源的只读文件夹. 里面由默认着色器, 默认渲染脚本, 默认材质等等. 如果需要自定义这些默认资源, 只要把它们拷贝到你的项目目录中去, 然后自由修改即可.
+![Builtins](images/icons/builtins.png){.left} 内置项目文件夹是一个只读文件夹,包含有用的默认资源。在这里您可以找到默认渲染器、渲染脚本、材质等。如果您需要对这些资源进行自定义修改,只需将它们复制到您的项目中并按照您的需要进行编辑即可。
 
 ## Camera
 
-![Camera](images/icons/camera.png){.left} 摄像机组件决定了游戏世界哪些可见哪些不可见以及视口的投射类型. 一个常见用法是把摄像机放到主角游戏对象上, 或者放到一个跟随主角的包含一些平滑移动算法的游戏对象上. 详情请见 [摄像机教程](/manuals/camera).
+![Camera](images/icons/camera.png){.left} 摄像机组件有助于决定游戏世界的哪些部分应该可见以及应该如何投影。一个常见的用例是将摄像机附加到玩家游戏对象,或者拥有一个带有摄像机的独立游戏对象,通过某种平滑算法跟随玩家移动。有关更多信息,请参阅[摄像机文档](/manuals/camera)。
 
 ## Collision object
 
-![Collision object](images/icons/collision-object.png){.left} 碰撞对象组件为游戏对象增添了物理属性 (比如形状, 重量, 摩擦力和弹性). 这些属性决定了碰撞对象之间的碰撞效果. 常见碰撞对象有运动学, 动态和触发器三种类型. 运动学碰撞对象必须手动设置它的物理属性值, 动态碰撞对象由物理引擎基于牛顿物理定律计算它的物理属性. 触发器是一个形状, 能够检测其他物体进入或者离开. 详情请见 [物理教程](/manuals/physics).
+![Collision object](images/icons/collision-object.png){.left} 碰撞对象是扩展游戏对象物理属性(如空间形状、重量、摩擦力和恢复力)的组件。这些属性决定了碰撞对象应该如何与其他碰撞对象碰撞。最常见的碰撞对象类型是运动学对象、动态对象和触发器。运动学对象提供您必须手动响应的详细碰撞信息,动态对象由物理引擎自动模拟以遵守牛顿物理学定律。触发器是检测其他形状是否已进入或退出触发器的简单形状。有关其工作原理的详细信息,请参阅[物理文档](/manuals/physics)。
 
 ## Component
 
-组件赋予游戏对象以独特的功能和表现, 如图像, 动画, 逻辑和声音等等. 组件依附于游戏对象之上. Defold 中预置了许多组件. 详情请见 [游戏组成教程](/manuals/building-blocks).
+组件用于赋予游戏对象特定的表达和/或功能,如图形、动画、编码行为和声音。它们没有自己的生命,必须包含在游戏对象内。Defold中有多种类型的组件可用。有关组件的描述,请参阅[构建块手册](/manuals/building-blocks)。
 
 ## Collection
 
-![Collection](images/icons/collection.png){.left} 集合是 Defold 的模板机制, 相当于其他引擎的 "prefabs" 即可重用游戏对象的树形结构. 集合可以包含游戏对象和其他集合. 集合结构作为文件资源储存, 既可以在编辑器里手动创建实例, 又可以在运行时动态创建实例. 详情请见 [游戏组成教程](/manuals/building-blocks).
+![Collection](images/icons/collection.png){.left} 集合是Defold创建模板的机制,或在其他引擎中称为"prefabs",其中游戏对象的层次结构可以被重用。集合是包含游戏对象和其他集合的树结构。集合始终存储在文件中,并通过在编辑器中手动放置或通过生成动态地引入游戏。有关集合的描述,请参阅[构建块手册](/manuals/building-blocks)。
 
 ## Collection factory
 
-![Collection factory](images/icons/collection-factory.png){.left} 集合工厂是集合实例制造者, 可以在运行时动态创建集合实例. 详情请见 [集合工程教程](/manuals/collection-factory).
+![Collection factory](images/icons/collection-factory.png){.left} 集合工厂组件用于将游戏对象层次结构动态生成到运行中的游戏中。有关详细信息,请参阅[集合工厂手册](/manuals/collection-factory)。
 
 ## Collection proxy
 
-![Collection proxy](images/icons/collection-proxy.png){.left} 集合代理可以在游戏进行时加载并激活集合. 常常被用来切换游戏关卡. 详情请见 [集合代理教程](/manuals/collection-proxy).
+![Collection](images/icons/collection.png){.left} 集合代理用于在应用程序或游戏运行时动态加载和启用集合。集合代理最常见的用例是在游戏进行时加载关卡。有关详细信息,请参阅[集合代理文档](/manuals/collection-proxy)。
 
 ## Cubemap
 
-![Cubemap](images/icons/cubemap.png){.left} Cubemap 是由 6 张纹理组成的一种特殊纹理, 可以完整覆盖在立方体上. 常常被用于天空盒, 也被用作各种反射纹理和光照纹理等.
+![Cubemap](images/icons/cubemap.png){.left} 立方体贴图是一种特殊类型的纹理,由6种不同的纹理组成,这些纹理映射到立方体的侧面。这对于渲染天空盒和各种反射和光照贴图很有用。
 
 ## Debugging
 
-调试是程序除错的方法. Defold 给用户提供了方便的内置调试器. 详情请见 [调试教程](/manuals/debugging).
+在某个时刻,您的游戏会以意外的方式运行,您需要找出问题所在。学习如何调试是一门艺术,幸运的是,Defold附带了一个内置调试器来帮助您。有关更多信息,请参阅[调试手册](/manuals/debugging)。
 
 ## Display profiles
 
-![Display profiles](images/icons/display-profiles.png){.left} 显示档案是一种文件资源用来确定在指定屏幕方向, 宽高比, 或设备型号匹配到显示设备时使用哪种用户界面布局方案. 它能帮助用户适配各种设备屏幕. 详情请见 [界面布局教程](/manuals/gui-layouts).
+![Display profiles](images/icons/display-profiles.png){.left} 显示配置文件资源文件用于指定GUI布局依赖于方向、纵横比或设备型号。它有助于使您的UI适应任何类型的设备。在[布局手册](/manuals/gui-layouts)中阅读更多内容。
 
 ## Factory
 
-![Factory](images/icons/factory.png){.left} 工厂是游戏对象实例制造者, 用来在运行时创建游戏对象实例. 例如, 发射子弹游戏对象, 就可以可以使用工厂 (其内部含有对象池功能). 详情请见 [工厂教程](/manuals/factory).
+![Factory](images/icons/factory.png){.left} 在某些情况下,您无法手动将所有需要的游戏对象放置在集合中,您必须动态地、即时地创建游戏对象。例如,玩家可能会发射子弹,每次按下扳机时都应该动态生成并发射子弹。要动态创建游戏对象(来自预分配的对象池),您可以使用工厂组件。有关详细信息,请参阅[工厂手册](/manuals/factory)。
 
 ## Font
 
-![Font file](images/icons/font.png){.left} 字体资源源自 TrueType 或 OpenType 字体文件. 可以设置渲染文字的大小和外观 (描边和阴影). GUI 和 Label 组件要用到字体资源. 详情请见 [字体教程](/manuals/font/).
+![Font file](images/icons/font.png){.left} 字体资源是从TrueType或OpenType字体文件构建的。字体指定了渲染字体的大小以及渲染字体应具有的装饰类型(轮廓和阴影)。字体由GUI和标签组件使用。有关详细信息,请参阅[字体手册](/manuals/font/)。
 
 ## Fragment shader
 
-![Fragment shader](images/icons/fragment-shader.png){.left} 一种运行于显卡上的用于处理多边形上每个像素 (片元) 的渲染程序. 由此程序决定每个像素的颜色. 最终像素颜色值通过计算和纹理查找 (一个或多个) 的方法得出. 详情请见 [着色器教程](/manuals/shader).
+![Fragment shader](images/icons/fragment-shader.png){.left} 这是一个在图形处理器上运行的程序,用于多边形绘制到屏幕时每个像素(片段)的处理。片段着色器的目的是决定每个结果片段的颜色。这是通过计算、纹理查找(一个或多个)或查找和计算的组合来完成的。有关更多信息,请参阅[着色器手册](/manuals/shader)。
 
 ## Gamepads
 
-![Gamepads](images/icons/gamepad.png){.left} 手柄资源文件用来定义游戏手柄设备在指定平台上的输入对游戏的意义. 详情请见 [输入教程](/manuals/input).
+![Gamepads](images/icons/gamepad.png){.left} 手柄资源文件定义了特定手柄设备输入如何映射到特定平台上的手柄输入触发器。有关详细信息,请参阅[输入手册](/manuals/input)。
 
 ## Game object
 
-![Game object](images/icons/game-object.png){.left} 游戏对象在游戏过程中有各自的生命周期. 游戏对象是组件的容器, 比如可以包含声音和图像组件等. 游戏对象还是游戏逻辑脚本代码的载体. 游戏对象既可以使用编辑器创建并放置于集合志宏, 也可以使用工厂在运行时进行实例化. 详情请见 [游戏组成教程](/manuals/building-blocks).
+![Game object](images/icons/game-object.png){.left} 游戏对象是简单对象,在游戏执行期间具有独立的生命周期。游戏对象是容器,通常配备有视觉或可听组件,如声音或精灵。它们也可以通过脚本组件配备行为。您在编辑器中创建游戏对象并将其放置在集合中,或者在运行时使用工厂动态生成它们。有关游戏对象的描述,请参阅[构建块手册](/manuals/building-blocks)。
 
 ## GUI
 
-![GUI component](images/icons/gui.png){.left} GUI 组件用来组成用户界面: 包含文字, 图像等等. 这些组件组成树形结构, 可以被脚本和动画控制. GUI 组件常用于组成屏幕操作界面, 菜单系统和提示框等等. GUI 组件使用 GUI 脚本控制以实现交互行为. 详情请见 [GUI 教程](/manuals/gui).
+![GUI component](images/icons/gui.png){.left} GUI组件包含用于构建用户界面的元素:文本以及有颜色和/或有纹理的块。元素可以组织成层次结构,进行脚本化和动画化。GUI组件通常用于创建抬头显示器、菜单系统和屏幕通知。GUI组件由GUI脚本控制,这些脚本定义GUI的行为并控制用户与GUI的交互。在[GUI文档](/manuals/gui)中阅读更多内容。
 
 ## GUI script
 
-![GUI script](images/icons/script.png){.left} GUI 脚本用于控制界面组件的行为. 它决定了界面元素如何移动, 用户如何与界面元素交互. 详情请见 [Defold 的 Lua 教程](/manuals/lua).
+![GUI script](images/icons/script.png){.left} GUI脚本用于控制GUI组件的行为。它们控制GUI动画以及用户如何与GUI交互。有关Lua脚本在Defold中如何使用的详细信息,请参阅[Defold中的Lua手册](/manuals/lua)。
 
 ## Hot reload
 
-Defold 允许在游戏运行时进行内容更新, 支持桌面和移动设备. 这项功能能为游戏开发者大大节省开发和调试时间. 详情请见 [热重载教程](/manuals/hot-reload).
+Defold编辑器允许您在已经运行的游戏中更新内容,无论是在桌面还是设备上。此功能非常强大,可以大大改善开发工作流程。有关更多信息,请参阅[热重载手册](/manuals/hot-reload)。
 
 ## Input binding
 
-![Input binding](images/icons/input-binding.png){.left} 输入绑定定义了输入设备 (鼠标, 键盘, 触摸屏和手柄等) 输入信息的含义. 它把硬件输入与游戏行为进行绑定, 比如 "跳跃" 和 "前进" _行为_. 这样监听输入的脚本就能根据这些行为控制与之相配的动作. 详情请见 [输入教程](/manuals/input).
+![Input binding](images/icons/input-binding.png){.left} 输入绑定文件定义了游戏应该如何解释硬件输入(鼠标、键盘、触摸屏和游戏手柄)。该文件将硬件输入绑定到高级输入_动作_,如"跳跃"和"向前移动"。在监听输入的脚本组件中,您能够编写游戏或应用程序在给定某些输入时应该采取的动作的脚本。有关详细信息,请参阅[输入文档](/manuals/input)。
 
 ## Label
 
-![Label](images/icons/label.png){.left} 标签组件用来给游戏对象加上文字内容. 它使用指定字体在游戏空间中被渲染出来. 详情请见 [标签教程](/manuals/label).
+![Label](images/icons/label.png){.left} 标签组件允许您将文本内容附加到任何游戏对象。它在屏幕上的游戏空间中渲染一段带有特定字体的文本。有关更多信息,请参阅[标签手册](/manuals/label)。
 
 ## Library
 
-![Game object](images/icons/builtins.png){.left} Defold 使用库机制进行资源共享. 资源共享可以是项目间的, 也可以是团队成员间的. 详情请见 [库教程](/manuals/libraries).
+![Game object](images/icons/builtins.png){.left} Defold允许您通过强大的库机制在项目之间共享数据。您可以使用它来设置可从所有项目访问的共享库,无论是为您自己还是整个团队。在[库文档](/manuals/libraries)中阅读有关库机制的更多信息。
 
 ## Lua language
 
-Lua 语言在 Defold 中用来创建游戏逻辑. Lua 是一种强大高效而又轻量级的脚本语言. 它支持多种设计模式和数据描述. 详情请见官网 https://www.lua.org/ 和 [Defold 脚本手册](/manuals/lua).
+Lua编程语言在Defold中用于创建游戏逻辑。Lua是一种强大、高效、非常小的脚本语言。它支持过程式编程、面向对象编程、函数式编程、数据驱动编程和数据描述。您可以在官方Lua主页https://www.lua.org/上阅读有关该语言的更多信息,并在[Defold中的Lua手册](/manuals/lua)中阅读相关信息。
 
 ## Lua module
 
-![Lua module](images/icons/lua-module.png){.left} Lua 模块可以用来构建项目编写可重用代码. 详情请见 [Lua 模块教程](/manuals/modules/)
+![Lua module](images/icons/lua-module.png){.left} Lua模块允许您构建项目结构并创建可重用的库代码。在[Lua模块手册](/manuals/modules/)中阅读更多相关信息。
 
 ## Material
 
-![Material](images/icons/material.png){.left} 材质使用指定的着色器及其属性来实现特定的视觉效果. 详情请见 [材质教程](/manuals/material).
+![Material](images/icons/material.png){.left} 材质通过指定着色器及其属性来定义不同对象应该如何渲染。有关更多信息,请参阅[材质手册](/manuals/material)。
 
 ## Message
 
-组件使用消息与系统或者与其他游戏对象进行信息交流. 有许多预定义的消息提供给组件使用以便实现某些功能. 比如隐藏图像或者推动物理物体. 游戏引擎通过消息传递事件, 比如物理物体碰撞事件. 要发送消息必须有接收者. 所以每个游戏对象每个组件的路径都是唯一的. Defold 给 Lua 增添了消息传递功能以及包含各种功能的库.
+组件通过消息传递相互通信和与其他系统通信。组件还响应一组预定义的消息,这些消息会改变它们或触发特定动作。您发送消息来隐藏图形或推动物理对象。引擎还使用消息来通知组件事件,例如当物理形状碰撞时。消息传递机制需要为每个发送的消息指定接收者。因此,游戏中的一切都被唯一寻址。为了允许对象之间进行通信,Defold扩展了Lua的消息传递功能。Defold还提供了一组有用的函数库。
 
-举个例子, 要隐藏一个 sprite 可以这么写:
+例如,在游戏对象上隐藏精灵组件所需的Lua代码如下:
 
 ```lua
 msg.post("#weapon", "disable")
 ```
 
-此处, `"#weapon"` 就是游戏对象 sprite 组件的路径. `"disable"` 是发给 sprite 组件的消息内容. 详情请见 [消息传递教程](/manuals/message-passing).
+这里,`"#weapon"`是当前对象精灵组件的地址。`"disable"`是精灵组件响应的消息。有关消息传递如何工作的深入解释,请参阅[消息传递文档](/manuals/message-passing)。
 
 ## Model
 
-![Model](images/icons/model.png){.left} 3D 模型组件支持在游戏中使用 glTF 和 Collada 网格模型, 骨骼和动画. 详情请见 [模型教程](/manuals/model/).
+![Model](images/icons/model.png){.left} 3D模型组件可以将glTF和Collada网格、骨骼和动画资源导入到您的游戏中。有关更多信息,请参阅[模型手册](/manuals/model/)。
 
 ## ParticleFX
 
-![ParticleFX](images/icons/particlefx.png){.left} 粒子特效用来实现游戏里的某些视觉效果. 包括雾, 烟, 火, 雨或者落叶等等. Defold 自带了一个功能强大的粒子编辑器用来创建和实时调整粒子效果. 详情请见 [粒子教程](/manuals/particlefx).
+![ParticleFX](images/icons/particlefx.png){.left} 粒子在创建漂亮的视觉效果方面非常有用,特别是在游戏中。您可以使用它们来创建雾、烟、火、雨或落叶。Defold包含一个强大的粒子效果编辑器,允许您在游戏中实时运行效果时构建和调整效果。[ParticleFX文档](/manuals/particlefx)为您提供了其工作原理的详细信息。
 
 ## Profiling
 
-性能对于游戏至关重要, 通过数据分析你可以发现游戏性能上的瓶颈以及内存泄漏等问题. 详情请见 [性能分析教程](/manuals/profiling).
+良好的性能是游戏的关键,您必须能够进行性能和内存分析来测量您的游戏并识别需要修复的性能瓶颈和内存问题。有关Defold可用的分析工具的更多信息,请参阅[分析手册](/manuals/profiling)。
 
 ## Render
 
-![Render](images/icons/render.png){.left} 渲染文件包含把游戏渲染到屏幕所需的设置和参数. 渲染文件决定了使用哪个渲染脚本和哪个材质资源. 详情请见 [Render manual](/manuals/render/).
+![Render](images/icons/render.png){.left} 渲染文件包含将游戏渲染到屏幕时使用的设置。渲染文件定义了用于渲染的渲染脚本以及要使用的材质。有关更多详细信息,请参阅[渲染手册](/manuals/render/)。
 
 ## Render script
 
-![Render script](images/icons/script.png){.left} 渲染脚本是由 Lua 语言编写的用于渲染游戏内容的脚本. 自带的默认渲染脚本大多数情况下可用, 但是如果需求自定义效果就需要自己写渲染脚本了. 详情请见 [渲染教程](/manuals/render/) for more details on how the render pipeline works, and the [Lua in Defold manual](/manuals/lua).
+![Render script](images/icons/script.png){.left} 渲染脚本是一个Lua脚本,用于控制游戏或应用程序应该如何渲染到屏幕。有一个默认的渲染脚本涵盖了最常见的情况,但如果您需要自定义光照模型和其他效果,您可以编写自己的渲染脚本。有关渲染管道如何工作的更多详细信息,请参阅[渲染手册](/manuals/render/),有关Lua脚本在Defold中如何使用的详细信息,请参阅[Defold中的Lua手册](/manuals/lua)。
 
 ## Script
 
-![Script](images/icons/script.png){.left}  脚本是包含代码的组件, 它控制着游戏对象的行为. 使用脚本可以编写游戏逻辑, 对象交互 (人机交互或者游戏内游戏对象交互). 脚本用 Lua 语言写成. 使用 Defold, 必须要会写 Lua 脚本. 详情请见 [Defold 脚本教程](/manuals/lua).
+![Script](images/icons/script.png){.left} 脚本是一个组件,包含定义游戏对象行为的程序。通过脚本,您可以指定游戏的规则,对象应该如何响应各种交互(与玩家以及其他对象)。所有脚本都用Lua编程语言编写。为了能够使用Defold工作,您或您团队中的某人需要学习如何用Lua编程。有关Lua的概述以及Lua脚本在Defold中如何使用的详细信息,请参阅[Defold中的Lua手册](/manuals/lua)。
 
 ## Sound
 
-![Sound](images/icons/sound.png){.left} 声音组件用于播放声音. 目前 Defold 支持 WAV 和 Ogg Vorbis 格式的声音文件. 详情请见 [声音教程](/manuals/sound).
+![Sound](images/icons/sound.png){.left} 声音组件负责播放特定的声音。目前,Defold支持WAV和Ogg Vorbis格式的声音文件。有关更多信息,请参阅[声音手册](/manuals/sound)。
 
 ## Sprite
 
-![Sprite](images/icons/sprite.png){.left} Sprite 可以使游戏对象显示出图像. 它使用瓷砖图源或者图集资源的数据显示图像. Sprite 也支持逐帧动画. 它常常被用于显示人物, 物品等.
+![Sprite](images/icons/sprite.png){.left} 精灵是一个组件,用图形扩展游戏对象。它显示来自瓦片源或图集的图像。精灵内置支持翻页和骨骼动画。精灵通常用于角色和物品。
 
 ## Texture profiles
 
-![Texture profiles](images/icons/texture-profiles.png){.left} 纹理档案资源文件用于编译时自动处理和压缩图片数据 (Atlas, Tile sources, 3D Cubemaps 和 textures , GUI 等等). 详情请见 [Texture profiles manual](/manuals/texture-profiles).
+![Texture profiles](images/icons/texture-profiles.png){.left} 纹理配置文件资源文件用于在打包过程中自动处理和压缩图像数据(图集、瓦片源、立方体贴图和用于模型、GUI等的独立纹理)。在[纹理配置文件手册](/manuals/texture-profiles)中阅读更多相关信息。
 
 ## Tile map
 
-![Tile map](images/icons/tilemap.png){.left} 瓷砖地图使用瓷砖图源数据建立一层或多层结构的平铺图像. 通常用来作为游戏场景: 背景, 墙, 建筑物和遮挡物等等. 可以指定混合模式显示多层关系. 比如叶子落在地上. 瓷砖也可以动态更换. 比如可以用来制作桥梁被炸毁的效果. 详情请见 [瓷砖地图教程](/manuals/tilemap).
+![Tile map](images/icons/tilemap.png){.left} 瓦片地图组件在一个或多个重叠网格中显示来自瓦片源的图像。它们最常用于构建游戏环境:地面、墙壁、建筑物和障碍物。瓦片地图可以显示几个层叠在一起的层,具有指定的混合模式。这很有用,例如,将叶子放在草地背景瓦片上。还可以动态更改瓦片中显示的图像。这允许您,例如,通过简单地用描绘破损桥梁的瓦片替换瓦片并包含相应的物理形状,来摧毁一座桥梁并使其无法通行。有关更多信息,请参阅[瓦片地图文档](/manuals/tilemap)。
 
 ## Tile source
 
-![Tile source](images/icons/tilesource.png){.left} 瓷砖图源由许多相同大小码放整齐的小图组成. 可以使用瓷砖图源创建逐帧动画. 瓷砖图源可以通过图片数据自动生成碰撞形状. 做关卡时碰撞形状可以当作障碍或者与角色产生交互. 瓷砖地图 (以及 Sprite 和 ParticleFX) 之间可以共享图像资源. 注意能用图集别用瓷砖图源. 详情请见 [瓷砖地图教程](/manuals/tilemap).
+![Tile source](images/icons/tilesource.png){.left} 瓦片源描述了一种纹理,该纹理由多个较小图像组成,每个图像大小相同。您可以从瓦片源中的一系列图像定义翻页动画。瓦片源还可以自动从图像数据计算碰撞形状。这对于创建对象可以碰撞和交互的瓦片化关卡非常有用。瓦片源由瓦片地图组件(以及精灵和粒子效果)使用,以共享图形资源。请注意,图集通常比瓦片源更适合。有关更多信息,请参阅[瓦片地图文档](/manuals/tilemap)。
 
 ## Vertex shader
 
-![Vertex shader](images/icons/vertex-shader.png){.left} 顶点着色器用于计算多边形在屏幕上投射的位置. 对于各种可视组件, 比如 sprite, 瓷砖地图 或者 3D 模型, 它们的形状由多边形顶点构成. 顶点着色程序负责处理顶点 (在全局游戏空间) 的位置并且负责计算出每个多边形顶点的在屏幕上的映射位置. 详情请见 [Shader manual](/manuals/shader).
+![Vertex shader](images/icons/vertex-shader.png){.left} 顶点着色器计算组件原始多边形形状的屏幕几何图形。对于任何类型的视觉组件,无论是精灵、瓦片地图还是模型,形状都由一组多边形顶点位置表示。顶点着色器程序处理每个顶点(在世界空间中)并计算原始顶点应该具有的结果坐标。有关更多信息,请参阅[着色器手册](/manuals/shader)。

+ 2 - 2
docs/zh/manuals/gpgs.md

@@ -1,5 +1,5 @@
 ---
 title: Defold 中的 Google Play Game 服务
-brief: 本教程介绍了配置和使用 Google Play Game 服务的方法
+brief: 本文档介绍了如何设置和使用 Google Play Game 服务
 ---
-[本教程已被移至这里](/extension-gpgs)
+[本文档已移至此处](/extension-gpgs)

+ 6 - 6
docs/zh/manuals/graphics.md

@@ -1,10 +1,10 @@
 ---
-title: Defold 图像教程
-brief: 本教程简述了 Defold 支持的图像组件.
+title: Defold 图形手册
+brief: 本手册概述了Defold对图形元素的支持.
 ---
 
-该教程已废弃!
+已弃用的手册!
 
-* 参见 [如何导入和使用 2D 图片](/manuals/importing-graphics)
-* 参见 [贴图滤镜](/manuals/texture-filtering)
-* 参见 [材质](/manuals/material)
+* 阅读更多关于[如何导入和使用2D图形](/manuals/importing-graphics)的信息
+* 阅读更多关于[纹理过滤](/manuals/texture-filtering)的信息
+* 阅读更多关于[材质](/manuals/material)的信息

+ 7 - 7
docs/zh/manuals/gui-box.md

@@ -1,28 +1,28 @@
 ---
-title: Defold 中的 GUI 方块节点
-brief: 本教程介绍了如何使用 GUI 方块节点.
+title: Defold中的GUI方块节点
+brief: 本手册介绍了如何使用GUI方块节点。
 ---
 
 # GUI 方块节点
 
-方块节点是一个可以填充颜色, 纹理或者动画的矩形.
+方块节点是一个填充了颜色、纹理或动画的矩形。
 
 ## 添加方块节点
 
 添加方块节点可以在 *Outline* 中 <kbd>右键点击</kbd> 然后选择 <kbd>Add ▸ Box</kbd>, 或者按 <kbd>A</kbd> 然后选择 <kbd>Box</kbd>.
 
-你可以使用图集或者瓷砖图源里的图片或者动画添加到GUI上去. 要添加纹理 <kbd>右键点击</kbd>  *Outline* 中的 *Textures* 文件夹图标, 选择 <kbd>Add ▸ Textures...</kbd>. 然后设置方块节点的 *Texture* 属性:
+你可以使用已添加到GUI中的图集或瓦片图源的图像和动画。通过<kbd>右键点击</kbd>*Outline*中的*Textures*文件夹图标并选择<kbd>Add ▸ Textures...</kbd>来添加纹理。然后设置方块节点的*Texture*属性:
 
 ![纹理](images/gui-box/create.png)
 
-注意方块节点的图像可以染色. 使用 color 加成到图片上面, 也就是说如果设置 color 为白色 (默认值) 则没有染色.
+注意方块节点的颜色会对图形进行染色。染色颜色会与图像数据相乘,这意味着如果将颜色设置为白色(默认值),则不会应用染色效果。
 
 ![染色纹理](images/gui-box/tinted.png)
 
-即使没有纹理设置, 方块节点也会被渲染, 或者不论把 alpha 设置成 `0`, 还是把 sized 设置成 `0, 0, 0`. 方块节点应该设置纹理以便渲染器合批而减少 draw call.
+即使没有分配纹理,或者将alpha设置为`0`,或者将大小设置为`0, 0, 0`,方块节点也始终会被渲染。方块节点应该始终分配纹理,以便渲染器能够正确地进行批处理并减少绘制调用次数。
 
 ## 播放动画
 
-Box 节点可以由其图集或者瓷砖图源内容来播放动画. 详情请见 [逐帧动画教程](/manuals/flipbook-animation).
+方块节点可以播放图集或瓦片图源中的动画。有关详细信息,请参阅[逐帧动画手册](/manuals/flipbook-animation)。
 
 :[Slice-9](../shared/slice-9-texturing.md)

+ 36 - 36
docs/zh/manuals/gui-clipping.md

@@ -1,75 +1,75 @@
 ---
-title: GUI 蒙版教程
-brief: 本教程介绍了创建使用蒙版剪裁遮蔽其他 GUI 节点的方法.
+title: GUI裁剪手册
+brief: 本手册描述了如何创建通过模板裁剪来遮蔽其他节点的GUI节点。
 ---
 
-# 蒙版
+# 裁剪
 
-GUI 节点可以作为 *蒙版* 节点---遮蔽影响其他节点的显示方式. 本教程介绍了其用法.
+GUI节点可以用作*裁剪*节点——控制其他节点如何渲染的遮罩。本手册解释了此功能的工作原理。
 
-## 创建蒙版节点
+## 创建裁剪节点
 
-方块, 文本 和 饼状图节点可以被裁剪. 要创建裁剪节点, 在 GUI 里添加一个节点, 然后设置相关属性:
+方块、文本和饼状图节点可用于裁剪。要创建裁剪节点,请在GUI中添加一个节点,然后相应地设置其属性:
 
 Clipping Mode
-: 裁剪模式.
-  - `None` 不施加裁剪.
-  - `Stencil` 施加裁剪.
+: 用于裁剪的模式。
+  - `None` 渲染节点时不进行任何裁剪。
+  - `Stencil` 使节点写入到当前模板蒙版。
 
 Clipping Visible
-: 选中则蒙版内容可见.
+: 勾选以渲染节点的内容。
 
 Clipping Inverted
-: 选中则遮蔽内容反转.
+: 勾选以将节点形状的反转写入蒙版。
 
-然后把被裁剪节点作为蒙版子节点加入进来.
+然后将要裁剪的节点作为子节点添加到裁剪节点中。
 
 ![Create clipping](images/gui-clipping/create.png)
 
-## 裁剪蒙版
+## 模板蒙版
 
-原理上裁剪是把节点写入 *裁剪缓冲区*. 此缓冲区包含蒙版: 就是告诉显卡哪些像素该渲染, 哪些不该渲染.
+裁剪的工作原理是让节点写入*模板缓冲区*。此缓冲区包含裁剪蒙版:告诉显卡像素是否应该被渲染的信息。
 
-- 一个没有父蒙版的节点, 如果设置了 clipping mode 为 `Stencil` 的话相当于把它的形状 (或者其反转形状) 写入裁剪蒙版保存在裁剪缓冲区当中.
-- 如果一个蒙版节点有父蒙版那么它会继续裁剪父蒙版. 子蒙版不会 _继承_ 当前蒙版, 只会继续剪裁当前蒙版.
-- 非蒙版节点作为蒙版的子节点的话, 会被父蒙版层级裁剪渲染.
+- 没有裁剪器父节点但裁剪模式设置为`Stencil`的节点会将其形状(或其反转形状)写入存储在模板缓冲区中的新裁剪蒙版。
+- 如果裁剪节点有裁剪器父节点,它将裁剪父节点的裁剪蒙版。裁剪子节点永远不能_扩展_当前裁剪蒙版,只能进一步裁剪它。
+- 作为裁剪器子节点的非裁剪器节点将使用由父层级创建的裁剪蒙版进行渲染。
 
 ![Clipping hierarchy](images/gui-clipping/setup.png)
 
-这里, 我们建立了节点的三层结构:
+这里,三个节点以层级结构设置:
 
-- 六边形和矩形都是蒙版节点.
-- 六边形是第一个蒙版, 矩形进一步裁剪.
-- 园是最下层被裁剪的普通节点.
+- 六边形和矩形形状都是模板裁剪器。
+- 六边形创建新的裁剪蒙版,矩形进一步裁剪它。
+- 圆形节点是常规的饼状图节点,因此它将使用其父裁剪器创建的裁剪蒙版进行渲染。
 
-这种结构下可以有四种裁剪方式. 绿色标志出园被裁剪以后的样子. 结果如下所示:
+对于此层级结构,可能有四种正常和反转裁剪器的组合。绿色区域标记了圆形中被渲染的部分。其余部分被遮罩:
 
 ![Stencil masks](images/gui-clipping/modes.png)
 
-## 蒙版局限性
+## 模板限制
 
-- 蒙版数最大不超过 256 个.
-- _蒙版_ 节点最大嵌套8层. (只计算设置了蒙版的节点)
-- 同层次蒙版不超过 127 个. 每深一层, 数目减半.
-- 反转蒙版很耗性能. 最多8个反转蒙版并且每个反转蒙版会使非反转蒙版的最大数目减半.
-- 裁剪渲染基于蒙版节点的 _几何形状_  (而非纹理). 设置 *Inverted clipper* 可以反转蒙版渲染.
+- 模板裁剪器的总数不能超过256个。
+- 子_模板_节点的最大嵌套深度为8层。(仅计算具有模板裁剪的节点。)
+- 模板节点的同级节点最大数量为127个。对于模板层级中的每一层,最大限制减半。
+- 反转节点的成本更高。反转裁剪节点的限制为8个,每个节点将使非反转裁剪节点的最大数量减半。
+- 模板从节点的_几何形状_(而不是纹理)渲染模板蒙版。可以通过设置*Inverted clipper*属性来反转蒙版。
 
 
 ## 层
 
-层用于控制节点的渲染顺序 (以及合批顺序). 使用层和蒙版节点时原本的层顺序会被覆盖. 层顺序的优先级高于蒙版顺序---如果一个层的节点与蒙版节点组合在一起, 如果启用蒙版的父节点属于比其子节点更高的层,则裁剪可能会发生乱序. 没被分配层的子节点仍具备父子结构, 继父节点之后还会被渲染和裁剪.
+层可用于控制节点的渲染顺序(和批处理)。当使用层和裁剪节点时,通常的分层顺序会被覆盖。层顺序始终优先于裁剪顺序——如果层分配与裁剪节点结合,如果启用了裁剪的父节点属于比其子节点更高的层,则裁剪可能会发生乱序。没有分配层的子节点仍将尊重层级结构,并随后在父节点之后被绘制和裁剪。
 
 ::: sidenote
-蒙版节点及其层级有层设置的话会优先显示, 没有设置的话按照普通顺序显示.
+如果分配了层,裁剪节点及其层级将首先被绘制,如果没有分配层,则按常规顺序绘制。
 :::
 
 ![Layers and clipping](images/gui-clipping/layers.png)
 
-本例中, 节点 "Donut BG" 和 "BG" 都使用了 layer 1. 它们的渲染顺序遵循层级即 "Donut BG" 先于 "BG" 渲染. 然而, 子节点 "Donut Shadow" 归为 layer 2 即更高层级, 则它的渲染晚于这两个节点. 这种情况下, 渲染顺序为:
+在此示例中,裁剪节点`Donut BG`和`BG`都使用相同的层1。它们之间的渲染顺序将按照层级中的相同顺序,其中`Donut BG`在`BG`之前渲染。但是,子节点`Donut Shadow`被分配到具有更高层顺序的层2,因此将在两个裁剪节点之后渲染。在这种情况下,渲染顺序将是:
 
-- Donut BG
-- BG
-- BG Frame
-- Donut Shadow
+- `Donut BG`
+- `BG`
+- `BG Frame`
+- `Donut Shadow`
 
-可见 "Donut Shadow" 对象基于层级被两个蒙版节点裁剪, 即使它是蒙版节点的唯一子节点.
+在这里,您可以看到`Donut Shadow`对象将由于分层而被两个裁剪节点裁剪,即使它只是其中一个的子节点。

+ 29 - 29
docs/zh/manuals/gui-layouts.md

@@ -1,76 +1,76 @@
 ---
-title: Defold 里的 GUI 布局
-brief: Defold 支持让 GUIs 自动适配手机屏幕方向的改变. 本教程介绍这部分功能.
+title: Defold中的GUI布局
+brief: Defold支持GUI自动适应移动设备上的屏幕方向变化。本文档解释了此功能的工作原理。
 ---
 
 # 布局
 
-Defold支持可自动适应移动设备上屏幕方向变化的GUI.通过使用此功能,您可以设计适合各种屏幕尺寸的方向和纵横比的GUI.也可以创建与特定设备型号匹配的布局.
+Defold支持GUI自动适应移动设备上的屏幕方向变化。通过使用此功能,您可以设计适应各种屏幕尺寸的方向和纵横比的GUI。还可以创建与特定设备型号匹配的布局。
 
-## 新建显示档案
+## 创建显示配置文件
 
-*game.project* 默认使用内置显示档案文件 ("builtins/render/default.display_profiles"). 默认 "横屏" (1280 像素宽 720 像素高) 和 "竖屏" (720 像素宽 1280 像素高). 未指定显示器型号以便适应各种设备.
+默认情况下,*game.project*设置指定使用内置的显示配置文件设置文件("builtins/render/default.display_profiles")。默认配置文件是"Landscape"(1280像素宽和720像素高)和"Portrait"(720像素宽和1280像素高)。配置文件上没有设置设备型号,因此它们将匹配任何设备。
 
-要新建显示档案文件, 要么把 "builtins" 文件夹拷贝出来, 要么在  *Assets* 视图中 <kbd>右键点击</kbd> 然后选择 <kbd>New... ▸ Display Profiles</kbd>. 输入文件名然后点击 <kbd>Ok</kbd>.
+要创建新的配置文件设置文件,可以复制"builtins"文件夹中的文件,或者在*Assets*视图中<kbd>右键点击</kbd>合适位置并选择<kbd>New... ▸ Display Profiles</kbd>。给新文件一个合适的名称,然后点击<kbd>Ok</kbd>。
 
-编辑器会自动打开新建的文件. 在 *Profiles* 列表里点击 <kbd>+</kbd>. 给每个档案加入不同的 *限定*:
+编辑器现在会打开新文件进行编辑。通过点击*Profiles*列表中的<kbd>+</kbd>添加新的配置文件。对于每个配置文件,添加一组*限定符*:
 
 Width
-: 限定宽度像素数.
+: 限定符的像素宽度。
 
 Height
-: 限定高度像素数.
+: 限定符的像素高度。
 
 Device Models
-: 以逗号分隔的设备型号名称表. 型号名只要匹配设备型号的开头就算匹配成功, 例如 `iPhone10` 匹配 "iPhone10,\*" 的所有设备. 型号名带逗号的要使用双引号包裹, 例如 `"iPhone10,3", "iPhone10,6"` 匹配 iPhone X 那两种设备 (参考 https://www.theiphonewiki.com/wiki/Models). 注意调用 `sys.get_sys_info()` 函数在 Android 和 iOS 会返回设备名. 其他平台返回空字符, 也就是说这样的设备对于限定了设备型号的档案都无法匹配.
+: 以逗号分隔的设备型号列表。设备型号匹配设备型号名称的开头,例如`iPhone10`将匹配"iPhone10,*"型号。带有逗号的型号名称应该用引号括起来,即`"iPhone10,3", "iPhone10,6"`匹配iPhone X型号(参见[iPhone wiki](https://www.theiphonewiki.com/wiki/Models))。请注意,调用`sys.get_sys_info()`时报告设备型号的唯一平台是Android和iOS。其他平台返回空字符串,因此永远不会选择具有设备型号限定符的显示配置文件。
 
 ![New display profiles](images/gui-layouts/new_profiles.png)
 
-别忘了指定引擎使用你自己的档案文件. 打开 *game.project* 在 *display* 部分 *Display Profiles* 项里进行设置:
+您还需要指定引擎应该使用您的新配置文件。打开*game.project*并在*display*下的*Display Profiles*设置中选择显示配置文件:
 
 ![Settings](images/gui-layouts/settings.png)
 
-勾选 *Dynamic Orientation* 选项可以使引用在屏幕上自动旋转以适应横屏竖屏. 游戏引擎也会根据横屏竖屏选取合适的界面布局.
+如果您希望引擎在设备旋转时自动在横屏和竖屏布局之间切换,请勾选*Dynamic Orientation*框。引擎将动态选择匹配的布局,并在设备改变方向时也更改选择。
 
-## GUI 布局
+## GUI布局
 
-显示档案里可以为用户界面设置各种布局. 为 GUI 常见添加布局, 在 *Outline* 视图的 *Layouts* 图标上右键点击然后选择 <kbd>Add ▸ Layout ▸ ...</kbd>:
+当前的显示配置文件集可用于创建GUI节点设置的布局变体。要向GUI场景添加新布局,请在*Outline*视图中右键点击*Layouts*图标并选择<kbd>Add ▸ Layout ▸ ...</kbd>:
 
 ![Add layout to scene](images/gui-layouts/add_layout.png)
 
-编辑用户界面时, 每个操作都是针对一种布局而进行. 即针对在 GUI 场景的工具栏的下拉框中选中的布局进行编辑操作. 如果未选择任何布局, 默认操作的是 *Default* 布局.
+编辑GUI场景时,所有节点都在特定布局上进行编辑。当前选定的布局在工具栏的GUI场景布局下拉框中指示。如果未选择布局,则在*Default*布局中编辑节点。
 
 ![Layouts toolbar](images/gui-layouts/toolbar.png)
 
 ![portrait edit](images/gui-layouts/portrait.png)
 
-选择指定布局之后每个节点的属性编辑都会 _覆盖_ *Default* 布局里的属性. 被覆盖的属性以蓝色高亮显示. 其节点同样以蓝色高亮显示. 属性旁边的重置按钮用来恢复默认属性值.
+对节点属性所做的每个更改(在选择布局时)会_覆盖_*Default*布局中的属性。被覆盖的属性以蓝色标记。具有被覆盖属性的节点也以蓝色标记。您可以点击任何被覆盖属性旁边的重置按钮将其重置为原始值。
 
 ![landscape edit](images/gui-layouts/landscape.png)
 
-布局不会增加或减少节点, 只会覆盖节点属性. 如果某个布局需要减少节点可以把它移到屏幕之外或者使用脚本删除掉. 注意不要忘记当前选择的布局. 新建布局之后编辑器会自动把它设置为当前布局. 而且复制粘贴节点的时候尤其要考虑当前选择的布局, 包括复制节点的时候 *和* 粘贴节点的时候.
+布局不能删除或创建新节点,只能覆盖属性。如果需要从布局中移除节点,可以将其移出屏幕或使用脚本逻辑删除它。您还应注意当前选定的布局。如果向项目添加布局,新布局将根据当前选定的布局进行设置。此外,复制和粘贴节点时考虑当前选定的布局,在复制*和*粘贴时都是如此。
 
-## 动态布局选择
+## 动态配置文件选择
 
-动态布局匹配度根据以下规则为每个显示档案文件限制匹配评分:
+动态布局匹配根据以下规则对每个显示配置文件限定符进行评分:
 
-1. 无设备型号限制或者匹配到了设备, 分数 (S) 加一.
+1. 如果没有设置设备型号,或者设备型号匹配,则为限定符计算分数(S)。
 
-2. 分数 (S) 的计算公式用到了显示器面积 (A), 面积限制 (A_Q), 显示器宽高比 (R) 和宽高比限制 (R_Q):
+2. 分数(S)使用显示面积(A)、限定符的面积(A_Q)、显示的纵横比(R)和限定符的纵横比(R_Q)计算:
 
 <img src="https://latex.codecogs.com/svg.latex?\inline&space;S=\left|1&space;-&space;\frac{A}{A_Q}\right|&space;&plus;&space;\left|1&space;-&space;\frac{R}{R_Q}\right|" title="S=\left|1 - \frac{A}{A_Q}\right| + \left|1 - \frac{R}{R_Q}\right|" />
 
-3. 如果屏幕方向 (横屏或者竖屏) 与限制匹配, 则分数最低的显示档案被采用.
+3. 如果限定符的方向(横屏或竖屏)与显示匹配,则选择得分最低的限定符的配置文件。
 
-4. 如果屏幕方向无匹配, 则另一方向分数最高的显示档案被采用.
+4. 如果找不到具有相同方向限定符的配置文件,则选择具有另一方向最佳得分限定符的配置文件。
 
-5. 如果没有显示档案被采用, 则 *Default* 显示档案被采用.
+5. 如果无法选择配置文件,则使用*Default*回退配置文件。
 
-*Default* 布局只在没有自定义布局时产生作用, 也就是说如果你只制作了 "横屏" 布局, *任何* 方向的设备屏幕都会匹配到这个布局, 直到你又制作了 "竖屏" 布局.
+由于*Default*布局在运行时用作回退,如果没有更好的匹配布局,这意味着如果您添加"Landscape"布局,它将是*所有*方向的最佳匹配,直到您也添加"Portrait"布局。
 
-## 布局变换消息
+## 布局更改消息
 
-当引擎发现屏幕方向被旋转, 就会向受影响的用户界面组件脚本发送一个 `layout_changed` 消息. 消息包含布局id的哈希值以便代码做针对性处理:
+当引擎因设备旋转而切换布局时,会向受更改影响的GUI组件脚本发送`layout_changed`消息。消息包含布局的哈希ID,以便脚本可以根据选择的布局执行逻辑:
 
 ```lua
 function on_message(self, message_id, message, sender)
@@ -82,7 +82,7 @@ function on_message(self, message_id, message, sender)
 end
 ```
 
-而且当应用窗体 (游戏视口) 发生改变时, 包括屏幕方向改变时, 渲染脚本也会收到相应的消息.
+此外,每当窗口(游戏视图)更改时,当前渲染脚本都会收到消息,这包括方向更改。
 
 ```lua
 function on_message(self, message_id, message)
@@ -93,4 +93,4 @@ function on_message(self, message_id, message)
 end
 ```
 
-屏幕方向改变时, 用户界面布局管理器会根据定义好的布局和节点属性缩放节点. 但是非用户界面节点的游戏内容, 默认用另一个渲染管线进行渲染, 所以会在改变的窗体里进行拉伸. 不想要这种效果的话, 要么自己写渲染脚本, 要么使用 [摄像机](/assets/).
+当方向切换时,GUI布局管理器将根据您的布局和节点属性自动缩放和重新定位GUI节点。然而,游戏内容在单独的通道中渲染(默认情况下),使用拉伸适配投影到当前窗口。要更改此行为,要么提供自己修改的渲染脚本,要么使用相机[库](/assets/)。

+ 12 - 12
docs/zh/manuals/gui-particlefx.md

@@ -1,34 +1,34 @@
 ---
-title: Defold的GUI粒子特效
-brief: 本教程解释了 Defold GUI 的粒子特效如何工作.
+title: Defold的GUI粒子特效
+brief: 本手册解释了Defold GUI中粒子特效的工作原理。
 ---
 
-# GUI ParticleFX 节点
+# GUI ParticleFX节点
 
-粒子特效节点用来在 GUI 屏幕空间中实现粒子特效.
+粒子特效节点用于在GUI屏幕空间中播放粒子特效系统。
 
-## 添加 Particle FX 节点
+## 添加ParticleFX节点
 
-在 *outline 视图* 中点击 <kbd>鼠标右键</kbd> 选择 <kbd>Add ▸ ParticleFX</kbd>, 或者按 <kbd>A</kbd> 选择 <kbd>ParticleFX</kbd> 来添加新粒子节点.
+通过在*Outline*中<kbd>右键点击</kbd>并选择<kbd>Add ▸ ParticleFX</kbd>,或按<kbd>A</kbd>并选择<kbd>ParticleFX</kbd>来添加新的粒子节点。
 
-也可以使用 GUI 里已经存在的资源创建粒子特效. 在 *outline 视图* 的 *Particle FX* 文件夹上点击 <kbd>鼠标右键</kbd> 选择 <kbd>Add ▸ Particle FX...</kbd>. 然后设置节点的 *Particlefx* 属性:
+您可以使用已添加到GUI中的粒子特效作为效果的源。通过在*Outline*中的*Particle FX*文件夹图标上<kbd>右键点击</kbd>并选择<kbd>Add ▸ Particle FX...</kbd>来添加粒子特效。然后在节点上设置*Particlefx*属性:
 
 ![Particle fx](images/gui-particlefx/create.png)
 
-## 控制
+## 控制效
 
-可以使用脚本控制节点上的特效:
+您可以通过脚本控制节点来启动和停止效果:
 
 ```lua
--- start the particle effect
+-- 启动粒子特效
 local particles_node = gui.get_node("particlefx")
 gui.play_particlefx(particles_node)
 ```
 
 ```lua
--- stop the particle effect
+-- 停止粒子特效
 local particles_node = gui.get_node("particlefx")
 gui.stop_particlefx(particles_node)
 ```
 
-详情请见 [粒子特效教程](/manuals/particlefx).
+有关粒子特效工作原理的详细信息,请参阅[粒子特效手册](/manuals/particlefx)。

+ 19 - 19
docs/zh/manuals/gui-pie.md

@@ -1,56 +1,56 @@
 ---
-title: Defold GUI 饼状图节点
-brief: 本教程介绍了在 Defold GUI 场景中如何使用饼状图节点.
+title: Defold GUI饼状图节点
+brief: 本手册解释了如何在Defold GUI场景中使用饼状图节点。
 ---
 
-# GUI 饼状图节点
+# GUI饼状图节点
 
-饼状图节点用以创建圆的或者椭圆的从实心到环状的可视对象.
+饼状图节点用于创建圆形或椭圆形对象,范围从普通圆形到饼形和方形甜甜圈形状。
 
 ## 创建饼状图节点
 
-<kbd>右键点击</kbd>  *Outline* 中的 *Nodes* 部分, 选择 <kbd>Add ▸ Pie</kbd>. 饼状图就创建好了.
+在*Outline*中的*Nodes*部分<kbd>右键点击</kbd>并选择<kbd>Add ▸ Pie</kbd>。新的饼状图节点被选中,您可以修改其属性。
 
 ![创建饼状图节点](images/gui-pie/create.png)
 
-以下属性是饼状图节点的特有属性:
+以下属性是饼状图节点特有的:
 
 Inner Radius
-: 节点的内半径, 延X轴.
+: 节点的内半径,沿X轴表示。
 
 Outer Bounds
-: 节点外轮廓.
+: 节点外边界的形状。
 
-  - `Ellipse` 可以把节点扩展到外半径处.
-  - `Rectangle` 可以把节点扩展到边界方框处.
+  - `Ellipse` 将节点扩展到外半径。
+  - `Rectangle` 将节点扩展到节点的边界框。
 
 Perimeter Vertices
-: 图形的分段数, 就是360度一圈需要的顶点数.
+: 用于构建形状的分段数,表示为完全环绕节点360度周长所需的顶点数。
 
 Pie Fill Angle
-: 饼状图的填充. 从右侧开始按逆时针方向.
+: 饼状图应填充多少。表示为从右侧开始的逆时针角度。
 
 ![属性](images/gui-pie/properties.png)
 
-如果为节点设置了纹理, 那么纹理图会和边界框的角对应起来平铺.
+如果在节点上设置了纹理,纹理图像将平展地应用,纹理的角与节点边界框的角相对应。
 
-## 运行时修改饼状图
+## 运行时修改饼状图节点
 
-饼状图节点同样可以控制 size, pivot, color 之类的属性. 此外还有饼状图特定属性:
+饼状图节点响应任何通用的节点操作函数,用于设置大小、轴心、颜色等。还存在一些仅适用于饼状图节点的函数和属性:
 
 ```lua
 local pienode = gui.get_node("my_pie_node")
 
--- get the outer bounds
+-- 获取外边界
 local fill_angle = gui.get_fill_angle(pienode)
 
--- increase perimeter vertices
+-- 增加周长顶点
 local vertices = gui.get_perimeter_vertices(pienode)
 gui.set_perimeter_vertices(pienode, vertices + 1)
 
--- change outer bounds
+-- 更改外边界
 gui.set_outer_bounds(pienode, gui.PIEBOUNDS_RECTANGLE)
 
--- animate the inner radius
+-- 动画内半径
 gui.animate(pienode, "inner_radius", 100, gui.EASING_INOUTSINE, 2, 0, nil, gui.PLAYBACK_LOOP_PINGPONG)
 ```

+ 40 - 40
docs/zh/manuals/gui-script.md

@@ -1,59 +1,59 @@
 ---
-title: Defold 中的 GUI 脚本 
-brief: 本教程介绍了 GUI 脚本.
+title: Defold中的GUI脚本
+brief: 本手册解释了GUI脚本。
 ---
 
-# GUI 脚本
+# GUI脚本
 
-为了控制 GUI 逻辑和动画节点要使用 Lua 脚本. GUI 脚本和游戏对象脚本一样, 但是扩展名不一样而且使用的函数集不一样: 使用 `gui` 模块函数.
+要控制GUI的逻辑和动画节点,您使用Lua脚本。GUI脚本与常规游戏对象脚本的工作方式相同,但保存为不同的文件类型,并且可以访问不同的函数集:`gui`模块函数。
 
-## 在 GUI 上添加脚本
+## 向GUI添加脚本
 
-要在 GUI 上添加脚本, 首先在 *Assets* 浏览器里<kbd>右键点击</kbd> 再在弹出菜单选择 <kbd>New ▸ Gui Script</kbd> 来创建 GUI 脚本.
+要向GUI添加脚本,首先通过在*Assets*浏览器中<kbd>右键点击</kbd>一个位置并从弹出上下文菜单中选择<kbd>New ▸ Gui Script</kbd>来创建GUI脚本文件。
 
-编辑器会自动打开脚本文件. 它基于一个模板, 各种空白生命周期函数齐全, 跟游戏对象脚本一样:
+编辑器会自动打开新的脚本文件。它基于一个模板,并配备了空的生命周期函数,就像游戏对象脚本一样:
 
 ```lua
 function init(self)
-   -- Add initialization code here
-   -- Remove this function if not needed
+   -- 在此添加初始化代码
+   -- 如果不需要,请删除此函数
 end
 
 function final(self)
-   -- Add finalization code here
-   -- Remove this function if not needed
+   -- 在此添加最终化代码
+   -- 如果不需要,请删除此函数
 end
 
 function update(self, dt)
-   -- Add update code here
-   -- Remove this function if not needed
+   -- 在此添加更新代码
+   -- 如果不需要,请删除此函数
 end
 
 function on_message(self, message_id, message, sender)
-   -- Add message-handling code here
-   -- Remove this function if not needed
+   -- 在此添加消息处理代码
+   -- 如果不需要,请删除此函数
 end
 
 function on_input(self, action_id, action)
-   -- Add input-handling code here
-   -- Remove this function if not needed
+   -- 在此添加输入处理代码
+   -- 如果不需要,请删除此函数
 end
 
 function on_reload(self)
-   -- Add input-handling code here
-   -- Remove this function if not needed
+   -- 在此添加输入处理代码
+   -- 如果不需要,请删除此函数
 end
 ```
 
-要把脚本添加到 GUI 组件, 打开 GUI 蓝图文件, 在 *Outline* 里选择根节点显示出 GUI *Properties*. 把 *Script* 属性设置为脚本文件即可.
+要将脚本附加到GUI组件,请打开GUI组件原型文件(在其他引擎中也称为"prefabs"或"blueprints"),并在*Outline*中选择根节点以调出GUI*Properties*。将*Script*属性设置为脚本文件。
 
 ![Script](images/gui-script/set_script.png)
 
-如果这个 GUI 组件被添加到游戏中的游戏对象里, 它上面的脚本就可以运行了.
+如果GUI组件已添加到游戏中某处的游戏对象,脚本现在将运行。
 
-## "gui" 命名空间
+## "gui"命名空间
 
-GUI 脚本访问 `gui` 命名空间及其 [所有gui函数](/ref/gui). `go` 命名空间不可用, 所以要注意区分游戏对象的脚本组件以及二者间的消息传递. 尝试使用 `go` 函数会报错:
+GUI脚本可以访问`gui`命名空间和[所有gui函数](/ref/gui)。`go`命名空间不可用,因此您需要将游戏对象逻辑分离到脚本组件中,并在GUI和游戏对象脚本之间进行通信。任何尝试使用`go`函数的操作都会导致错误:
 
 ```lua
 function init(self)
@@ -70,9 +70,9 @@ stack traceback:
 
 ## 消息传递
 
-游戏运行时 GUI 脚本可与其他对象互相传递消息, 同其他脚本组件相同.
+任何附加了脚本的GUI组件都能够通过消息传递与游戏运行时环境中的其他对象通信,它的行为就像任何其他脚本组件一样。
 
-定位 GUI 组件也与其他脚本组件中定位方法相同:
+您可以像处理任何其他脚本组件一样寻址GUI组件:
 
 ```lua
 local stats = { score = 4711, stars = 3, health = 6 }
@@ -81,16 +81,16 @@ msg.post("hud#gui", "set_stats", stats)
 
 ![message passing](images/gui-script/message_passing.png)
 
-## 定位节点
+## 寻址节点
 
-GUI 中的节点可由脚本控制. 在编辑器中每个节点都有唯一 *Id*:
+GUI节点可以通过附加到组件的GUI脚本进行操作。每个节点必须在编辑器中设置唯一的*Id*:
 
 ![message passing](images/gui-script/node_id.png)
 
-*Id* 使得脚本引用节点并对其使用 [gui 命名空间函数](/ref/gui) 进行控制:
+*Id*允许脚本获取对节点的引用,并使用[gui命名空间函数](/ref/gui)对其进行操作:
 
 ```lua
--- 扩展 10 单位血条
+-- 扩展血条10个单位
 local healthbar_node = gui.get_node("healthbar")
 local size = gui.get_size(healthbar_node)
 size.x = size.x + 10
@@ -99,16 +99,16 @@ gui.set_size(healthbar_node, size)
 
 ## 动态创建节点
 
-在运行时使用脚本创建新节点有两种方法. 一种是通过调用 `gui.new_[type]_node()` 函数. 该函数返回新节点引用以便对其进行控制:
+要在运行时使用脚本创建新节点,您有两个选择。第一个选择是通过调用`gui.new_[type]_node()`函数从头创建节点。这些函数返回对新节点的引用,您可以使用该引用来操作节点:
 
 ```lua
--- 新建节点
+-- 创建新方框节点
 local new_position = vmath.vector3(400, 300, 0)
 local new_size = vmath.vector3(450, 400, 0)
 local new_boxnode = gui.new_box_node(new_position, new_size)
 gui.set_color(new_boxnode, vmath.vector4(0.2, 0.26, 0.32, 1))
 
--- 新文本节点
+-- 创建新文本节点
 local new_textnode = gui.new_text_node(new_position, "Hello!")
 gui.set_font(new_textnode, "sourcesans")
 gui.set_color(new_textnode, vmath.vector4(0.69, 0.6, 0.8, 1.0))
@@ -116,7 +116,7 @@ gui.set_color(new_textnode, vmath.vector4(0.69, 0.6, 0.8, 1.0))
 
 ![dynamic node](images/gui-script/dynamic_nodes.png)
 
-第二种方法是通过调用 `gui.clone()` 函数克隆一个已存在的节点或者通过调用 `gui.clone_tree()` 函数克隆一个已存在的节点树:
+创建新节点的另一种方法是使用`gui.clone()`函数克隆现有节点,或使用`gui.clone_tree()`函数克隆节点树:
 
 ```lua
 -- 克隆血条
@@ -127,23 +127,23 @@ local healthbar_node_2 = gui.clone(healthbar_node)
 local button = gui.get_node("my_button")
 local new_button_nodes = gui.clone_tree(button)
 
--- 获得节点树根节点
+-- 获取新树的根节点
 local new_root = new_button_nodes["my_button"]
 
--- 向右移动根节点 (及其子节点) 300 像素
+-- 将根节点(及其子节点)向右移动300个单位
 local root_position = gui.get_position(new_root)
 root_position.x = root_position.x + 300
 gui.set_position(new_root, root_position)
 ```
 
-## 动态节点id
+## 动态节点ID
 
-动态创建的节点没有id. 设计上就是这样. 引用由 `gui.new_[type]_node()`, `gui.clone()` 和 `gui.clone_tree()` 函数返回, 这是访问动态节点的唯一途径, 记得保留好这个引用.
+动态创建的节点没有分配ID。这是设计上的选择。从`gui.new_[type]_node()`、`gui.clone()`和`gui.clone_tree()`返回的引用是访问节点所必需的唯一内容,您应该跟踪该引用。
 
 ```lua
 -- 添加文本节点
 local new_textnode = gui.new_text_node(vmath.vector3(100, 100, 0), "Hello!")
--- "new_textnode" 保存新节点的引用.
--- 新节点没有 id, 但是没关系. 得到节点的引用
--- 就没有必要使用 gui.get_node() 函数了.
+-- "new_textnode"包含对节点的引用。
+-- 节点没有ID,这很好。我们没有理由想要
+-- 在我们已经有引用的情况下使用gui.get_node()。
 ```

+ 3 - 3
docs/zh/manuals/gui-spine.md

@@ -1,6 +1,6 @@
 ---
-title: Defold GUI Spine 节点
-brief: 本教程介绍了 Defold GUI 场景中骨骼动画 Spine 节点的使用.
+title: Defold GUI Spine节点
+brief: 本手册解释了如何在Defold GUI场景中使用骨骼动画Spine节点。
 ---
 
-[该教程已被移至这里](/extension-spine).
+[此手册已移至](/extension-spine)。

+ 19 - 19
docs/zh/manuals/gui-template.md

@@ -1,56 +1,56 @@
 ---
-title: GUI 模板教程
-brief: 本教程介绍了用以创建基于模板(或称作'prefabs')的可重用可视 GUI 组件的 Defold GUI 模板系统.
+title: GUI模板手册
+brief: 本手册解释了Defold GUI模板系统,该系统用于创建基于共享模板或'prefabs'的可重用可视化GUI组件。
 ---
 
-# GUI 模板节点
+# GUI模板节点
 
-GUI 模板节点提供了基于模板或者叫 "prefabs"基于模板或者叫 "prefabs" 创建可重用 GUI 组件的有效机制. 本教程介绍了如何使用这一特性.
+GUI模板节点提供了一种强大的机制,用于基于共享模板或"prefabs"创建可重用的GUI组件。本手册解释了这一功能及其使用方法。
 
-GUI 模板是 GUI 某个场景的实例化版本. GUI 模板里节点的设置可以覆盖GUI场景的设定.
+GUI模板是在另一个GUI场景中逐个节点实例化的GUI场景。然后可以覆盖原始模板节点中的任何属性值。
 
 ## 创建模板
 
-GUI 模板也是一种场景, 创建和普通场景一样. 在 *Assets* 面板里某位置上 <kbd>右键点击</kbd> 然后选择 <kbd>New... ▸ Gui</kbd>.
+GUI模板是一个普通的GUI场景,因此它的创建方式与任何其他GUI场景相同。在 *Assets* 面板中<kbd>右键点击</kbd>一个位置并选择 <kbd>New... ▸ Gui</kbd>。
 
 ![Create template](images/gui-templates/create.png)
 
-输入名称并保存. 注意节点都是参照模板原点设置位置的, 所以模板位置也最好设置成 0, 0, 0.
+创建模板并保存。注意,实例的节点将相对于原点放置,因此在 0, 0, 0 位置创建模板是一个好主意。
 
-## 创建模板节点
+## 从模板创建实例
 
-一个模板可以创建许多实例. 先创建或者打开 GUI 场景, 然后 <kbd>右键点击</kbd> *Outline* 视图里的 *Nodes* 部分, 然后选择 <kbd>Add ▸ Template</kbd>.
+您可以根据模板创建任意数量的实例。创建或打开要放置模板的GUI场景,然后在*Outline*视图中<kbd>右键点击</kbd>*Nodes*部分,并选择<kbd>Add ▸ Template</kbd>。
 
 ![Create instance](images/gui-templates/create_instance.png)
 
-然后便可以在GUI场景里设置 *Template* 的属性.
+将*Template*属性设置为模板GUI场景文件。
 
-一个模板可以创建多个实例节点, 实例里的每个节点都可以修改自身属性, 比如位置,  颜色, 大小, 纹理之类的.
+您可以添加任意数量的模板实例,并且对于每个实例,您可以覆盖每个节点的属性,并更改实例节点的位置、颜色、大小、纹理等。
 
 ![Instances](images/gui-templates/instances.png)
 
-更改了的属性会以蓝色显示. 点击重置按钮可以退回成原始的模板属性:
+任何已更改的属性在编辑器中会标记为蓝色。单击属性旁边的重置按钮可将其值设置为模板值:
 
 ![Properties](images/gui-templates/properties.png)
 
-被修改了属性的节点也会在 *Outline* 视图中以蓝色显示:
+任何具有覆盖属性的节点在*Outline*视图中也会以蓝色显示:
 
 ![Outline](images/gui-templates/outline.png)
 
-这些模板实例以折叠方式在 *Outline* 视图中显示. 然而, 你要明确它 *不是一个普通节点*. 同样, 运行时也没有模板的概念, 只是其所有节点存在着.
+模板实例在*Outline*视图中列为可折叠条目。但是,需要注意的是,大纲中的此项*不是一个节点*。模板实例在运行时也不存在,但属于实例的所有节点都存在。
 
-有些模板实例会自动以 模板名加正斜杠 (`"/"`) 加 *Id* 的形式命名.
+属于模板实例的节点会自动在其*Id*前附加前缀和斜杠(`"/"`)。前缀是在模板实例中设置的*Id*。
 
 ## 运行时修改模板
 
-代码访问节点只需使用模板 *Id* 作为前缀加上实例节点名即可:
+操作或查询通过模板机制添加的节点的脚本只需要考虑实例节点的命名,并将模板实例*Id*作为节点名称前缀包含在内:
 
 ```lua
 if gui.pick_node(gui.get_node("button_1/button"), x, y) then
-    -- Do something...
+    -- 做些什么...
 end
 ```
 
-模板本身没有实例. 如果需要根节点, 请在模板里面添加.
+没有与模板实例本身对应的节点。如果需要实例的根节点,请将其添加到模板中。
 
-如果脚本被添加到 GUI 场景里, 那么此脚本不存在于节点树状结构中. 每个 GUI 场景可以添加一个脚本, 实例化的时候脚本执行与 GUI 场景之上.
+如果脚本与模板GUI场景相关联,则该脚本不属于实例节点树的一部分。您可以将单个脚本附加到每个GUI场景,因此您的脚本逻辑需要位于已实例化模板的GUI场景上。

+ 19 - 19
docs/zh/manuals/gui-text.md

@@ -1,51 +1,51 @@
 ---
-title: Defold GUI 文本节点
-brief: 本教程介绍了如何在 GUI 场景中添加文本.
+title: Defold GUI文本节点
+brief: 本手册描述了如何在GUI场景中添加文本。
 ---
 
-# GUI 文本节点
+# GUI文本节点
 
-Defold 支持专门用于GUI场景中显示文本的GUI节点. 各种字体资源都可以被文本节点用以渲染文字.
+Defold支持一种特定类型的GUI节点,允许在GUI场景中渲染文本。项目中添加的任何字体资源都可以用于文本节点渲染。
 
 ## 添加文本节点
 
-需要在文本节点使用的字体首先要应用到 GUI 组件之中. 或者使用右键点击 *Fonts* 文件夹, 使用 <kbd>GUI</kbd> 顶级菜单或者快捷键.
+您希望在GUI文本节点中使用的字体必须添加到GUI组件中。可以右键单击*Fonts*文件夹,使用<kbd>GUI</kbd>顶部菜单或按相应的键盘快捷键。
 
 ![Fonts](images/gui-text/fonts.png)
 
-文本节点有一些特有属性:
+文本节点具有一组特殊属性:
 
 *Font*
-: 每个文本节点都要有 *字体* 属性设置.
+: 您创建的任何文本节点都必须设置*Font*属性。
 
 *Text*
-: 此属性设置节点显示的文字.
+: 此属性包含显示的文本。
 
 *Line Break*
-: 文本对齐与锚点相关, 此属性可以让文本流动几行. 节点宽度决定文本在哪里换行.
+: 文本对齐遵循 pivot 设置,设置此属性允许文本流到多行。节点的宽度决定文本将在何处换行。
 
-## 锚点和对齐
+## 对齐
 
-你可以通过设置锚点来改变文本的对齐方式.
+通过设置节点 pivot,您可以更改文本的对齐模式。
 
 *Center*
-: 如果锚点设置成 `Center`, `North` 或者 `South`, 则文本居中对齐.
+: 如果 pivot 设置为`Center`、`North`或`South`,则文本居中对齐。
 
 *Left*
-: 如果锚点设置成任何 `West` 模式, 则文本左对齐.
+: 如果 pivot 设置为任何`West`模式,则文本左对齐。
 
 *Right*
-: 如果锚点设置成任何 `East` 模式, 则文本右对齐.
+: 如果 pivot 设置为任何`East`模式,则文本右对齐。
 
 ![文本对齐](images/gui-text/align.png)
 
-## 运行时控制操作
+## 运行时修改文本节点
 
-文本节点同样可以控制 size, pivot, color 之类的属性. 此外还有一些文本节点特有属性:
+文本节点响应任何通用的节点操作函数,用于设置大小、pivot、颜色等。存在一些仅用于文本节点的函数:
 
-* 要改变文本字体, 使用 [`gui.set_font()`](/ref/gui/#gui.set_font) 函数.
-* 要改变文本换行行为, 使用 [`gui.set_line_break()`](/ref/gui/#gui.set_line_break) 函数.
-* 要改变文本文字, 使用 [`gui.set_text()`](/ref/gui/#gui.set_text) 函数.
+* 要更改文本节点的字体,请使用[`gui.set_font()`](/ref/gui/#gui.set_font)函数。
+* 要更改文本节点的换行行为,请使用[`gui.set_line_break()`](/ref/gui/#gui.set_line_break)函数。
+* 要更改文本节点的内容,请使用[`gui.set_text()`](/ref/gui/#gui.set_text)函数。
 
 ```lua
 function on_message(self, message_id, message, sender)

+ 214 - 137
docs/zh/manuals/gui.md

@@ -1,289 +1,366 @@
 ---
-title: Defold 里的 GUI 场景
-brief: 本教程介绍了 Defold GUI 编辑器, 各种各样的 GUI 节点以及 GUI 脚本.
+title: Defold中的GUI场景
+brief: 本手册介绍了Defold GUI编辑器、各种类型的GUI节点和GUI脚本。
 ---
 
 # GUI
 
-Defold 提供了 GUI 编辑器以及与之配套的脚本用以实现用户界面.
+Defold为您提供了自定义的GUI编辑器和强大的脚本功能,这些功能专门用于构建和实现用户界面。
 
-Defold 的图形用户界面是被放在集合里的, 依附于游戏对象的 GUI 组件. 这种组件有如下特点:
+Defold中的图形用户界面是一个组件,您可以构建它并将其附加到游戏对象上,然后放置在集合中。该组件具有以下特性:
 
-* 简单且功能强大的布局功能, 可以适配各种分辨率和纵横比的屏幕
-* 通过 *GUI 脚本* 进行逻辑控制.
-* 界面 (默认) 被渲染于其他内容之上, 于视口摄像机无关, GUI 始终保持最上端显示. 这种特性可以根据需要手动修改.
+* 它具有简单但强大的布局功能,允许您的用户界面进行独立于分辨率和纵横比的渲染。
+* 它可以通过*GUI脚本*附加逻辑行为。
+* 它(默认情况下)在其他内容之上渲染,与摄像机视图无关,因此即使您有移动的摄像机,您的GUI元素也会保持在屏幕上的位置。渲染行为可以更改。
 
-界面独立于游戏内容. 所以集合编辑器里并不显示界面元素. 但是界面必须依附于一个游戏对象而这个游戏对象要被放在集合里. 具体放在集合什么位置上并不影响界面的位置.
+GUI组件独立于游戏视图渲染。因此,它不会放置在集合编辑器中的特定位置,也不会在集合编辑器中具有视觉表示。但是,GUI组件必须驻留在位于集合中的游戏对象中。更改该位置不会对GUI产生影响。
 
-## 创建界面文
+## 创建GUI组
 
-GUI 的创建基于一个模板文件. 要新建GUI文件, 在 *Assets* 浏览器中 <kbd>右键点击</kbd> 然后选择 <kbd>New ▸ Gui</kbd>. 为文件命名然后点击 <kbd>Ok</kbd>.
+GUI组件是从GUI场景原型文件(在其他引擎中也称为"prefabs"或"blueprints")创建的。要创建新的GUI组件,在*Assets*浏览器中<kbd>右键点击</kbd>一个位置,然后选择<kbd>New ▸ Gui</kbd>。为新GUI文件键入一个名称,然后按<kbd>Ok</kbd>。
 
 ![New gui file](images/gui/new_gui_file.png)
 
-Defold 会自动启动场景编辑器打开这个文件.
+Defold现在会自动在GUI场景编辑器中打开该文件。
 
 ![New gui](images/gui/new_gui.png)
 
-*大纲* 视图里列出了所有 GUI:s 内容: 节点及其资源列表(见下文).
+*Outline*列出了所有GUI的内容:它的节点列表和任何依赖项(见下文)。
 
-中间编辑区显示 GUI. 右上角的工具栏有 *移动*, *旋转* 和 *缩放* 工具, 以及一个 [布局](/manuals/gui-layouts) 选择器.
+中央编辑区域显示GUI。编辑区域右上角的工具栏包含*移动*、*旋转*和*缩放*工具,以及一个[布局](/manuals/gui-layouts)选择器。
 
 ![toolbar](images/gui/toolbar.png)
 
-当前布局用白色方框表示, 其宽度高度是在项目配置文件里设置的.
+白色矩形显示当前选定布局的边界,即项目设置中设置的默认显示宽度和高度。
 
-在 *大纲* 视图中选中根节点 "Gui" 就会显示出当前GUI的 *属性*:
+## Gui属性
 
-Script
-: 当前界面的GUI脚本.
+在*Outline*中选择根"Gui"节点会显示GUI组件的*Properties*:
 
-Material
-: 当前界面的渲染用材质.
+*Script*
+: 绑定到此GUI组件的GUI脚本。
 
-Adjust Reference
-: 控制节点的 *Adjust Mode* 算法:
+*Material*
+: 渲染此GUI时使用的材质。请注意,也可以从大纲面板向GUI添加多个材质,并将这些材质分配给各个节点。
 
-  - `Per Node` 当父节点或屏幕大小改变时, 调整各个节点大小.
-  - `Disable` 关闭调整. 各个节点保持不变.
+*Adjust Reference*
+: 控制如何计算每个节点的*Adjust Mode*:
 
-Max Nodes
-: 界面最大节点数.
+  - `Per Node` 根据父节点调整后的大小或调整后的屏幕大小调整每个节点。
+  - `Disable` 关闭节点调整模式。这将强制所有节点保持其设置的大小。
 
-## 资源
+*Current Nodes*
+: 此GUI中当前使用的节点数。
 
-界面的结构与集合不同, 是分门别类的. *Outline* 视图中可以看到所有资源都被按照其类型分配到 "子文件夹" 下:
+*Max Nodes*
+: 此GUI的最大节点数。
+
+*Max Dynamic Textures*
+: 可以使用[`gui.new_texture()`](/ref/stable/gui/#gui.new_texture:texture_id-width-height-type-buffer-flip)创建的最大纹理数。
+
+## 运行时操作
+
+您可以使用`go.get()`和`go.set()`从脚本组件在运行时操作GUI属性:
+
+字体
+: 获取或设置GUI中使用的字体。
+
+![get_set_font](images/gui/get_set_font.png)
+
+```lua
+go.property("mybigfont", resource.font("/assets/mybig.font"))
+
+function init(self)
+  -- 获取当前分配给id为'default'的字体的字体文件
+  print(go.get("#gui", "fonts", { key = "default" })) -- /builtins/fonts/default.font
+
+  -- 将id为'default'的字体设置为分配给资源属性'mybigfont'的字体文件
+  go.set("#gui", "fonts", self.mybigfont, { key = "default" })
+
+  -- 获取分配给id为'default'的新字体文件
+  print(go.get("#gui", "fonts", { key = "default" })) -- /assets/mybig.font
+end
+```
+
+材质
+: 获取或设置GUI中使用的材质。
+
+![get_set_material](images/gui/get_set_material.png)
+
+```lua
+go.property("myeffect", resource.material("/assets/myeffect.material"))
+
+function init(self)
+  -- 获取当前分配给id为'effect'的材质文件
+  print(go.get("#gui", "materials", { key = "effect" })) -- /effect.material
+
+  -- 将id为'effect'的材质设置为分配给资源属性'myeffect'的材质文件
+  go.set("#gui", "materials", self.myeffect, { key = "effect" })
+
+  -- 获取分配给id为'effect'的新材质文件
+  print(go.get("#gui", "materials", { key = "effect" })) -- /assets/myeffect.material
+end
+```
+
+纹理
+: 获取或设置GUI中使用的纹理(图集)。
+
+![get_set_texture](images/gui/get_set_texture.png)
+
+```lua
+go.property("mytheme", resource.atlas("/assets/mytheme.atlas"))
+
+function init(self)
+  -- 获取当前分配给id为'theme'的纹理文件
+  print(go.get("#gui", "textures", { key = "theme" })) -- /theme.atlas
+
+  -- 将id为'theme'的纹理设置为分配给资源属性'mytheme'的纹理文件
+  go.set("#gui", "textures", self.mytheme, { key = "theme" })
+
+  -- 获取分配给id为'theme'的新纹理文件
+  print(go.get("#gui", "textures", { key = "theme" })) -- /assets/mytheme.atlas
+end
+```
+
+## 依赖项
+
+Defold游戏中的资源树是静态的,因此您需要为GUI节点添加的任何依赖项都必须添加到组件中。*Outline*按类型将所有依赖项分组在"文件夹"下:
 
 ![dependencies](images/gui/dependencies.png)
 
-要添加资源, <kbd>右键点击k</kbd> *Outline* 里的 "Gui" 根节点, 然后从上下文菜单中选择 <kbd>Add ▸ [资源类型]</kbd>.
+要添加新的依赖项,将其从*Asset*窗格拖放到编辑器视图中。
 
-也可以在相应类型文件夹上 <kbd>右键点击</kbd> 然后选择 <kbd>Add ▸ [资源类型]</kbd>.
+或者,<kbd>右键点击</kbd>*Outline*中的"Gui"根节点,然后从弹出上下文菜单中选择<kbd>Add ▸ [type]</kbd>。
+
+您也可以<kbd>右键点击</kbd>要添加类型的文件夹图标,然后选择<kbd>Add ▸ [type]</kbd>。
 
 ## 节点类型
 
-界面有节点组成. 节点是一种类似游戏对象的元素. 可以进行位移 (移动, 旋转和缩放) 并且以父子树形结构排列. 有以下几种节点类型:
+GUI组件由一组节点构建而成。节点是简单的元素。它们可以被平移(移动、缩放和旋转),并在编辑器中或通过脚本在运行时按父子层次结构排序。存在以下节点类型:
 
 Box node
 : ![box node](images/icons/gui-box-node.png){.left}
-  显示为纯色, 纹理或者逐帧动画的矩形. 详情请见 [方块节点教程](/manuals/gui-box).
+  具有单一颜色、纹理或翻书动画的矩形节点。详情请参见[Box节点文档](/manuals/gui-box)。
 
 <div style="clear: both;"></div>
 
 Text node
 : ![text node](images/icons/gui-text-node.png){.left}
-  显示文字. 详情请见 [文本节点教程](/manuals/gui-text).
+  显示文本。详情请参见[Text节点文档](/manuals/gui-text)。
 
 <div style="clear: both;"></div>
 
 Pie node
 : ![pie node](images/icons/gui-pie-node.png){.left}
-  圆形或椭圆饼图. 详情请见 [饼图节点教程](/manuals/gui-pie).
+  可以部分填充或反转的圆形或椭圆节点。详情请参见[Pie节点文档](/manuals/gui-pie)。
 
 <div style="clear: both;"></div>
 
 Template node
 : ![template node](images/icons/gui.png){.left}
-  模板用来基于其他界面文件创建节点实例. 详情请见 [模板节点教程](/manuals/gui-template).
+  模板用于基于其他GUI场景文件创建实例。详情请参见[Template节点文档](/manuals/gui-template)。
 
 <div style="clear: both;"></div>
 
 ParticleFX node
 : ![particlefx node](images/icons/particlefx.png){.left}
-  显示粒子特效. 详情请见 [粒子特效节点教程](/manuals/gui-particlefx).
+  播放粒子效果。详情请参见[ParticleFX节点文档](/manuals/gui-particlefx)。
 
 <div style="clear: both;"></div>
 
-右键点击 *Nodes* 文件夹选择 <kbd>Add ▸</kbd> 然后点击 <kbd>Box</kbd>, <kbd>Text</kbd>, <kbd>Pie</kbd>, <kbd>Template</kbd> 或 <kbd>ParticleFx</kbd> 即可创建节点.
+通过右键点击*Nodes*文件夹并选择<kbd>Add ▸</kbd>,然后选择<kbd>Box</kbd>、<kbd>Text</kbd>、<kbd>Pie</kbd>、<kbd>Template</kbd>或<kbd>ParticleFx</kbd>来添加节点。
 
 ![Add nodes](images/gui/add_node.png)
 
-还可以用快捷键 <kbd>A</kbd> 来创建节点.
+您也可以按<kbd>A</kbd>并选择要添加到GUI的类型。
 
 ## 节点属性
 
-节点有自身属性:
+每个节点都有一组广泛的属性来控制其外观:
 
 Id
-: 节点id. 每个id是这个界面中的唯一值.
+: 节点的标识。此名称在GUI场景中必须是唯一的。
 
 Position, Rotation and Scale
-: 节点位移. 可以使用 *移动*, *旋转* 和 *缩放* 工具自由修改. 也可以用脚本动画形式控制这些值.
+: 控制节点的位置、方向和拉伸。您可以使用*移动*、*旋转*和*缩放*工具更改这些值。这些值可以从脚本中动画化([了解更多](/manuals/property-animation))。
 
-Size (box, text 和 pie 节点)
-: 默认尺寸设置为自动, 如果需要手动设定尺寸可以设置 *Size Mode* 为 `Manual`. 节点尺寸决定了节点接收输入操作的范围. 此值也可使用脚本动画进行控制.
+Size (box, text和pie节点)
+: 节点的大小默认为自动,但通过将*Size Mode*设置为`Manual`,您可以更改该值。大小定义了节点的边界,并在进行输入选择时使用。此值可以从脚本中动画化([了解更多](/manuals/property-animation))。
 
-Size Mode (box 和 pie 节点)
-: 如果设为 `Automatic` 则自动计算并设置节点尺寸. 如果设为 `Manual` 则需手动设置节点尺寸.
+Size Mode (box和pie节点)
+: 如果设置为`Automatic`,编辑器将为节点设置大小。如果设置为`Manual`,您可以自己设置大小。
 
 Enabled
-: 如果未选中, 则节点不会被渲染, 不会被动画驱动且不能使用 `gui.pick_node()` 返回节点. 可以使用 `gui.set_enabled()` 和 `gui.is_enabled()` 函数手动打开或检查该属性.
+: 如果未选中,节点不会被渲染,不会被动画化,也不能使用`gui.pick_node()`进行选择。使用`gui.set_enabled()`和`gui.is_enabled()`以编程方式更改和检查此属性。
 
 Visible
-: 如果未选中, 则节点不会被渲染, 但是可以被动画驱动且可以使用 `gui.pick_node()` 返回节点. 可以使用 `gui.set_visible()` 和 `gui.get_visible()` 函数手动打开或检查该属性.
+: 如果未选中,节点不会被渲染,但仍然可以被动画化,并且可以使用`gui.pick_node()`进行选择。使用`gui.set_visible()`和`gui.get_visible()`以编程方式更改和检查此属性。
+
+Text (text节点)
+: 要在节点上显示的文本。
 
-Text (text 节点)
-: 节点上显示的文字.
+Line Break (text节点)
+: 设置文本根据节点的宽度进行换行。
 
-Line Break (text 节点)
-: 文字基于节点宽度换行.
+Font (text节点)
+: 渲染文本时要使用的字体。
 
-Font (text 节点)
-: 文字字体.
+Texture (box和pie节点)
+: 要在节点上绘制的纹理。这是对图集或瓷砖图源中的图像或动画的引用。
 
-Texture (box 和 pie 节点)
-: 节点上显示的纹理. 可以使用图集和瓷砖图源的图片或动画.
+Material (box, pie节点, text和particlefx节点)
+: 绘制节点时要使用的材质。这可以是添加到大纲的Materials部分的材质,或者留空以使用分配给GUI组件的默认材质。
 
-Slice 9 (box 节点)
-: 缩放九宫格. 详情请见 [box 节点教程](/manuals/gui-box).
+Slice 9 (box节点)
+: 设置当节点调整大小时保留节点纹理边缘周围的像素大小。详情请参见[Box节点文档](/manuals/gui-box)。
 
-Inner Radius (pie 节点)
-: 节点内半径, 延 X 轴. 详情请见 [pie 节点教程](/manuals/gui-pie).
+Inner Radius (pie节点)
+: 节点的内半径,沿X轴表示。详情请参见[Pie节点文档](/manuals/gui-pie)。
 
-Outer Bounds (pie 节点)
-: 节点外轮廓. 详情请见 [pie 节点教程](/manuals/gui-pie).
+Outer Bounds (pie节点)
+: 控制外边界的行为。详情请参见[Pie节点文档](/manuals/gui-pie)。
 
-Perimeter Vertices (pie 节点)
-: 图形的分段数, 就是360度一圈需要的顶点数. 详情请见 [Pie 节点教程](/manuals/gui-pie)
+Perimeter Vertices (pie节点)
+: 将用于构建形状的段数。详情请参见[Pie节点文档](/manuals/gui-pie)。
 
-Pie Fill Angle (pie 节点)
-: 饼状图的填充. 详情请见 [Pie 节点教程](/manuals/gui-pie)
+Pie Fill Angle (pie节点)
+: 饼图应该填充多少。详情请参见[Pie节点文档](/manuals/gui-pie)。
 
-Template (template 节点)
-: 节点模板界面文件. 详情请见 [Template 节点教程](/manuals/gui-template)
+Template (template节点)
+: 用作节点模板的GUI场景文件。详情请参见[Template节点文档](/manuals/gui-template)。
 
-ParticleFX (particlefx 节点)
-: 节点上显示的粒子特效. 详情请见 [ParticleFX 节点教程](/manuals/gui-particlefx)
+ParticleFX (particlefx节点)
+: 在此节点上使用的粒子效果。详情请参见[ParticleFX节点文档](/manuals/gui-particlefx)。
 
 Color
-: 节点颜色. 如果用纹理填充, 则对纹理进行染色. 颜色可由脚本动画控制.
+: 节点的颜色。如果节点有纹理,颜色会着色纹理。颜色可以从脚本中动画化([了解更多](/manuals/property-animation))。
 
 Alpha
-: 节点不透明度. 不透明度可由脚本动画控制.
+: 节点的半透明性。alpha值可以从脚本中动画化([了解更多](/manuals/property-animation))。
 
 Inherit Alpha
-: 继承父节点不透明度. 最终结果是父节点与此节点不透明度的叠加.
+: 设置此复选框使节点继承父节点的alpha值。然后节点的alpha值将与父节点的alpha值相乘。
 
-Leading (text 节点)
-: 每行开头空白. `0` 无空白. 默认值为 `1`.
+Leading (text节点)
+: 行间距的缩放数字。值为`0`表示没有行间距。`1`(默认值)是正常行间距。
 
-Tracking (text 节点)
-: 字符间距缩放值. 默认值为 0.
+Tracking (text节点)
+: 字母间距的缩放数字。默认为0。
 
 Layer
-: 把此节点分配给层. 详情请见下文.
+: 为节点分配层会覆盖正常的绘制顺序,而是遵循层顺序。详情请参见下文。
 
 Blend mode
-: 混合模式控制其与下层颜色混合后的结果:
-  - `Alpha` 覆盖下层颜色. 有的软件将其称作 "普通" 混合模式.
-  - `Add` 叠加下层颜色. 有的软件将其称作 "增强" 混合模式.
-  - `Multiply` 与下层颜色相乘.
-  - `Screen` 将节点的像素值与背景成反比. 这种混合模式在图形软件中称作 "Screen".
+: 控制节点图形与背景图形的混合方式:
+  - `Alpha` 将节点的像素值与背景进行alpha混合。这对应于图形软件中的"正常"混合模式。
+  - `Add` 将节点的像素值与背景相加。这对应于某些图形软件中的"线性减淡"。
+  - `Multiply` 将节点的像素值与背景相乘。
+  - `Screen` 将节点的像素值与背景成反比相乘。这对应于图形软件中的"屏幕"混合模式。
 
 Pivot
-: 节点的轴点. 可以看作是节点 "中心点". 各种旋转缩放等操作都基于这个轴点.
+: 设置节点的枢轴点。这可以看作是节点的"中心点"。任何旋转、缩放或大小更改都将围绕此点发生。
 
-  可选值有 `Center`, `North`, `South`, `East`, `West`, `North West`, `North East`, `South West` 和 `South East`.
+  可能的值是`Center`、`North`、`South`、`East`、`West`、`North West`、`North East`、`South West`或`South East`。
 
   ![pivot point](images/gui/pivot.png)
 
-  如果修改了节点的轴点, 节点会适当移动以保证坐标位置不变. 对于文本节点来说 `Center` 意味着文字居中对齐, `West` 意味着文字左对齐, `East` 意味着文字右对齐.
+  如果您更改节点的pivot,节点将移动,使新pivot位于节点的位置。文本节点对齐方式设置为`Center`表示文本居中对齐,`West`表示文本左对齐,`East`表示文本右对齐。
 
 X Anchor, Y Anchor
-: 锚点控制着当窗体或者父节点拉伸时当前节点位置如何处理.
+: 锚点控制当场景边界或父节点边界被拉伸以适应物理屏幕大小时节点的垂直和水平位置如何改变。
 
   ![Anchor unadjusted](images/gui/anchoring_unadjusted.png)
 
-  可选值有:
+  以下锚点模式可用:
 
-  - `None` (*X轴* 和 *Y轴*) 相对于窗体或者父节点的中心, 保持自身位置.
-  - `Left` 或 `Right` (*X轴*) 缩放水平方向位置以便保持其相对于窗体或者父节点宽度方向上的百分比位置不变.
-  - `Top` 或 `Bottom` (*Y轴*) 缩放垂直方向位置以便保持其相对于窗体或者父节点高度方向上的百分比位置不变.
+  - `None`(对于*X Anchor*和*Y Anchor*)保持节点相对于父节点或场景中心的位置,相对于其*调整后*的大小。
+  - `Left`或`Right`(*X Anchor*)缩放节点的水平位置,使其与父节点或场景的左边缘和右边缘保持相同的百分比距离。
+  - `Top`或`Bottom`(*Y Anchor*)缩放节点的垂直位置,使其与父节点或场景的顶部和底部边缘保持相同的百分比距离。
 
   ![Anchoring](images/gui/anchoring.png)
 
 Adjust Mode
-: 节点调整模式. 调整模式控制着当窗体或者父节点拉伸时当前节点尺寸如何处理.
+: 设置节点的调整模式。调整模式设置控制当场景边界或父节点边界被调整以适应物理屏幕大小时节点会发生什么。
 
-  这里有一个节点放置在逻辑分辨率为横屏的场景中:
+  在为典型横向分辨率创建的场景中创建的节点:
 
   ![Unadjusted](images/gui/unadjusted.png)
 
-  当场景需要填充竖屏时. 每个节点都会被拉伸. 但是如果使用了适当的调整模式, 节点内容的长宽比可以保持不变. 可选值有:
+  使场景适应纵向屏幕会导致场景被拉伸。每个节点的边界框同样被拉伸。但是,通过设置调整模式,可以保持节点内容的纵横比不变。以下模式可用:
 
-  - `Fit` 缩放节点内容,使其等于拉伸的边界框宽度或高度, 以数值最小者为准. 换句话说, 内容将拉伸到父级的边界.
-  - `Zoom` 缩放节点内容,使其等于拉伸的边界框宽度或高度, 以数值最大者为准. 换句话说, 内容将超越过父级的边界.
-  - `Stretch` 拉伸节点内容, 使其填充父级的边界框.
+  - `Fit` 缩放节点内容,使其等于拉伸的边界框宽度或高度,以较小者为准。换句话说,内容将适合拉伸的节点边界框内。
+  - `Zoom` 缩放节点内容,使其等于拉伸的边界框宽度或高度,以较大者为准。换句话说,内容将完全覆盖拉伸的节点边界框。
+  - `Stretch` 拉伸节点内容,使其填充拉伸的节点边界框。
 
   ![Adjust modes](images/gui/adjusted.png)
 
-  如果场景的 *Adjust Reference* 设置为 `Disabled` 的话, 此设置被忽略.
+  如果GUI场景属性*Adjust Reference*设置为`Disabled`,此设置将被忽略。
 
-Clipping Mode (box  pie 节点)
-: 剔除模式:
+Clipping Mode (box和pie节点)
+: 设置节点上的裁剪模式:
 
-  - `None` 正常渲染.
-  - `Stencil` 以当前节点边框作为子节点蒙版.
+  - `None` 正常渲染节点。
+  - `Stencil` 使节点边界定义用于裁剪节点子节点的模板蒙版。
 
-  详情请见 [GUI 蒙版教程](/manuals/gui-clipping)
+  详情请参见[GUI裁剪手册](/manuals/gui-clipping)。
 
-Clipping Visible (box  pie 节点)
-: 蒙版可见. 详情请见 [GUI clipping manual](/manuals/gui-clipping)
+Clipping Visible (box和pie节点)
+: 设置为在模板区域中渲染节点内容。详情请参见[GUI裁剪手册](/manuals/gui-clipping)。
 
-Clipping Inverted (box  pie 节点)
-: 反转蒙版. 详情请见 [GUI clipping manual](/manuals/gui-clipping)
+Clipping Inverted (box和pie节点)
+: 反转模板蒙版。详情请参见[GUI裁剪手册](/manuals/gui-clipping)。
 
 
-## 原点, 锚点和调整模式
+## 枢轴、锚点和调整模式
 
-轴点, 锚点和调整模式互相配合可以给设计者很大的发挥空间. 但是但凭想象很难搞清楚它们对应的具体功能. 这里列举了一个具体的例子, 屏幕分辨率 640x1136 的界面:
+枢轴、锚点和调整模式属性的组合允许非常灵活的GUI设计,但如果不看具体示例,可能很难理解它们是如何工作的。让我们以这个为640x1136屏幕创建的GUI模型为例:
 
 ![](images/gui/adjustmode_example_original.png)
 
- 界面的 X 和 Y 锚点为 None 调整模式为 left. 上面板轴点为 North, 下面板轴点为 South 上面版里的进度条轴点为 West. 其他节点轴点都为 Center. 如果把窗体拉宽, 看看会发生什么:
+界面是使用X和Y锚点设置为None创建的,每个节点的调整模式保留为默认值Fit。顶部面板的pivot是North,底部面板的pivot是South,顶部面板中的条的pivot设置为West。其余节点的pivot都设置为Center。如果我们将窗口调整得更宽,会发生以下情况:
 
 ![](images/gui/adjustmode_example_resized.png)
 
-如果我们希望上下面板保持屏幕宽度要怎么做? 可以把两个面板的调整模式设置为 Stretch:
+现在,如果我们希望顶部和底部条始终与屏幕一样宽怎么办?我们可以将顶部和底部的灰色背景面板的调整模式更改为Stretch:
 
 ![](images/gui/adjustmode_example_resized_stretch.png)
 
-出不多了. 上下两个面板会拉伸并一直保持屏幕宽度大小, 但是进度条和下面版的内容位置不太对. 要是想让进度条于上面版左对齐, 修改 X 锚点为 Left:
+这样更好。灰色背景面板现在将始终拉伸到窗口的宽度,但顶部面板中的条以及底部的两个框位置不正确。如果我们希望将顶部的条保持在左侧对齐,我们需要将X锚点从None更改为Left:
 
 ![](images/gui/adjustmode_example_top_anchor_left.png)
 
-上面版完美了. 进度条本身轴点是 West 也就是说让它们的左端 (轴点) 与父级面板左边缘 (X 锚点) 对齐.
+这正是我们想要的顶部面板。顶部面板中的条已经将其枢轴点设置为West,这意味着它们将很好地定位,条的左/西边缘(枢轴)锚定到父面板的左边缘(X锚点)。
 
-然后再把下面版左边方块的 X 锚点设置为 Left, 右边方块的 X 锚点设置为 Right, 就会变成这样:
+现在,如果我们将左侧框的X锚点设置为Left,右侧框的X锚点设置为Right,我们得到以下结果:
 
 ![](images/gui/adjustmode_example_bottom_anchor_left_right.png)
 
-结果还是不太对. 我们想让两个方块分别呆在下面版的左右两端. 但是轴点搞错了:
+这还不是预期的结果。两个框应该像顶部面板中的两个条一样保持靠近左右边缘。原因是pivot错误:
 
 ![](images/gui/adjustmode_example_bottom_pivot_center.png)
 
-两个方块的轴点都是 Center. 也就是说当窗体变宽时方块的位置 (轴点) 处于相对于边缘的固定位置上. 本例中左边方块在 640x1136 分辨率窗口中大约位于离左边界 17% 的地方:
+两个框的pivot都设置为Center。这意味着当屏幕变宽时,框的中心点(pivot)将保持与边缘相同的相对距离。对于左侧框,在原始的640x1136窗口中,它距离左边缘17%:
 
 ![](images/gui/adjustmode_example_original_ratio.png)
 
-屏幕缩放时它保持这个 17% 的位置:
+当屏幕调整大小时,左侧框的中心点保持与左边缘相同的17%距离:
 
 ![](images/gui/adjustmode_example_resized_stretch_ratio.png)
 
-如果把左边方块轴点设为 West, 右边方块设为 East 结果就是我们想要的样子了:
+如果我们将左侧框的pivot从Center更改为West,右侧框更改为East,并重新定位框,即使屏幕调整大小,我们也能得到我们想要的结果:
 
 ![](images/gui/adjustmode_example_bottom_pivot_west_east.png)
 
 
 ## 绘制顺序
 
-节点基于 "Nodes" 文件夹的排序进行绘制. 最高处节点最先绘制, 也就是会被放置于其他节点的后面. 最下面的节点最后绘制, 即它会位于其他节点前面. 至于节点 Z 值并不影响绘制顺序; 但是记得如果Z值超过了渲染脚本的渲染范围就不被渲染了. 可以使用层来覆盖这个默认的绘制顺序 (见下文).
+所有节点都按照它们在"Nodes"文件夹下列出的顺序进行渲染。列表顶部的节点首先绘制,因此将出现在所有其他节点的后面。列表中的最后一个节点最后绘制,意味着它将出现在所有其他节点的前面。更改节点上的Z值不会控制其绘制顺序;但是,如果您将Z值设置在渲染脚本的渲染范围之外,该节点将不再渲染到屏幕上。您可以使用层覆盖节点的索引顺序(见下文)。
 
 ![Draw order](images/gui/draw_order.png)
 
-选中节点按 <kbd>Alt + Up/Down</kbd> 移动其在列表中的排序.
+选择一个节点并按<kbd>Alt + Up/Down</kbd>向上或向下移动节点并更改其索引顺序。
 
-排序也可使用脚本控制:
+绘制顺序可以在脚本中更改:
 
 ```lua
 local bean_node = gui.get_node("bean")
@@ -294,50 +371,50 @@ if gui.get_index(shield_node) < gui.get_index(bean_node) then
 end
 ```
 
-## 父子结构
+## 父子层次结构
 
-把节点拖放到另一节点上就组成了一个父子结构. 子节点基于父节点轴点继承父节点的位移 (位置, 旋转和缩放).
+通过将一个节点拖放到您希望成为其父节点的节点上,使该节点成为另一个节点的子节点。具有父节点的节点继承应用于父节点的变换(位置、旋转和缩放),并相对于父节点pivot。
 
 ![Parent child](images/gui/parent_child.png)
 
-父节点先于子节点进行绘制. 使用层可以改变这个顺序还可以优化性能 (见下文).
+父节点在其子节点之前绘制。使用层来更改父节点和子节点的绘制顺序并优化节点的渲染(见下文)。
 
 
-## 层与 draw call
+## 层和绘制调用
 
-Layers 可以方便控制节点绘制顺序以及减少draw call. 引擎绘制界面前, 会根据以下规则合批渲染:
+层提供了对节点绘制方式的精细控制,可用于减少引擎绘制GUI场景必须创建的绘制调用次数。当引擎即将绘制GUI场景的节点时,它根据以下条件将节点分组到绘制调用批次中:
 
-- 节点类型相同.
-- 节点纹理源自同一张图集或瓷砖图源.
-- 节点的渲染模式相同.
-- 节点使用的字体相同.
+- 节点必须使用相同的类型。
+- 节点必须使用相同的图集或瓷砖图源。
+- 节点必须使用相同的混合模式渲染。
+- 它们必须使用相同的字体。
 
-如果有一条不符合, 就会破坏合批产生另一个 draw call. 蒙版和被蒙节点必然会破坏合批产生draw call.
+如果其中任何一个条件不满足,就会破坏合批并产生另一个绘制调用。蒙版和被蒙版节点必然会破坏合批并产生绘制调用。
 
-树形结构对于节点管理非常方便. 但是不同类型节点的混合一定会打破合批渲染:
+树形结构对于节点管理非常方便。但是混合不同类型的节点一定会破坏合批渲染:
 
 ![Breaking batch hierarchy](images/gui/break_batch.png)
 
-渲染管线被迫为不同类型的节点建立不同的渲染批次. 这三个按钮就会产生6次 draw call.
+渲染管线被迫为不同类型的节点建立不同的渲染批次。这三个按钮就会产生6次绘制调用。
 
-要是使用层, 就可以重塑节点的绘制顺序, 渲染管线就能更好地进行合批减少 draw call. 第一步新建层. 在 *Outline* 的 "Layers" 文件夹上 <kbd>右键点击</kbd> 然后选择 <kbd>Add ▸ Layer</kbd>. 在 *Properties* 视图中填充 *Name* 属性给层命名.
+如果使用层,可以重塑节点的绘制顺序,渲染管线就能更好地进行合批并减少绘制调用。第一步是创建新层。在*大纲*的"Layers"文件夹上<kbd>右键点击</kbd>,然后选择<kbd>Add ▸ Layer</kbd>。在*Properties*视图中填写*Name*属性为层命名。
 
 ![Layers](images/gui/layers.png)
 
-现在给每个节点的 *Layer* 属性都分配适当的层. 层的绘制顺序优先级高于默认情况, 所以把按钮底图都分配给 "graphics" 层, 文本节点都分配给 "text" 层, 那么界面绘制的顺序就是这样的:
+现在为每个节点的*Layer*属性分配适当的层。层的绘制顺序优先级高于默认情况,所以将按钮背景都分配给"graphics"层,文本节点都分配给"text"层,那么界面绘制的顺序就是这样的:
 
-* 先绘制 "graphics" 层里的节点:
+* 首先绘制"graphics"层中的节点:
 
   1. "button-1"
   2. "button-2"
   3. "button-3"
 
-* 再绘制 "text" 层里的节点:
+* 然后绘制"text"层中的节点:
 
   4. "button-text-1"
   5. "button-text-2"
   6. "button-text-3"
 
-这样一来合批就成形了, 不再需要那么多 draw call 了!
+这样一来合批就形成了,不再需要那么多绘制调用!
 
-注意如果子节点没有设置分配层默认继承分配父节点所在的层. 没有设置分配层的节点会被归为 "null" 层, 这个层最先被绘制.
+注意,如果子节点没有设置分配层,默认会继承分配父节点所在的层。没有设置分配层的节点会被归为"null"层,这个层最先被绘制。

+ 30 - 30
docs/zh/manuals/hot-reload.md

@@ -1,46 +1,46 @@
 ---
-title: 热重载
-brief: 本教程介绍了 Defold 中的热重载特性.
+title: Defold热重载
+brief: 本手册解释了Defold中的热重载功能。
 ---
 
 # 热重载资源
 
-Defold 允许资源的热重载. 开发游戏时此功能可以大大节省时间. 它可以让你在游戏运行时修改代码和内容. 经常用于:
+Defold允许您对资源进行热重载。在开发游戏时,此功能可以极大地加快某些任务的速度。它允许您在游戏运行时更改游戏的代码和内容。常见用例包括:
 
-- 使用 Lua 脚本调整游戏.
-- 编辑调整可视元素 (比如粒子特效或 GUI 元素) 即时观察效果.
-- 编辑调整 shader 代码即时观察效果.
-- 测试时重启关卡, 设定状态之类---而不用关闭游戏.
+- 在Lua脚本中调整游戏参数。
+- 编辑和调整图形元素(如粒子效果或GUI元素)并在适当的上下文中查看结果。
+- 编辑和调整着色器代码并在适当的上下文中查看结果。
+- 通过重启关卡、设置状态等来促进游戏测试---而无需停止游戏。
 
 ## 如何热重载
 
-从编辑器启动游戏 (<kbd>Project ▸ Build</kbd>).
+从编辑器启动游戏(<kbd>Project ▸ Build</kbd>)。
 
-选择菜单项 <kbd>File ▸ Hot Reload</kbd> 或者通过键盘快捷键实现热重载:
+然后要重新加载更新的资源,只需选择菜单项<kbd>File ▸ Hot Reload</kbd>或按键盘上相应的快捷键:
 
 ![Reloading resources](images/hot-reload/menu.png)
 
-## 设备上热重载
+## 设备上热重载
 
-除了桌面设备, 热重载也可以其他设备上使用. 要在设备上使用热重载, 在移动设备上运行游戏的调试(debug)版本, 或者运行 [开发应用](/manuals/dev-app) , 然后在编辑器中选择目标设备:
+热重载在设备上和桌面上一样有效。要在设备上使用它,请在您的移动设备上运行游戏的调试版本,或运行[开发应用](/manuals/dev-app),然后在编辑器中选择它作为目标:
 
 ![target device](images/hot-reload/target.png)
 
-当编译运行时, 编辑器会把所有资源上传到设备上运行着的游戏里. 也就是说, 热重载的所有文件都会在设备上进行更新.
+现在当您构建并运行时,编辑器会将所有资源上传到设备上运行的应用程序并启动游戏。从那时起,您热重载的任何文件都将在设备上更新。
 
-比如, 想在手机上运行着的游戏 GUI 上添加几个按钮, 仅需要打开 GUI 文件:
+例如,要在手机上运行的游戏中显示的GUI上添加几个按钮,只需打开GUI文件:
 
 ![reload gui](images/hot-reload/gui.png)
 
-加入按钮, 保存并热重载 GUI 文件. 然后在手机上就能看见新建的按钮了:
+添加新按钮,保存并热重载GUI文件。您现在可以在手机屏幕上看到新按钮:
 
 ![reloaded gui](images/hot-reload/gui-reloaded.png)
 
-当你将某个文件进行热重载, 游戏引擎会在控制台列出每个被热重载了的资源文件.
+当您热重载文件时,引擎将在控制台中打印每个重新加载的资源文件。
 
-## 重载脚本
+## 重新加载脚本
 
-任何被重载的 Lua 脚本文件都会在 Lua 运行环境里重新执行.
+任何重新加载的Lua脚本文件都将在运行的Lua环境中重新执行。
 
 ```lua
 local my_value = 10
@@ -50,7 +50,7 @@ function update(self, dt)
 end
 ```
 
-修改 `my_value` 为 11 然后进行热重载就可以看到改动立刻生效了:
+将`my_value`更改为11并热重载文件将立即生效:
 
 ```text
 ...
@@ -64,11 +64,11 @@ DEBUG:SCRIPT: 11
 ...
 ```
 
-注意热重载不影响生命周期函数的执行. 比如热更新不会自动调用 `init()` 函数. 当然在这些函数上所做的修改, 还是会被更新的.
+请注意,热重载不会改变生命周期函数的执行。例如,热重载时不会调用`init()`。但是,如果您重新定义生命周期函数,将使用新版本。
 
-## 重载 Lua 模块
+## 重新加载Lua模块
 
-只要在模块文件中加入了全局变量, 重载此模块文件后变量也会随之更新:
+只要您在模块文件中将变量添加到全局作用域,重新加载文件将更改这些全局变量:
 
 ```lua
 --- my_module.lua
@@ -81,15 +81,15 @@ my_module.val = 10
 require "my_module"
 
 function update(self, dt)
-    print(my_module.val) -- hot reload "my_module.lua" and the new value will print
+    print(my_module.val) -- 热重载 "my_module.lua",新值将被打印
 end
 ```
 
-Lua 模块的一个常用方法是构造一个局部数据表, 输出并返回它:
+常见的Lua模块模式是构造一个本地表,填充它然后返回它:
 
 ```lua
 --- my_module.lua
-local M = {} -- a new table object is created here
+local M = {} -- 在这里创建一个新的表对象
 M.val = 10
 return M
 ```
@@ -99,15 +99,15 @@ return M
 local mm = require "my_module"
 
 function update(self, dt)
-    print(mm.val) -- will print 10 even if you change and hot reload "my_module.lua"
+    print(mm.val) -- 即使您更改并热重载 "my_module.lua",仍将打印 10
 end
 ```
 
-更改并重载 "my_module.lua" 并 _不会_ 更新 "user.script" 的输出值. 关于这种情况的成因以及如何避免, 详见 [模块教程](/manuals/modules).
+更改并重新加载"my_module.lua"将_不会_改变"user.script"的行为。有关原因以及如何避免此陷阱的更多信息,请参见[模块手册](/manuals/modules)。
 
-## on_reload() 函数
+## on_reload()函数
 
-所有脚本组件都能定义 `on_reload()` 函数. 如果此函数存在, 则在重载时会自动被调用. 对于检查和修改数据, 发送消息之类的很有用:
+每个脚本组件都可以定义`on_reload()`函数。如果存在,它将在脚本重新加载时被调用。这对于检查或更改数据、发送消息等非常有用:
 
 ```lua
 function on_reload(self)
@@ -117,6 +117,6 @@ function on_reload(self)
 end
 ```
 
-## 重载shader数据
+## 重新加载着色器代码
 
-当重载顶点与片元着色器时, GLSL 代码会被显卡驱动程序重新编译并上传至 GPU. 因为 GLSL 很底层的所以很有可能出现着色器代码崩溃的情况, 这种情况下游戏引擎也会崩溃.
+重新加载顶点和片段着色器时,GLSL代码会被图形驱动程序重新编译并上传到GPU。如果着色器代码导致崩溃,这是很容易发生的,因为GLSL是在非常低的级别上编写的,它将使引擎崩溃。

+ 113 - 88
docs/zh/manuals/html5.md

@@ -1,131 +1,140 @@
 ---
-title: Defold HTML5 平台开发
-brief: 本教程介绍了 HTML5 游戏开发, 及其已知问题和局限性.
+title: Defold HTML5平台开发
+brief: 本手册描述了创建HTML5游戏的过程,以及已知问题和局限性。
 ---
 
-# HTML5 开发
+# HTML5开发
 
-通过编辑器编译菜单可以看到, Defold 支持导出 HTML5 游戏. 进一步说, 游戏会通过一个模板系统嵌入到一个 HTML 页面之中.
+Defold支持通过常规打包菜单为HTML5平台构建游戏,与其他平台一样。此外,生成的游戏会嵌入到一个常规HTML页面中,该页面可以通过简单的模板系统进行样式设置。
 
 *game.project* 文件包含了 HTML5 相关设置:
 
 ![Project settings](images/html5/html5_project_settings.png)
 
-## Heap size
+## 堆大小
 
-Defold 通过 Emscripten (详见 http://en.wikipedia.org/wiki/Emscripten) 支持 HTML5 导出. 简单地说, 它为应用的运行建立了一个虚拟内存堆. 默认情况下, 引擎分配了一块内存 (256MB). 这对一般游戏足够了. 通过游戏优化, 可以做到申请内存最小化. 要调整内存分配, 步骤如下:
+Defold对HTML5的支持由Emscripten驱动(参见http://en.wikipedia.org/wiki/Emscripten)。简而言之,它为应用程序运行的堆创建了一个内存沙箱。默认情况下,引擎分配了大量的内存(256MB)。这对于典型游戏来说应该绰绰有余。作为优化过程的一部分,您可以选择使用较小的值。为此,请按照以下步骤操作:
 
-1. 设置 *heap_size* 为需要的值. 以兆字节表示.
-2. 打包 HTML5 游戏 (见下文)
+1. 将*heap_size*设置为您偏好的值。它应以兆字节表示。
+2. 创建您的HTML5包(见下文)
 
-## 测试 HTML5 游戏
+## 测试HTML5构建
 
-要测试 HTML5 游戏, 需要先启动一个 HTTP 服务程序. Defold 可以通过 <kbd>Project ▸ Build HTML5</kbd> 启动内建 HTTP 服务.
+对于测试,HTML5构建需要一个HTTP服务器。如果您选择<kbd>Project ▸ Build HTML5</kbd>,Defold会为您创建一个。
 
 ![Build HTML5](images/html5/html5_build_launch.png)
 
-要测试 HTML5 游戏, 把游戏上传到远程 HTTP 服务器或者使用本地服务程序, 比如, 使用 python 自带的 HTTP 服务.
-Python 2:
-> python -m SimpleHTTPServer
+如果您想测试您的包,只需将其上传到远程HTTP服务器或在包文件夹中创建本地服务器,例如,使用python:
+Python 2:
 
-Python 3:
-> python -m http.server
+```sh
+python -m SimpleHTTPServer
+```
+
+Python 3:
+
+```sh
+python -m http.server
+```
 
 或者
-> python3 -m http.server
+
+```sh
+python3 -m http.server
+```
 
 ::: important
-不能直接用浏览器打开 HTML5 游戏的 `index.html` 文件. 要通过服务器访问打开.
+您不能通过在浏览器中打开`index.html`文件来测试HTML5包。这需要HTTP服务器。
 :::
 
 ::: important
-如果在控制台见到 "wasm streaming compile failed: TypeError: Failed to execute ‘compile’ on ‘WebAssembly’: Incorrect response MIME type. Expected ‘application/wasm’." 错误, 请确保你的服务器设置了 `application/wasm` MIME 类型对应 .wasm 文件.
+如果您在控制台中看到`"wasm streaming compile failed: TypeError: Failed to execute 'compile' on 'WebAssembly': Incorrect response MIME type. Expected 'application/wasm'."`错误,您必须确保您的服务器对`.wasm`文件使用`application/wasm` MIME类型。
 :::
 
-## HTML5游戏打
+## 创建HTML5包
 
-Defold 打包 HTML5 游戏很简单, 跟其他平台一样: 从菜单栏选择 <kbd>Project ▸ Bundle... ▸ HTML5 Application...</kbd> :
+使用Defold创建HTML5内容很简单,并且遵循与所有其他支持平台相同的模式:从菜单中选择<kbd>Project ▸ Bundle... ▸ HTML5 Application...</kbd>:
 
 ![Create HTML5 bundle](images/html5/html5_bundle.png)
 
-可以选择让 HTML5 包含 `asm.js` 和一个 Defold 引擎 WebAssembly (wasm) 双版本. 多数情况下选择 WebAssembly 版就够了, 因为 [所有主流浏览器都支持 WebAssembly](https://caniuse.com/wasm).
+您可以选择在HTML5包中同时包含`asm.js`和WebAssembly(wasm)版本的Defold引擎。在大多数情况下,只选择WebAssembly就足够了,因为[所有现代浏览器都支持WebAssembly](https://caniuse.com/wasm)。
 
 ::: important
-即使包含了 `asm.js` 和 `wasm` 双版本, 浏览器加载游戏时也只是下载其中一个. 如果浏览器支持 WebAssembly 则优先下载 WebAssembly 版, 否则回撤下载 asm.js 版.
+即使您同时包含`asm.js`和`wasm`版本的引擎,启动游戏时浏览器只会下载其中一个。如果浏览器支持WebAssembly,将下载WebAssembly版本,而在不支持WebAssembly的极少数情况下,将使用`asm.js`版本作为后备。
 :::
 
-当点选 <kbd>Create bundle</kbd> 按钮会弹出目录对话框让你选择应用的保存位置. 等输出工作完成, 你会获得应用所需的所有文件.
+当您单击<kbd>Create bundle</kbd>按钮时,系统将提示您选择一个文件夹来创建您的应用程序。导出过程完成后,您将找到运行应用程序所需的所有文件。
 
 ## 已知问题和局限性
 
-* Hot Reload - HTML5 游戏不支持热更新. Defold 应用必须通过服务器加载运行才能接收热更新. 纯浏览器网页无法获得热更新.
+* 热重载 - 热重载在HTML5构建中不起作用。Defold应用程序必须运行自己的小型Web服务器才能从编辑器接收更新,这在HTML5构建中是不可能的。
 * Internet Explorer 11
-  * Audio - Defold 使用 HTML5 _WebAudio_ (详见 http://www.w3.org/TR/webaudio) 来处理声音, 目前 Internet Explorer 11 还不支持. 所以这种情况下没有声音.
-  * WebGL - Microsoft 没有完全实现 _WebGL_ API (详见 https://www.khronos.org/registry/webgl/specs/latest/). 所以, 较其他浏览器而言对WebGL支持不好.
-  * Full screen - 全屏模式在浏览器中不可靠.
+  * 音频 - Defold使用HTML5 _WebAudio_(参见http://www.w3.org/TR/webaudio)处理音频播放,而Internet Explorer 11目前不支持。使用此浏览器时,应用程序将回退到空音频实现。
+  * WebGL - Microsoft尚未完成实现_WebGL_ API的工作(参见https://www.khronos.org/registry/webgl/specs/latest/)。因此,它的性能不如其他浏览器。
+  * 全屏 - 浏览器中的全屏模式不可靠。
 * Chrome
-  * Slow debug builds - 为了在 HTML5 平台更好地调试我们开启了校验所有 WebGL 图像调用来检测错误. 但是这样做在 Chrome 上会运行缓慢. 可以把 *game.project* 里的 *Engine Arguments* 部分设置为 `–-verify-graphics-calls=false` 来关闭图像调用校验.
-* 游戏手柄支持 - 对于 HTML5 平台的游戏手柄支持与配置[参见手柄教程](/manuals/input-gamepads/#gamepads-in-html5).
+  * 调试构建缓慢 - 在HTML5的调试构建中,我们验证所有WebGL图形调用以检测错误。不幸的是,在Chrome上测试时这非常慢。可以通过将*game.project*的*Engine Arguments*字段设置为`--verify-graphics-calls=false`来禁用此功能。
+* 游戏手柄支持 - 有关HTML5上可能需要采取的特殊考虑和步骤,请[参阅游戏手柄文档](/manuals/input-gamepads/#gamepads-in-html5)。
 
-## 自定义HTML5
+## 自定义HTML5包
 
-针对 HTML5 版本的游戏, Defold 提供了一个默认模板网页. 其中包含的样式和脚本代码决定了游戏的显示方式.
+当生成游戏的HTML5版本时,Defold提供了一个默认网页。它引用了样式和脚本资源,这些资源决定了游戏的呈现方式。
 
-游戏输出时, 这个页面也会重新生成. 如果想要自定义网页模板需要在项目设置里手动配置. 要配置的话, 打开 Defold 编辑器的 *game.project* 文件然后找到 *html5* 部分:
+每次导出应用程序时,都会重新创建此内容。如果您希望自定义这些元素中的任何一个,您必须对项目设置进行修改。为此,请在Defold编辑器中打开*game.project*并滚动到*html5*部分:
 
 ![HTML5 Section](images/html5/html5_section.png)
 
-关于每个选项详情请见 [形目设置教程](/manuals/project-settings/#HTML5).
+有关每个选项的更多信息,请参见[项目设置手册](/manuals/project-settings/#html5)。
 
 ::: important
-`builtins` 文件夹下的默认 html/css 模板文件是不能直接修改的. 要先从 `builtins` 里把文件拷贝出来然后再在 *game.project* 文件里指明要使用的文件的位置.
+您不能修改`builtins`文件夹中的默认html/css模板文件。要应用您的修改,请从`builtins`复制所需的文件,并在*game.project*中设置此文件。
 :::
 
 ::: important
-网页 canvas 不能有 border 或者 padding. 否则的话, 鼠标输入坐标会产生偏差.
+画布不应使用任何边框或内边距进行样式设置。如果这样做,鼠标输入坐标将会出错。
 :::
 
-可以在 *game.project* 文件里禁用 `Fullscreen` 按钮以及 `Made with Defold` 链接.
-Defold 提供了 index.html 文件的亮暗两种风格. 默认亮风格但是可以在 `Custom CSS` 修改成暗风格. 在 `Scale Mode` 部分还预定义了四种缩放模式可供选择.
+在*game.project*中,可以关闭`Fullscreen`按钮和`Made with Defold`链接。
+Defold为index.html提供了深色和浅色主题。默认情况下设置浅色主题,但可以通过更改`Custom CSS`文件来更改。在`Scale Mode`字段中还有四种预定义的缩放模式可供选择。
 
 ::: important
-各种缩放模式计算时考虑了当前屏幕 DPI 以支持 *game.project* 里的 `High Dpi` 选项 (在 `Display` 部分)
+如果您在*game.project*(`Display`部分)中打开`High Dpi`选项,所有缩放模式的计算都包括当前屏幕DPI。
 :::
 
-### Fit 和 Downscale Fit
+### Downscale Fit和Fit
 
-使用 `Fit` 模式 canvas 会以原始比例缩放来适配当前屏幕. `Downscale Fit` 的区别在于, 如果内嵌网页比游戏 canvas 小, 则游戏缩小;反之则以原始大小显示而并不放大=.
+对于`Fit`模式,画布大小将更改为以原始比例在屏幕上显示完整游戏画布。`Downscale Fit`的唯一区别是,仅当网页内部大小小于游戏的原始画布时才更改大小,但当网页大于原始游戏画布时不会放大。
 
 ![HTML5 Section](images/html5/html5_fit.png)
 
 ### Stretch
 
-使用 `Stretch` 模式 canvas 会充满整个内嵌网页.
+对于`Stretch`模式,画布大小将更改为完全填充网页的内部大小。
 
 ![HTML5 Section](images/html5/html5_stretch.png)
 
 ### No Scale
-使用 `No Scale` 模式游戏 canvas 大小保持在 *game.project* 文件里 `[display]` 部分设置的值.
+使用`No Scale`模式,画布大小与您在*game.project*文件`[display]`部分中预定义的大小完全相同。
 
 ![HTML5 Section](images/html5/html5_no_scale.png)
 
-## Tokens
+## 标记
 
-使用 [Mustache 模板语言](https://mustache.github.io/mustache.5.html) 创建 `index.html` 文件. 编译或打包时, HTML 和 CSS 文件会基于项目设置填充模板里面对应的 Tokens. 这些 Tokens 通常使用双大括号或者三层大括号标注 (`{{TOKEN}}` 或者 `{{{TOKEN}}}`), 用哪种取决于标注里面有没有转义字符. 这种方法便于频繁修改以及代码重用.
+我们使用[Mustache模板语言](https://mustache.github.io/mustache.5.html)来创建`index.html`文件。当您构建或打包时,HTML和CSS文件会通过一个编译器,该编译器能够用取决于您的项目设置的值替换某些标记。这些标记总是用双大括号或三重大括号(`{{TOKEN}}`或`{{{TOKEN}}}`)括起来,取决于字符序列是否应该被转义。如果您经常更改项目设置或打算材料在其他项目中重用,此功能可能很有用。
 
 ::: sidenote
-关于 Mustache 模板语言详情请见 [官方手册](https://mustache.github.io/mustache.5.html).
+有关Mustache模板语言的更多信息,请参见[手册](https://mustache.github.io/mustache.5.html)。
 :::
 
-*game.project* 里的设置都可以使用标注来引用. 比如说, 引用 `Display` 里 `Width` 的值:
+任何*game.project*都可以是一个标记。例如,如果您想使用`Display`部分中的`Width`值:
 
 ![Display section](images/html5/html5_display.png)
 
-用普通文本编辑器打开 *game.project* 找到想引用的 `[section_name]` 部分. 像这样引用设置的值: `{{section_name.field}}` 或者 `{{{section_name.field}}}`.
+将*game.project*作为文本打开,并检查您想使用的字段的`[section_name]`和字段名称。然后您可以将其用作标记:`{{section_name.field}}`或`{{{section_name.field}}}`。
 
 ![Display section](images/html5/html5_game_project.png)
 
-比如, 在 HTML 模板的 JavaScript 里:
+例如,在HTML模板中的JavaScript中:
 
 ```javascript
 function doSomething() {
@@ -134,10 +143,10 @@ function doSomething() {
 }
 ```
 
-而且, 我们还可以自定义标注:
+此外,我们还有以下自定义标记:
 
 DEFOLD_SPLASH_IMAGE
-: 溅射屏幕图片文件名, 如果 *game.project* 里的 `html5.splash_image` 为空, 则设置为 `false`.
+: 写入启动图像文件的文件名,如果*game.project*中的`html5.splash_image`为空,则为`false`
 
 
 ```css
@@ -147,11 +156,11 @@ DEFOLD_SPLASH_IMAGE
 ```
 
 exe-name
-: 不包含任何非法符号的项目名
+: 不包含不可接受符号的项目名称
 
 
 DEFOLD_CUSTOM_CSS_INLINE
-: 这里就是在 *game.project* 里设置的内联 CSS 文件的地方.
+: 这是我们在*game.project*设置中指定的CSS文件内联的地方。
 
 
 ```html
@@ -160,36 +169,39 @@ DEFOLD_CUSTOM_CSS_INLINE
 </style>
 ```
 
-::: sidenote
-内联块要出现在主程序脚本加载之前. 因为里面有 HTML 标签, 所以要用三层大括号 `{{{TOKEN}}}` 来引用它.
+::: important
+这个内联块出现在主应用程序脚本加载之前很重要。由于它包含HTML标签,此宏应该出现在三重大括号`{{{TOKEN}}}`中,以防止字符序列被转义。
 :::
 
 DEFOLD_SCALE_MODE_IS_DOWNSCALE_FIT
-: 如果 `html5.scale_mode` 是 `Downscale Fit` 的话则值为 `true`.
+: 如果`html5.scale_mode`是`Downscale Fit`,则此标记为`true`。
 
 DEFOLD_SCALE_MODE_IS_FIT
-: 如果 `html5.scale_mode` 是 `Fit` 的话则值为 `true`.
+: 如果`html5.scale_mode`是`Fit`,则此标记为`true`。
 
 DEFOLD_SCALE_MODE_IS_NO_SCALE
-: 如果 `html5.scale_mode` 是 `No Scale` 的话则值为 `true`.
+: 如果`html5.scale_mode`是`No Scale`,则此标记为`true`。
 
 DEFOLD_SCALE_MODE_IS_STRETCH
-: 如果 `html5.scale_mode` 是 `Stretch` 的话则值为 `true`.
+: 如果`html5.scale_mode`是`Stretch`,则此标记为`true`。
 
 DEFOLD_HEAP_SIZE
-: 在 *game.project* 里设置的内存大小, `html5.heap_size` 的值以字节为单位.
+: 在*game.project*`html5.heap_size`中指定的堆大小,转换为字节。
 
 DEFOLD_ENGINE_ARGUMENTS
-: 在 *game.project* 里设置的引擎参数, `html5.engine_arguments` 以逗号 `,` 分隔.
+: 在*game.project*`html5.engine_arguments`中指定的引擎参数,以`,`符号分隔。
+
+build-timestamp
+: 当前构建时间戳(以秒为单位)。
 
 
 ## 额外参数
 
-要创建自定义模板, 可以为引擎加载预定义额外参数. 预定义参数需要在 `<script>` 标签下, 把参数定义到 `CUSTOM_PARAMETERS`里. 
+如果您创建自定义模板,可以重新定义引擎加载器的参数集。为此,您需要添加`<script>`部分并在`CUSTOM_PARAMETERS`内重新定义值。
 ::: important
-你的 `<script>` 要放在引用 dmloader.js 的`<script>`之后, 调用 `EngineLoader.load` 函数之前.
+您的自定义`<script>`应放在引用`dmloader.js`的`<script>`部分之后,但在调用`EngineLoader.load`函数之前。
 :::
-例如:
+例如
 ```
     <script id='custom_setup' type='text/javascript'>
         CUSTOM_PARAMETERS['disable_context_menu'] = false;
@@ -199,63 +211,69 @@ DEFOLD_ENGINE_ARGUMENTS
     </script>
 ```
 
-`CUSTOM_PARAMETERS` 可包含如下参数:
+`CUSTOM_PARAMETERS`可能包含以下字段:
 
 ```
 'archive_location_filter':
-    包地址过滤.
+    将为每个存档路径运行的过滤函数。
 
 'unsupported_webgl_callback':
-    如果不支持 WebGL 则需调用的回调函数.
+    如果不支持WebGL则调用的函数。
 
 'engine_arguments':
-    传入引擎的参数列表 (字符串).
+    将传递给引擎的参数列表(字符串)。
 
 'custom_heap_size':
-    自定义内存使用的大小.
+    指定内存堆大小的字节数。
 
 'disable_context_menu':
-    为 true 的话则在canvas上关闭右键上下文弹出菜单.
+    如果为true,则在canvas元素上禁用右键单击上下文菜单。
 
 'retry_time':
-    文件下载失败重试时间间隔.
+    错误后重试文件加载之前的暂停时间(以秒为单位)。
 
 'retry_count':
-    文件下载失败充实次数.
+    尝试下载文件时我们进行多少次尝试。
 
 'can_not_download_file_callback':
-    如果重试次数已满但是仍没有得到文件则需调用的回调函数.
+    如果在'retry_count'尝试后无法下载文件则调用的函数。
 
 'resize_window_callback':
-    当屏幕 改变大小/改变方向/改变焦点 时调用.
+    当发生调整大小/方向更改/焦点事件时调用的函数。
+
+'start_success':
+    成功加载后调用main之前调用的函数。
+
+'update_progress':
+    进度更新时调用的函数。参数进度更新为0-100。
 ```
 
-## HTML5 的文件操作
+## HTML5的文件操作
 
-HTML5 支持 `sys.save()`, `sys.load()` 和 `io.open()` 之类的文件操作, 但是与其他平台实现方法不同. 基于安全考虑浏览器里运行的 Javascript 无权直接读写本地文件. Emscripten (即 Defold) 使用 [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB) 代替, 它是基于浏览器的持久化存储方案, 基于浏览器的虚拟文件系统. 与其他平台的区别主要是比直接读写文件要慢而且实质上读写的是一个数据库. 浏览器开发者工具通常都提供了 IndexedDB 的读写功能.
+HTML5构建支持诸如`sys.save()`、`sys.load()`和`io.open()`之类的文件操作,但这些操作的内部处理方式与其他平台不同。当Javascript在浏览器中运行时,没有真正的文件系统概念,并且出于安全原因阻止了本地文件访问。相反,Emscripten(因此Defold)使用[IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB),这是一个用于持久存储数据的浏览器内数据库,在浏览器中创建虚拟文件系统。与其他平台文件系统访问的重要区别在于,写入文件和更改实际存储在数据库之间可能存在轻微延迟。浏览器开发者控制台通常允许您检查IndexedDB的内容。
 
 
-## 给 HTML5 游戏传递参数
+## 向HTML5游戏传递参数
 
-一些情况下我们需要在游戏启动前或者启动时为其提供某些参数. 可能是用户 id, session 令牌或者告诉游戏启动时为当前玩家加载哪一关. 有多种方法实现这样的功能, 下面就列举一些.
+有时有必要在游戏启动之前或启动时向游戏提供额外的参数。例如,这可能是用户ID、会话令牌或游戏启动时要加载的关卡。这可以通过多种不同的方式实现,其中一些在此描述。
 
 ### 引擎参数
 
-用于在引进加载时指定引擎参数. 这些参数在运行时可以使用 `sys.get_config()` 得到. 在 `index.html` 里修改 `extra_params` 对象的 `engine_arguments` 项, 加入键值对以提供参数:
+可以在配置和加载引擎时指定额外的引擎参数。这些额外的引擎参数可以在运行时使用`sys.get_config()`检索。要添加键值对,请修改传递给`index.html`中加载的引擎的`extra_params`对象的`engine_arguments`字段:
 
 
 ```
     <script id='engine-setup' type='text/javascript'>
     var extra_params = {
         ...,
-        engine_arguments: ["config=foo1=bar1","--config=foo2=bar2"],
+        engine_arguments: ["--config=foo1=bar1","--config=foo2=bar2"],
         ...
     }
 ```
 
-也可以在项目 *game.project* 的 HTML5 部分加入如 `"–config=foo1=bar1","--config=foo2=bar2"` 的引擎参数, 它们会被注入到自动生成的 index.html 文件中.
+您也可以将`--config=foo1=bar1, --config=foo2=bar2`添加到*game.project*的HTML5部分的引擎参数字段中,它将被注入到生成的index.html文件中。
 
-运行时可以这样取得引擎参数:
+在运行时,您可以这样获取值:
 
 ```lua
 local foo1 = sys.get_config("foo1")
@@ -265,9 +283,9 @@ print(foo2) -- bar2
 ```
 
 
-### 在 URL 中提供参数
+### URL中的查询参数
 
-可以在游戏页面的 URL 中提供参数, 然后在运行时读取:
+您可以将参数作为页面URL中查询参数的一部分传递,并在运行时读取这些参数:
 
 ```
 https://www.mygame.com/index.html?foo1=bar1&foo2=bar2
@@ -278,19 +296,19 @@ local url = html5.run("window.location")
 print(url)
 ```
 
-下面提供一个获取所有查询参数并把它们保存为 Lua 表的函数:
+一个完整的辅助函数,用于将所有查询参数作为Lua表获取:
 
 ```lua
 local function get_query_parameters()
     local url = html5.run("window.location")
-    -- get the query part of the url (the bit after ?)
+    -- 获取url的查询部分(?号后面的部分)
     local query = url:match(".*?(.*)")
     if not query then
         return {}
     end
 
     local params = {}
-    -- iterate over all key value pairs
+    -- 迭代所有键值对
     for kvp in query:gmatch("([^&]+)") do
         local key, value = kvp:match("(.+)=(.+)")
         params[key] = value
@@ -305,5 +323,12 @@ end
 ```
 
 
-## 问答
-:[HTML5 问答](../shared/html5-faq.md)
+## 优化
+HTML5游戏通常对初始下载大小、启动时间和内存使用有严格要求,以确保游戏在低端设备和慢速互联网连接上加载快速并运行良好。要优化HTML5游戏,建议重点关注以下领域:
+
+* [内存使用](/manuals/optimization-memory)
+* [引擎大小](/manuals/optimization-size)
+* [游戏大小](/manuals/optimization-size)
+
+## 常见问题
+:[HTML5 常见问题](../shared/html5-faq.md)

+ 13 - 13
docs/zh/manuals/http-requests.md

@@ -1,15 +1,15 @@
 ---
-title: HTTP 请求
-brief: 本教程介绍了发布 HTTP 请求的方法.
+title: Defold HTTP请求
+brief: 本手册解释了如何进行HTTP请求。
 ---
 
-## HTTP 请求
+## HTTP请求
 
-Defold 可以使用 `http.request()` 函数发布普通 HTTP 请求.
+Defold可以使用`http.request()`函数进行常规HTTP请求。
 
 ### HTTP GET
 
-这是最常见的获得信息的请求类型. 举个例子:
+这是从服务器获取一些数据的最基本请求。示例:
 
 ```Lua
 local function handle_response(self, id, response)
@@ -19,15 +19,15 @@ end
 http.request("https://www.defold.com", "GET", handle_response)
 ```
 
-这段代码向 https://www.defold.com 发送了一个 HTTP GET 请求. 函数是异步的所以不会把游戏卡住. 一接到服务器回复便会调用回调函数. 回调函数里可以获取服务器返回的所有信息, 包括状态码和回复头信息.
+这将向https://www.defold.com发出HTTP GET请求。该函数是异步的,在发出请求时不会阻塞。一旦请求完成并收到服务器响应,它将调用提供的回调函数。回调函数将接收完整的服务器响应,包括状态码和响应头。
 
 ::: sidenote
-为了提高效率, HTTP 请求会自动缓存在客户端. 缓存文件保存在一个叫 `defold/http-cache` 的文件夹里, 其路径根据操作系统不同而不同. 一般来说不必关心缓存的存在, 除非你需要手动清除缓存文件. macOS 系统路径是 `%HOME%/Library/Application Support/Defold/http-cache/` , Windows 系统路径是 `%APP_DATA%/defold/http-cache`.
+HTTP请求会自动缓存在客户端以提高网络性能。缓存的文件存储在操作系统特定的应用程序支持路径中,位于名为`defold/http-cache`的文件夹中。您通常不需要关心HTTP缓存,但如果在开发过程中需要清除缓存,可以手动删除包含缓存文件的文件夹。在macOS上,此文件夹位于`%HOME%/Library/Application Support/Defold/http-cache/`,在Windows上位于`%APP_DATA%/defold/http-cache`。
 :::
 
 ### HTTP POST
 
-当需要传输数据, 比如上传分数或者认证信息到服务器时, 通常需要发布 POST 请求:
+当向服务器发送数据,如分数或某些认证数据时,通常使用POST请求:
 
 ```Lua
 local function handle_response(self, id, response)
@@ -41,14 +41,14 @@ local body = "foo=bar"
 http.request("https://httpbin.org/post", "POST", handle_response, headers, body)
 ```
 
-### 其他 HTTP 请求类型
+### 其他HTTP方法
 
-Defold HTTP 请求支持 HEAD, DELETE 和 PUT 类型.
+Defold HTTP请求还支持HEAD、DELETE和PUT方法。
 
-### API 文档
+### API参考
 
-请参考 [API 文档](/ref/http/).
+请参考[API参考](/ref/http/)了解更多。
 
 ### 扩展
 
-有一个第三方实现的 HTTP 请求扩展库叫做 [TinyHTTP extension](https://defold.com/assets/tinyhttp/).
+替代的HTTP请求实现可以在[TinyHTTP扩展](https://defold.com/assets/tinyhttp/)中找到。

+ 15 - 15
docs/zh/manuals/iac.md

@@ -1,37 +1,37 @@
 ---
-title: Defold 的应用内通信
-brief: 应用内通信可以让你获得应用启动时的启动参数信息. 本教程解释了Defold中此功能的API.
+title: Defold应用间通信
+brief: 应用间通信允许您获取启动应用程序时使用的启动参数。本手册解释了Defold中用于此功能的API。
 ---
 
-# 应用通信
+# 应用通信
 
-大多数操作系统中应用可以由以下方式启动:
+应用程序在大多数操作系统上可以通过多种方式启动:
 
-* 从已安装应用表中启动
-* 从应用链接启动
-* 从推送消息中启动
-* 在安装程序最后一步启动.
+* 从已安装应用程序列
+* 从应用程序特定链接
+* 从推送通知
+* 作为安装过程的最后一步。
 
-从链接, 通知, 安装程序启动应用时可以获得引用, 比如安装时的快捷方式或者超级链接, 通知里的长链接. Defold 使用一个native extension提供一个统一的方法来获得应用是如何启动的相关信息.
+在应用程序从链接、通知或安装启动的情况下,可以传递额外的参数,例如安装时的安装来源或从应用程序特定链接或通知启动时的深度链接。Defold提供了一种统一的方式来获取有关应用程序如何被调用的信息,使用原生扩展。
 
 ## 安装扩展
 
-要使用应用内通信扩展程序你需要在你的 *game.project* 里添加一个依赖. 此依赖的URL是:
+要开始使用应用间通信扩展,您需要将其作为依赖项添加到您的*game.project*文件中。最新稳定版本的依赖URL是:
 ```
 https://github.com/defold/extension-iac/archive/master.zip
 ```
 
-推荐使用 [指定版本](https://github.com/defold/extension-iac/releases) 的zip包链接作为依赖.
+我们建议使用[特定版本](https://github.com/defold/extension-iac/releases)的zip文件链接。
 
 ## 使用扩展
 
-API很简单. 提供给扩展程序一个回调用的监听器函数.
+API非常易于使用。您为扩展提供一个监听器函数并对监听器回调做出反应。
 
 ```
 local function iac_listener(self, payload, type)
      if type == iac.TYPE_INVOCATION then
-         -- This was an invocation
-         print(payload.origin) -- origin may be empty string if it could not be resolved
+         -- 这是一个调用
+         print(payload.origin) -- 如果无法解析,origin可能是空字符串
          print(payload.url)
      end
 end
@@ -41,4 +41,4 @@ function init(self)
 end
 ```
 
-API完整文档在[此页面](https://defold.github.io/extension-iac/).
+API的完整文档可在[扩展GitHub页面](https://defold.github.io/extension-iac/)上找到。

+ 3 - 3
docs/zh/manuals/iap.md

@@ -1,6 +1,6 @@
 ---
-title: Defold 中的内支付
-brief: 应用内支付 (也称内购买) 允许用户付费以获得额外的内容或功能. 本教程介绍了相关功能的 Defold API.
+title: Defold应用内购买
+brief: 应用内购买(或应用内计费)允许您向玩家或应用用户收取额外内容或功能的费用。本手册解释了Defold用于此功能的API。
 ---
 
-[本教程已被移至](/extension-iap)
+[此手册已移至](/extension-iap)

+ 16 - 18
docs/zh/manuals/importing-assets.md

@@ -1,44 +1,42 @@
 ---
-title: 导入和编辑资源
-brief: 本教程介绍了导入, 编辑资源的方法.
+title: Defold资源导入和编辑
+brief: 本手册介绍了如何导入和编辑资源。
 ---
 
-# 导入和编辑资源导入和编辑资源
+# 资源导入和编辑
 
-一个游戏项目通常包含了大量其他程序生成的资源文件, 比如图像, 3D 模型, 音乐文件, 动画之类的. Defold 工作流就包括使用第三方工具创建资源然后导入Defold中使用. 当这些资源导入之后就可以被Defold的各种组件使用, 比如 逐帧动画, 瓷砖地图, 粒子特效之类的:
+游戏项目通常包含大量外部资源,这些资源是在各种专业程序中制作的,用于制作图形、3D模型、声音文件、动画等。Defold专为这样的工作流程而构建:您在外部工具中工作,然后在它们完成后将资源导入到Defold中。
 
 
 ## 导入资源
 
-Defold 要求其所用资源全部位于项目文件夹内. 先导入后使用. 导入方法很简单, 从文件系统任意位置拖动任意文件放入 Defold 编辑器 _资源面板_ 里即可.
+Defold需要项目中使用的所有资源都位于项目层次结构中的某个位置。因此,您需要先导入所有资源,然后才能使用它们。要导入资源,只需将文件从计算机的文件系统中拖出,然后放到Defold编辑器的*Assets*面板中的适当位置。
 
 ![Importing files](images/graphics/import.png)
 
 ::: sidenote
-Defold 支持 PNG 和 JPEG 图片格式. 其中 PNG 图片必须是 32 位 RGBA 格式的. 其他格式要先转换成支持格式后再使用.
+Defold支持PNG和JPEG图像格式。PNG图像必须是32位RGBA格式。其他图像格式需要先转换才能使用。
 :::
 
 ## 使用资源
 
-当资源文件导入 Defold 之后就可以使用各种组件来创造逐帧动画, 瓷砖地图, 粒子特效等各种内容:
+当资源导入到Defold后,它们可以被Defold支持的各种组件类型使用:
 
-* 图片可以用来实现2D游戏常见的各种可视内容. 详情请见 [如何导入和使用2D图像](/manuals/importing-graphics).
-* 声音文件可以用 [声音组件](/manuals/sound)来播放.
-* 字体文件 可以用于 [Label 组件](/manuals/label) 和GUI中的 [text 节点](/manuals/gui-text).
-* glTF 和 Collada 模型可以用于 [Model 组件](/manuals/model) 来显示3D模型和动画. [关于3D模型导入详见这里](/manuals/importing-models).
+* 图像可用于创建2D游戏中常用的多种视觉组件。阅读更多关于[如何导入和使用2D图形的内容](/manuals/importing-graphics)。
+* 声音可以被[声音组件](/manuals/sound)用来播放声音。
+* 字体被[标签组件](/manuals/label)和GUI中的[文本节点](/manuals/gui-text)使用。
+* glTF和Collada模型可以被[模型组件](/manuals/model)用来显示带动画的3D模型。阅读更多关于[如何导入和使用3D模型的内容](/manuals/importing-models)。
 
 
 ## 编辑外部资源
 
-Defold 并不提供图片, 声音, 模型 或者 动画文件的创建功能. 这些文件应该由 Defold 以外的工具创建好之后再导入到 Defold 里使用. Defold 自动检测资源文件的改动然后自动刷新到编辑器里. 之后 Defold 会自动进行资源文件的更新.
+Defold不提供用于图像、声音文件、模型或动画的编辑工具。此类资源需要在Defold之外的专业工具中创建,然后导入到Defold。Defold会自动检测项目文件中任何资源的更改,并相应地更新编辑器视图。
 
 
-## 编辑 Defold 资源
+## 编辑Defold资源
 
-Defold 编辑器自己生成的资源都是纯文本格式的以方便合并.甚至可以使用代码来修改 参见 [这个帖子](https://forum.defold.com/t/deftree-a-python-module-for-editing-defold-files/15210).
+编辑器将所有Defold资源保存在基于文本的文件中,这些文件易于合并。它们也易于使用简单脚本创建和修改。有关更多信息,请参阅[此论坛帖子](https://forum.defold.com/t/deftree-a-python-module-for-editing-defold-files/15210)。但请注意,我们不发布文件格式详细信息,因为它们偶尔会更改。您也可以使用[编辑器脚本](/manuals/editor-scripts/)来挂钩编辑器中的某些生命周期事件,以运行脚本来生成或修改资源。
 
-注意我们没有发布固定的资源文本格式, 因为格式可能随着升级不断变化. 你也可以使用 [编辑器脚本](/manuals/editor-scripts/) 在编辑器特定的生命周期中运行脚本来生成或者修改资源.
+通过文本编辑器或外部工具处理Defold资源文件时应格外小心。如果引入错误,可能会阻止文件在Defold编辑器中打开。
 
-另外要注意一点就是如果使用外部编辑器破坏了资源文本的话, 再回到 Defold 可能就无法打开这个文件了.
-
-某些第三方工具比如 [Tiled](/assets/tiled/) 和 [Tilesetter](https://www.tilesetter.org/beta) 也可以用来自动生成 Defold 资源.
+某些外部工具,如[Tiled](/assets/tiled/)和[Tilesetter](https://www.tilesetter.org/beta),可用于自动生成Defold资源。

+ 28 - 28
docs/zh/manuals/importing-graphics.md

@@ -1,73 +1,73 @@
 ---
-title: 导入和使用2D图像
-brief: 本教程介绍了如何导入和使用2D图像.
+title: Defold 2D图形导入和使用
+brief: 本手册介绍了如何导入和使用2D图形。
 ---
 
-# 导入2D图
+# 导入2D图
 
-Defold 支持2D游戏常见的可视内容. 可以使用 Defold 制作静态或动态Sprite, UI 组件, 粒子特效, 瓷砖地图 和 位图字体. 先导入图片文件再创建相应资源以使用它们. 把文件系统任意图片文件拖放到 Defold 编辑器的 *资源面板* 中即完成导入操作.
+Defold支持2D游戏中常用的多种视觉组件。您可以使用Defold创建静态和动画精灵、UI组件、粒子效果、瓦片地图和位图字体。在创建任何这些视觉组件之前,您需要导入包含您希望使用的图形的图像文件。要导入图像文件,只需将文件从计算机的文件系统中拖出,然后放到Defold编辑器的*Assets*面板中的适当位置。
 
 ![Importing files](images/graphics/import.png)
 
 ::: sidenote
-Defold 支持 PNG 和 JPEG 图片格式. 其他格式要先转换成支持格式后使用.
+Defold支持PNG和JPEG图像格式。其他图像格式需要先转换才能使用。
 :::
 
 
-## 创建 Defold 资源
+## 创建Defold资源
 
-图片导入 Defold 后即可创建相应资源:
+当图像导入到Defold后,它们可以用来创建Defold特定的资源:
 
-![atlas](images/icons/atlas.png){.icon} Atlas
-: 图集是多张图片组成的大图. 图集可以包含单个图片或者 *动画组*, 即组成逐帧动画的一组图片.
+![atlas](images/icons/atlas.png){.icon} 图集
+: 图集包含单独图像文件的列表,这些文件会自动组合成更大的纹理图像。图集可以包含静态图像和*动画组*,即组成翻页动画的图像集。
 
   ![atlas](images/graphics/atlas.png)
 
-关于图集资源详情请见 [图集教程](/manuals/atlas).
+在[图集手册](/manuals/atlas)中了解更多关于图集资源的信息。
 
-![tile source](images/icons/tilesource.png){.icon} Tile Source
-: 瓷砖图集是由小图按一定顺序排列好的大图. 这种图又被叫做 _精灵表_. 瓷砖图集也可以通过指定第一帧与最后一帧的图块, 来创造逐帧动画. 也可以使用图片自动生成图块的碰撞方块.
+![tile source](images/icons/tilesource.png){.icon} 瓦片源
+: 瓦片源引用一个图像文件,该文件已经被设计成由在统一网格上排序的较小子图像组成。这种复合图像常用的另一个术语是_精灵表_。瓦片源可以包含翻页动画,由动画的第一帧和最后一帧定义。还可以使用图像自动为瓦片附加碰撞形状。
 
   ![tile source](images/graphics/tilesource.png)
 
-关于瓷砖图集资源详情请见 [瓷砖图集教程](/manuals/tilesource).
+在[瓦片源手册](/manuals/tilesource)中了解更多关于瓦片源资源的信息。
 
-![bitmap font](images/icons/font.png){.icon} Bitmap Font
-: 位图字体是 PNG 图片格式的文字表. 这种字体比起 TrueType 或者 OpenType 字体文件并没有性能优势, 但是由于是图片, 颜色阴影等效果可以随意加入.
+![bitmap font](images/icons/font.png){.icon} 位图字体
+: 位图字体将其字形包含在PNG字体表中。这些类型的字体与从TrueType或OpenType字体文件生成的字体相比没有性能改进,但可以在图像中直接包含任意图形、颜色和阴影。
 
-关于字体资源详情请见 [字体教程](/manuals/font/#位图 BMFont).
+在[字体手册](/manuals/font/#bitmap-bmfonts)中了解更多关于位图字体的信息。
 
   ![BMfont](images/font/bm_font.png)
 
 
-## 使用 Defold 资源
+## 使用Defold资源
 
-当图片转化为图集或者瓷砖图集之后就可以用于各种可视组件之中:
+当您将图像转换为图集和瓦片源文件后,您可以使用这些文件创建多种不同类型的视觉组件:
 
 ![sprite](images/icons/sprite.png){.icon}
-: Sprite是可以显示的图片或者逐帧动画.
+: 精灵是显示在屏幕上的静态图像或翻页动画。
 
   ![sprite](images/graphics/sprite.png)
 
-关于Sprite详情请见 [Sprite教程](/manuals/sprite).
+在[精灵手册](/manuals/sprite)中了解更多关于精灵的信息。
 
-![tile map](images/icons/tilemap.png){.icon} Tile map
-: 瓷砖地图是由若干源自瓷砖图集的地图块 (图片连同其碰撞方块) 组成的可视组件. 瓷砖地图不能使用图集资源.
+![tile map](images/icons/tilemap.png){.icon} 瓦片地图
+: 瓦片地图组件将来自瓦片源的瓦片(图像和碰撞形状)拼凑成地图。瓦片地图不能使用图集源。
 
   ![tilemap](images/graphics/tilemap.png)
 
-关于瓷砖地图详情请见 [瓷砖地图教程](/manuals/tilemap).
+在[瓦片地图手册](/manuals/tilemap)中了解更多关于瓦片地图的信息。
 
-![particle effect](images/icons/particlefx.png){.icon} Particle fx
-: 粒子是由粒子发射器发射的, 源自图集或者瓷砖图集图片生成的一组组静态图片或逐帧动画.
+![particle effect](images/icons/particlefx.png){.icon} 粒子特效
+: 从粒子发射器生成的粒子由来自图集或瓦片源的静态图像或翻页动画组成。
 
   ![particles](images/graphics/particles.png)
 
-关于粒子特效详情请见 [粒子特效教程](/manuals/particlefx).
+在[粒子特效手册](/manuals/particlefx)中了解更多关于粒子特效的信息。
 
 ![gui](images/icons/gui.png){.icon} GUI
-: GUI 方块节点和 饼图节点也可以使用来自图集或者瓷砖图集的静态或逐帧动画.
+: GUI方块节点和饼图节点可以使用来自图集和瓦片源的静态图像和翻页动画。
 
   ![gui](images/graphics/gui.png)
 
-关于GUI详情请见 [GUI教程](/manuals/gui).
+在[GUI手册](/manuals/gui)中了解更多关于GUI的信息。

+ 27 - 33
docs/zh/manuals/importing-models.md

@@ -1,68 +1,62 @@
 ---
-title: 导入模型
-brief: 本教程介绍了通过模型组件导入 3D 模型的方法.
+title: Defold模型导入
+brief: 本手册介绍了如何导入模型组件使用的3D模型。
 ---
 
 # 导入3D模型
-Defold 目前支持 GL Transmission Format *.glTF* 和 Collada *.dae* 格式的模型,骨骼和动画. 可以使用类似 Maya, 3D Max, Sketchup 和 Blender 的软件保存或者转换3D模型为Collada格式. Blender 是一个著名的3D建模, 动画及渲染软件. 它在 Windows, macOS 和 Linux 都能运行并且在 http://www.blender.org 上免费下载.
+Defold目前支持GL传输格式*.glTF*和Collada*.dae*格式的模型、骨骼和动画。您可以使用Maya、3D Max、Sketchup和Blender等工具来创建和/或将3D模型转换为glTF和Collada格式。Blender是一款功能强大且流行的3D建模、动画和渲染程序。它可在Windows、macOS和Linux上运行,并可从http://www.blender.org免费下载。
 
 ![Model in Blender](images/model/blender.png)
 
 
-## 导入模型 Defold
-要导入模型, 只需将 *.gltf* 文件或者 *.dae* 文件及其相应贴图拖拽至 *资源面板* 即可.
+## 导入到Defold
+要导入模型,只需将*.gltf*文件或*.dae*文件以及相应的纹理图像拖放到*Assets*面板中的某个位置。
 
 ![导入模型资源](images/model/assets.png)
 
 
 ## 使用模型
-当模型导入到 Defold 之后即可在 [模型组件](/manuals/model) 上使用它.
+将模型导入Defold后,您可以在[模型组件](/manuals/model)中使用它。
 
 
-## 导出 glTF 和 Collada 格式文件
-导出的 *.gltf* 或 *.dae* 文件包含模型所有的点, 边和面的信息, 如果模型贴了图, 同时还包含 _UV 坐标_ (用于确定纹理如何铺在模型表面), 以及骨架骨骼和动画数据.
+## 导出为glTF和Collada
+导出的*.gltf*或*.dae*文件包含构成模型的所有顶点、边和面,以及_UV坐标_(如果已定义,则表示纹理图像的哪部分映射到网格的特定部分)、骨架中的骨骼和动画数据。
 
-* 关于多边形网格的解释详见 http://en.wikipedia.org/wiki/Polygon_mesh.
+* 关于多边形网格的详细描述可以在http://en.wikipedia.org/wiki/Polygon_mesh找到。
 
-* UV 坐标和 UV 映射的解释详见 http://en.wikipedia.org/wiki/UV_mapping.
+* UV坐标和UV映射在http://en.wikipedia.org/wiki/UV_mapping中有描述。
 
-Defold 对于导出的动画作了一些限制:
+Defold对导出的动画数据施加了一些限制:
 
-* Defold 目前只支持烘焙好的动画. 动画每一关键帧每个骨骼都要提供矩阵数据而不是位置, 旋转和缩放这样分开的数据.
+* Defold目前只支持烘焙动画。动画需要为每个关键帧的每个动画骨骼提供矩阵,而不是将位置、旋转和缩放作为单独的键。
 
-* 动画都是线性插值的. 如果需要曲线插值请在导出前预烘焙好.
+* 动画也是线性插值的。如果您进行更高级的曲线插值,动画需要从导出器预烘焙。
 
-* 不支持 Collada 的动画片段. 一个模型如有多个动画, 请分别导出 *.dae* 文件然后在 Defold 中合并成一个 *.animationset* 文件.
+* 不支持Collada中的动画剪辑。要为每个模型使用多个动画,请将它们导出到单独的*.dae*文件中,然后在Defold中将这些文件收集到一个*.animationset*文件中。
 
 
-### 需求
-导出模型的时候需遵循以下需求:
+### 要求
+当您导出模型时,最好知道我们还不支持所有功能。
+目前glTF格式中已知的问题/不支持的功能:
 
-* 模型必须由单个网格组成
-* 模型必须使用单个材质
-* 导出的 *.gltf* 文件要嵌入网格数据. 附带于其他文件的二进制网格数据不受支持. 
+* 变形目标动画
+* 材质属性
+* 嵌入纹理
 
-可以使用 Blender 来组合多个网格. 选中所有网格, 按 `CTRL`/`CMD` + `J` 来进行组合操作.
-
-![组合网格](images/model/blender_join_meshes.png)
-
-
-#### 删除材质
-可以使用 Blender 删除模型上的多余材质. 选中要删除的材质, 按 `-` 来进行删除.
-
-![删除材质](images/model/blender_remove_materials.png)
+虽然我们的目标是完全支持glTF格式,但我们还没有完全实现。
+如果缺少某个功能,请在[我们的仓库](https://github.com/defold/defold/issues)中为其提出功能请求。
 
 
 ### 导出纹理
-如果模型没有纹理, 可以使用 Blender 来生成一个. 这个工作要在删除多余材质之前完成. 从选择网格及其所有的点开始:
+如果您还没有模型的纹理,可以使用Blender生成一个。您应该在从模型中移除额外材质之前执行此操作。首先选择网格及其所有顶点:
 
 ![Select all](images/model/blender_select_all_vertices.png)
 
-选中所有点后即可展开UV:
+当所有顶点被选中后,您可以展开网格以获取UV布局:
 
 ![Unwrap mesh](images/model/blender_unwrap_mesh.png)
 
-接下来就可以把它保存为图片文件作为网格纹理:
+然后您可以继续将UV布局导出为可用作纹理的图像:
 
 ![Export UV layout](images/model/blender_export_uv_layout.png)
 
@@ -71,7 +65,7 @@ Defold 对于导出的动画作了一些限制:
 ![Export UV layout result](images/model/blender_export_uv_layout_result.png)
 
 
-### 从 Blender 中导出
-从导出菜单选项中导出模型文件. 选中模型然后点选导出模型菜单项, 选中 "Selection Only" 选项即可导出文件.
+### 使用Blender导出
+您使用导出菜单选项导出模型。在选择导出菜单选项之前选择模型,并勾选"Selection Only"以仅导出模型。
 
 ![Exporting using Blender](images/model/blender_export.png)

+ 103 - 102
docs/zh/manuals/input-gamepads.md

@@ -1,98 +1,98 @@
 ---
-title: Defold 游戏手柄输入教程
-brief: 本教程介绍了游戏手柄输入的功能.
+title: Defold游戏手柄输入
+brief: 本手册解释了游戏手柄输入的工作原理。
 ---
 
 ::: sidenote
-建议首先熟练掌握 Defold 中常规输入的消息处理方式, 例如输入消息获取以及脚本间输入消息广播顺序等. 关于输入系统详情请见 [输入系统教程](/manuals/input).
+建议您先熟悉Defold中输入的一般工作方式,如何接收输入以及输入在脚本文件中的接收顺序。有关输入系统的更多信息,请参阅[输入系统概述手册](/manuals/input)。
 :::
 
 # Gamepads
-游戏手柄触发器可以绑定标准手柄输入到游戏功能的映射. 游戏手柄可以绑定:
+游戏手柄触发器允许您将标准游戏手柄输入绑定到游戏功能。游戏手柄输入提供以下绑定:
 
-- 左右摇杆 (方向和按下)
-- 手柄按钮. 通常右手柄 Xbox 为 "A", "B", "X" 和 "Y", Playstation 为 "方块", "圆圈", "三角" 和 "十叉".
-- 方向按钮.
-- 左右肩按钮.
-- 开始, 后退, 暂停按钮
+- 左右摇杆(方向和点击)
+- 左右数字板。右数字板通常对应Xbox控制器上的"A"、"B"、"X"和"Y"按钮,以及PlayStation控制器上的"方块"、"圆圈"、"三角"和"十字"按钮。
+- 左右扳机键
+- 左右肩
+- 开始、返回和指南按钮
 
 ![](images/input/gamepad_bindings.png)
 
 ::: important
-下面的例子中使用了上图的映射绑定配置. 映射与命名可以根据项目需要自由设置.
+下面的示例使用了上图中显示的操作。与所有输入一样,您可以自由命名输入操作。
 :::
 
-## 十字键
-十字键可以生成按下, 抬起和连按消息. 获取十字键消息的方法如下 (按下和抬起):
+## 数字按钮
+数字按钮生成按下、释放和重复事件。以下示例显示如何检测数字按钮的输入(按下或释放):
 
 ```lua
 function on_input(self, action_id, action)
     if action_id == hash("gamepad_lpad_left") then
         if action.pressed then
-            -- 向左移动
+            -- 开始向左移动
         elseif action.released then
-            -- 停止移动
+            -- 停止向左移动
         end
     end
 end
 ```
 
-## 摇杆
-摇杆拨动到阈值以外就可以持续生成输入消息 (阈值配置见下文). 获取摇杆消息的方法如下:
+## 模拟摇杆
+当摇杆移动到手柄设置文件中定义的死区之外时,模拟摇杆会生成连续的输入事件(见下文)。以下示例显示如何检测模拟摇杆的输入:
 
 ```lua
 function on_input(self, action_id, action)
     if action_id == hash("gamepad_lstick_down") then
-        -- 左摇杆向下
-        print(action.value) -- 取值范围 0.0  -1.0
+        -- 左摇杆向下
+        print(action.value) -- 0.0到-1.0之间的值
     end
 end
 ```
 
-摇杆处于某方向极值的时候还会生成按下和抬起消息. 这样类似十字键的消息很适合用作方向导航:
+模拟摇杆在移动到超过特定阈值的主要方向时也会生成按下和释放事件。这使得将模拟摇杆也用作数字方向输入变得容易:
 
 ```lua
 function on_input(self, action_id, action)
     if action_id == hash("gamepad_lstick_down") and action.pressed then
-        -- 左摇杆向下拨动到头
+        -- 左摇杆被移动到极端向下位置
     end
 end
 ```
 
-## 多手柄
-Defold 基于其宿主操作系统支持多个手柄, 事件里 `gamepad` 项对应手柄输入来源:
+## 多个游戏手柄
+Defold通过主机操作系统支持多个游戏手柄,操作会将操作表的`gamepad`字段设置为输入来源的游戏手柄编号:
 
 ```lua
 function on_input(self, action_id, action)
     if action_id == hash("gamepad_start") then
         if action.gamepad == 0 then
-          -- 手柄0号玩家申请加入游戏
+          -- 游戏手柄0想要加入游戏
         end
     end
 end
 ```
 
-## Connect 和 Disconnect
-游戏手柄还有 `Connected` 和 `Disconnected` 两种事件用以通知手柄的连接(包括一开始就连着的手柄)和断开.
+## 连接和断开
+游戏手柄输入绑定还提供两个名为`Connected`和`Disconnected`的独立绑定,用于检测游戏手柄何时连接(包括从一开始就连接的手柄)或断开。
 
 ```lua
 function on_input(self, action_id, action)
     if action_id == hash("gamepad_connected") then
         if action.gamepad == 0 then
-          -- 手柄0已连接
+          -- 游戏手柄0已连接
         end
-    elseif action_id == hash("gamepad_dicconnected") then
+    elseif action_id == hash("gamepad_disconnected") then
         if action.gamepad == 0 then
-          -- 手柄0已断开
+          -- 游戏手柄0已断开连接
         end
     end
 end
 ```
 
-## 手柄原始数据
-(更新于 Defold 1.2.183)
+## 原始游戏手柄
+(自Defold 1.2.183起)
 
-手柄输入绑定提供了一个 `Raw` 事件给出按键, 十字键或者摇杆的原始 (不使用阈值) 数据.
+游戏手柄输入绑定还提供一个名为`Raw`的独立绑定,用于提供任何连接的游戏手柄的未过滤(未应用死区)的按钮、轴和方向键输入。
 
 ```lua
 function on_input(self, action_id, action)
@@ -104,12 +104,12 @@ function on_input(self, action_id, action)
 end
 ```
 
-## 手柄配置文件
-每种手柄分别对应一份映射文件, 可以在 *gamepads* 配置文件中设置. Defold 自带一个通用的手柄映射配置文件:
+## 游戏手柄设置文件
+游戏手柄输入设置为每种硬件游戏手柄类型使用单独的映射文件。特定硬件游戏手柄的游戏手柄映射在*gamepads*文件中设置。Defold附带了一个内置的游戏手柄文件,其中包含常见游戏手柄的设置:
 
 ![Gamepad settings](images/input/gamepads.png)
 
-如需自定义文件, 可以配合使用这个工具:
+如果您需要创建新的游戏手柄设置文件,我们有一个简单的工具可以帮助您:
 
 [Click to download gdc.zip](https://forum.defold.com/t/big-thread-of-gamepad-testing/56032).
 
@@ -119,116 +119,117 @@ end
 ./gdc
 ```
 
-这个工具通过收集连接控制器的输入自动生成映射文件. 新的映射文件可以在 *game.project* 里进行指定或者混合使用:
+该工具将要求您按下连接控制器上的不同按钮。然后,它将输出一个新的游戏手柄文件,其中包含您控制器的正确映射。保存新文件,或将其与现有的游戏手柄文件合并,然后在*game.project*中更新设置:
 
 ![Gamepad settings](images/input/gamepad_setting.png)
 
-### 未映射手柄
-(更新于 Defold 1.2.186)
+### 未识别的游戏手柄
+(自Defold 1.2.186起)
 
-如果手柄没有配置消息映射的话, 就只有 "connected", "disconnected" 和 "raw" 三种事件. 这种情况下只能使用手柄原始数据来控制游戏.
+当游戏手柄连接且没有该游戏手柄的映射时,游戏手柄将只生成"connected"、"disconnected"和"raw"操作。在这种情况下,您需要在游戏中手动将原始游戏手柄数据映射到操作。
 
-(更新于 Defold 1.4.8)
+(自Defold 1.4.8起)
 
-可以通过查看 action 的 `gamepad_unknown` 值来确定输入行为是否来源于未知手柄:
+可以通过从操作中读取`gamepad_unknown`值来检查游戏手柄的输入操作是否来自未知游戏手柄:
 
 ```lua
 function on_input(self, action_id, action)
     if action_id == hash("connected") then
         if action.gamepad_unknown then
-            print("The connected gamepad is unidentified and will only generate raw input")
+            print("The connected gamepad is unidentified and will only generate raw input") -- 连接的游戏手柄未被识别,只会生成原始输入
         else
-            print("The connected gamepad is known and will generate input actions for buttons and sticks")
+            print("The connected gamepad is known and will generate input actions for buttons and sticks") -- 连接的游戏手柄已知,将为按钮和摇杆生成输入操作
         end
     end
 end
 ``` 
 
-## HTML5的游戏手柄
-HTML5平台同样支持游戏手柄, 效果和原生应用一样. 游戏手柄的支持基于 [标准游戏手柄API](https://www.w3.org/TR/gamepad/), 并且受绝大多数浏览器支持 ([详见此图表](https://caniuse.com/?search=gamepad)). 万一遇到不支持的浏览器 Defold 会忽略所有游戏手柄的操作. 可以通过检查浏览器的`navigator`对象中是否存在`getGamepads`函数来判断其是否支持游戏手柄:
+## HTML5的游戏手柄
+HTML5构建中支持游戏手柄,并生成与其他平台相同的输入事件。游戏手柄的支持基于[游戏手柄API](https://www.w3.org/TR/gamepad/),大多数浏览器都支持此API([参考此支持图表](https://caniuse.com/?search=gamepad))。如果浏览器不支持游戏手柄API,Defold将静默忽略项目中的任何游戏手柄触发器。您可以通过检查`navigator`对象上是否存在`getGamepads`函数来检查浏览器是否支持游戏手柄API:
 
 ```lua
 local function supports_gamepads()
     return not html5 or (html5.run('typeof navigator.getGamepads === "function"') == "true")
 end
+
 if supports_gamepads() then
-    print("Platform supports gamepads")
+    print("Platform supports gamepads") -- 平台支持游戏手柄
 end
 ```
 
-运行在 `iframe` 上的游戏要确保 `iframe` 的 `gamepad` 权限已被开启:
+如果您的游戏在`iframe`内运行,您还必须确保`iframe`已添加`gamepad`权限:
 
 ```html
 <iframe allow="gamepad"></iframe>
 ```
 
 
-### 标准手柄
-(自 Defold 1.4.1 版本起)
+### 标准游戏手柄
+(自Defold 1.4.1起)
 
-如果连着的手柄被浏览器视为标准手柄, 则它会使用 [手柄配置文件](/manuals/input-gamepads/#gamepads-settings-file) (在 `/builtins` 目录下有一个标准手柄映射配置文件 `default.gamepads`) 里的 "Standard Gamepad" 映射. 所谓标准手柄是指包含个 16 按钮和 2 个摇杆的手柄, 布局类似 PlayStation 或者 Xbox 手柄 (更多详情请参考 [W3C 定义及按钮布局](https://w3c.github.io/gamepad/#dfn-standard-gamepad)). 如果连接着的手柄未被视为标准手柄 Defold 会根据硬件类型在手柄配置文件里寻找匹配的映射.
+如果连接的游戏手柄被浏览器识别为标准游戏手柄,它将使用[游戏手柄设置文件](/manuals/input-gamepads/#gamepads-settings-file)中的"Standard Gamepad"映射(在`/builtins`中的`default.gamepads`文件中包含标准游戏手柄映射)。标准游戏手柄定义为具有16个按钮和2个模拟摇杆,按钮布局类似于PlayStation或Xbox控制器(有关更多信息,请参阅[W3C定义和按钮布局](https://w3c.github.io/gamepad/#dfn-standard-gamepad))。如果连接的游戏手柄未被识别为标准游戏手柄,Defold将在游戏手柄设置文件中查找与硬件游戏手柄类型匹配的映射。
 
-## Windows 上的手柄
-在 Windows 上, 只支持 XBox 360 兼容手柄. To hook up your 360 controller to your Windows machine, [make sure it is setup correctly](http://www.wikihow.com/Use-Your-Xbox-360-Controller-for-Windows).
-## 安卓手柄
-(更新于 Defold 1.2.183)
+## Windows上的游戏手柄
+在Windows上,目前只支持XBox 360控制器。要将360控制器连接到Windows机器,[请确保正确设置](http://www.wikihow.com/Use-Your-Xbox-360-Controller-for-Windows)。
+## Android上的游戏手柄
+(自Defold 1.2.183起)
 
-Android 和其他平台一样支持手柄的输入事件. 手柄支持基于 [Android 按键和运动事件输入系统](https://developer.android.com/training/game-controllers/controller-input). 通过上文提到的 *gamepad* 文件把安卓输入事件转化成 Defold 手柄事件.
+Android构建中支持游戏手柄,并生成与其他平台相同的输入事件。游戏手柄的支持基于[Android按键和运动事件输入系统](https://developer.android.com/training/game-controllers/controller-input)。Android输入事件将使用上述相同的*gamepad*文件转换为Defold游戏手柄事件。
 
-安卓手柄输入按键到 *gamepad* 文件手柄事件对应表如下:
+在Android上添加额外的游戏手柄绑定时,您可以使用以下查找表将Android输入事件转换为*gamepad*文件值:
 
-| 按键输入 | 事件编号 | 引擎版本 |
+| 按键事件到按钮索引   | 索引 | 版本 |
 |-----------------------------|-------|---------|
-| AKEYCODE_BUTTON_A           | 0     | 1.2.183 |
-| AKEYCODE_BUTTON_B           | 1     | 1.2.183 |
-| AKEYCODE_BUTTON_C           | 2     | 1.2.183 |
-| AKEYCODE_BUTTON_X           | 3     | 1.2.183 |
-| AKEYCODE_BUTTON_L1          | 4     | 1.2.183 |
-| AKEYCODE_BUTTON_R1          | 5     | 1.2.183 |
-| AKEYCODE_BUTTON_Y           | 6     | 1.2.183 |
-| AKEYCODE_BUTTON_Z           | 7     | 1.2.183 |
-| AKEYCODE_BUTTON_L2          | 8     | 1.2.183 |
-| AKEYCODE_BUTTON_R2          | 9     | 1.2.183 |
-| AKEYCODE_DPAD_CENTER        | 10    | 1.2.183 |
-| AKEYCODE_DPAD_DOWN          | 11    | 1.2.183 |
-| AKEYCODE_DPAD_LEFT          | 12    | 1.2.183 |
-| AKEYCODE_DPAD_RIGHT         | 13    | 1.2.183 |
-| AKEYCODE_DPAD_UP            | 14    | 1.2.183 |
-| AKEYCODE_BUTTON_START       | 15    | 1.2.183 |
-| AKEYCODE_BUTTON_SELECT      | 16    | 1.2.183 |
-| AKEYCODE_BUTTON_THUMBL      | 17    | 1.2.183 |
-| AKEYCODE_BUTTON_THUMBR      | 18    | 1.2.183 |
-| AKEYCODE_BUTTON_MODE        | 19    | 1.2.183 |
-| AKEYCODE_BUTTON_1           | 20    | 1.2.186 |
-| AKEYCODE_BUTTON_2           | 21    | 1.2.186 |
-| AKEYCODE_BUTTON_3           | 22    | 1.2.186 |
-| AKEYCODE_BUTTON_4           | 23    | 1.2.186 |
-| AKEYCODE_BUTTON_5           | 24    | 1.2.186 |
-| AKEYCODE_BUTTON_6           | 25    | 1.2.186 |
-| AKEYCODE_BUTTON_7           | 26    | 1.2.186 |
-| AKEYCODE_BUTTON_8           | 27    | 1.2.186 |
-| AKEYCODE_BUTTON_9           | 28    | 1.2.186 |
-| AKEYCODE_BUTTON_10          | 29    | 1.2.186 |
-| AKEYCODE_BUTTON_11          | 30    | 1.2.186 |
-| AKEYCODE_BUTTON_12          | 31    | 1.2.186 |
-| AKEYCODE_BUTTON_13          | 32    | 1.2.186 |
-| AKEYCODE_BUTTON_14          | 33    | 1.2.186 |
-| AKEYCODE_BUTTON_15          | 34    | 1.2.186 |
-| AKEYCODE_BUTTON_16          | 35    | 1.2.186 |
+| `AKEYCODE_BUTTON_A`           | 0     | 1.2.183 |
+| `AKEYCODE_BUTTON_B`           | 1     | 1.2.183 |
+| `AKEYCODE_BUTTON_C`           | 2     | 1.2.183 |
+| `AKEYCODE_BUTTON_X`           | 3     | 1.2.183 |
+| `AKEYCODE_BUTTON_L1`          | 4     | 1.2.183 |
+| `AKEYCODE_BUTTON_R1`          | 5     | 1.2.183 |
+| `AKEYCODE_BUTTON_Y`           | 6     | 1.2.183 |
+| `AKEYCODE_BUTTON_Z`           | 7     | 1.2.183 |
+| `AKEYCODE_BUTTON_L2`          | 8     | 1.2.183 |
+| `AKEYCODE_BUTTON_R2`          | 9     | 1.2.183 |
+| `AKEYCODE_DPAD_CENTER`        | 10    | 1.2.183 |
+| `AKEYCODE_DPAD_DOWN`          | 11    | 1.2.183 |
+| `AKEYCODE_DPAD_LEFT`          | 12    | 1.2.183 |
+| `AKEYCODE_DPAD_RIGHT`         | 13    | 1.2.183 |
+| `AKEYCODE_DPAD_UP`            | 14    | 1.2.183 |
+| `AKEYCODE_BUTTON_START`       | 15    | 1.2.183 |
+| `AKEYCODE_BUTTON_SELECT`      | 16    | 1.2.183 |
+| `AKEYCODE_BUTTON_THUMBL`      | 17    | 1.2.183 |
+| `AKEYCODE_BUTTON_THUMBR`      | 18    | 1.2.183 |
+| `AKEYCODE_BUTTON_MODE`        | 19    | 1.2.183 |
+| `AKEYCODE_BUTTON_1`           | 20    | 1.2.186 |
+| `AKEYCODE_BUTTON_2`           | 21    | 1.2.186 |
+| `AKEYCODE_BUTTON_3`           | 22    | 1.2.186 |
+| `AKEYCODE_BUTTON_4`           | 23    | 1.2.186 |
+| `AKEYCODE_BUTTON_5`           | 24    | 1.2.186 |
+| `AKEYCODE_BUTTON_6`           | 25    | 1.2.186 |
+| `AKEYCODE_BUTTON_7`           | 26    | 1.2.186 |
+| `AKEYCODE_BUTTON_8`           | 27    | 1.2.186 |
+| `AKEYCODE_BUTTON_9`           | 28    | 1.2.186 |
+| `AKEYCODE_BUTTON_10`          | 29    | 1.2.186 |
+| `AKEYCODE_BUTTON_11`          | 30    | 1.2.186 |
+| `AKEYCODE_BUTTON_12`          | 31    | 1.2.186 |
+| `AKEYCODE_BUTTON_13`          | 32    | 1.2.186 |
+| `AKEYCODE_BUTTON_14`          | 33    | 1.2.186 |
+| `AKEYCODE_BUTTON_15`          | 34    | 1.2.186 |
+| `AKEYCODE_BUTTON_16`          | 35    | 1.2.186 |
 
 ([Android `KeyEvent` 定义](https://developer.android.com/ndk/reference/group/input#group___input_1gafccd240f973cf154952fb917c9209719))
 
-| 摇杆输入  | 事件编号 |
+| 运动事件到轴索引  | 索引 |
 |-----------------------------|-------|
-| AMOTION_EVENT_AXIS_X        | 0     |
-| AMOTION_EVENT_AXIS_Y        | 1     |
-| AMOTION_EVENT_AXIS_Z        | 2     |
-| AMOTION_EVENT_AXIS_RZ       | 3     |
-| AMOTION_EVENT_AXIS_LTRIGGER | 4     |
-| AMOTION_EVENT_AXIS_RTRIGGER | 5     |
-| AMOTION_EVENT_AXIS_HAT_X    | 6     |
-| AMOTION_EVENT_AXIS_HAT_Y    | 7     |
+| `AMOTION_EVENT_AXIS_X`        | 0     |
+| `AMOTION_EVENT_AXIS_Y`        | 1     |
+| `AMOTION_EVENT_AXIS_Z`        | 2     |
+| `AMOTION_EVENT_AXIS_RZ`       | 3     |
+| `AMOTION_EVENT_AXIS_LTRIGGER` | 4     |
+| `AMOTION_EVENT_AXIS_RTRIGGER` | 5     |
+| `AMOTION_EVENT_AXIS_HAT_X`    | 6     |
+| `AMOTION_EVENT_AXIS_HAT_Y`    | 7     |
 
 ([Android `MotionEvent` 定义](https://developer.android.com/ndk/reference/group/input#group___input_1ga157d5577a5b2f5986037d0d09c7dc77d))
 
-为了正确使用手柄事件映射请参考上表以及 Google Play Store 上的手柄映射测试小工具.
+将此查找表与Google Play商店中的游戏手柄测试应用程序结合使用,以确定您游戏手柄上的每个按钮映射到哪个按键事件。

+ 16 - 16
docs/zh/manuals/input-key-and-text.md

@@ -1,14 +1,14 @@
 ---
-title: Defold 键盘按键和文本输入教程
-brief: 本教程介绍了键盘按键和文本输入的功能.
+title: Defold键和文本输入
+brief: 本手册解释了键和文本输入的工作原理。
 ---
 
 ::: sidenote
-建议首先熟练掌握 Defold 中常规输入的消息处理方式, 例如输入消息获取以及脚本间输入消息广播顺序等. 关于输入系统详情请见 [输入系统教程](/manuals/input).
+建议您先熟悉Defold中输入的一般工作方式,如何接收输入以及输入在脚本文件中的接收顺序。有关输入系统的更多信息,请参阅[输入系统概述手册](/manuals/input)。
 :::
 
-# Key Triggers
-键盘输入触发器用以把键盘按键输入映射为游戏需要的动作. 每个按键分别与动作一一对应, 比如箭头键和WASD键映射为角色移动. 如果需要文字输入, 要使用 text triggers (见下文).
+# 键触发器
+键触发器允许您将单个键的键盘输入绑定到游戏操作。每个键分别映射到相应的操作。键触发器用于将特定按钮绑定到特定功能,例如使用箭头键或WASD键进行角色移动。如果您需要读取任意键盘输入,请使用文本触发器(见下文)。
 
 ![](images/input/key_bindings.png)
 
@@ -16,26 +16,26 @@ brief: 本教程介绍了键盘按键和文本输入的功能.
 function on_input(self, action_id, action)
     if action_id == hash("left") then
         if action.pressed then
-            -- start moving left
+            -- 开始向左移动
         elseif action.released then
-            -- stop moving left
+            -- 停止向左移动
         end
     end
 end
 ```
 
-# Text Triggers
-文本触发器用来读取输入的文字. 分为两种: text 和 marked text.
+# 文本触发器
+文本触发器用于读取任意文本输入。有两种类型的文本触发器:文本和标记文本。
 
 ![](images/input/text_bindings.png)
 
-## Text
-`text` 捕获一般字符输入. 事件 `text` 项保存了输入的字符. 动作由按下按钮时触发, 不存在 `release` 和 `repeated` 事件.
+## 文本
+`text`捕获普通文本输入。它将操作表的`text`字段设置为包含键入字符的字符串。该操作仅在按下按钮时触发,不会发送`release`或`repeated`操作。
 
   ```lua
 function on_input(self, action_id, action)
     if action_id == hash("text") then
-        -- 收集输入字符填充 "user" 节点...
+        -- 将键入的字符连接到"user"节点...
         local node = gui.get_node("user")
         local name = gui.get_text(node)
         name = name .. action.text
@@ -44,10 +44,10 @@ function on_input(self, action_id, action)
 end 
   ```
 
-## Marked text
-`marked-text` 一般用于亚洲键盘可把多个按键事件合为一个输入事件. 比如说, iOS 里的 "Japanese-Kana" 键盘, 用户输入多个键时键盘上方就会显示出可供输入的文字或字符串.
+## 标记文本
+`marked-text`主要用于亚洲键盘,其中多次按键可以映射到单个输入。例如,使用iOS的"Japanese-Kana"键盘,用户可以键入组合,键盘顶部将显示可输入的符号或符号序列。
 
 ![Input marked text](images/input/marked_text.png)
 
-- 每个键被按下时触发事件, 动作 `text` 为目前已经输入了的字符串 (星号标记文本).
-- 用户选择了要提交的文字时, 一个 `text` 类型动作被触发 (证明当前触发器配置正确). 而这个动作的 `text` 项保存了用户最终提交的文字.
+- 每次按键生成单独的操作,并将操作字段`text`设置为当前输入的符号序列("标记文本")。
+- 当用户选择符号或符号组合时,会发送单独的`text`类型触发器操作(前提是在输入绑定列表中设置了一个)。单独的操作将操作字段`text`设置为最终的符号序列。

+ 35 - 35
docs/zh/manuals/input-mouse-and-touch.md

@@ -1,14 +1,14 @@
 ---
-title: Defold 鼠标和触摸输入教程
-brief: 本教程介绍了鼠标和触摸输入的功能.
+title: Defold鼠标和触摸输入
+brief: 本手册解释了鼠标和触摸输入的工作原理。
 ---
 
 ::: sidenote
-建议首先熟练掌握 Defold 中常规输入的消息处理方式, 例如输入消息获取以及脚本间输入消息广播顺序等. 关于输入系统详情请见 [输入系统教程](/manuals/input).
+建议您熟悉Defold中输入的一般工作方式,如何接收输入以及在脚本文件中接收输入的顺序。有关输入系统的更多信息,请参阅[输入系统概述手册](/manuals/input)。
 :::
 
-# Mouse Triggers
-鼠标触发器可以绑定鼠标按键和滚轮输入到游戏功能的映射.
+# 鼠标触发器
+鼠标触发器允许您将鼠标按钮和滚轮输入绑定到游戏操作。
 
 ![](images/input/mouse_bindings.png)
 
@@ -17,11 +17,11 @@ brief: 本教程介绍了鼠标和触摸输入的功能.
 :::
 
 ::: important
-下面的例子中使用了上图的映射绑定配置. 映射与命名可以根据项目需要自由设置.
+下面的示例使用了上图中显示的操作。与所有输入一样,您可以自由命名输入操作。
 :::
 
-## 鼠标
-鼠标键可以生成按下, 抬起和连按消息. 获取鼠标键消息的方法如下 (按下和抬起):
+## 鼠标按钮
+鼠标按钮会生成按下、释放和重复事件。以下示例显示如何检测鼠标左键的输入(按下或释放):
 
 ```lua
 function on_input(self, action_id, action)
@@ -29,18 +29,18 @@ function on_input(self, action_id, action)
         if action.pressed then
             -- 鼠标左键按下
         elseif action.released then
-            -- 鼠标左键抬起
+            -- 鼠标左键释放
         end
     end
 end
 ```
 
 ::: important
-单点触摸也会触发 `MOUSE_BUTTON_LEFT` (或 `MOUSE_BUTTON_1`) 事件.
+`MOUSE_BUTTON_LEFT`(或`MOUSE_BUTTON_1`)输入操作也会为单点触摸输入发送。
 :::
 
 ## 鼠标滚轮
-鼠标滚轮可以生成滚动消息. 如果 `action.value` 为 `1` 代表转动, 为 `0` 代表不转动. (滚轮转动被当作一种按钮消息来处理. Defold 目前不支持触摸板上的滚轮输入.)
+鼠标滚轮输入检测滚动操作。如果滚轮滚动,`action.value`字段为`1`,否则为`0`。(滚动操作被视为按钮按下处理。Defold目前不支持触摸板上的精细滚动输入。)
 
 ```lua
 function on_input(self, action_id, action)
@@ -53,14 +53,14 @@ end
 ```
 
 ## 鼠标移动
-鼠标移动消息有点特别. 如果输入绑定表里没有鼠标的话, 鼠标移动事件也会被丢弃.
+鼠标移动是单独处理的。除非在输入绑定中设置了至少一个鼠标触发器,否则不会接收到鼠标移动事件。
 
-但是不用特地为了鼠标移动配置绑定, 因为鼠标移动时会自动生成事件, 其中 `action_id` 为 `nil` 并且 `action` 表保存了鼠标位置与移动距离.
+鼠标移动不在输入绑定中绑定,但`action_id`设置为`nil`,并且`action`表中填充了鼠标位置和增量移动。
 
 ```lua
 function on_input(self, action_id, action)
     if action.x and action.y then
-        -- 游戏对象跟随鼠标/触摸
+        -- 游戏对象跟随鼠标/触摸移动
         local pos = vmath.vector3(action.x, action.y, 0)
         go.set_position(pos)
     end
@@ -68,20 +68,20 @@ end
 ```
 
 # 触摸触发器
-iOS 和 Android 设备上运行的原生应用与HTML5应用都支持单点和多点触摸输入.
+单点和多点触摸类型触发器在iOS和Android设备上的原生应用程序和HTML5包中可用。
 
 ![](images/input/touch_bindings.png)
 
-## Single-touch
-单点触摸不用在触摸映射部分进行设置. 而在 **鼠标映射设置了 `MOUSE_BUTTON_LEFT` 或称 `MOUSE_BUTTON_1`** 之后自行配置.
+## 单点触摸
+单点触摸类型触发器不是从输入绑定的触摸触发器部分设置的。相反,**当您为`MOUSE_BUTTON_LEFT`或`MOUSE_BUTTON_1`设置了鼠标按钮输入时,单点触摸触发器会自动设置**。
 
-## Multi-touch
-多点触摸在输入映射表里叫做 `touch`. 其元素索引为数字 `1`--`N`, 这里 `N` 是触摸点的编号. 其元素值为触摸点数据:
+## 多点触摸
+多点触摸类型触发器在操作表中填充一个名为`touch`的表。表中的元素是用数字`1`--`N`进行整数索引的,其中`N`是触摸点的数量。表的每个元素包含输入数据的字段:
 
 ```lua
 function on_input(self, action_id, action)
     if action_id == hash("touch_multi") then
-        -- 在触摸点的位置生成游戏对象
+        -- 在每个触摸点生成
         for i, touchdata in ipairs(action.touch) do
             local pos = vmath.vector3(touchdata.x, touchdata.y, 0)
             factory.create("#factory", pos)
@@ -90,32 +90,32 @@ function on_input(self, action_id, action)
 end
 ```
 
-::: sidenote
-多点触摸动作名不能与 `MOUSE_BUTTON_LEFT` 或 `MOUSE_BUTTON_1` 的动作名重名. 否则的话将导致事件覆盖, 就监听不到单点触摸事件了.
+::: important
+多点触摸不能分配与`MOUSE_BUTTON_LEFT`或`MOUSE_BUTTON_1`的鼠标按钮输入相同的操作。分配相同的操作将有效地覆盖单点触摸,并阻止您接收任何单点触摸事件。
 :::
 
 ::: sidenote
-公共资源 [Defold 输入手柄](https://defold.com/assets/defoldinput/) 可以用来在多点触摸屏上模拟手柄输入.
+[Defold-Input资源](https://defold.com/assets/defoldinput/)可用于轻松设置虚拟屏幕控件,如按钮和支持多点触摸的模拟摇杆。
 :::
 
 
-## 拾取检测
-游戏里经常可见拾取操作. 可能是玩家点击界面按钮或者战略游戏里玩家选取一个作战单位, RPG 游戏点取宝箱等等. 不同组件有不同解决方法.
+## 检测对象上的点击或触摸
+检测用户何时点击或触摸视觉组件是许多游戏中需要的非常常见的操作。可能是用户与按钮或其他UI元素的交互,或者与游戏对象的交互,如策略游戏中的玩家控制单位、地牢爬行游戏中关卡上的宝藏或RPG中的任务给予者。使用的方法取决于视觉组件的类型。
 
-### 界面点击检测
-界面有一个 `gui.pick_node(node, x, y)` 函数来判断点击输入是否处在某个节点范围之内. 详见 [API 文档](/ref/gui/#gui.pick_node:node-x-y), [指针悬停示例](https://www.defold.com/examples/pointer_over/) 或者 [按钮示例](https://www.defold.com/examples/button/).
+### 检测与GUI节点的交互
+对于UI元素,有一个`gui.pick_node(node, x, y)`函数,它将根据指定坐标是否在GUI节点的边界内返回true或false。请参阅[API文档](/ref/gui/#gui.pick_node:node-x-y)、[指针悬停示例](/examples/gui/pointer_over/)或[按钮示例](/examples/gui/button/)了解更多信息。
 
-### 游戏对象点击检测
-游戏对象检测有点复杂, 因为摄像机移动和渲染脚本映射都会影响位置计算. 方法主要分为两种:
+### 检测与游戏对象的交互
+对于游戏对象,检测交互更加复杂,因为诸如摄像机平移和渲染脚本投影等因素将影响所需的计算。检测与游戏对象的交互有两种通用方法:
 
-  1. 追踪游戏对象的位置和大小然后检测点选位置是否包含在内.
-  2. 给游戏对象加入碰撞组件再在点选位置生成一个碰撞对象检查二者碰撞情况.
+  1. 跟踪用户可以与之交互的游戏对象的位置和大小,并检查鼠标或触摸坐标是否在任何对象的边界内。
+  2. 将碰撞对象附加到用户可以与之交互的游戏对象上,并附加一个跟随鼠标或手指的碰撞对象,并检查它们之间的碰撞。
 
 ::: sidenote
-公共资源 [Defold 输入库](https://github.com/britzl/defold-input) 是一个开箱即用的输入检测库.
+可以在[Defold-Input资源](https://defold.com/assets/defoldinput/)中找到使用碰撞对象检测用户输入的现成解决方案,支持拖动和点击。
 :::
 
-无论哪种方案都必须将鼠标手点选的屏幕坐标转换成游戏对象的世界坐标. 实现思路如下:
+在这两种情况下,都需要从鼠标或触摸事件的屏幕空间坐标和游戏对象的世界空间坐标进行转换。这可以通过几种不同的方式完成:
 
-  * 手动跟踪渲染脚本使用的视口和投射用以进行坐标转换. 详见 [摄像机教程的这个示例](/manuals/camera/#鼠标位置转换为世界坐标).
-  * 使用 [第三方摄像机解决方案](/manuals/camera/#第三方摄像机解决方案) 里面的屏幕到世界坐标转换函数.
+  * 手动跟踪渲染脚本使用的视图和投影,并使用它在世界空间之间进行转换。有关此示例,请参阅[摄像机手册](/manuals/camera/#converting-mouse-to-world-coordinates)。
+  * 使用[第三方摄像机解决方案](/manuals/camera/#third-party-camera-solutions)并利用提供的屏幕到世界转换函数。

+ 69 - 69
docs/zh/manuals/input.md

@@ -1,120 +1,120 @@
 ---
-title: Defold 的设备输入操作
-brief: 本教程介绍了输入系统如何工作, 如何捕获输入行为和相关脚本代码.
+title: 设备输入在Defold中
+brief: 本手册解释了输入如何工作,如何捕获输入操作并创建交互式脚本反应。
 ---
 
 # 输入
 
-输入由引擎捕获并转化为输入行为传送到获取了输入焦点并且实现了 `on_input()` 函数的游戏对象脚本组件中去. 本教程介绍了捕获输入绑定行为的方法以及如何用代码对输入做出响应.
+所有用户输入都由引擎捕获,并作为操作分派给已获取输入焦点并实现了`on_input()`函数的游戏对象中的脚本和GUI脚本组件。本手册解释了如何设置绑定以捕获输入,以及如何创建响应输入的代码。
 
-输入系统包含一些概念, 用以让开发者直观地处理游戏逻辑.
+输入系统使用一组简单而强大的概念,允许您按照适合游戏的方式管理输入。
 
 ![Input bindings](images/input/overview.png)
 
-Devices
-: 不管是插上的, 连上的, 有线无线的, 操作系统级别的底层能够进行输入的设备. Defold 支持以下设备:
+设备
+: 输入设备是计算机或移动设备的一部分或插入其中的设备,为Defold运行时提供原始系统级输入。支持以下设备类型:
 
   1. 键盘 (包括按键输入和文本输入)
   2. 鼠标 (位置, 按键, 滚轮输入)
   3. 单点/多点触摸屏 (iOS, Android 设备和 HTML5 手机端)
   4. 游戏手柄 (操作系统负责将其输入发送给游戏然后映射给脚本. 详见 [游戏手柄配置文件](#gamepads-settings-file))
 
-Input bindings
-: 发送给脚本之前设备原始输入信号要通过映射表转化为有意义的 *动作* 指令.
+输入绑定
+: 在输入发送到脚本之前,来自设备的原始输入通过输入绑定表转换为有意义的*操作*。
 
-Actions
-: 动作是列在输入绑定文件里的 (哈希过的) 名字. 每种动作还包括其相关数据: 比如按钮是被按下还是抬起, 鼠标或触摸屏幕坐标等等.
+操作
+: 操作通过您在输入绑定文件中列出的(哈希)名称来标识。每个操作还包含有关输入的相关数据:按钮是按下还是释放,鼠标和触摸的坐标等。
 
-Input listeners
-: 脚本可以得到 *获取了输入焦点的* 组件的输入消息. 一个输入信息可以同时激活多个输入监听器.
+输入监听器
+: 任何脚本组件或GUI脚本都可以通过*获取输入焦点*来接收输入操作。可以同时激活多个监听器。
 
-Input stack
-: 首个获取输入焦点的组件位于最下端, 最后一个获取输入焦点的组件位于最上端的输入监听器堆栈.
+输入栈
+: 输入监听器列表,第一个获取焦点的组件在栈底,最后一个获取焦点的组件在栈顶。
 
-Consuming input
-: 脚本消耗了输入信息, 不再让输入栈的深层监听器得到这个信息.
+消耗输入
+: 脚本可以选择消耗接收到的输入,阻止栈中更下方的监听器接收它。
 
-## 输入绑定设置
+## 设置输入绑定
 
-输入绑定是整个项目通用的, 记录如何把设备输入映射为带名字的 *动作* 以方便脚本使用的列表. 新建输入绑定文件, 在 *Assets* 视图中 <kbd>右键点击</kbd> 选择 <kbd>New... ▸ Input Binding</kbd>. 然后修改 *game.project* 里 *Game Binding* 项对输入绑定文件的引用.
+输入绑定是项目范围的表,允许您指定设备输入在分派到脚本组件和GUI脚本之前如何转换为命名的*操作*。您可以创建一个新的输入绑定文件,在*Assets*视图中<kbd>右键点击</kbd>一个位置并选择<kbd>New... ▸ Input Binding</kbd>。要使引擎使用新文件,请更改*game.project*中的*Game Binding*条目。
 
 ![Input binding setting](images/input/setting.png)
 
-每个新建项目都会自动生成默认输入绑定文件. 默认叫做 "game.input_binding", 位于项目根目录下 "input" 文件夹内. <kbd>双击</kbd> 即可在编辑器中打开此文件:
+所有新项目模板都会自动创建一个默认的输入绑定文件,因此通常不需要创建新的绑定文件。默认文件名为"game.input_binding",可以在项目根目录的"input"文件夹中找到。<kbd>双击</kbd>该文件在编辑器中打开:
 
 ![Input set bindings](images/input/input_binding.png)
 
-点击相关触发类型底部的 <kbd>+</kbd> 按钮, 即可新建一个绑定项. 每一项有两个部分:
+要创建新绑定,点击相关触发类型部分底部的<kbd>+</kbd>按钮。每个条目有两个字段:
 
-*Input*
-: 需要监听的底层输入信号, 从滚动列表里选择.
+*输入*
+: 要监听的原始输入,从可用输入的滚动列表中选择。
 
-*Action*
-: 输入对应的用于发送给脚本的动作名. 一个动作可以对应多个输入. 例如, 可以设置按下 <kbd>空格</kbd> 键和游戏手柄 "A" 按钮都是 `jump` 动作. 可是触屏输入的动作名必须是唯一值.
+*操作*
+: 给输入操作指定的名称,当它们被创建并分派到您的脚本时使用。可以将相同的操作名称分配给多个输入。例如,您可以将<kbd>空格</kbd>键和游戏手柄"A"按钮绑定到操作`jump`。请注意,存在一个已知错误,即触摸输入不幸不能与其他输入具有相同的操作名称。
 
 ## 触发器类型
 
-触发器有五种类型:
+您可以创建五种设备特定的触发器类型:
 
-Key Triggers
-: 键盘单键输入. 每个键分别映射为指定的动作. 一一对应. 详情请见 [键盘按键输入教程](/manuals/input-key-and-text).
+键触发器
+: 单键键盘输入。每个键分别映射到相应的操作。在[键和文本输入手册](/manuals/input-key-and-text)中了解更多。
 
-Text Triggers
-: 文本触发器用来读取输入的文字. 详情请见 [键盘按键输入教程](/manuals/input-key-and-text).
+文本触发器
+: 文本触发器用于读取任意文本输入。在[键和文本输入手册](/manuals/input-key-and-text)中了解更多。
 
-Mouse Triggers
-: 来自鼠标按键和滚轮的输入. 详情请见 [鼠标和触摸输入教程](/manuals/input-mouse-and-touch).
+鼠标触发器
+: 来自鼠标按钮和滚轮的输入。在[鼠标和触摸输入手册](/manuals/input-mouse-and-touch)中了解更多。
 
-Touch Triggers
-: iOS 和 Android 设备上运行的原生应用与HTML5应用都支持单点和多点触摸输入. 详情请见 [鼠标和触摸输入教程](/manuals/input-mouse-and-touch).
+触摸触发器
+: 单点和多点触摸类型触发器在iOS和Android设备上的原生应用程序和HTML5包中可用。在[鼠标和触摸手册](/manuals/input-mouse-and-touch)中了解更多。
 
-Gamepad Triggers
-: 这种触发器可以绑定标准手柄输入到游戏功能的映射. 详情请见 [游戏手柄输入教程](/manuals/input-gamepads).
+游戏手柄触发器
+: 游戏手柄触发器允许您将标准游戏手柄输入绑定到游戏功能。在[游戏手柄手册](/manuals/input-gamepads)中了解更多。
 
 ### 加速度计输入
 
-除了上述五种输入触发器, Defold 还支持 Android 和 iOS 原生系统加速度计输入. 需要勾选 *game.project* 配置文件中输入部分里的 Use Accelerometer.
+除了上面列出的五种不同触发器类型外,Defold还在原生Android和iOS应用程序中支持加速度计输入。在*game.project*文件的Input部分中勾选Use Accelerometer框。
 
 ```lua
 function on_input(self, action_id, action)
     if action.acc_x and action.acc_y and action.acc_z then
-        -- 读取加速度计数据
+        -- 对加速度计数据做出反应
     end
 end
 ```
 
 ## 输入焦点
 
-脚本要想获得输入消息, 就要把 `acquire_input_focus` 消息发给其所在的游戏对象:
+要在脚本组件或GUI脚本中监听输入操作,应将`acquire_input_focus`消息发送到持有该组件的游戏对象:
 
 ```lua
--- 告诉当前游戏对象 (".") 要接收输入消息了
+-- 告诉当前游戏对象(".")获取输入焦点
 msg.post(".", "acquire_input_focus")
 ```
 
-此消息让引擎把可接收输入的游戏对象组件 (脚本, GUI 和集合代理) 压入 *输入栈*. 这些组件位于栈顶; 最后入栈的组件位于栈顶. 注意如果一个游戏对象包含多个输入组件, 所有组件都会入栈:
+此消息指示引擎将游戏对象中具有输入功能的组件(脚本组件、GUI组件和集合代理)添加到*输入栈*中。游戏对象组件被放在输入栈的顶部;最后添加的组件将位于栈顶。请注意,如果游戏对象包含多个具有输入功能的组件,所有组件都将被添加到栈中:
 
 ![Input stack](images/input/input_stack.png)
 
-如果已获得输入焦点的游戏对象再次请求输入焦点, 那么其组件会被移至输入栈顶端.
+如果已经获取输入焦点的游戏对象再次这样做,其组件将被移动到栈顶。
 
 
-## 输入调度和 on_input() 函数
+## 输入分派和 on_input()
 
-输入事件在输入栈上, 从上到下传递.
+输入操作根据输入栈进行分派,从顶部到底部。
 
 ![Action dispatch](images/input/actions.png)
 
-每个入栈组件都有 `on_input()` 函数, 一帧中每个输入都调用一次该函数, 连同如下参数:
+栈上任何包含`on_input()`函数的组件都将调用该函数,在帧期间每个输入操作调用一次,并带有以下参数:
 
 `self`
-: 当前脚本实例引用.
+: 当前脚本实例
 
 `action_id`
-: 动作名哈希串, 与输入映射配置的名称一致.
+: 操作的哈希名称,如在输入绑定中设置的那样。
 
 `action`
-: 有关动作的表, 包含比如输入值, 位置和移动距离, 按键是不是 `按下` 状态等等. 详情请见 [on_input() 函数](/ref/go#on_input).
+: 包含有关操作的有用数据的表,如输入的值、其位置(绝对和增量位置)、按钮输入是否`按下`等。有关可用操作字段的详细信息,请参阅[on_input()](/ref/go#on_input)。
 
 ```lua
 function on_input(self, action_id, action)
@@ -133,49 +133,49 @@ end
 ```
 
 
-### 输入焦点集合代理组件
+### 输入焦点集合代理组件
 
-由集合代理动态载入的游戏世界都有自己的输入栈. 为了让被载入的游戏世界获得输入信息, 集合代理组件必须位于主游戏世界的输入栈里. 被加载的游戏世界优先于主游戏世界获得输入信息:
+每个通过集合代理动态加载的游戏世界都有自己的输入栈。为了使操作分派到达加载世界的输入栈,代理组件必须位于主世界的输入栈上。加载世界栈上的所有组件都在分派继续向下主栈之前被处理:
 
 ![Action dispatch to proxies](images/input/proxy.png)
 
-::: sidenote
-开发者经常会忘记发送 `acquire_input_focus` 来使集合代理所在的游戏对象获得输入焦点. 不这么做的话此集合代理加载的所有游戏世界都无法获得输入消息.
+::: important
+忘记发送`acquire_input_focus`给持有集合代理组件的游戏对象是一个常见错误。跳过这一步将阻止输入到达加载世界输入栈上的任何组件。
 :::
 
 
-### 释放输入焦点
+### 释放输入
 
-要取消动作监听, 发送 `release_input_focus` 消息给游戏对象即可. 这样该游戏对象的所有组件都会从输入栈中移除:
+要停止监听输入操作,请将`release_input_focus`消息发送到游戏对象。此消息将从输入栈中移除游戏对象的任何组件:
 
 ```lua
--- 告诉当前游戏对象 (".") 释放输入焦点.
+-- 告诉当前游戏对象(".")释放输入焦点。
 msg.post(".", "release_input_focus")
 ```
 
 
-## 输入传播
+## 消耗输入
 
-每个 `on_input()` 函数都能决定当前动作是否要阻止其继续传播下去:
+组件的`on_input()`可以主动控制操作是否应该进一步传递到栈的下方:
 
-- 如果 `on_input()` 返回 `false`, 或者未返回值 (此时默认返回 `nil` 也被看作是false) 输入动作会继续传播.
-- 如果 `on_input()` 返回 `true` 输入就此销毁. 再无组件可以接收到这个消息. 作用于 *全部* 输入栈. 也就是说集合代理加载的组件销毁输入那么主栈的组件就收不到这个输入消息了:
+- 如果`on_input()`返回`false`,或者省略返回值(这暗示了一个`nil`返回,在Lua中是假值),输入操作将被传递到输入栈上的下一个组件。
+- 如果`on_input()`返回`true`,输入被消耗。输入栈中更下方的任何组件都不会接收到输入。请注意,这适用于*所有*输入栈。代理加载世界栈上的组件可以消耗输入,阻止主栈上的组件接收输入:
 
 ![consuming input](images/input/consuming.png)
 
-输入消耗可以使游戏变得灵活, 控制性更强. 例如, 如果需要弹出菜单暂时只有部分界面可以接受点击:
+有许多很好的用例,其中输入消耗提供了一种简单而强大的方式,在游戏的不同部分之间转移输入。例如,如果您需要一个弹出菜单,暂时是游戏中唯一监听输入的部分:
 
 ![consuming input](images/input/game.png)
 
-菜单开始是隐藏的 (disabled) 玩家点击 "PAUSE" 组件, 菜单被激活:
+暂停菜单最初是隐藏的(禁用的),当玩家触摸"PAUSE" HUD项时,它被启用:
 
 ```lua
 function on_input(self, action_id, action)
     if action_id == hash("mouse_press") and action.pressed then
-        -- 玩家点击了 PAUSE?
+        -- 玩家按下了PAUSE吗?
         local pausenode = gui.get_node("pause")
         if gui.pick_node(pausenode, action.x, action.y) then
-            -- 弹出暂停菜单.
+            -- 告诉暂停菜单接管。
             msg.post("pause_menu", "show")
         end
     end
@@ -184,16 +184,16 @@ end
 
 ![pause menu](images/input/game_paused.png)
 
-此时弹出的暂停菜单获得输入焦点并且消耗输入, 以防止点击穿透:
+暂停菜单GUI获取输入焦点并消耗输入,防止除弹出菜单相关之外的任何输入:
 
 ```lua
 function on_message(self, message_id, message, sender)
   if message_id == hash("show") then
-    -- 显示暂停菜单.
+    -- 显示暂停菜单
     local node = gui.get_node("pause_menu")
     gui.set_enabled(node, true)
 
-    -- 获得输入焦点.
+    -- 获取输入。
     msg.post(".", "acquire_input_focus")
   end
 end
@@ -201,7 +201,7 @@ end
 function on_input(self, action_id, action)
   if action_id == hash("mouse_press") and action.pressed then
 
-    -- 这里做其他游戏逻辑...
+    -- 做一些事情...
 
     local resumenode = gui.get_node("resume")
     if gui.pick_node(resumenode, action.x, action.y) then
@@ -209,13 +209,13 @@ function on_input(self, action_id, action)
         local node = gui.get_node("pause_menu")
         gui.set_enabled(node, false)
 
-        -- 释放输入焦点.
+        -- 释放输入
         msg.post(".", "release_input_focus")
     end
   end
 
-  -- 消耗掉输入. 输入栈里其他组件
-  -- 不会得到输入, 直到脚本释放输入焦点.
+  -- 消耗所有输入。输入栈中位于我们下方的任何内容
+  -- 在我们释放输入焦点之前都不会看到输入。
   return true
 end
 ```

+ 3 - 3
docs/zh/manuals/install.md

@@ -1,10 +1,10 @@
 ---
 title: 安装 Defold
-brief: 本教程解释了在你的操作系统下如何下载和安装 Defold 编辑器.
+brief: 本手册解释了如何在您的操作系统上下载和安装 Defold 编辑器。
 ---
 
 # 安装 Defold
 
-安装 Defold 编辑器很简单. 下载你的操作系统对应的Defold版本, 解压到你的目标文件夹.
+安装 Defold 编辑器非常简单。下载为您的操作系统构建的版本,解压它并将软件复制到合适的位置。
 
-:[安装](../shared/install.md)
+:[install](../shared/install.md)

+ 2 - 2
docs/zh/manuals/instant-games.md

@@ -1,6 +1,6 @@
 ---
 title: Facebook Instant Games
-brief: 本教程介绍了如何使用 Defold 创建 Facebook Instant Games.
+brief: 本手册解释了如何使用 Defold 创建 Facebook Instant Games。
 ---
 
-本教程已被移至 [这里](/extension-fbinstant)
+[此手册已移至](/extension-fbinstant)

+ 16 - 16
docs/zh/manuals/introduction.md

@@ -1,36 +1,36 @@
 ---
 title: Defold 介绍
-brief: Defold 简介.
+brief: Defold 简要介绍。
 ---
 
 # 欢迎来到 Defold
 
-Defold 是提供设计, 编译和发布游戏功能的一站式工具. 具体功能详见 [Product Overview](/product).
+Defold 是一个一站式解决方案,提供了设计、构建和发布游戏所需的一切。支持功能的完整列表可以在我们的[产品概述](/product)中查看。
 
-我们致力于使游戏开发阶段尽可能的有效率, 这使得 Defold 在诸多游戏引擎中脱颖而出. 请看 [使用 Defold 的理由](/why).
+我们投入了大量时间和精力,确保游戏开发过程中的某些关键元素尽可能顺畅和轻松,我们相信这使得 Defold 在众多引擎中脱颖而出。了解[我们为什么认为您应该使用 Defold](/why)。
 
-## 从哪开始?
+## 从哪里开始?
 
-我们建议你先尝试一下, 学习手册, 阅读教程和 API 文档, 然后到官方论坛里向他人积极取经并且关注 Defold 的每次更新公告. 教程材料多多, 如果还不知道从哪下手, 建议学学下面的内容:
+我们鼓励您进行实验、跟随教程、阅读我们的手册和 API 文档,并在论坛上积极活动,以向其他用户学习并关注 Defold 的开发。有相当多的文档可用,包括手册、API 参考文档、示例和教程。如果您不知道从哪里开始,这里有一些指引:
 
 #### 编辑器
-![Editor overview](images/introduction/editor.png){.left} [编辑器概述](/manuals/editor/) 是个能让你快速入门的介绍, 使用可视的工具进行创作和代码编写. 如果你对 3D 建模软件和各种代码编辑器比较熟悉, 那我们的编辑器看起来会很亲切, 虽说可能在某些地方还是和你想象的稍有区别.
+![Editor overview](images/introduction/editor.png){.left} [编辑器概述](/manuals/editor/)很好地介绍了编辑器,将帮助您熟悉环境、使用可视化工具和编写代码。如果您熟悉 3D 建模程序和编程 IDE,应该不会有太多意外,但总会有一些与您最喜欢的软件不同的地方。
 
-#### 简单
-![Examples](images/introduction/examples.jpg){.left} [简单实例集](/examples/) 直接展示出了各个功能运行时的小例子. 在这里你可以看到这些功能在Defold里是如何实现的.
+#### 简单
+![Examples](images/introduction/examples.jpg){.left} [我们的简单示例集合](/examples/)很好地介绍了如何将各个部分组合成有效的东西。您将找到如何在 Defold 中实现各种常见事物的最小示例。
 
 #### Lua 语言
-![Lua overview](images/introduction/lua.png){.left} [Defold 使用 Lua](/manuals/lua/) 来控制所有游戏逻辑. 引擎是高效 C++ 程序, 但是其控制脚本是高层 Lua 语言. 如果你编写过 Python, Javascript 或者其他高级语言代码, 你就会发现 Lua 非常好理解. 没写过脚本程序的, 可以先从Lua教程开始学.
+![Lua overview](images/introduction/lua.png){.left} [Defold 使用 Lua](/manuals/lua/)进行所有逻辑控制。引擎是一个快速的 C++ 机器,但在高层次上由 Lua 程序控制。如果您使用过 Python、Javascript 或任何其他高级语言进行编程,您会发现 Lua 相当容易掌握,并且可能可以很好地跟随教程。否则,请通读我们的 Lua 手册,然后从那里开始。
 
 #### 游戏教程
-![Tutorials](images/introduction/tutorials.jpg){.left} 我们相信做是学的最好方法. 这就是我们花费很多精力在Defold [编辑器](/manuals/editor/) 里集成一些教程和复杂关卡的原因.打开一两个教程跟着做一遍就知道 Defold 是怎么编译和工作的了.
+![Tutorials](images/introduction/tutorials.jpg){.left} 我们相信通过实践学习是最好的。这就是为什么我们直接从[编辑器](/manuals/editor/)中提供了各种技能和复杂程度级别的教程。启动它并跟随一两个教程,学习如何构建事物以及 Defold 是如何工作的。
 
-#### Defold 的资源组成
-![Building blocks](images/introduction/building_blocks.png){.left} [Defold 游戏由许多资源构成](/manuals/building-blocks/), 有些和其他游戏引擎类似. 还有另一些 Defold 里特有的, 用熟才感觉方便的东西. 要想知道Defold的底层工作方式可以先从资源教程学起.
+#### Defold 的构建块
+![Building blocks](images/introduction/building_blocks.png){.left} [Defold 游戏是通过组合简单块构建的](/manuals/building-blocks/),如果您使用过其他引擎,其中一些看起来会很熟悉。有一些架构设计决策使 Defold 的块变得特殊,需要一些时间才能习惯使用它们。如果您觉得需要彻底理解它的工作原理,我们的构建块手册是一个很好的起点。
 
-#### 社区论坛
-![论坛](images/introduction/forum.jpg){.left} [论坛](//forum.defold.com/) 是一个互相学习的好地方. 我们的社区很友好, 我们的老司机在游戏开发, 尤其是 Defold 开发方面都很精通. 如果你卡壳了, 可以来论坛寻求帮助!
+#### 论坛
+![Forum](images/introduction/forum.jpg){.left} [向他人学习](//forum.defold.com/)通常是学习的最佳方式。我们的社区非常友好,对一般游戏开发和特别是 Defold 开发了解很多。如果您遇到困难,不要犹豫,请前往论坛寻求帮助!
 
-不管从哪开始学习 Defold, 都可以随时回来这个页面再深入理解 Defold 提供的功能和方法. 哪里不理解或者哪里写错了都可以跟我们说. 我们的初衷就是把这套教程做的尽善尽美.
+请记住,无论您选择哪种方式学习 Defold,您都可以随时回到这里,深入了解 Defold 提供的各种功能和概念。不要犹豫,指出您不理解或认为错误的地方。这些页面是为您准备的,我们希望使它们尽可能完善。
 
-希望你能使用 Defold 创作出绝妙的游戏来!
+我们希望您会喜欢在 Defold 中创作您的下一个精彩游戏!

+ 97 - 99
docs/zh/manuals/ios.md

@@ -1,233 +1,232 @@
 ---
 title: Defold iOS 平台开发
-brief: 本教程介绍了如何在 Defold 里编译运行 iOS 设备应用.
+brief: 本手册解释了如何在 Defold 中构建和运行 iOS 设备上的游戏和应用。
 ---
 
 # iOS 开发
 
 ::: sidenote
-必須使用 Mac版 Defold編輯器 才能打包 iOS 項目.
+为 iOS 打包游戏仅适用于 Mac 版本的 Defold 编辑器。
 :::
 
-iOS 要求 _所有_ 运行于手机或者平板电脑上的应用 _必须_ 使用 Apple 核发的 certificate 和 provisioning profile 进行签名. 本教程介绍了 iOS 平台的游戏打包. 在开发阶段, 推荐使用 [开发用app](/manuals/dev-app) 以利用热重载功能实现对移动设备的无线推送.
+iOS 要求 _所有_ 你想要在手机或平板电脑上运行的应用 _必须_ 使用 Apple 颁发的证书和配置文件进行签名。本手册解释了为 iOS 打包游戏所涉及的步骤。在开发过程中,通过 [开发应用](/manuals/dev-app) 运行游戏通常是首选,因为它允许你直接将内容和代码热重载到你的设备上。
 
-## Apple 签名过程
+## Apple 的代码签名过程
 
-iOS 应用安全包含几个要素. 通过访问 [Apple's iOS Developer Program](https://developer.apple.com/programs/) 可以得到必要的工具. 如需注册, 请访问 [Apple's Developer Member Center](https://developer.apple.com/membercenter/index.action).
+与 iOS 应用相关的安全性由多个组件组成。你可以通过注册 [Apple 的 iOS 开发者计划](https://developer.apple.com/programs/) 获得所需工具的访问权限。注册后,请前往 [Apple 开发者会员中心](https://developer.apple.com/membercenter/index.action)。
 
 ![Apple Member Center](images/ios/apple_member_center.png)
 
-*Certificates, Identifiers & Profiles* 部分包含了所有所需工具. 在这里可以创建, 删除和编辑:
+*证书、标识符和配置文件* 部分包含了你需要的所有工具。从这里你可以创建、删除和编辑:
 
-Certificates
-: Apple 为开发者颁发的加密证书. 分为开发证书和发布证书两种. 开发证书用以在沙盒环境中测试某些功能比如应用内购. 发布证书是将应用发布到 App Store 时用的证书. 在设备上测试之前要用证书对应用进行签名.
+证书
+: Apple 颁发的加密证书,用于标识你作为开发者的身份。你可以创建开发或生产证书。开发者证书允许你在沙盒测试环境中测试某些功能,例如应用内购买机制。生产证书用于对最终应用进行签名以便上传到 App Store。在将应用放到设备上进行测试之前,你需要使用证书对应用进行签名。
 
-Identifiers
-: 应用id. 用于多个应用的通配符id (类似 `some.prefix.*`) 是允许的. 应用id也在集成某些服务时使用, 比如 Passbook, Game Center 之类的. 这种情况下不支持通配符id. 因为使用服务时 *bundle identifier* 必须与应用id一致.
+标识符
+: 用于各种用途的标识符。可以注册通配符标识符(即 `some.prefix.*`),这些标识符可以用于多个应用。应用 ID 可以包含应用服务信息,例如应用是否启用 Passbook 集成、Game Center 等。此类应用 ID 不能是通配符标识符。为了使应用服务正常工作,你的应用的 *包标识符* 必须与应用 ID 标识符匹配。
 
-Devices
-: 用于开发的设备要注册 UDID (Unique Device IDentifier, 见下文).
+设备
+: 每个开发设备都需要使用其 UDID(唯一设备标识符,见下文)进行注册。
 
-Provisioning Profiles
-: 提供商档案与应用id与开发设备的证书相关. 这样可以确保让谁的哪个应用可以运行于哪个设备上.
+配置文件
+: 配置文件将证书与应用 ID 和设备列表相关联。它们指明哪个开发者的哪个应用被允许在哪些设备上运行。
 
-在 Defold 中给应用做签名时, 需要提供加密证书和提供商档案文件.
+在 Defold 中为游戏和应用签名时,你需要有效的证书和有效的配置文件。
 
 ::: sidenote
-Member Center 页面的一些功能在 Xcode 里也可以进行---前提是先安装好Xcode.
+你可以在会员中心主页上执行的一些操作也可以在 Xcode 开发环境中执行---前提是你已安装了 Xcode。
 :::
 
-Device identifier (UDID)
-: iOS 设备的 UDID 可以通过wifi或者线路连接计算机查找. 打开 Xcode 选择 <kbd>Window ▸ Devices and Simulators</kbd>. 选中设备就会显示出序列号和UDID.
+设备标识符 (UDID)
+: iOS 设备的 UDID 可以通过 wifi 或线缆将设备连接到计算机来找到。打开 Xcode 并选择 <kbd>Window ▸ Devices and Simulators</kbd>。当你选择设备时,会显示序列号和标识符。
 
-  ![Xcode devices](images/ios/Xcode_devices.png)
+  ![xcode devices](images/ios/xcode_devices.png)
 
-  如果没安装 Xcode也可以从 iTunes 里查看. 首先选中要查看的设备.
+  如果你没有安装 Xcode,你可以在 iTunes 中找到标识符。点击设备符号并选择你的设备。
 
   ![itunes devices](images/ios/itunes_devices.png)
 
-  1. 在 *Summary* 页, 可以找到 *Serial Number*.
-  2. 点击 *Serial Number* 一次, 它会切换成 *UDID*. 再点击下去还会显示其他设备信息. 这里我们找到 *UDID* 即可.
-  3. 右键点击 UDID 那一长串字符, 选择 <kbd>Copy</kbd> 即可将其存入剪贴板, 在 Apple 开发中心注册设备时就可以直接粘贴填入了.
+  1. 在 *摘要* 页面上,找到 *序列号*。
+  2. 点击 *序列号* 一次,使该字段变为 *UDID*。如果你反复点击,将会显示设备的几条信息。继续点击直到显示 *UDID*。
+  3. 右键点击长 UDID 字符串并选择 <kbd>复制</kbd> 将标识符复制到剪贴板,这样你就可以在 Apple 开发者会员中心注册设备时轻松地将其粘贴到 UDID 字段中。
 
-## 使用免费账户开发应用
+## 使用免费的 Apple 开发者账户进行开发
 
-从 Xcode 7 开始, 所有人都被允许安装 Xcode 并且免费开发设备应用. 无需注册iOS开发者. Xcode 会为设备自动核发一个临时开发者证书 (有效期1年) 和一个临时应用提供商档案 (有效期1周).
+从 Xcode 7 开始,任何人都可以安装 Xcode 并免费进行设备开发。你不必注册 iOS 开发者计划。相反,Xcode 会自动为你作为开发者颁发一个证书(有效期1年)和针对你的应用的配置文件(在你的特定设备上有效一周)。
 
-1. 连接设备.
-2. 安装 Xcode.
-3. 在 Xcode 注册并登录 Apple ID.
-4. 新建项目. 最简单的 "Single View App" 就好.
-5. 选择 "Team" (自动生成) 并为app设置 bundle identifier.
+1. 连接你的设备。
+2. 安装 Xcode
+3. 向 Xcode 添加新账户并使用你的 Apple ID 登录。
+4. 创建一个新项目。最简单的"单视图应用"即可。
+5. 选择你的"团队"(为你自动创建)并为应用提供一个包标识符。
 
 ::: important
-请牢记 bundle identifier 因为在 Defold 项目中需要配置同样的 bundle identifier.
+记下包标识符,因为你必须在你的 Defold 项目中使用相同的包标识符。
 :::
 
-6. 确保 Xcode 为app生成了 *Provisioning Profile* 和 *Signing Certificate*.
+6. 确保 Xcode 已为应用创建了 *配置文件* 和 *签名证书*。
 
-   ![](images/ios/Xcode_certificates.png)
+   ![](images/ios/xcode_certificates.png)
 
-7. 编译并且在设备上运行. 首次运行, Xcode 会提示打开开发者模式并为调试做好准备. 可能要等待一会儿.
-8. 确定应用正常运行后, 在硬盘上找到编译好的app. 可以在 "Report Navigator" 的编译报告里找到app位置.
+7. 在你的设备上构建应用。第一次,Xcode 会要求你启用开发者模式,并会用调试器支持准备设备。这可能需要一段时间。
+8. 当你验证应用可以正常工作后,在磁盘上找到它。你可以在"报告导航器"的构建报告中查看构建位置。
 
    ![](images/ios/app_location.png)
 
-9. 找到app, 右键选择 <kbd>Show Package Contents</kbd>.
+9. 找到应用,右键单击它并选择 <kbd>显示包内容</kbd>。
 
    ![](images/ios/app_contents.png)
 
-10. 把 "embedded.mobileprovision" 文件拷贝出来.
+10. 将"embedded.mobileprovision"文件复制到你驱动器上你将找到它的某个位置。
 
    ![](images/ios/free_provisioning.png)
 
-这个供应商档案文件连同加密证书可以在 Defold 为应用签名, 有效期为一周.
+此配置文件可以与你的代码签名身份一起使用,在 Defold 中为应用签名,有效期为一周。
 
-档案过期后, 可以在 Xcode 里如法炮制再次生成临时档案文件.
+当配置文件过期时,你需要在 Xcode 中再次构建应用并获取新的临时配置文件,如上所述。
 
-## iOS应用
+## 创建 iOS 应用包
 
-如果你有加密证书和这个供应商档案文件, 就可以在编辑器里打包应用了. 从菜单中选择 <kbd>Project ▸ Bundle... ▸ iOS Application...</kbd>.
+当你拥有代码签名身份和配置文件后,你就可以从编辑器中为你的游戏创建独立的应用包。只需从菜单中选择 <kbd>Project ▸ Bundle... ▸ iOS Application...</kbd>。
 
 ![Signing iOS bundle](images/ios/sign_bundle.png)
 
-选择证书和档案. 设置架构 (32 bit, 64 bit 和 iOS 模拟器) 再选择打包模式 (Debug 或者 Release). 也可以取消选择 `Sign application` 跳过签名步骤留待后面完成.
+选择你的代码签名身份并浏览你的移动配置文件。选择要打包的架构(32位、64位和iOS模拟器)以及变体(Debug或Release)。你可以选择取消选中`Sign application`复选框以跳过签名过程,然后在稍后阶段手动签名。
 
 ::: important
-要在模拟器中测试游戏 **必须取消** `Sign application` 选项. 否则的话游戏能安装却不能运行.
+在 iOS 模拟器上测试游戏时,你 **必须** 取消选中 `Sign application` 复选框。你将能够安装应用程序,但它无法启动。
 :::
 
-点击 *Create Bundle* 并选择打包应用存放位置.
+按*创建包*,然后系统会提示你指定包将在你的计算机上的哪个位置创建。
 
 ![ipa iOS application bundle](images/ios/ipa_file.png){.left}
 
-可以在 *game.project* 项目配置文件的 [iOS 部分](/manuals/project-settings/#iOS) 设置应用的图标, 启动屏幕 storyboard 等等.
+你在 *game.project* 项目设置文件的 [iOS 部分](/manuals/project-settings/#ios) 中指定要使用的图标、启动屏幕故事板等。
 
 :[Build Variants](../shared/build-variants.md)
 
-## 在已连接的 iPhone 上安装和运行应用
+## 在已连接的 iPhone 上安装和启动包
 
-选择编辑器中的 "Install on connected device" 和打包对话框的 "Launch installed app" 即可安装和运行应用:
+你可以使用编辑器的打包对话框中的"在已连接设备上安装"和"启动已安装应用"复选框来安装和启动构建的包:
 
 ![Install and launch iOS bundle](images/ios/install_and_launch.png)
 
-这个特性需要你先安装好 [ios-deploy](https://github.com/ios-control/ios-deploy) 命令行工具. 最简单的方法是使用 Homebrew:
+你需要安装 [ios-deploy](https://github.com/ios-control/ios-deploy) 命令行工具才能使此功能工作。安装它的最简单方法是使用 Homebrew:
 ```
 $ brew install ios-deploy
 ```
 
-如果编辑器无法自动找到 ios-deploy 工具, 你需要在 [Preferences](/manuals/editor-preferences/#tools) 中手动指定. 
+如果编辑器无法检测到 ios-deploy 工具的安装位置,你需要在 [首选项](/manuals/editor-preferences/#tools) 中指定它。 
 
-### 创建 storyboard
+### 创建故事板
 
-使用 Xcode 创建 storyboard. 启动 Xcode 新建一个项目. 选择 iOS 和单视图应用:
+你使用 Xcode 创建故事板文件。启动 Xcode 并创建一个新项目。选择 iOS 和单视图应用:
 
-![Create project](images/ios/storyboard_create_project.png)
+![Create project](images/ios/xcode_create_project.png)
 
-点击 Next 继续配置项目并输入名称:
+点击 Next 并继续配置你的项目。输入产品名称:
 
-![Project settings](images/ios/storyboard_create_project_settings.png)
+![Project settings](images/ios/xcode_storyboard_create_project_settings.png)
 
-点击 Create 完成项目创建. 接下来就可以创建 storyboard 了:
+点击 Create 完成该过程。你的项目现已创建,我们可以继续创建故事板:
 
 ![The project view](images/ios/xcode_storyboard_project_view.png)
 
-把需要的图片拖入项目. 然后打开 `Assets.xcassets`, 再把图片拖放到 `Assets.xcassets` 中去:
+拖放图像以将其导入项目。接下来选择 `Assets.xcassets` 并将图像拖放到 `Assets.xcassets`:
 
-![Add image](images/ios/storyboard_add_image.png)
+![Add image](images/ios/xcode_storyboard_add_image.png)
 
-打开 `LaunchScreen.storyboard` 点击加号 (<kbd>+</kbd>) 按钮. 输入 "imageview" 找到 ImageView 控件.
+打开 `LaunchScreen.storyboard` 并点击加号按钮(<kbd>+</kbd>)。在对话框中输入"imageview"以查找 ImageView 组件。
 
-![Add image view](images/ios/storyboard_add_imageview.png)
+![Add image view](images/ios/xcode_storyboard_add_imageview.png)
 
-把控件拖放到 storyboard 上:
+将图像视图组件拖放到故事板上:
 
-![Add to storyboard](images/ios/storyboard_add_imageview_to_storyboard.png)
+![Add to storyboard](images/ios/xcode_storyboard_add_imageview_to_storyboard.png)
 
-从下拉列表中选择刚才放入 `Assets.xcassets` 的图片:
+从图像下拉列表中选择你之前添加到 `Assets.xcassets` 的图像:
 
-![](images/ios/storyboard_select_image.png)
+![](images/ios/xcode_storyboard_select_image.png)
 
-摆放好位置定义好组件, 比如可以加个标签什么的. 配置好之后选择 "Build -> Any iOS Device (arm64, armv7)"(或者 "Generic iOS Device") 然后 Product -> Build. 等待编译完成.
+定位图像并进行你需要的任何其他调整,也许添加标签或其他 UI 元素。完成后,将活动方案设置为"Build -> Any iOS Device (`arm64`, `armv7`)"(或"Generic iOS Device")并选择 Product -> Build。等待构建过程完成。
 
 ::: sidenote
-如果你的 "Any iOS Device (arm64)" 里只有一个 `arm64` 选项, 则需要把 "Project -> Basic -> Deployment" 里的 `iOS Deployment target` 设置为 10.3. 这样你的 storyboard 才能支持 `armv7` 设备 (比如 iPhone5c)  
+如果"Any iOS Device (arm64)"中只有 `arm64` 选项,请在"Project -> Basic -> Deployment"设置中将 `iOS Deployment target` 更改为 10.3。这将使你的故事板与 `armv7` 设备(例如 iPhone5c)兼容。
 :::
 
-在 storyboard 里使用的图片不会自动包含进 `LaunchScreen.storyboardc` 里. 要在 *game.project* 的 `Bundle Resources` 选项中配置需要包含的图片资源.
-例如, 在 Defold 项目目录下有个 `LaunchScreen` 文件夹, 里面包含 `ios` 文件夹 (`ios` 文件夹下的文件只针对 ios 打包使用), 所以先要把资源文件放入 `LaunchScreen/ios/`. 然后配置 `Bundle Resources` 为此路径.
+如果你在故事板中使用图像,它们不会自动包含在你的 `LaunchScreen.storyboardc` 中。使用 *game.project* 中的 `Bundle Resources` 字段来包含资源。
+例如,在 Defold 项目中创建 `LaunchScreen` 文件夹,并在其中创建 `ios` 文件夹(`ios` 文件夹仅用于包含这些文件到 ios 包中),然后将你的文件放入 `LaunchScreen/ios/`。在 `Bundle Resources` 中添加此路径。
 
 ![](images/ios/bundle_res.png)
 
-最后一步, 拷贝编译生成的 `LaunchScreen.storyboardc` 文件. 打开仿达, 把 `LaunchScreen.storyboardc` 文件粘贴到你的 Defold 项目目录:
-
+最后一步是将编译的 `LaunchScreen.storyboardc` 文件复制到你的 Defold 项目。在 Finder 中打开以下位置并将 `LaunchScreen.storyboardc` 文件复制到你的 Defold 项目:
 
     /Library/Developer/Xcode/DerivedData/YOUR-PRODUCT-NAME-cbqnwzfisotwygbybxohrhambkjy/Build/Intermediates.noindex/YOUR-PRODUCT-NAME.build/Debug-iphonesimulator/YOUR-PRODUCT-NAME.build/Base.lproj/LaunchScreen.storyboardc
 
 ::: sidenote
-社区牛人 Sergey Lerg 已把上述步骤 [录成了视频](https://www.youtube.com/watch?v=6jU8wGp3OwA&feature=emb_logo) 供大家参考.
+论坛用户 Sergey Lerg 已经整理了[展示此过程的视频教程](https://www.youtube.com/watch?v=6jU8wGp3OwA&feature=emb_logo)。
 :::
 
-得到 storyboard 文件之後就可以在 *game.project* 裏引用它了.
+一旦你有了故事板文件,就可以从 *game.project* 中引用它。
 
 
-### 建立圖標資源列表
+### 创建图标资源目录
 
 ::: sidenote
-從 Defold 1.2.175 版本開始需要這個設置.
+从 Defold 1.2.175 开始需要此设置。
 :::
 
-Apple 建議使用圖標資源列表來管理應用圖標. 這也是能讓你的圖標在 App Store 裏展示出來的唯一方法. 建立圖標資源表跟建立 storyboard 類似, 也要使用 Xcode. 啓動 Xcode 新建項目. 選擇 iOS and Single View App:
+使用资源目录是 Apple 管理应用图标的首选方式。实际上,这是提供 App Store 列表中使用的图标的唯一方法。你以与故事板相同的方式创建资源目录,使用 Xcode。启动 Xcode 并创建一个新项目。选择 iOS 和单视图应用:
 
 ![Create project](images/ios/xcode_create_project.png)
 
-點擊 Next 進行設置操作. 輸入產品名:
+点击 Next 并继续配置你的项目。输入产品名称:
 
 ![Project settings](images/ios/xcode_icons_create_project_settings.png)
 
-點擊 Create 完成配置工作. 此時項目已經建立, 接著就可以繼續建立資源列表了:
+点击 Create 完成该过程。你的项目现已创建,我们可以继续创建资源目录:
 
 ![The project view](images/ios/xcode_icons_project_view.png)
 
-依據圖標大小把圖片分別拖放到空白方框裏:
+将图像拖放到代表不同支持图标大小的空框中:
 
 ![Add icons](images/ios/xcode_icons_add_icons.png)
 
 ::: sidenote
-Notifications, Settings 和 Spotlight 這三項不要拖放圖標.
+不要为通知、设置或 Spotlight 添加任何图标。
 :::
 
-完成之后, 配置好之后选择 "Build -> Any iOS Device (arm64, armv7)"(或者 "Generic iOS Device") 然后 Product -> Build. 等待编译完成.
+完成后,将活动方案设置为"Build -> Any iOS Device (arm64)"(或"Generic iOS Device")并选择 <kbd>Product</kbd> -> <kbd>Build</kbd>。等待构建过程完成。
 
 ::: sidenote
-确保编译目标为 "Any iOS Device (arm64)" 或者 "Generic iOS Device", 否则上传游戏时会报 `ERROR ITMS-90704` 错误.
+确保你为"Any iOS Device (arm64)"或"Generic iOS Device"构建,否则在上传构建时你会得到 `ERROR ITMS-90704` 错误。
 :::
 
 ![Build project](images/ios/xcode_icons_build.png)
 
-最後一步是將編譯好的 `Assets.car` 文件拷貝到你的 Defold 項目中去. 打開訪達依照如下路徑找到 `Assets.car` 文件, 將其複製到 Defold 項目中:
+最后一步是将编译的 `Assets.car` 文件复制到你的 Defold 项目。在 Finder 中打开以下位置并将 `Assets.car` 文件复制到你的 Defold 项目:
 
     /Library/Developer/Xcode/DerivedData/YOUR-PRODUCT-NAME-cbqnwzfisotwygbybxohrhambkjy/Build/Products/Debug-iphoneos/Icons.app/Assets.car
 
-得到圖標資源列表文件之後就可以在 *game.project* 裏引用它和其中的圖標了:
+一旦你有了资源目录文件,就可以从 *game.project* 中引用它和图标:
 
 ![Add icon and asset catalog to game.project](images/ios/defold_icons_game_project.png)
 
 ::: sidenote
-無需在 *game.project* 裏設置 App Store 的圖標. App 上傳到 iTunes Connect 時, 圖標會自動從 `Assets.car` 文件中選取並解壓出來.
+App Store 图标不必从 *game.project* 中引用。上传到 iTunes Connect 时,它会自动从 `Assets.car` 文件中提取。
 :::
 
 
-## 安装 iOS 打包应用
+## 安装 iOS 应用
 
-编辑器对iOS应用打包后生成 *.ipa* 文件. 要安装此文件, 可以使用以下所列举工具之一:
+编辑器会写入一个 *.ipa* 文件,这是一个 iOS 应用包。要在你的设备上安装该文件,你可以使用以下工具之一:
 
-* Xcode 的 "Devices and Simulators" 窗口
-* [ios-deploy](https://github.com/ios-control/ios-deploy) 命令行工具
-* macOS App Store 的 [Apple Configurator 2](https://apps.apple.com/us/app/apple-configurator-2/)
+* 通过 Xcode 的"设备和模拟器"窗口
+* [`ios-deploy`](https://github.com/ios-control/ios-deploy) 命令行工具
+* 来自 macOS App Store 的 [`Apple Configurator 2`](https://apps.apple.com/us/app/apple-configurator-2/)
 * iTunes
 
-可以使用 `xcrun simctl` 命令行工具与 Xcode 的 iOS 模拟器进行交互:
+你还可以使用 `xcrun simctl` 命令行工具与通过 Xcode 提供的 iOS 模拟器一起工作:
 
 ```
 # 显示可用设备列表
@@ -236,7 +235,7 @@ xcrun simctl list
 # 启动 iPhone X 模拟器
 xcrun simctl boot "iPhone X"
 
-# 在模拟器上安装 your.app
+# 将 your.app 安装到已启动的模拟器
 xcrun simctl install booted your.app
 
 # 启动模拟器
@@ -248,20 +247,19 @@ open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app
 
 ## 出口合规信息
 
-将游戏上传到 App Store 时要提供加密部分的出口合规信息. [Apple 在此解释了这个需求的原因](https://developer.apple.com/documentation/security/complying_with_encryption_export_regulations):
+当你将游戏提交到 App Store 时,你将被要求提供有关游戏中使用加密的出口合规信息。[Apple 解释了为什么这是必需的](https://developer.apple.com/documentation/security/complying_with_encryption_export_regulations):
 
-"把应用往 TestFlight 或者 App Store 上传的时候, 你是把应用上传到了美国的服务器上. 一旦要把应用分发到美国或者加拿大之外的国家, 无论你的法人实体在哪里, 都必须遵守美国出口法案. 如果你的应用使用, 访问, 包含, 实现, 或者汇入了加密内容, 就会被视作加密软件出口, 这意味着你的应用必须符合美国出口法案的要求, 同时也要符合你的出口目的国家的法律需求."
+"当你将应用提交到 TestFlight 或 App Store 时,你将应用上传到美国的服务器。如果你在美国或加拿大之外分发你的应用,无论你的法律实体位于何处,你的应用都受美国出口法律的约束。如果你的应用使用、访问、包含、实现或合并加密,这被视为加密软件的出口,这意味着你的应用必须符合美国的出口合规要求,以及你分发应用所在国家的进口合规要求。"
 
-相关文档:
+Defold 游戏引擎将加密用于以下目的:
 
-* 出口合规概要 - https://help.apple.com/app-store-connect/#/dev88f5c7bf9
-* 查看游戏是否符合出口规范 - https://help.apple.com/app-store-connect/#/dev63c95e436
+* 通过安全通道进行调用(即 HTTPS 和 SSL)
+* Lua 代码的版权保护(以防止复制)
 
-Defold 引擎会对以下内容实施加密:
+Defold 引擎中这些加密的使用在美国和欧盟法律下免于出口合规文件要求。大多数 Defold 项目将保持豁免,但添加其他加密方法可能会改变此状态。你有责任确保你的项目符合这些法律和 App Store 规则的要求。有关更多信息,请参阅 Apple 的[出口合规概述](https://help.apple.com/app-store-connect/#/dev88f5c7bf9)。
 
-* 加密信道调用 (如 HTTPS 和 SSL)
-* Lua 代码版权保护
+如果你认为你的项目是豁免的,请在项目的 `Info.plist` 中将 [`ITSAppUsesNonExemptEncryption`](https://developer.apple.com/documentation/bundleresources/information-property-list/itsappusesnonexemptencryption) 键设置为 `False`,有关详细信息,请参阅[应用程序清单](/manuals/extensions-manifest-merge-tool)。
 
 
-## 常見問題
+## 常见问题
 :[iOS FAQ](../shared/ios-faq.md)

+ 38 - 39
docs/zh/manuals/label.md

@@ -1,11 +1,11 @@
 ---
-title: Defold 里的 Label 文本组件
-brief: 本教程介绍了文本组件 label 的使用方法.
+title: Defold中的Label文本组件
+brief: 本手册解释了如何使用label组件在游戏世界中为游戏对象添加文本。
 ---
 
 # Label
 
-*Label* 组件能在游戏空间中渲染出一些文本. 默认连同 sprite 和瓷砖图一起排序和渲染. 组件的各种属性控制着文本如何被渲染. Defold 的 GUI 也能显示文本但是难以把它放在游戏世界里. Label 可以更容易做到这一点.
+*Label* 组件在游戏空间中渲染一段文本。默认情况下,它会与所有精灵和图块图形一起排序和绘制。该组件有一组属性,用于控制文本的渲染方式。Defold的GUI支持文本,但在游戏世界中放置GUI元素可能比较棘手。Labels使这一过程变得更加简单。
 
 ## 创建 label
 
@@ -13,119 +13,118 @@ brief: 本教程介绍了文本组件 label 的使用方法.
 
 ![Add label](images/label/add_label.png)
 
-(如果你希望从一个模板创建多个 label 可以: 在 *Assets* 浏览器里的文件夹上 <kbd>右键点击</kbd> 选择 <kbd>New... ▸ Label</kbd> 来创建Label文件, 然后再在任意游戏对象上把它作为组件添加上去)
+(如果你想从同一模板实例化多个label,也可以创建一个新的label组件文件:在*Assets*浏览器中的文件夹上<kbd>右键点击</kbd>并选择<kbd>New... ▸ Label</kbd>,然后将该文件作为组件添加到任何游戏对象)
 
 ![New label](images/label/label.png)
 
-设置 *Font* 属性为需要使用的字体还要确定 *Material* 属性的设置与字体相匹配:
+将*Font*属性设置为您想要使用的字体,并确保将*Material*属性设置为与字体类型相匹配的材质:
 
 ![Font and material](images/label/font_material.png)
 
 ## Label 属性
 
-除了 *Id*, *Position*, *Rotation* 和 *Scale* 外还有一些特有属性:
+除了*Id*、*Position*、*Rotation*和*Scale*属性外,还存在以下组件特有属性:
 
 *Text*
-: label的文本.
+: 标签的文本内容。
 
 *Size*
-: 边界方块的大小. 如果 *Line Break* 设置了某值, 文本就会在相应宽度换行.
+: 文本边界框的大小。如果设置了*Line Break*,宽度将指定文本应在何处换行。
 
 *Color*
 : 文本的颜色.
 
 *Outline*
-: 描边的颜色.
+: 轮廓的颜色。
 
 *Shadow*
-: 阴影的颜色.
+: 阴影的颜色
 
 ::: sidenote
-默认材质出于性能原因关闭了阴影渲染.
+请注意,默认材质出于性能原因禁用了阴影渲染。
 :::
 
 *Leading*
-: 行间距倍数. 设置为 0 则没有行间距. 默认是 1.
+: 行间距的缩放数值。0值表示没有行间距。默认为1。
 
 *Tracking*
-: 字间距倍数. 默认是 0.
+: 字间距的缩放数值。默认为0。
 
 *Pivot*
-: 文本的锚点. 此值关系到文本对齐效果 (详见下文).
+: 文本的轴心点。使用此属性来更改文本对齐方式(见下文)。
 
 *Blend Mode*
-: 此 label 渲染时使用的混合模式.
+: 渲染标签时使用的混合模式。
 
 *Line Break*
-: 文本对齐与锚点相关, 此属性可以让文本流动几行. 节点宽度决定文本在哪里换行.文本对齐与锚点相关, 此属性可以让文本溢出几行. 节点宽度决定文本在哪里换行. 注意文本换行处要留有空间.
+: 文本对齐遵循轴心点设置,设置此属性允许文本流到多行。组件的宽度决定文本换行的位置。请注意,文本中必须有空格才能换行。
 
 *Font*
-: 此 label 所使用的字体资源.
+: 用于此标签的字体资源。
 
 *Material*
-: 用于渲染此 label 所使用的材质. 确保选中的材质是为你所使用的字体 (bitmap, distance field or BMFont) 创建的.
+: 用于渲染此标签的材质。确保选择为您使用的字体类型(位图、距离场或BMFont)创建的材质。
 
 ### 混合模式
 :[blend-modes](../shared/blend-modes.md)
 
-### 点和对齐
+### 轴心点和对齐
 
-你可以通过设置锚点来改变文本的对齐方式.
+通过设置*Pivot*属性,您可以更改文本的对齐模式。
 
 *Center*
-: 如果锚点设置成 `Center`, `North` 或者 `South`, 则文本居中对齐.
+: 如果轴心点设置为`Center`、`North`或`South`,则文本居中对齐。
 
 *Left*
-: 如果锚点设置成任何 `West` 模式, 则文本左对齐.
+: 如果轴心点设置为任何`West`模式,则文本左对齐。
 
 *Right*
-: 如果锚点设置成任何 `East` 模式, 则文本右对齐.
+: 如果轴心点设置为任何`East`模式,则文本右对齐。
 
 ![Text alignment](images/label/align.png)
 
-## 运行时控制操作
+## 运行时操作
 
-你可以使用在运行时操控 labels 的文本以及其他一系列的值.
+您可以在运行时通过获取和设置标签文本以及其他各种属性来操作标签。
 
 `color`
-: label颜色 (`vector4`)
+: 标签颜色(`vector4`)
 
 `outline`
-: label描边颜色 (`vector4`)
+: 标签轮廓颜色(`vector4`)
 
 `shadow`
-: label阴影颜色 (`vector4`)
+: 标签阴影颜色(`vector4`)
 
 `scale`
-: label缩放, 要么是 `number` 用于等比缩放, 要么是 `vector3` 分轴向缩放.
+: 标签缩放,可以是用于均匀缩放的`number`,或者是用于沿各轴单独缩放的`vector3`。
 
 `size`
-: label大小 (`vector3`)
+: 标签大小(`vector3`)
 
 ```lua
 function init(self)
-    -- Set the text of the "my_label" component in the same game object
-    -- as this script.
-    label.set_text("#my_label", "New text")
+    -- 设置与此脚本在同一游戏对象中的"my_label"组件的文本。
+    label.set_text("#my_label", "新文本")
 end
 ```
 
 ```lua
 function init(self)
-    -- Set the color of the "my_label" component in the same game object
-    -- as this script. Color is a RGBA value stored in a vector4.
+    -- 设置与此脚本在同一游戏对象中的"my_label"组件的颜色。
+    -- 颜色是存储在vector4中的RGBA值。
     local grey = vmath.vector4(0.5, 0.5, 0.5, 1.0)
     go.set("#my_label", "color", grey)
 
-    -- ...and remove the outline, by setting its alpha to 0...
+    -- ...通过将其alpha设置为0来移除轮廓...
     go.set("#my_label", "outline.w", 0)
 
-    -- ...and scale it x2 along x axis.
+    -- ...沿x轴将其缩放2倍。
     local scale_x = go.get("#my_label", "scale.x")
     go.set("#my_label", "scale.x", scale_x * 2)
 end
 ```
 
-## 相关项目配置
+## 项目配置
 
-在 *game.project* 文件里有些关于标签的 [配置项目](/manuals/project-settings#label).
+*game.project*文件中有一些与标签相关的[项目设置](/manuals/project-settings#label)。

+ 68 - 44
docs/zh/manuals/libraries.md

@@ -1,104 +1,128 @@
 ---
-title: Defold 中库的使用
-brief: 项目间可以使用库共享资源. 本教程解释了其工作方式.
+title: Defold库项目
+brief: 库功能允许您在项目之间共享资源。本手册解释了其工作原理。
 ---
 
 # 库
 
-库实现了项目间共享资源. 在工作流中使用库方便而更有效率.
+库功能允许您在项目之间共享资源。这是一个简单但非常强大的机制,您可以通过多种方式在工作流程中使用它。
 
-库在以下情形下很有用:
+库在以下情况下非常有用:
 
-* 把已完成项目的资源复制到新建项目里使用. 如果要为你的游戏出续集, 很需要这种方法.
-* 编译一个模板的库以便导入到项目中再定制使用.
-* 编译一些包含做好了的对象和脚本的库以便直接使用. 对于保存通用脚本模块或者创建共享资源非常有用.
+* 将资源从已完成的项目复制到新项目。如果您正在制作早期游戏的续作,这是一种简单的方法。
+* 构建一个模板库,您可以将其复制到项目中,然后进行定制或专门化。
+* 构建一个或多个包含现成对象或脚本的库,您可以直接引用它们。这对于存储通用脚本模块或构建共享的图形、声音和动画资源库非常方便。
 
-## 库共享设置
+## 设置库共享
 
-比如你想创建一个包含共享 sprite 和瓷砖图源的库. 先从 [新建项目设置](/manuals/project-setup/) 开始. 确定项目中你要共享的文件夹然后把它加入到项目设置的 *include_dirs* 属性列表里. 如果需要加入多个, 以空格分隔文件夹名称:
+假设您想要构建一个包含共享精灵和图块源的库。首先从[设置新项目](/manuals/project-setup/)开始。确定您要从项目中共享哪些文件夹,并将这些文件夹的名称添加到项目设置中的*`include_dirs`*属性中。如果您想列出多个文件夹,请用空格分隔名称:
 
-![Include dirs](images/libraries/libraries_include_dirs.png)
+![Include directories](images/libraries/libraries_include_dirs.png)
 
-我们需要先定位库才能把它导入到项目里.
+在我们能够将此库添加到另一个项目之前,我们需要一种定位库的方法。
 
-## 库地址
+## 库URL
 
-库使用标准 URL 来引用. 对于托管在 GitHub 上的项目, 就是项目发布的 URL:
+库通过标准URL进行引用。对于托管在GitHub上的项目,它将是项目发布的URL:
 
 ![GitHub Library URL](images/libraries/libraries_library_url_github.png)
 
 ::: important
-最好使用库项目的发布地址而不是主分支来引用库. 作为开发者你要决定什么时候该合并更新而不是时刻保持主分支最新代码 (使用主分支最新版可能引入潜在的不稳定性).
+建议始终依赖库项目的特定版本,而不是主分支。这样,作为开发者,您可以决定何时合并库项目的更改,而不是总是从库项目的主分支获取最新的(可能具有破坏性的)更改。
 :::
 
+::: important
+建议在使用前始终审查第三方库。了解更多关于[保护您对第三方软件的使用](https://defold.com/manuals/application-security/#securing-your-use-of-third-party-software)的信息。
+:::
 
-### 基本訪問驗證
+### 基本访问认证
 
-對於不公開的庫可以通過在 URL 上加入用戶名密碼 / 訪問權token的方法來訪問:
+可以在库URL中添加用户名和密码/令牌,以便在使用非公开库时执行基本访问认证:
 
 ```
 https://username:[email protected]/defold/private/archive/main.zip
 ```
 
-這裏 `username` 和 `password` 項會被提取並轉化爲 `Authorization` 請求頭. 這種方法一般服務器都適用. 包括從 GitHub 上獲取私有庫. GitHub 還支持使用 [生成訪問權token](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token) 的方法來代替密碼.
+`username`和`password`字段将被提取并添加为`Authorization`请求头。这适用于任何支持基本访问认证的服务器。
+
+::: important
+确保不要共享或意外泄露您生成的个人访问令牌或密码,因为如果它们落入错误的手中,可能会造成严重后果!
+:::
+
+为避免在库URL中以明文形式泄露任何凭据,也可以使用字符串替换模式并将凭据存储为环境变量:
 
 ```
-https://github-username:[email protected]/defold/private/archive/main.zip
+https://__PRIVATE_USERNAME__:__PRIVATE_TOKEN__@github.com/defold/private/archive/main.zip
 ```
 
-::: sidenote
-不要共享或者不小心泄露你的密碼或訪問權token, 否則可能會落入他人之手造成不良後果.
-:::
+在上面的示例中,用户名和令牌将从系统环境变量`PRIVATE_USERNAME`和`PRIVATE_TOKEN`中读取。
+
+#### GitHub认证
 
-为避免泄密在库 URL 上的明文用户名密码字符串可以使用环境变量代替:
+要从GitHub上的私有仓库获取,您需要[生成个人访问令牌](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token)并将其用作您的密码。
 
 ```
-https://__PRIVATE_USERNAME__:__PRIVATE_TOKEN__@github.com/defold/private/archive/main.zip
+https://github-username:personal-access-token@github.com/defold/private/archive/main.zip
 ```
 
-上面的例子里用户名和令牌会被替换为环境变量 `PRIVATE_USERNAME` 和 `PRIVATE_TOKEN` 的值.
+#### GitLab认证
+
+要从GitLab上的私有仓库获取,您需要[生成个人访问令牌](https://docs.gitlab.com/ee/security/token_overview.html)并将其作为URL参数发送。
 
+```
+https://gitlab.com/defold/private/-/archive/main/test-main.zip?private_token=personal-access-token
+```
 
-### 严格访问权限
+### 高级访问认证
 
-基本訪問权限下token和用户名都在项目依赖库上公开. 这对于多人开发团队来说可能会造成麻烦. 解决办法是给库引入一个 "只读" 用户, 在 GitHub 上可以设置一个机构, 一个团队以及一个不需要编辑代码的用户 (也就是只读用户).
+使用基本访问认证时,用户的访问令牌和用户名将在用于项目的任何仓库上共享。对于超过1人的团队,这可能是一个问题。为了解决这个问题,需要使用一个"只读"用户来访问仓库的库,在GitHub上,这需要一个组织、一个团队和一个不需要编辑仓库的用户(因此是只读的)。
 
-GitHub 具体步骤:
-* [创建机构](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/creating-a-new-organization-from-scratch)
-* [机构之下的团队](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/creating-a-team)
-* [把需要的私有库存放到机构之下](https://docs.github.com/en/github/administering-a-repository/transferring-a-repository)
-* [将开发团队设置为对库 "只读"](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/managing-team-access-to-an-organization-repository)
-* [创建只读团队的只读用户成员](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/organizing-members-into-teams)
-* 给只读用户发放 "基本访问权限" token
+GitHub步骤:
+* [创建组织](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/creating-a-new-organization-from-scratch)
+* [在组织内创建团队](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/creating-a-team)
+* [将所需的私有仓库转移到您的组织](https://docs.github.com/en/github/administering-a-repository/transferring-a-repository)
+* [授予团队对仓库的"只读"访问权限](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/managing-team-access-to-an-organization-repository)
+* [创建或选择一个用户作为此团队的一部分](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/organizing-members-into-teams)
+* 使用上面的"基本访问认证"为此用户创建个人访问令牌
 
-此时这个只读用户的信息就可以放心公开在依赖库上. 这样就可以将私有库公开化而不用担心被恶意篡改.
+此时,新用户的认证详细信息可以提交并推送到仓库。这将允许任何使用您的私有仓库工作的人将其作为库获取,而无需对库本身具有编辑权限。
 
 ::: important
-使用这种只读用户的 token 可以访问所有依赖私有库的游戏.
+只读用户的令牌对于任何可以访问使用该库的游戏仓库的人都是完全可访问的。
 :::
 
-上述解决方案于 Defold 论坛提出并 [于此帖子上进行谈论](https://forum.defold.com/t/private-github-for-library-solved/67240).
+此解决方案在Defold论坛上提出并[在此线程中讨论](https://forum.defold.com/t/private-github-for-library-solved/67240)。
 
 ## 设置库依赖
 
-打开需要引入库的项目. 在项目设置里, 把 URL 加入到 *dependencies* 属性下. 如果需要可以加入多个. 使用 `+` 按钮一个一个加入, 使用 `-` 按钮移除:
+打开您想要访问库的项目。在项目设置中,将库URL添加到*dependencies*属性中。如果需要,您可以指定多个依赖项目。只需使用`+`按钮一个一个地添加它们,并使用`-`按钮删除:
 
 ![Dependencies](images/libraries/libraries_dependencies.png)
 
-然后, 选择 <kbd>Project ▸ Fetch Libraries</kbd> 来更新库依赖. 这项工作会在打开项目时自动执行所以只有当库需要更新而不想重新打开项目时才会用到这个命令. 比如你修改了库依赖或者库本身被修改和同步了的时候.
+现在,选择<kbd>Project ▸ Fetch Libraries</kbd>来更新库依赖。每当您打开项目时,这都会自动发生,因此只有当依赖项更改而不重新打开项目时,您才需要这样做。如果您添加或删除依赖库,或者如果某个依赖库项目被某人更改并同步,就会发生这种情况。
 
 ![Fetch Libraries](images/libraries/libraries_fetch_libraries.png)
 
-此时你共享的文件夹就会出现在资源面板中等待使用. 库的各种修改都会同步到你的项目之中.
+现在,您共享的文件夹出现在*Assets*面板中,您可以使用您共享的所有内容。对库项目所做的任何同步更改都将在您的项目中可用。
 
 ![Library setup done](images/libraries/libraries_done.png)
 
-## 引用破坏
+## 编辑库依赖中的文件
+
+库中的文件无法保存。您可以进行更改,编辑器将能够使用这些更改进行构建,这对于测试很有用。但是,文件本身保持不变,当文件关闭时,所有修改都将被丢弃。
+
+如果您想要更改库文件,请确保创建您自己的库分支并在那里进行更改。另一个选择是将整个库文件夹复制/粘贴到您的项目目录中并使用本地副本。在这种情况下,您的本地文件夹将遮蔽原始依赖项,并且应该从`game.project`中删除依赖项链接(不要忘记之后选择<kbd>Project ▸ Fetch Libraries</kbd>)。
+
+`builtins`也是引擎提供的一个库。如果您想要编辑那里的文件,请确保将它们复制到您的项目中并使用它们,而不是原始的`builtins`文件。例如,要修改`default.render_script`,将`/builtins/render/default.render`和`/builtins/render/default.render_script`都复制到您的项目文件夹中,作为`my_custom.render`和`my_custom.render_script`。然后,更新您的本地`my_custom.render`以引用`my_custom.render_script`而不是内置的,并在Render设置下的`game.project`中设置您的自定义`my_custom.render`。
+
+如果您复制粘贴材质并希望跨某种类型的所有组件使用它,使用[每个项目的模板](/manuals/editor/#creating-new-project-files)可能很有用。
+
+## 损坏的引用
 
-共享库仅限于使用共享文件夹下的文件. 如果你引用了共享文件夹之外的资源, 则共享引用就会被破坏.
+库共享仅包括位于共享文件夹下的文件。如果您创建的内容引用了位于共享层次结构之外的资源,引用路径将被损坏。
 
-## 命名冲突
+## 名冲突
 
-如果项目设置 *dependencies* 中引用了很多库你可能会遇到命名冲突的情况. 如果两个或者多个项目的项目设置中 *include_dirs* 里包含的共享文件夹名一样就会造成这种情况.
+由于您可以在*dependencies*项目设置中列出多个项目URL,您可能会遇到名称冲突。如果两个或更多依赖项目在*`include_dirs`*项目设置中共享一个同名的文件夹,就会发生这种情况。
 
-Defold 解决库命名冲突的办法很简单, 除了 *dependencies* 列表中最后一个, 其他都忽略掉. 比如说. 你的项目依赖3个库, 每个库都有一个叫做 *items* 的共享文件夹, 则只有一个 *items* 文件夹会被显示出来---那就是处于 URL 列表里的最后一个.
+Defold通过简单地忽略除对同名文件夹的最后一个引用之外的所有引用来解决名称冲突,顺序是项目URL在*dependencies*列表中指定的顺序。例如,如果您在依赖项中列出了3个库项目URL,并且它们都共享一个名为*items*的文件夹,则只会显示一个*items*文件夹——属于URL列表中最后一个项目的那个。

+ 7 - 7
docs/zh/manuals/linux.md

@@ -1,16 +1,16 @@
 
 ---
-title: Defold 开发 Linux 游戏
-brief: 本教程介绍了如何在 Linux 上编译运行 Defold 游戏
+title: Linux平台Defold开发
+brief: 本手册描述了如何在 Linux 上构建和运行 Defold 应用程序
 ---
 
 # Linux 开发
 
-在 Linux 上编译运行 Defold 游戏十分简单.
+为 Linux 平台开发 Defold 应用程序是一个直接明了的过程,几乎不需要考虑什么。
 
-## 项目
+## 项目
 
-Linux 相关设置位于 *game.project* 文件的 Linux 部分.
+Linux 特定的应用程序配置是在 *game.project* 设置文件的 [Linux 部分](/manuals/project-settings/#linux) 中完成的。
 
-## 问答
-:[Linux 问答](../shared/linux-faq.md)
+## FAQ
+:[Linux FAQ](../shared/linux-faq.md)

+ 25 - 25
docs/zh/manuals/live-update-aws.md

@@ -1,23 +1,23 @@
 ---
-title: Live update content uploads to AWS
-brief: This section will explain how to create a new user with limited access on Amazon Web Services that can be used together with the Defold editor to automatically upload Live update resources when you bundle your game.
+title: AWS Live Update内容上传
+brief: 本节将解释如何在 Amazon Web Services 上创建一个具有有限访问权限的新用户,该用户可以与 Defold 编辑器一起使用,在您打包游戏时自动上传 Live update 资源。
 ---
 
-# 创建 Amazon 网络服务器
+# 设置 Amazon Web Service
 
-要使用 Defold 配合 Amazon 服务器进行热更新首先要有 Amazon Web Services 账户. 没有的话请在这里注册: https://aws.amazon.com/.
+要将 Defold Live update 功能与 Amazon 服务一起使用,您需要一个 Amazon Web Services 账户。如果您还没有账户,可以在这里创建:https://aws.amazon.com/。
 
-这里介绍一下如何开通 Amazon 服务以配合 Defold 进行热更新, 在 Amazon S3 需要那些配置. 更多关于 Amazon S3 的信息, 请参考 [Amazon S3 文档](http://docs.aws.amazon.com/AmazonS3/latest/dev/Welcome.html).
+本节将解释如何在 Amazon Web Services 上创建一个具有有限访问权限的新用户,该用户可以与 Defold 编辑器一起使用,在您打包游戏时自动上传 Live update 资源,以及如何配置 Amazon S3 以允许游戏客户端检索资源。有关如何配置 Amazon S3 的更多信息,请参阅 [Amazon S3 文档](http://docs.aws.amazon.com/AmazonS3/latest/dev/Welcome.html)。
 
-1. 开通服务
+1. 为 Live update 资源创建存储桶
 
-    在 _Storage_ 类目 ([Amazon S3 Console](https://console.aws.amazon.com/s3)) 下打开 `Services` 菜单选择 `S3`. 页面上会列出已存在的所有服务器与开通新服务器的选项. 使用已存在的服务器是可以的, 但是建议为热更新资源创建一个新服务器,以便设置访问限制.
+    打开 `Services` 菜单并选择位于 _Storage_ 类别下的 `S3`([Amazon S3 Console](https://console.aws.amazon.com/s3))。您将看到所有现有的存储桶以及创建新存储桶的选项。虽然可以使用现有的存储桶,但我们建议您为 Live update 资源创建一个新的存储桶,以便您可以轻松限制访问。
     
     ![Create a bucket](images/live-update/01-create-bucket.png)
 
-2. 服务配置
+2. 为您的存储桶添加存储桶策略
 
-    开通服务器, 打开 *Properties* 面板展开折叠的 *Permissions* 选项. 点击 *Add bucket policy* 按钮添加配置文件. 本例中的配置是允许任何客户端访问服务器资源, 以便热更新顺利工作. 更多配置信息, 请参考 [Amazon 文档](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-iam-policies.html).
+    选择您希望使用的存储桶,打开 *Properties* 面板并展开面板内的 *Permissions* 选项。通过点击 *Add bucket policy* 按钮打开存储桶策略。本示例中的存储桶策略将允许匿名用户从存储桶中检索文件,这将允许游戏客户端下载游戏所需的 Live update 资源。有关存储桶策略的更多信息,请参阅 [Amazon 文档](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-iam-policies.html)。
 
     ```json
     {
@@ -36,11 +36,11 @@ brief: This section will explain how to create a new user with limited access on
 
     ![Bucket policy](images/live-update/02-bucket-policy.png)
 
-3. 添加 CORS 配置 (可选)
+3. 为您的存储桶添加 CORS 配置(可选)
 
-    [Cross-Origin Resource Sharing (CORS)](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) 是一种能让服务器使用 JavaScript 访问另一服务器资源的机制. 如果你发布的是 HTML5 游戏, 就需要给服务器添加 CORS 配置.
+    [Cross-Origin Resource Sharing (CORS)](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) 是一种允许网站使用 JavaScript 从不同域检索资源的机制。如果您打算将游戏发布为 HTML5 客户端,则需要为存储桶添加 CORS 配置。
 
-    选择服务器, 打开 *Properties* 面板展开折叠的 *Permissions* 选项. 点击 *Add CORS Configuration* 按钮添加 CORS 配置. 本例中的配置是允许任何服务器访问本服务器资源, 如果需要可以做详细的限制. 更多 Amazon CORS 配置信息, 请参考 [Amazon 文档](https://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html).
+    选择您希望使用的存储桶,打开 *Properties* 面板并展开面板内的 *Permissions* 选项。通过点击 *Add CORS Configuration* 按钮打开存储桶策略。本示例中的配置将通过指定通配符域允许来自任何网站的访问,尽管如果您知道将在哪些域上提供游戏,可以进一步限制此访问。有关 Amazon CORS 配置的更多信息,请参阅 [Amazon 文档](https://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html)。
 
     ```xml
     <?xml version="1.0" encoding="UTF-8"?>
@@ -54,11 +54,11 @@ brief: This section will explain how to create a new user with limited access on
 
     ![CORS configuration](images/live-update/03-cors-configuration.png)
 
-4. 创建 IAM 配置
+4. 创建 IAM 策略
 
-    打开 *Services* 菜单, 在 _Security, Identity & Compliance_ 类目 ([Amazon IAM Console](https://console.aws.amazon.com/iam)) 下打开 *IAM*. 选择左边的 *Policies*, 页面会列出已存在的所有 IAM 配置与创建新配置的选项.
+    打开 *Services* 菜单并选择位于 _Security, Identity & Compliance_ 类别下的 *IAM*([Amazon IAM Console](https://console.aws.amazon.com/iam))。选择左侧菜单中的 *Policies*,您将看到所有现有的策略以及创建新策略的选项。
 
-    点击 *Create Policy* 按钮, 选择 _Create Your Own Policy_. 本例中的配置是允许用户获得服务器列表, 这是 Defold 热更新的必要配置. 这里还可以允许用户获得 Access Control List (ACL) 和把资源文件上传至服务器的权力. 关于 Amazon Identity and Access Management (IAM) 的更多信息, 详见 [Amazon 文档](http://docs.aws.amazon.com/IAM/latest/UserGuide/access.html).
+    点击 *Create Policy* 按钮,然后选择 _Create Your Own Policy_。本示例中的策略将允许用户列出所有存储桶,这仅在为 Live update 配置 Defold 项目时才需要。它还将允许用户获取访问控制列表(ACL)并将资源上传到用于 Live update 资源的特定存储桶。有关 Amazon Identity and Access Management (IAM) 的更多信息,请参阅 [Amazon 文档](http://docs.aws.amazon.com/IAM/latest/UserGuide/access.html)。
 
     ```json
     {
@@ -91,30 +91,30 @@ brief: This section will explain how to create a new user with limited access on
 
     ![IAM policy](images/live-update/04-create-policy.png)
 
-5. 创建管理账
+5. 创建用于编程访问的用
 
-    打开 *Services* 菜单, 在 _Security, Identity & Compliance_ 类目 ([Amazon IAM Console](https://console.aws.amazon.com/iam)) 下打开 *IAM*. 选择左边的 *Users*, 页面会列出已存在的所有用户与创建新用户的选项. 使用已存在的用户是可以的, 但是建议为热更新资源创建一个新用户,以便设置访问限制.
+    打开 *Services* 菜单并选择位于 _Security, Identity & Compliance_ 类别下的 *IAM*([Amazon IAM Console](https://console.aws.amazon.com/iam))。选择左侧菜单中的 *Users*,您将看到所有现有的用户以及添加新用户的选项。虽然可以使用现有用户,但我们建议您为 Live update 资源添加一个新用户,以便您可以轻松限制访问。
 
-    点击 *Add User* 按钮, 输入用户名选择 *Programmatic access* 作为 *Access type*, 然后点击 *Next: Permissions*. 选择 *Attach existing policies directly* 然后选择第4步中所作的配置.
+    点击 *Add User* 按钮,提供用户名并选择 *Programmatic access* 作为 *Access type*,然后按 *Next: Permissions*。选择 *Attach existing policies directly* 并选择您在第 4 步中创建的策略。
 
-    完成之后你会得到 *Access key ID* 和 *Secret access key*.
+    完成该过程后,您将获得一个 *Access key ID* 和一个 *Secret access key*。
 
     ::: important
-    保存好密匙 *非常重要* 因为离开 Amazon 页面后就无法再次获得密匙了.
+    存储这些密钥 *非常重要*,因为离开页面后您将无法从 Amazon 检索它们。
     :::
 
-6. 创建档案文件
+6. 创建凭证配置文件
 
-    此时你已经开启了服务器, 做好了客户端访问配置, 添加了服务端方位配置, 新建了用户权限和一个新用户. 剩下的最后一件事是创建 [档案文件](https://aws.amazon.com/blogs/security/a-new-and-standardized-way-to-manage-credentials-in-the-aws-sdks) 以便让 Defold 也能访问服务器.
+    此时,您应该已经创建了一个存储桶,配置了存储桶策略,添加了 CORS 配置,创建了用户策略并创建了一个新用户。剩下的唯一事情是创建一个[凭证配置文件](https://aws.amazon.com/blogs/security/a-new-and-standardized-way-to-manage-credentials-in-the-aws-sdks),以便 Defold 编辑器可以代表您访问存储桶。
 
-    在本地新建一个 *.aws* 文件夹, 在里面新建一个 *credentials* 文件.
+    在您的主文件夹中创建一个新目录 *.aws*,并在新目录中创建一个名为 *credentials* 的文件。
 
     ```bash
     $ mkdir ~/.aws
     $ touch ~/.aws/credentials
     ```
 
-    文件 *~/.aws/credentials* 要包含访问 Amazon 服务所需的凭证即标准 AWS 证书. 打开文件按照如下格式输入你的 *Access key ID* 和 *Secret access key*.
+    文件 *~/.aws/credentials* 将包含您通过编程访问访问 Amazon Web Services 的凭证,是管理 AWS 凭证的标准方式。在文本编辑器中打开文件,并按照下面显示的格式输入您的 *Access key ID* 和 *Secret access key*。
 
     ```ini
     [defold-liveupdate-example]
@@ -122,6 +122,6 @@ brief: This section will explain how to create a new user with limited access on
     aws_secret_access_key = <Secret access key>
     ```
 
-    服务器名, 本例中是 _defold-liveupdate-example_, 在 Defold 编辑器热更新配置里也要提供.
+    在括号内指定的标识符,在本例中为 _defold-liveupdate-example_,是您在 Defold 编辑器中配置项目的 Live update 设置时应提供的相同标识符。
 
     ![Live update settings](images/live-update/05-liveupdate-settings.png)

+ 39 - 39
docs/zh/manuals/live-update-scripting.md

@@ -1,62 +1,62 @@
 ---
-title: 热更新脚本
-brief: 使用热更新, 需要下载并挂载游戏数据. 本手册介绍了热更新脚本.
+title: Live Update脚本编写
+brief: 要使用 live update 内容,您需要将数据下载并挂载到游戏中。在本手册中学习如何使用 live update 进行脚本编写。
 ---
 
-# 热更新脚本
-[live-update-scripting.md](live-update-scripting.md)
-热更新API只是如下几个函数:
+# Live Update 脚本编写
+
+API 仅包含几个函数:
 
 * `liveupdate.add_mount()`
 * `liveupdate.remove_mount()`
-* `liveupdate.get_mounts()`.
+* `liveupdate.get_mounts()`
 
-## 得到 mounts
+## 获取挂载点
 
-如果使用一个以上的热更新卷, 推荐在启动时遍历每个 mount
-来检测这个 mount 是否还在使用中.
+如果您使用多个 live update 归档文件,建议在启动时遍历每个挂载点
+并确定是否仍应使用该挂载点。
 
-这很重要因为内容可能对于引擎来说不在可用, 因为文件格式改变了.
+这很重要,因为由于文件格式更改,内容可能对引擎不再有效。
 
 ```lua
 local function remove_old_mounts()
-	local mounts = liveupdate.get_mounts() -- 得到 mounts 
+	local mounts = liveupdate.get_mounts() -- 包含挂载点的
 
-    -- 每个 mount 包含: mount.uri, mount.priority, mount.name
+    -- 每个挂载点包含:mount.uri, mount.priority, mount.name
 	for _,mount in ipairs(mounts) do
 
-        -- 这需要文件名是唯一的, 以便我们不会从不同卷里获得同名文件
-        -- 这里数据由开发者创建作为给卷指定元数据的方法
+        -- 这需要文件名是唯一的,这样我们就不会从不同的归档文件中获取文件
+        -- 这些数据由开发人员创建,作为为归档文件指定元数据的方式
 		local version_data = sys.load_resource("/version_" .. mount.name .. ".json")
 
 		if version_data then
 			version_data = json.decode(version_data)
 		else
-			version_data = {version = 0} -- 没有版本文件的话, 很可能是老旧/不可用卷
+			version_data = {version = 0} -- 如果没有版本文件,它可能是旧的/无效的归档文件
 		end
 
-        -- 指定卷版本到游戏支持的版本
+        -- 验证归档文件版本与游戏支持的版本
         if version_data.version < sys.get_config_int("game.minimum_lu_version") then
-            -- 不可用的话, 卸载它!
+            -- 它无效,所以我们卸载它!
             liveupdate.remove_mount(mount.name)
         end
 	end
 end
 ```
 
-## 排除的集合代理脚本
+## 使用排除的集合代理进行脚本编写
 
-被打包排除的集合代理使用上跟普通集合代理类似, 但有一个重要区别. 当它还有资源没就位的时候给它发送 `load` 消息会直接报错.
+被排除在打包之外的集合代理与普通集合代理的工作方式类似,但有一个重要区别。当它仍然有在捆绑存储中不可用的资源时,向它发送 `load` 消息将导致它失败。
 
-所以在给它发送 `load` 之前, 我们检查是否有遗漏的资源. 如果有, 我们需要下载包含这些资源的卷并保存起来.
+所以在向它发送 `load` 之前,我们需要检查是否有任何缺失的资源。如果有,我们必须下载包含这些资源的归档文件,然后存储它。
 
- 下例代码默认资源依照 `game.http_url` 的地址下可得到.
+以下示例代码假设资源可以通过设置 `game.http_url` 中指定的 URL 获得。
 
 ```lua
 
--- 你要跟踪哪个卷里有那些内容
--- 本例中, 我们只用一个热更新卷, 包含所有遗漏资源.
--- 如果需要用多个卷, 必须相应地构建好下载表
+-- 您需要跟踪哪个归档文件包含哪些内容
+-- 在本例中,我们只使用一个 liveupdate 归档文件,包含所有缺失的资源。
+-- 如果您使用多个归档文件,您需要相应地构建下载
 local lu_infos = {
     liveupdate = {
         name = "liveupdate",
@@ -81,7 +81,7 @@ function init(self)
 
     local level_name = "level1"
 
-    local info = get_lu_archive_for_level(level_name) -- <3>
+    local info = get_lu_info_for_level(level_name) -- <3>
 
     msg.post("#", "load_level", {level = "level1", info = info }) -- <4>
 end
@@ -101,34 +101,34 @@ function on_message(self, message_id, message, sender)
 		local download_path = sys.get_save_file("mygame", zip_filename)
         local url = self.http_url .. "/" .. zip_filename
 
-        -- 开始请求. 可以使用 credentials
+        -- 发出请求。您可以使用凭据
         http.request(url, "GET", function(self, id, response) -- <7>
 			if response.status == 200 or response.status == 304 then
 				mount_zip(self, message.info.name, message.info.priority, download_path, function(uri, path, status) -- <8>
-					msg.post("#", "load_level", message) -- 尝试重新加载 level
+					msg.post("#", "load_level", message) -- 再次尝试加载关卡
 				end)
 
 			else
-				print("Failed to download archive ", download_path, "from", url, ":", get_status_string(status))
+				print("Failed to download archive ", download_path, "from", url, ":", response.status)
 			end
 		end, nil, nil, {path=download_path})
 
-    elseif message_id == hash("proxy_loaded") then -- level 已加载, 可以 enable 了
+    elseif message_id == hash("proxy_loaded") then -- 关卡已加载,我们可以启用它
         msg.post(sender, "init")
         msg.post(sender, "enable")
     end
 end
 ```
 
-1. 依照指定名称, 优先级和 zip 文件, 使用 `liveupdate.add_mount()` 挂载一个卷. 数据马上便可以用于加载 (不用重启引擎).
-mount 信息被保存然后下次引擎重启便会被自动读取 (同一 mount 不必再一次调用 liveupdate.add_mount())
-2. 线上保存卷 (比如放在 S3 上), 以便等待下载.
-3. 提供集合代理名, 要指出哪个卷需要下载, 然后如何挂载
-4. 游戏开始, 尝试载入 level.
-5. 检查集合代理的所有资源已就位.
-6. 如果有遗漏资源, 需要下载卷然后挂载它.
-7. 提出 http 请求, 下载卷到 `download_path`
-8. 数据已下载, 应该给当前引擎挂载它.
+1. `liveupdate.add_mount()` 使用指定的名称、优先级和 zip 文件挂载单个归档文件。数据立即可用于加载(无需重启引擎)。
+挂载点信息被存储,并在下次引擎重启时自动重新添加(无需在同一挂载点上再次调用 liveupdate.add_mount())
+2. 您需要将归档文件在线存储(例如在 S3 上),以便您可以从中下载。
+3. 给定集合代理名称,您需要确定要下载哪些归档文件,以及如何挂载它们
+4. 在启动时,我们尝试加载关卡。
+5. 检查集合代理是否具有所有可用资源。
+6. 如果有资源缺失,那么我们需要下载归档文件并挂载它。
+7. 发出 http 请求并将归档文件下载到 `download_path`
+8. 数据已下载,是时候将其挂载到正在运行的引擎上了。
 
 
-载入代码完成后, 我们就可以测试游戏了. 然而, 从编辑器里运行游戏不会下载任何东西. 这是因为热更新是一个游戏包特性. 在编辑器环境运行游戏所有资源都就位. 为了测试该特性, 我们需要打游戏包.
+有了加载代码,我们就可以测试应用程序了。但是,从编辑器运行它不会下载任何内容。这是因为 Live update 是一个捆绑功能。在编辑器环境中运行时,资源永远不会被排除。为了确保一切正常,我们需要创建一个捆绑包。

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików