From 4967a1379b7f251448be813e183f07d1239eac4b Mon Sep 17 00:00:00 2001 From: taliesin Date: Mon, 11 May 2026 02:08:54 +1000 Subject: [PATCH] i18n(zh-cn): add Simplified Chinese translations 2026-05-11 (batch 3) --- docs/.translation-cache/zh-cn.json | 418 ++++++- .../docs/zh-cn/contributing/architecture.mdx | 91 ++ .../docs/zh-cn/contributing/asset-server.mdx | 195 ++++ .../zh-cn/contributing/binding-system.mdx | 234 ++++ .../zh-cn/contributing/build-packaging.mdx | 197 ++++ .../zh-cn/contributing/codebase-layout.mdx | 212 ++++ .../zh-cn/contributing/extending-wails.mdx | 246 ++++ .../zh-cn/contributing/getting-started.mdx | 367 ++++++ .../content/docs/zh-cn/contributing/index.mdx | 87 ++ .../zh-cn/contributing/runtime-internals.mdx | 206 ++++ .../content/docs/zh-cn/contributing/setup.mdx | 297 +++++ .../docs/zh-cn/contributing/standards.mdx | 463 ++++++++ .../zh-cn/contributing/template-system.mdx | 220 ++++ .../docs/zh-cn/contributing/testing-ci.mdx | 215 ++++ .../docs/zh-cn/features/bindings/advanced.mdx | 342 ++++++ .../features/bindings/best-practices.mdx | 365 ++++++ .../docs/zh-cn/features/bindings/enums.mdx | 397 +++++++ .../docs/zh-cn/features/bindings/methods.mdx | 410 +++++++ .../docs/zh-cn/features/bindings/models.mdx | 456 ++++++++ .../docs/zh-cn/features/bindings/services.mdx | 615 ++++++++++ .../zh-cn/features/browser/integration.mdx | 510 +++++++++ .../docs/zh-cn/features/clipboard/basics.mdx | 409 +++++++ .../docs/zh-cn/features/dialogs/custom.mdx | 383 +++++++ .../docs/zh-cn/features/dialogs/file.mdx | 330 ++++++ .../docs/zh-cn/features/dialogs/message.mdx | 384 +++++++ .../docs/zh-cn/features/dialogs/overview.mdx | 376 ++++++ .../zh-cn/features/drag-and-drop/files.mdx | 212 ++++ .../zh-cn/features/drag-and-drop/html.mdx | 232 ++++ .../docs/zh-cn/features/environment/info.mdx | 616 ++++++++++ .../docs/zh-cn/features/events/system.mdx | 363 ++++++ .../zh-cn/features/keyboard/shortcuts.mdx | 438 +++++++ .../docs/zh-cn/features/menus/application.mdx | 508 +++++++++ .../docs/zh-cn/features/menus/context.mdx | 643 +++++++++++ .../docs/zh-cn/features/menus/reference.mdx | 359 ++++++ .../docs/zh-cn/features/menus/systray.mdx | 380 +++++++ .../zh-cn/features/notifications/overview.mdx | 303 +++++ .../docs/zh-cn/features/platform/dock.mdx | 241 ++++ .../docs/zh-cn/features/screens/info.mdx | 343 ++++++ .../docs/zh-cn/features/windows/basics.mdx | 417 +++++++ .../docs/zh-cn/features/windows/events.mdx | 422 +++++++ .../docs/zh-cn/features/windows/frameless.mdx | 789 +++++++++++++ .../docs/zh-cn/features/windows/multiple.mdx | 606 ++++++++++ .../docs/zh-cn/features/windows/options.mdx | 1003 +++++++++++++++++ .../docs/zh-cn/guides/architecture.mdx | 199 ++++ .../docs/zh-cn/guides/build/building.mdx | 121 ++ .../zh-cn/guides/build/cross-platform.mdx | 296 +++++ .../docs/zh-cn/guides/build/customization.mdx | 241 ++++ .../content/docs/zh-cn/guides/build/linux.mdx | 223 ++++ .../content/docs/zh-cn/guides/build/macos.mdx | 145 +++ .../docs/zh-cn/guides/build/signing.mdx | 684 +++++++++++ .../docs/zh-cn/guides/build/windows.mdx | 124 ++ docs/src/content/docs/zh-cn/guides/cli.mdx | 549 +++++++++ .../docs/zh-cn/guides/custom-templates.mdx | 286 +++++ .../docs/zh-cn/guides/custom-transport.mdx | 172 +++ .../docs/zh-cn/guides/customising-windows.mdx | 120 ++ .../guides/distribution/auto-updates.mdx | 564 +++++++++ .../guides/distribution/custom-protocols.mdx | 614 ++++++++++ .../content/docs/zh-cn/guides/e2e-testing.mdx | 173 +++ .../docs/zh-cn/guides/events-reference.mdx | 459 ++++++++ .../docs/zh-cn/guides/file-associations.mdx | 168 +++ .../content/docs/zh-cn/guides/gin-routing.mdx | 263 +++++ .../docs/zh-cn/guides/gin-services.mdx | 554 +++++++++ .../content/docs/zh-cn/guides/installers.mdx | 160 +++ docs/src/content/docs/zh-cn/guides/menus.mdx | 524 +++++++++ .../docs/zh-cn/guides/panic-handling.mdx | 116 ++ .../content/docs/zh-cn/guides/performance.mdx | 341 ++++++ .../docs/zh-cn/guides/raw-messages.mdx | 390 +++++++ .../src/content/docs/zh-cn/guides/routing.mdx | 107 ++ .../content/docs/zh-cn/guides/security.mdx | 261 +++++ .../docs/zh-cn/guides/server-build.mdx | 312 +++++ .../docs/zh-cn/guides/single-instance.mdx | 119 ++ .../src/content/docs/zh-cn/guides/testing.mdx | 175 +++ .../content/docs/zh-cn/guides/windows-uac.mdx | 152 +++ .../content/docs/zh-cn/migration/v2-to-v3.mdx | 670 +++++++++++ .../docs/zh-cn/reference/application.mdx | 486 ++++++++ docs/src/content/docs/zh-cn/reference/cli.mdx | 28 + .../content/docs/zh-cn/reference/dialogs.mdx | 831 ++++++++++++++ .../content/docs/zh-cn/reference/events.mdx | 736 ++++++++++++ .../docs/zh-cn/reference/frontend-runtime.mdx | 931 +++++++++++++++ .../src/content/docs/zh-cn/reference/menu.mdx | 722 ++++++++++++ .../content/docs/zh-cn/reference/overview.mdx | 282 +++++ .../content/docs/zh-cn/reference/updater.mdx | 501 ++++++++ .../content/docs/zh-cn/reference/window.mdx | 503 +++++++++ .../docs/zh-cn/troubleshooting/mac-syso.mdx | 23 + .../zh-cn/tutorials/01-creating-a-service.mdx | 707 ++++++++++++ .../docs/zh-cn/tutorials/02-todo-vanilla.mdx | 721 ++++++++++++ .../docs/zh-cn/tutorials/03-notes-vanilla.mdx | 701 ++++++++++++ .../content/docs/zh-cn/tutorials/overview.mdx | 84 ++ 88 files changed, 32833 insertions(+), 5 deletions(-) create mode 100644 docs/src/content/docs/zh-cn/contributing/architecture.mdx create mode 100644 docs/src/content/docs/zh-cn/contributing/asset-server.mdx create mode 100644 docs/src/content/docs/zh-cn/contributing/binding-system.mdx create mode 100644 docs/src/content/docs/zh-cn/contributing/build-packaging.mdx create mode 100644 docs/src/content/docs/zh-cn/contributing/codebase-layout.mdx create mode 100644 docs/src/content/docs/zh-cn/contributing/extending-wails.mdx create mode 100644 docs/src/content/docs/zh-cn/contributing/getting-started.mdx create mode 100644 docs/src/content/docs/zh-cn/contributing/index.mdx create mode 100644 docs/src/content/docs/zh-cn/contributing/runtime-internals.mdx create mode 100644 docs/src/content/docs/zh-cn/contributing/setup.mdx create mode 100644 docs/src/content/docs/zh-cn/contributing/standards.mdx create mode 100644 docs/src/content/docs/zh-cn/contributing/template-system.mdx create mode 100644 docs/src/content/docs/zh-cn/contributing/testing-ci.mdx create mode 100644 docs/src/content/docs/zh-cn/features/bindings/advanced.mdx create mode 100644 docs/src/content/docs/zh-cn/features/bindings/best-practices.mdx create mode 100644 docs/src/content/docs/zh-cn/features/bindings/enums.mdx create mode 100644 docs/src/content/docs/zh-cn/features/bindings/methods.mdx create mode 100644 docs/src/content/docs/zh-cn/features/bindings/models.mdx create mode 100644 docs/src/content/docs/zh-cn/features/bindings/services.mdx create mode 100644 docs/src/content/docs/zh-cn/features/browser/integration.mdx create mode 100644 docs/src/content/docs/zh-cn/features/clipboard/basics.mdx create mode 100644 docs/src/content/docs/zh-cn/features/dialogs/custom.mdx create mode 100644 docs/src/content/docs/zh-cn/features/dialogs/file.mdx create mode 100644 docs/src/content/docs/zh-cn/features/dialogs/message.mdx create mode 100644 docs/src/content/docs/zh-cn/features/dialogs/overview.mdx create mode 100644 docs/src/content/docs/zh-cn/features/drag-and-drop/files.mdx create mode 100644 docs/src/content/docs/zh-cn/features/drag-and-drop/html.mdx create mode 100644 docs/src/content/docs/zh-cn/features/environment/info.mdx create mode 100644 docs/src/content/docs/zh-cn/features/events/system.mdx create mode 100644 docs/src/content/docs/zh-cn/features/keyboard/shortcuts.mdx create mode 100644 docs/src/content/docs/zh-cn/features/menus/application.mdx create mode 100644 docs/src/content/docs/zh-cn/features/menus/context.mdx create mode 100644 docs/src/content/docs/zh-cn/features/menus/reference.mdx create mode 100644 docs/src/content/docs/zh-cn/features/menus/systray.mdx create mode 100644 docs/src/content/docs/zh-cn/features/notifications/overview.mdx create mode 100644 docs/src/content/docs/zh-cn/features/platform/dock.mdx create mode 100644 docs/src/content/docs/zh-cn/features/screens/info.mdx create mode 100644 docs/src/content/docs/zh-cn/features/windows/basics.mdx create mode 100644 docs/src/content/docs/zh-cn/features/windows/events.mdx create mode 100644 docs/src/content/docs/zh-cn/features/windows/frameless.mdx create mode 100644 docs/src/content/docs/zh-cn/features/windows/multiple.mdx create mode 100644 docs/src/content/docs/zh-cn/features/windows/options.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/architecture.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/build/building.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/build/cross-platform.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/build/customization.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/build/linux.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/build/macos.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/build/signing.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/build/windows.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/cli.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/custom-templates.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/custom-transport.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/customising-windows.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/distribution/auto-updates.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/distribution/custom-protocols.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/e2e-testing.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/events-reference.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/file-associations.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/gin-routing.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/gin-services.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/installers.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/menus.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/panic-handling.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/performance.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/raw-messages.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/routing.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/security.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/server-build.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/single-instance.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/testing.mdx create mode 100644 docs/src/content/docs/zh-cn/guides/windows-uac.mdx create mode 100644 docs/src/content/docs/zh-cn/migration/v2-to-v3.mdx create mode 100644 docs/src/content/docs/zh-cn/reference/application.mdx create mode 100644 docs/src/content/docs/zh-cn/reference/cli.mdx create mode 100644 docs/src/content/docs/zh-cn/reference/dialogs.mdx create mode 100644 docs/src/content/docs/zh-cn/reference/events.mdx create mode 100644 docs/src/content/docs/zh-cn/reference/frontend-runtime.mdx create mode 100644 docs/src/content/docs/zh-cn/reference/menu.mdx create mode 100644 docs/src/content/docs/zh-cn/reference/overview.mdx create mode 100644 docs/src/content/docs/zh-cn/reference/updater.mdx create mode 100644 docs/src/content/docs/zh-cn/reference/window.mdx create mode 100644 docs/src/content/docs/zh-cn/troubleshooting/mac-syso.mdx create mode 100644 docs/src/content/docs/zh-cn/tutorials/01-creating-a-service.mdx create mode 100644 docs/src/content/docs/zh-cn/tutorials/02-todo-vanilla.mdx create mode 100644 docs/src/content/docs/zh-cn/tutorials/03-notes-vanilla.mdx create mode 100644 docs/src/content/docs/zh-cn/tutorials/overview.mdx diff --git a/docs/.translation-cache/zh-cn.json b/docs/.translation-cache/zh-cn.json index f7420d1d707..e5bf9acb26a 100644 --- a/docs/.translation-cache/zh-cn.json +++ b/docs/.translation-cache/zh-cn.json @@ -1,22 +1,430 @@ { "index.mdx": { "hash": "8db97751a16d", - "translated_at": "2026-05-03T23:30:51Z" + "translated_at": "2026-05-05T11:35:00Z" }, "quick-start/why-wails.mdx": { "hash": "053b3578f336", - "translated_at": "2026-05-03T23:34:47Z" + "translated_at": "2026-05-05T14:07:20Z" }, "quick-start/next-steps.mdx": { "hash": "9b4cb8954865", - "translated_at": "2026-05-04T00:00:37Z" + "translated_at": "2026-05-05T14:10:15Z" }, "status.mdx": { "hash": "916ecd7da4d4", - "translated_at": "2026-05-04T00:00:44Z" + "translated_at": "2026-05-05T14:11:21Z" }, "getting-started/installation.mdx": { "hash": "8d33a6a61b02", - "translated_at": "2026-05-04T00:01:08Z" + "translated_at": "2026-05-05T14:12:34Z" + }, + "feedback.mdx": { + "hash": "a66bb5c84083", + "translated_at": "2026-05-06T20:41:09Z" + }, + "credits.mdx": { + "hash": "23aa065f90ef", + "translated_at": "2026-05-06T20:41:26Z" + }, + "community/links.md": { + "hash": "29ee416737c0", + "translated_at": "2026-05-06T20:41:32Z" + }, + "community/templates.md": { + "hash": "ca58feff1eac", + "translated_at": "2026-05-06T20:42:13Z" + }, + "faq.mdx": { + "hash": "eaa8fbfa4acf", + "translated_at": "2026-05-06T20:42:49Z" + }, + "quick-start/first-app.mdx": { + "hash": "c93bc077121b", + "translated_at": "2026-05-06T20:43:38Z" + }, + "getting-started/your-first-app.mdx": { + "hash": "396abb7e4fac", + "translated_at": "2026-05-06T20:44:36Z" + }, + "quick-start/installation.mdx": { + "hash": "87359ef751c8", + "translated_at": "2026-05-06T20:46:09Z" + }, + "concepts/architecture.mdx": { + "hash": "25b91fd732e4", + "translated_at": "2026-05-06T20:48:12Z" + }, + "concepts/bridge.mdx": { + "hash": "a60fbffa68bd", + "translated_at": "2026-05-06T20:50:02Z" + }, + "concepts/lifecycle.mdx": { + "hash": "b6f00029b744", + "translated_at": "2026-05-06T20:52:23Z" + }, + "concepts/manager-api.mdx": { + "hash": "e341d18b7b82", + "translated_at": "2026-05-06T20:53:02Z" + }, + "concepts/build-system.mdx": { + "hash": "fecbef0d115c", + "translated_at": "2026-05-06T20:54:53Z" + }, + "contributing.mdx": { + "hash": "306f4c3d7ea3", + "translated_at": "2026-05-06T20:55:30Z" + }, + "contributing/architecture/bindings.mdx": { + "hash": "1a645275cef3", + "translated_at": "2026-05-06T20:56:06Z" + }, + "contributing/architecture.mdx": { + "hash": "0da96d95fc40", + "translated_at": "2026-05-06T20:56:25Z" + }, + "contributing/asset-server.mdx": { + "hash": "bb202d50ab3d", + "translated_at": "2026-05-06T20:57:12Z" + }, + "contributing/binding-system.mdx": { + "hash": "15a1847702e6", + "translated_at": "2026-05-06T20:58:00Z" + }, + "contributing/build-packaging.mdx": { + "hash": "38819d5bdc3c", + "translated_at": "2026-05-06T20:58:53Z" + }, + "contributing/codebase-layout.mdx": { + "hash": "7f458a077ad7", + "translated_at": "2026-05-06T20:59:45Z" + }, + "contributing/extending-wails.mdx": { + "hash": "f3b3f52588fc", + "translated_at": "2026-05-06T21:00:28Z" + }, + "contributing/getting-started.mdx": { + "hash": "b440f9d48686", + "translated_at": "2026-05-06T21:01:39Z" + }, + "contributing/index.mdx": { + "hash": "6ec1a3542787", + "translated_at": "2026-05-06T21:02:01Z" + }, + "contributing/runtime-internals.mdx": { + "hash": "76e0f9076c9f", + "translated_at": "2026-05-06T21:03:09Z" + }, + "contributing/setup.mdx": { + "hash": "fa6ba1d71330", + "translated_at": "2026-05-06T21:03:49Z" + }, + "contributing/standards.mdx": { + "hash": "dff5cfcb8913", + "translated_at": "2026-05-06T21:04:53Z" + }, + "contributing/template-system.mdx": { + "hash": "694bc43c635b", + "translated_at": "2026-05-06T21:05:38Z" + }, + "contributing/testing-ci.mdx": { + "hash": "dd3e51012196", + "translated_at": "2026-05-06T21:06:20Z" + }, + "features/bindings/advanced.mdx": { + "hash": "dbe24ee2af58", + "translated_at": "2026-05-06T21:07:17Z" + }, + "features/bindings/best-practices.mdx": { + "hash": "24dae313b7f3", + "translated_at": "2026-05-06T21:09:11Z" + }, + "features/bindings/enums.mdx": { + "hash": "190ad53a8c23", + "translated_at": "2026-05-06T21:10:37Z" + }, + "features/bindings/methods.mdx": { + "hash": "81d390a468d6", + "translated_at": "2026-05-06T21:12:18Z" + }, + "features/bindings/models.mdx": { + "hash": "9f9ef8652dfb", + "translated_at": "2026-05-06T21:14:04Z" + }, + "features/bindings/services.mdx": { + "hash": "ce894343645a", + "translated_at": "2026-05-06T21:16:11Z" + }, + "features/browser/integration.mdx": { + "hash": "fdfdb4b62817", + "translated_at": "2026-05-06T21:17:44Z" + }, + "features/clipboard/basics.mdx": { + "hash": "4518bfb618be", + "translated_at": "2026-05-06T21:18:59Z" + }, + "features/dialogs/custom.mdx": { + "hash": "3c4459e7f9be", + "translated_at": "2026-05-06T21:20:39Z" + }, + "features/dialogs/file.mdx": { + "hash": "56f503b264ff", + "translated_at": "2026-05-06T21:22:10Z" + }, + "features/dialogs/message.mdx": { + "hash": "a0dbc0aa205c", + "translated_at": "2026-05-06T21:23:31Z" + }, + "features/dialogs/overview.mdx": { + "hash": "a53f2f2dbf57", + "translated_at": "2026-05-06T21:24:50Z" + }, + "features/drag-and-drop/files.mdx": { + "hash": "93cde3617c0a", + "translated_at": "2026-05-06T21:25:30Z" + }, + "features/drag-and-drop/html.mdx": { + "hash": "29d1b815879f", + "translated_at": "2026-05-06T21:26:13Z" + }, + "features/environment/info.mdx": { + "hash": "879b5e369c35", + "translated_at": "2026-05-06T21:28:04Z" + }, + "features/events/system.mdx": { + "hash": "99933796a4cd", + "translated_at": "2026-05-06T21:29:40Z" + }, + "features/keyboard/shortcuts.mdx": { + "hash": "0707801c419f", + "translated_at": "2026-05-06T21:31:02Z" + }, + "features/menus/application.mdx": { + "hash": "f3012e184058", + "translated_at": "2026-05-06T21:33:06Z" + }, + "features/menus/context.mdx": { + "hash": "0da9502ee8f9", + "translated_at": "2026-05-06T21:35:20Z" + }, + "features/menus/reference.mdx": { + "hash": "50c7083c6804", + "translated_at": "2026-05-06T21:36:51Z" + }, + "features/menus/systray.mdx": { + "hash": "35456a6a7c94", + "translated_at": "2026-05-06T21:38:55Z" + }, + "features/notifications/overview.mdx": { + "hash": "fd054a949c5c", + "translated_at": "2026-05-06T21:39:54Z" + }, + "features/platform/dock.mdx": { + "hash": "5508d0260390", + "translated_at": "2026-05-06T21:40:42Z" + }, + "features/screens/info.mdx": { + "hash": "7c75b63845ac", + "translated_at": "2026-05-06T21:42:06Z" + }, + "features/windows/basics.mdx": { + "hash": "22ab3ac2c722", + "translated_at": "2026-05-06T21:43:42Z" + }, + "features/windows/events.mdx": { + "hash": "68ae278863a2", + "translated_at": "2026-05-06T21:45:21Z" + }, + "features/windows/frameless.mdx": { + "hash": "8250472da67d", + "translated_at": "2026-05-06T21:47:43Z" + }, + "features/windows/multiple.mdx": { + "hash": "67f02d26da23", + "translated_at": "2026-05-06T21:49:49Z" + }, + "features/windows/options.mdx": { + "hash": "a56b6c508b23", + "translated_at": "2026-05-06T21:52:57Z" + }, + "guides/architecture.mdx": { + "hash": "656401718a17", + "translated_at": "2026-05-06T21:53:22Z" + }, + "guides/build/building.mdx": { + "hash": "b307db98ff3b", + "translated_at": "2026-05-06T21:53:43Z" + }, + "guides/build/cross-platform.mdx": { + "hash": "fe856503784b", + "translated_at": "2026-05-06T21:54:52Z" + }, + "guides/build/customization.mdx": { + "hash": "5fdb39dad876", + "translated_at": "2026-05-06T21:55:51Z" + }, + "guides/build/linux.mdx": { + "hash": "afa4feb031ad", + "translated_at": "2026-05-06T21:56:35Z" + }, + "guides/build/macos.mdx": { + "hash": "453cb1df5afe", + "translated_at": "2026-05-06T21:57:01Z" + }, + "guides/build/signing.mdx": { + "hash": "adcc7414ca8e", + "translated_at": "2026-05-06T21:59:53Z" + }, + "guides/build/windows.mdx": { + "hash": "34fb150bd1d1", + "translated_at": "2026-05-06T22:00:13Z" + }, + "guides/cli.mdx": { + "hash": "734e59534ff1", + "translated_at": "2026-05-06T22:02:37Z" + }, + "guides/custom-templates.mdx": { + "hash": "fd0479b54490", + "translated_at": "2026-05-06T22:03:47Z" + }, + "guides/custom-transport.mdx": { + "hash": "1f60cc55f45f", + "translated_at": "2026-05-06T22:04:19Z" + }, + "guides/customising-windows.mdx": { + "hash": "b2c0f84a76db", + "translated_at": "2026-05-06T22:04:42Z" + }, + "guides/distribution/auto-updates.mdx": { + "hash": "e511338ccc89", + "translated_at": "2026-05-06T22:06:29Z" + }, + "guides/distribution/custom-protocols.mdx": { + "hash": "d7e39edb8d62", + "translated_at": "2026-05-06T22:08:39Z" + }, + "guides/e2e-testing.mdx": { + "hash": "409942e28dff", + "translated_at": "2026-05-06T22:09:03Z" + }, + "guides/events-reference.mdx": { + "hash": "e1c103b7e422", + "translated_at": "2026-05-06T22:10:56Z" + }, + "guides/file-associations.mdx": { + "hash": "5756c5fd62ec", + "translated_at": "2026-05-06T22:11:29Z" + }, + "guides/gin-routing.mdx": { + "hash": "4b51d1052334", + "translated_at": "2026-05-06T22:12:18Z" + }, + "guides/gin-services.mdx": { + "hash": "4336b2c6dd73", + "translated_at": "2026-05-06T22:14:21Z" + }, + "guides/installers.mdx": { + "hash": "eb492627c525", + "translated_at": "2026-05-06T22:14:46Z" + }, + "guides/menus.mdx": { + "hash": "c43696cd9e44", + "translated_at": "2026-05-06T22:16:38Z" + }, + "guides/panic-handling.mdx": { + "hash": "cd4e3d40f28d", + "translated_at": "2026-05-06T22:17:06Z" + }, + "guides/performance.mdx": { + "hash": "2cd3efcd296b", + "translated_at": "2026-05-06T22:17:49Z" + }, + "guides/raw-messages.mdx": { + "hash": "974513802fdc", + "translated_at": "2026-05-06T22:19:05Z" + }, + "guides/routing.mdx": { + "hash": "1a9624a10457", + "translated_at": "2026-05-06T22:19:26Z" + }, + "guides/security.mdx": { + "hash": "4b98f155146f", + "translated_at": "2026-05-06T22:20:02Z" + }, + "guides/server-build.mdx": { + "hash": "14b9185722c8", + "translated_at": "2026-05-06T22:21:12Z" + }, + "guides/single-instance.mdx": { + "hash": "c9d6b1edf953", + "translated_at": "2026-05-06T22:21:44Z" + }, + "guides/testing.mdx": { + "hash": "8073196a1496", + "translated_at": "2026-05-06T22:22:10Z" + }, + "guides/windows-uac.mdx": { + "hash": "91140294509d", + "translated_at": "2026-05-06T22:22:38Z" + }, + "migration/v2-to-v3.mdx": { + "hash": "ba7228eb5374", + "translated_at": "2026-05-06T22:24:44Z" + }, + "reference/application.mdx": { + "hash": "6b97eb24f8db", + "translated_at": "2026-05-06T22:25:54Z" + }, + "reference/cli.mdx": { + "hash": "da0cd943a3de", + "translated_at": "2026-05-06T22:26:00Z" + }, + "reference/dialogs.mdx": { + "hash": "4a2534a0eb49", + "translated_at": "2026-05-06T22:28:07Z" + }, + "reference/events.mdx": { + "hash": "34ff503157f7", + "translated_at": "2026-05-06T22:30:40Z" + }, + "reference/frontend-runtime.mdx": { + "hash": "1040ebd9dffd", + "translated_at": "2026-05-06T22:32:54Z" + }, + "reference/menu.mdx": { + "hash": "1ac85e9b0a6d", + "translated_at": "2026-05-06T22:34:45Z" + }, + "reference/overview.mdx": { + "hash": "78b1b9e99288", + "translated_at": "2026-05-06T22:35:33Z" + }, + "reference/updater.mdx": { + "hash": "841cdfe235d9", + "translated_at": "2026-05-06T22:36:46Z" + }, + "reference/window.mdx": { + "hash": "c23046463063", + "translated_at": "2026-05-06T22:38:29Z" + }, + "troubleshooting/mac-syso.mdx": { + "hash": "7aa5d722de2d", + "translated_at": "2026-05-06T22:38:37Z" + }, + "tutorials/01-creating-a-service.mdx": { + "hash": "759d28b3e03b", + "translated_at": "2026-05-06T22:41:22Z" + }, + "tutorials/02-todo-vanilla.mdx": { + "hash": "a50167163c77", + "translated_at": "2026-05-06T22:44:00Z" + }, + "tutorials/03-notes-vanilla.mdx": { + "hash": "7da37d8fbf9c", + "translated_at": "2026-05-06T22:46:17Z" + }, + "tutorials/overview.mdx": { + "hash": "24d96283170f", + "translated_at": "2026-05-06T22:46:38Z" } } \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/contributing/architecture.mdx b/docs/src/content/docs/zh-cn/contributing/architecture.mdx new file mode 100644 index 00000000000..5021c0a2dca --- /dev/null +++ b/docs/src/content/docs/zh-cn/contributing/architecture.mdx @@ -0,0 +1,91 @@ +--- +title: Wails v3 架构 +description: Wails v3 内部各个组件的深入图解与说明 +sidebar: + order: 1 +--- + +Wails v3 是一个**全栈桌面框架**,由 Go 运行时、JavaScript 桥接层、基于任务驱动的命令行工具链以及一系列模板组成,让你能够利用现代 Web 技术构建并发布原生应用程序。 + +本页通过四张图表展示*整体概览*: + +1. **整体架构** – 各子系统如何连接 +2. **运行时流程** – JS 调用 Go 以及反向调用时发生的情况 +3. **开发环境与生产环境** – 资产服务器的两种模式 +4. **平台实现** – 操作系统特定代码的位置 + +--- + +## 1 · 整体架构 + +**Wails v3 – 高层级技术栈** + +{/* +TODO: Fix D2 diagram generation (triple quotes for multi-line strings) or embed as image. +The previous D2 code block was causing MDX parsing errors in the build pipeline. +*/} + +**[高层级技术栈图表占位符]** + +--- + +## 2 · 运行时调用流程 + +**运行时 – JavaScript ⇄ Go 调用路径** + +{/* +TODO: Fix D2 diagram generation (triple quotes for multi-line strings) or embed as image. +The previous D2 code block was causing MDX parsing errors in the build pipeline. +*/} + +**[运行时调用流程图表占位符]** + +关键点: + +* **无 HTTP / IPC** – 桥接层使用原生 WebView 的内存通道 +* **方法 ID** – 确定性的 FNV 哈希算法使 Go 端能够实现 O(1) 查找 +* **Promises** – 错误以拒绝(rejection)形式传播,包含堆栈信息和错误码 + +--- + +## 3 · 开发环境与生产环境的资产流程 + +**开发环境 ↔ 生产环境 资产服务器** + +{/* +TODO: Fix D2 diagram generation (triple quotes for multi-line strings) or embed as image. +The previous D2 code block was causing MDX parsing errors in the build pipeline. +*/} + +**[资产流程图表占位符]** + +* 在**开发环境**中,服务器将未知路径代理到框架的热重载服务器,并从磁盘提供静态资产。 +* 在**生产环境**中,相同的 API 由 `go:embed` 支持,生成零依赖的二进制文件。 + +--- + +## 4 · 平台特定的运行时拆分 + +**各操作系统运行时文件** + +{/* +TODO: Fix D2 diagram generation (triple quotes for multi-line strings) or embed as image. +The previous D2 code block was causing MDX parsing errors in the build pipeline. +*/} + +**[平台拆分图表占位符]** + +每个功能都遵循以下模式: + +1. `pkg/application` 中的**通用接口** +2. `pkg/application/messageprocessor_*.go` 中的**消息处理器**入口 +3. 在 `internal/runtime/*.go` 下按操作系统划分的**实现**,并通过构建标签进行保护 + +如果在某个操作系统上缺少某项功能,应返回 `ErrCapability` 并通过 `internal/capabilities` 注册可用性。 + +--- + +## 总结 + +这些图表概述了**代码的位置**、**数据的流动方式**以及**各层级的职责归属**。 +在探索后续详细页面时,请随时参考这些图表——它们是你理解 Wails v3 源码树的地图。 \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/contributing/asset-server.mdx b/docs/src/content/docs/zh-cn/contributing/asset-server.mdx new file mode 100644 index 00000000000..8c7761b07af --- /dev/null +++ b/docs/src/content/docs/zh-cn/contributing/asset-server.mdx @@ -0,0 +1,195 @@ +--- +title: 资源服务器 +description: Wails v3 如何在开发和生产环境中提供和嵌入你的 Web 资源 +sidebar: + order: 4 +--- + +## 概述 + +每个 Wails 应用程序都包含一个**单一的原生可执行文件**,它结合了: + +1. 你的 *Go* 后端 +2. 一个 *Web* 前端(HTML + JS + CSS) + +**资源服务器(Asset Server)** 是实现这一功能的关键粘合剂。 +它有**两种运行模式**,通过 Go 构建标签在编译时进行选择: + +| 模式 | 标签 | 用途 | +|------|-----|---------| +| **开发** | `//go:build dev` | 支持热重载的快速迭代 | +| **生产** | `//go:build !dev` | 零依赖,嵌入资源 | + +实现代码位于 +`v3/internal/assetserver/`,文件结构清晰: + +``` +assetserver_dev.go # ⬅️ 运行时开发服务器 +assetserver_production.go # ⬅️ 嵌入服务器 +assetserver_darwin.go # 特定操作系统的辅助函数(linux/windows 相同) +asset_fileserver.go # 共享的静态文件逻辑 +content_type_sniffer.go # MIME 类型检测 +ringqueue.go # 用于 MIME 缓存的小型 LRU +``` + +--- + +## 开发模式 + +### 生命周期 + +1. `wails3 dev` 启动并**启动你的前端开发服务器** + (Vite, SvelteKit, React-SWC …),通过运行 `build/Taskfile.yml` 中定义的任务(通常是 `npm run dev`)。 +2. Wails 启动监听 `localhost:<随机端口>` 的**开发资源服务器**, + 并指示 Go 运行时将 `http://:` 加载为窗口 URL。 +3. 传入的请求由 `assetserver_dev.go` 处理: + + ``` + ┌─────────┐ /runtime/... ┌─────────────┐ + │ Browser │ ── native bridge ───▶ │ Runtime │ + ├─────────┤ └─────────────┘ + │ JS │ / (index.html) proxy / -> Vite + └─────────┘ ◀─────────────┐ + AssetServer │ + ▼ + ┌────────────┐ + │ Vite Dev │ + │ Server │ + └────────────┘ + ``` + +4. 静态文件(`/assets/logo.svg`)通过 + `asset_fileserver.go` **直接从磁盘提供**(为了速度),而任何未知路径都**代理**到 + 框架开发服务器,为你提供*即时*热模块替换。 + +### 功能 + +* **实时重载(Live Reload)** – Vite/Snowpack/… 注入 HMR WebSocket;Wails 只需 + 代理它。 +* **Source Map 支持** – 因为资源未打包,你的浏览器开发者工具 + 可以将错误映射回原始源代码。 +* **无需重新编译 Go** – 只有前端重新构建;Go 代码保持运行,直到 + 你更改 `.go` 文件。 + +### 切换框架 + +开发代理是**与框架无关的**: + +* 根目录下的 `Taskfile.yml` 任务文件注入两个环境变量: + `APP_NAME` 和 `WAILS_VITE_PORT`。 +* 每个模板的 Taskfiles 在运行其开发服务器之前发出这些变量。 +* `assetserver_dev.go` 仅代理到该目标。 + +添加新模板 → 定义其开发任务 → 资源服务器即可正常工作。 + +--- + +## 生产模式 + +当你运行 `wails3 build` 时,管道流程: + +1. 运行前端**生产构建**(`npm run build`),生成 + `/frontend/dist/**`。 +2. 在编译时将那个文件夹**嵌入**到 `go:embed` 文件系统中(参见 + 生成的文件 `bundled_assetserver.go`)。 +3. 使用 `-tags production`(隐式)编译 Go 二进制文件。 + +### 请求处理 + +```go +func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // 1. 尝试嵌入的静态资源(精确路径) + // 2. 回退到 index.html 以支持 SPA 路由 + // 3. 如果扩展名未知,嗅探 content-type + // 4. 设置强缓存头 +} +``` + +* **MIME 检测** – 如果构建工具生成了无扩展名的文件(例如 + `/assets/manifest`),`content_type_sniffer.go` 会检查前 512 字节并将 + 结果缓存到一个小型无锁 LRU 中。 +* **环形队列缓存** – 频繁访问的资源(logo, CSS)在应用生命周期内 + 保留在内存中,消除了对磁盘或嵌入文件系统查找的需求。 +* **安全头** – 禁止 `file://` 导航,启用 `nosniff`。 + +因为所有内容都已嵌入,发布的二进制文件**没有外部 +依赖**(即使在 Windows 上也是如此)。 + +--- + +## 桥接开发 ↔ 生产 + +两种模式都暴露**相同的公共接口**: + +```go +type AssetServer interface { + URL() string // dev: http://localhost:34115, prod: wails://app + Open() error // 开始监听 + Close() // 优雅关闭 +} +``` + +`pkg/application` 很高兴地使用编译进来的任何一种实现,这意味着 +**你的应用程序代码在 `dev` 和 `build` 之间不会改变**。 + +--- + +## 前端框架如何集成 + +### 模板 + +每个官方模板(React, Vue, Svelte, Solid...)包含: + +* `build/Taskfile.yml` +* `frontend/vite.config.ts`(或等效文件) + +它们导出几个任务,包括: + +| 任务 | 用途 | +|------|---------| +| `dev:frontend` | 在**随机空闲端口**上启动框架开发服务器,并将其打印到 stdout(`PORT=5173`)。 | +| `build:frontend` | 将静态资源生成到 `dist/` + 用于缓存破坏的清单。 | + +`internal/commands/dev.go` 使用硬编码的 `localhost` 作为 `host` 和发出的 `VITE_PORT` 环境变量作为 `port` 来设置 `FRONTEND_DEVSERVER_URL` 环境变量,并启动**开发资源服务器**。 + +框架与 Go 完全解耦: + +* 构建时无需导入 Wails JS SDK – 运行时在窗口创建时注入它。 +* 任何具有 HTTP 开发服务器的框架都可以接入。 + +--- + +## 扩展 / 自定义 + +需要自定义头、身份验证或 gzip? + +1. 实现 `type Middleware func(http.Handler) http.Handler` +2. 通过 `internal/assetserver/options.go` 注册 +3. 对于生产环境,记得在 `assetserver_production.go` 中添加相同的中件间。 + +--- + +## 关键源文件 + +| 文件 | 角色 | +|------|------| +| `assetserver_dev.go` | 反向代理 + 磁盘文件服务器 | +| `assetserver_production.go` | 嵌入文件系统处理器 | +| `options.go` | 从 `pkg/options/assetserver` 解析的配置结构体 | +| `build_dev.go` / `build_production.go` | 选择正确实现的构建标签包装器 | +| `bundled_assetserver.go` | 生成的嵌入数据(仅存在于生产构建中) | + +--- + +## 注意事项与调试 + +* **生产环境白屏** – 通常是 SPA 路由问题:确保开发中启用了 `History API Fallback`,且生产环境中 `index.html` 回退正常工作。 +* **开发环境 404** – `FRONTEND_DEV_PORT` 不匹配;使用 + `WAILSDEV_VERBOSE=1` 运行以打印每个代理请求。 +* **大资源** – 它们被嵌入;考虑使用 + [`assetserver.WithExternalDir("/path")`](https://pkg.go.dev) 从磁盘加载。 + +--- + +你现在了解了 Wails **资源服务器**如何在**开发**和**生产**环境中将你的 Web 代码提供给原生窗口。 +掌握这一层,你就可以自信地调试加载问题、添加中间件,甚至替换整个前端工具链。 \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/contributing/binding-system.mdx b/docs/src/content/docs/zh-cn/contributing/binding-system.mdx new file mode 100644 index 00000000000..4f0ca724b95 --- /dev/null +++ b/docs/src/content/docs/zh-cn/contributing/binding-system.mdx @@ -0,0 +1,234 @@ +--- +title: 绑定系统 +description: Wails v3 如何以零样板代码实现 Go 和 JavaScript 之间的相互调用 +sidebar: + order: 5 +--- + +> “绑定(Bindings)”是**类型安全的契约**,让你可以编写: + +```go +msg, err := chatService.Send("Hello") +``` + +在 Go 中 *以及* + +```ts +const msg = await window.backend.ChatService.Send("Hello") +``` + +在 TypeScript 中,**无需手动编写胶水代码**。 +本文档将拆解这种魔法是如何实现的,从构建时的**静态分析**,到**代码生成**,再到在 WebView 中传输字节的**运行时桥接**。 + +--- + +## 1. 30 秒概览 + +| 阶段 | 组件 | 输出 | +|-------|-----------|--------| +| **分析** | `internal/generator/analyse.go` | 导出 Go 结构体、方法、参数、返回类型的内存中 AST | +| **生成** | `internal/generator/render/*.tmpl` | • `pkg/application/bindings.go` (Go)
• `frontend/src/wailsjs/**.ts` (TS 定义)
• `runtime/desktop/@wailsio/runtime/internal/bindings.json` | +| **运行时** | `pkg/application/messageprocessor_call.go` + JS 运行时 (`invoke.ts`) | 通过 WebView 原生桥接传输的 JSON 消息 | + +该流程由 `wails3` CLI 编排: + +``` +wails3 generate ─┬─> generator.Collect() // 解析 Go 包 + ├─> generator.Analyse() // 构建语义模型 + └─> generator.Render() // 写入文件 + `go fmt` +``` + +--- + +## 2. 静态分析 + +### 入口点 + +``` +internal/generator/analyse.go +``` + +`Analyse(cfg generator.Config)`: + +1. 使用 `go/packages` 递归加载提供的 Go 包。 +2. 遍历每个 AST 文件的 *类型* 和 *值* 规范。 +3. 过滤掉 `internal/` 包之外的**导出**符号(大写字母开头)。 +4. 记录: + * 接收者类型 (`struct`, `interface`) + * 方法名称 + * 参数列表(名称、类型、指针、可变参数) + * 返回元组(值 + 错误存在性) +5. 将类型规范化为**可序列化集** + (`int`, `float64`, `string`, `[]byte`, 切片、映射、结构体、指针)。 + +不支持的类型会产生**编译时错误**,以便尽早发现错误。 + +### 模型 + +```go +type Method struct { + ID uint32 // 用于运行时查找的稳定哈希 + Name string + Params []Param + Results []Result + Receiver *Struct // 包级函数为 nil +} +``` + +`.()` 的确定性 **FNV-1a** 哈希(`internal/hash/fnv.go`)成为运行时使用的*方法 ID*。 + +--- + +## 3. 代码生成 + +### 模板 + +`internal/generator/render/` 包含 text/template 文件: + +| 模板 | 目标 | +|----------|--------| +| `go_bindings.tmpl` | `pkg/application/bindings.go` | +| `ts_bindings.tmpl` | `frontend/wailsjs/go/models.d.ts` | +| `ts_index.tmpl` | `frontend/wailsjs/index.ts` | + +在此处添加或调整模板以自定义生成。 + +### Go 输出 + +`bindings.go` 注册一个查找表: + +```go +var bindings = []application.BoundMethod{ + {ID: 0x7A1201D3, Name: "ChatService.Send", Call: chatServiceSend}, +} + +func chatServiceSend(ctx context.Context, in []byte) ([]byte, error) { + var req struct{ Msg string } + if err := json.Unmarshal(in, &req); err != nil { return nil, err } + res, err := chatService.Send(req.Msg) + return json.Marshal(res), err +} +``` + +关键点: + +* 运行时**零反射** → 高性能。 +* Marshal/Unmarshal 是**每个方法**生成的结构体包装器。 + +### TypeScript 输出 + +```ts +export namespace backend { + export namespace ChatService { + function Send(msg: string): Promise; + } +} +``` + +* 作为 **ES 模块** 发出,以便任何打包工具都可以进行 tree-shake。 +* 方法 ID 嵌入在 JS 运行时自动生成的 `bindings.json` 中。 + +--- + +## 4. 运行时调用协议 + +### JavaScript 端 + +```ts +import { System } from "@wailsio/runtime"; + +await System.invoke(0x7a1201d3 /* ChatService.Send */, ["Hello"]); +``` + +实现:`runtime/desktop/@wailsio/runtime/invoke.ts` + +1. 将 `{t:"c", id:, p:[...args]}` 打包为 JSON。 +2. 调用 `window.external.invoke(payload)` (WebView2) 或等效方法。 +3. 返回一个 `Promise`,根据回复解析/拒绝。 + +### Go 端 + +1. `messageprocessor_call.go` 接收 JSON。 +2. 在 `bindings` 切片中查找 `methodID`。 +3. 执行生成的存根 (`chatServiceSend`)。 +4. 将 `{result, error}` 序列化回 JS。 + +### 错误映射 + +| Go | JavaScript | +|----|------------| +| `error == nil` | `Promise` 解析结果 | +| `errors.New(...)` | `Promise` 拒绝,包含 `{message, stack, code}` | + +映射代码位于 `runtime/desktop/@wailsio/runtime/errors.ts`。 + +--- + +## 5. 从 Go 调用 JavaScript + +*浏览器 → Go* 已在上面覆盖。 +*Go → 浏览器* 使用**事件**或 **Eval**: + +```go +window.Eval(`alert("Hi")`) +app.Publish("chat:new-message", msg) +``` + +绑定生成是单向的(Go 方法)。 +对于 JS 暴露的函数,请在 JS 中使用 `runtime.EventsOn`,在 Go 中使用 `application.Publish`。 + +--- + +## 6. 扩展与故障排除 + +### 添加自定义序列化器 + +* 实现 `generator.TypeConverter` 接口。 +* 在 `generator.Config.Converters` 中注册。 +* 如有需要,更新 JS 运行时反序列化。 + +### 不支持的类型错误 + +``` +error: field "Client" uses unsupported type: chan struct{} +``` + +→ 将通道包装在具有暴露 API 的结构体中,或重新设计。 + +### 版本偏差 + +绑定在**每次** `wails3 dev` / `wails3 build` 时都会重新生成。 +如果 IDE 智能提示显示过时的存根,请删除 `frontend/wailsjs` 并重新构建。 + +### 性能提示 + +* 对于小型结构体,优先使用**值**接收者以减少分配。 +* 避免通过桥接传输大型字节切片;改用 `application.FileServer`。 +* 将多个快速调用批处理到一个方法中,以最小化桥接延迟。 + +--- + +## 7. 关键文件映射 + +| 关注点 | 文件 | +|---------|------| +| 静态分析入口 | `internal/generator/analyse.go` | +| 渲染管道 | `internal/generator/generate.go` | +| 模板资源 | `internal/generator/render/*.tmpl` | +| Go 绑定表 | `pkg/application/bindings.go` (生成) | +| 调用处理器 | `pkg/application/messageprocessor_call.go` | +| JS 运行时 | `runtime/desktop/@wailsio/runtime/invoke.ts` | +| 错误映射 | `runtime/desktop/@wailsio/runtime/errors.ts` | + +在追踪桥接错误时,请保留此速查表。 + +--- + +## 8. 回顾 + +1. **生成器** 扫描你的 Go 代码 → 语义模型。 +2. **模板** 发出 **Go 存根** + **TypeScript 定义**。 +3. **消息处理器** 在运行时执行存根。 +4. **JS 运行时** 将所有内容包装为惯用的 promises。 + +所有这一切无需反射,无需 IPC 服务器,也无需你编写一行样板代码。这就是 Wails v3 绑定系统。去绑定吧! \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/contributing/build-packaging.mdx b/docs/src/content/docs/zh-cn/contributing/build-packaging.mdx new file mode 100644 index 00000000000..3e409083b9f --- /dev/null +++ b/docs/src/content/docs/zh-cn/contributing/build-packaging.mdx @@ -0,0 +1,197 @@ +--- +title: 构建与打包流水线 +description: 运行 `wails3 build` 时幕后发生了什么,如何生成交叉平台二进制文件,以及如何为每个操作系统生成安装程序。 +sidebar: + order: 6 +--- + +`wails3 build` 是一个**单命令**,它驱动一个_多阶段_流水线: + +1. **前端生产构建** (Vite / React / …) +2. **资源嵌入**到 Go 源码中 +3. **原生编译**目标操作系统/架构 +4. **后处理** (图标注入、版本信息、代码签名) +5. **打包**成分发制品 (AppImage, DMG, MSI, …) + +本文档将跟随每个阶段,展示代码所在位置,并解释如何自定义或调试它。 + +--- + +## 1. 入口点:`internal/commands/build-assets.go` + +``` +wails3 build # cmd/wails3/main.go +└─ internal/commands.Build() # build-assets.go +``` + +高层任务被委托给 **Taskfile** 目标,以便相同的逻辑在 CI 或本地环境中运行。 + +| 阶段 | Taskfile 目标 | Go 实现 | +|-------|---------|----| +| 前端构建 | `frontend:build` | `internal/commands/task.go` | +| 嵌入资源 | `embed:assets` | 生成的 `bundled_assetserver.go` | +| Go 编译 | `build:go` | `tool_buildinfo.go`, `tool_package.go` | +| 打包 | `package:*` | `internal/packager`, `internal/commands/*` | + +--- + +## 2. 前端生产构建 + +1. CLI 切换到 `frontend/` 目录并执行项目 `Taskfile.yml` 中找到的 `build` 任务(默认为 `npm run build`)。 +2. 输出写入 `frontend/dist/`。 +3. 生成**内容哈希**清单 (`manifest.json`),以便开箱即用地实现缓存破坏(cache-busting)。 + +如果任务失败,流水线将提前中止,并返回你的构建工具的退出代码。 + +--- + +## 3. 嵌入资源 + +实现在 `internal/assetserver/build_production.go` 中: + +* 遍历 `frontend/dist` 并生成一个 `go:embed` 文件 + `bundled_assetserver.go`(被 git 忽略)。 +* 添加 `production` 构建标签。 + +结果:最终的二进制文件包含每个 HTML/JS/CSS 字节,因此可执行文件是自包含的。 + +--- + +## 4. 原生编译 + +### 构建标志 + +| 标志 | 用途 | +|------|--| +| `-tags production` | 选择生产环境资源服务器和运行时存根 | +| `-ldflags "-s -w"` | 剥离符号表和 DWARF(减小二进制文件大小) | +| `-X internal/buildinfo.BuildTime=$(date)` | 嵌入可复现的元数据 | + +`internal/commands/tool_buildinfo.go` 收集版本、git 提交和构建时间,然后使用 `go build -ldflags` 注入它们。 + +### 交叉编译矩阵 + +| 操作系统 | 架构 | 构建标签 | CGO | 备注 | +|----|--|-----------|-----|----| +| Windows | amd64 / arm64 | `windows` | 为 WebView2 启用 cgo | 通过 `internal/commands/syso.go` 生成 `.syso` | +| macOS | amd64 / arm64 | `darwin` | 启用 cgo (Objective-C) | 提供代码签名和公证任务 | +| Linux | amd64 / arm64 | `linux` | 纯 Go (webkit 选项) | CGO 构建需要 GTK/WebKitGTK 头文件 | + +`wails3 build -platform darwin/arm64` 覆盖 GOOS/GOARCH。 +如果主机需要 CGO 但无法编译目标平台(例如从 Linux 构建 Windows),CLI 将回退到 **Docker** 镜像 (`ghcr.io/wailsapp/cross-compiler`)。 + +--- + +## 5. 后处理 + +### 图标与资源 + +* **Windows** – `syso.go` 将你的 PNG/ICO 合并到一个 `.syso` 文件中,`go build` 会自动链接它。 还写入 `manifest.xml` 以启用高 DPI 支持。 +* **macOS** – `icons.go` 将 `icon.png` 转换为 `.icns`,并注入到 + `MyApp.app/Contents/Resources` 中。 +* **Linux** – `.desktop` 文件由每个打包器后端生成在 `/usr/share/applications` 中。 + +### 代码签名(可选) + +* macOS: `codesign` + `xcrun altool --notarize-app` +* Windows: `signtool.exe` +* Linux: 不常见(仓库 GPG 由外部处理) + +Task 目标:`sign:mac`, `sign:windows`。 + +--- + +## 6. 打包后端 + +### Linux + +| 制品 | 代码路径 | 工具 | +|------|---------|---| +| **AppImage** (默认) | `internal/commands/appimage.go` | `linuxdeploy` + `linuxdeploy-plugin-gtk` | +| **deb / rpm / pacman** | `internal/packager` | `fpm` (通过 Go 调用) | + +标志: + +``` +wails3 build -package deb # 生成 myapp_1.0.0_amd64.deb +wails3 build -package rpm +``` + +### macOS + +* **DMG** – `internal/commands/packager.go` 调用 `appdmg` 生成一个拖放安装程序。 +* **ZIP** – 如果缺少 `appdmg` 时的回退方案。 +* 自动设置 CFBundle 标识符和版本 plist。 + +### Windows + +* **MSI** – `internal/commands/packager.go` 包装 **WiX** candle 和 light 工具。 + Heat 自动从构建的 `.exe` 生成组件树。 + +额外资源: + +* `internal/commands/windows_resources/` 包含模板化的 **.wxs** 片段。 +* 版本信息通过 `rsrc` 工具注入。 + +--- + +## 7. 构建制品布局 + +构建成功后,CLI 会打印: + +``` +build/bin/ +├── myapp-linux-amd64 +└── myapp-linux-amd64.AppImage + +build/package/ +└── myapp_1.0.0_amd64.deb +``` + +具体文件取决于 `-platform` 和 `-package` 标志。 + +--- + +## 8. 自定义流水线 + +| 需求 | 方法 | +|------|------| +| 在构建前运行 linter | 在 **Taskfile.yml** 中添加 `lint` 任务,并使 `build` 依赖于它。 | +| 额外的链接器标志 | `wails3 build -ldflags "-H windowsgui"` | +| 跳过打包 | `wails3 build -skip-package` (保留原始二进制文件)。 | +| 使用自己的打包器 | 实现 `internal/packager/.go`,在 `packager.go` 中注册。 | + +所有 Taskfile 目标都使用由 CLI 导出的环境变量,因此你可以在自定义任务中引用诸如 `$WAILS_VERSION` 或 `$WAILS_PLATFORM` 之类的值。 + +--- + +## 9. 故障排除 + +| 症状 | 可能原因 | 解决方法 | +|---------|-------|----| +| **`ld: framework not found WebKit` (mac)** | 缺少 Xcode CLI 工具 | `xcode-select --install` | +| **生产构建中窗口空白** | 前端构建失败或 SPA 路由问题 | 检查 `frontend/dist/index.html` 是否存在,并设置了 `History API Fallback`。 | +| **`wixl` not found** (Linux MSI 交叉构建) | Docker 镜像中未安装 WiX 工具集 | 使用 `--docker` 构建或手动安装 WiX。 | +| **重复符号 `_WinMain`** | 混合使用了 `windowsgui` 标志和 syso | 移除自定义 `-ldflags` 或让 Wails 管理资源。 | + +详细模式:`wails3 build -verbose` 会转储执行的每个命令。 + +--- + +## 10. 关键源码映射 + +| 关注点 | 文件 | +|---------|----| +| Task 运行器胶水代码 | `internal/commands/task_wrapper.go` | +| 构建调度器 | `internal/commands/build-assets.go` | +| AppImage 构建器 | `internal/commands/appimage.go` | +| 通用打包器接口 | `internal/packager/packager.go` | +| Windows 资源生成器 | `internal/commands/syso.go` | +| 构建信息注入器 | `internal/commands/tool_buildinfo.go` | +| 版本常量 | `internal/version/version.go` | + +在追踪构建失败时,请保留此表格以备查阅。 + +--- + +你现在拥有了从**源代码**到**安装程序**的全貌。凭借这些知识,你可以调整流水线、添加新的打包目标,或自信地调试交叉编译问题。祝发布顺利! \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/contributing/codebase-layout.mdx b/docs/src/content/docs/zh-cn/contributing/codebase-layout.mdx new file mode 100644 index 00000000000..93756899bd2 --- /dev/null +++ b/docs/src/content/docs/zh-cn/contributing/codebase-layout.mdx @@ -0,0 +1,212 @@ +--- +title: 代码库布局 +description: Wails v3 仓库的组织结构以及各部分如何协同工作 +sidebar: + order: 2 +--- + +Wails v3 位于一个 **monorepo**(单体仓库)中,其中包含框架运行时、CLI、 +示例、文档和构建工具链。 +本页将介绍对深入探究内部实现至关重要的*目录结构*。 + +## 顶层概览 + +``` +wails/ +├── v3/ # ⬅️ 所有与 Wails v3 相关的内容都位于此处 +├── v2/ # 遗留的 v2 实现(v3 开发可忽略) +├── docs/ # 由 Astro 驱动的 v3 文档站点(即本页!) +├── website/ # 由 Docusaurus v2 驱动的站点和营销页面(主站点) +├── scripts/ # 杂项辅助脚本(例如赞助商图片生成器) +├── mkdocs-website/ # 已弃用的 v3 文档原型 +└── *.md # 项目范围的元文件(CHANGELOG、LICENSE、…) +``` + +接下来,我们将深入查看 **`v3/`** 目录树。 + +## `v3/` 根目录 + +``` +v3/ +├── cmd/ # 可编译的命令(目前仅有 wails3 CLI) +├── examples/ # 用于测试各项功能的动手示例应用 +├── internal/ # 框架实现(非公开 API) +├── pkg/ # 公开的 Go 包 — API 表面 +├── tasks/ # 基于 Taskfile 的发布工具 +├── templates/ # RFC 风格的提案(WEP)+ 通用资源 +├── go.mod +└── go.sum +``` + +### 心智模型 + +1. **`pkg/`** 暴露了 *应用程序开发者需要导入的内容* +2. **`internal/`** 包含了 *魔法是如何实现的* +3. **`cmd/wails3`** 驱动 *项目生命周期和构建* +4. **`examples/`** 同时作为 *活体测试* 和 *参考代码* + +其他所有内容都支持这三大支柱。 + +--- + +## `cmd/` – 命令 + +| 路径 | 说明 | +|------|-------| +| `v3/cmd/wails3` | **CLI 入口点**。一个小型的 `main.go` 将所有逻辑委托给 `internal/commands` 中的包。 | +| `internal/commands/*` | 子命令(init、dev、build、doctor、…)。每个子命令位于独立文件中,便于查找。 | +| `internal/commands/task_wrapper.go` | 在 CLI 标志和 Taskfile 构建管道之间进行桥接。 | + +CLI 负责: + +* **项目脚手架**(`init`、模板生成) +* **开发服务器编排**(`dev`、热重载) +* **生产构建和打包**(`build`、`package`、平台包装器) +* **诊断**(`doctor`) + +--- + +## `internal/` – 引擎室 + +``` +internal/ +├── assetserver/ # 提供和嵌入 Web 资源 +├── buildinfo/ # 可重现的构建元数据 +├── commands/ # CLI 机制(见上文) +├── runtime/ # 桌面运行时(按平台划分) +├── generator/ # 静态分析和绑定生成器 +├── templates/ # 项目模板(前端技术栈) +├── packager/ # Linux AppImage/deb/rpm、Windows MSI、macOS DMG +├── capabilities/ # 主机操作系统能力探测 +├── dbus/ # Linux 系统托盘集成 +├── service/ # IPC 微服务框架 +└── ... # [其他辅助子包] +``` + +### 关键子包 + +| 包 | 职责 | 连接位置 | +|---------|----------------|-------------------| +| `runtime` | 窗口/事件循环、剪贴板、对话框、系统托盘。每个 OS 一个文件,使用构建标签(`*_darwin.go`、`*_linux.go`、…)。 | 由 `pkg/application` 和消息处理器调用。 | +| `assetserver` | 双模式文件服务器:
• 开发模式:从磁盘提供文件并代理 Vite
• 生产模式:通过 `go:embed` 嵌入资源 | 在启动期间由 `pkg/application` 初始化。 | +| `generator` | 解析 Go 源代码以构建 **绑定元数据**,随后生成 TypeScript 存根文件和 Go 编组/解组代码。 | 由 `wails3 init` / `wails3 generate` 触发。 | +| `packager` | 将平台特定的打包 CLI(例如 `electron-builder` 的等效工具)包装为 Go 代码,以实现跨平台自动化。 | 由 `wails3 package` 调用。 | + +辅助工具(例如 `s/`、`hash/`、`flags/`)保持内部关注点解耦。 + +--- + +## `pkg/` – 公开 API + +``` +pkg/ +├── application/ # 核心 API:窗口、菜单、对话框、事件、… +├── runtime/ # JS 端辅助工具(桥接、事件、屏幕、…) +├── options/ # 强类型配置结构体 +├── menu/ # 声明式菜单 DSL +└── ... # 平台辅助工具(mac/、windows/、assetserver/、…) +``` + +`pkg/application` 启动 Wails 程序: + +```go +func main() { + app := application.New(application.Options{ + Name: "MyApp", + Assets: application.NewAssetsFS(assetsFS), + }) + window := app.Window.New(&application.WebviewWindowOptions{ + Title: "Hello", + Width: 1024, + Height: 768, + }) + app.Run() +} +``` + +其底层机制: + +1. 启动 `internal.runtime.*` +2. 设置 `assetserver` +3. 注册由 `internal.generator` 生成的绑定 +4. 进入 OS 主线程 + +--- + +## `examples/` – 活体规范 + +每个子文件夹都是一个 **独立的应用程序**,用于演示一项功能。 +你将在真实代码中看到以下模式: + +* 绑定服务(`examples/binding/`) +* 多窗口(`examples/window/`) +* 系统托盘(`examples/systray-*`) +* 打包(`examples/file-association/`) + +如有疑虑,请从此处开始并深入探究实现细节。 + +--- + +## `templates/` – 脚手架蓝图 + +`internal/templates` 提供 **基础模板**(Go 布局)和 **前端皮肤** +(React、Svelte、Vue、…)。 +在 `wails3 init -t react` 时,CLI 会: + +1. 复制 `_common` Go 文件 +2. 合并所需的前端包 +3. 运行 `npm install` + `task deps` + +编辑模板 **不会** 影响现有应用,仅影响未来的 `init` 操作。 + +--- + +## `tasks/` – 发布自动化 + +Taskfile 封装了复杂的交叉编译、版本递增和变更日志生成。它们被 `internal/commands/task.go` 以编程方式调用, +因此相同的逻辑同时驱动 **CLI** 和 **CI**。 + +--- + +## 各部分如何交互 + +```d2 +direction: down +CLI: "wails3 CLI" +Generator: "internal/generator" +AssetDev: "assetserver (dev)" +Packager: "internal/packager" +AppRuntime: { + label: "App runtime" + ApplicationPkg: "pkg.application" + InternalRuntime: "internal.runtime" + OSAPIs: "OS APIs" +} +CLI -> Generator: "build / generate" +CLI -> AssetDev: "dev" +CLI -> Packager: "package" +Generator -> ApplicationPkg: "bindings" +ApplicationPkg -> InternalRuntime +InternalRuntime -> OSAPIs +ApplicationPkg -> AssetDev +``` + +*CLI → generator → runtime* 构成了从 **源代码** 到 **运行中的桌面应用** 的核心路径。 + +--- + +## 定位提示 + +| 需要了解… | 查看… | +|---------------------|----------| +| 平台适配层 | `internal/runtime/*_DARWIN.go`、`*_windows.go`、… | +| 桥接协议 | `pkg/application/messageprocessor_*.go` | +| 资源工作流 | `internal/assetserver`、`v3/templates/base/assets` | +| 打包流程 | `internal/commands/appimage.go`、`internal/packager` | +| 模板引擎 | `internal/templates/templates.go` | +| 静态分析 | `internal/generator/*` | + +--- + +你现在已经拥有了仓库的 **心智地图**。 +结合 `ripgrep`、IDE 的“转到文件/符号”功能以及示例应用,深入探索任何功能。祝你编码愉快! \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/contributing/extending-wails.mdx b/docs/src/content/docs/zh-cn/contributing/extending-wails.mdx new file mode 100644 index 00000000000..f86553935d2 --- /dev/null +++ b/docs/src/content/docs/zh-cn/contributing/extending-wails.mdx @@ -0,0 +1,246 @@ +--- +title: 扩展 Wails +description: 向 Wails v3 添加新功能和平台的实用指南 +sidebar: + order: 8 +--- + +> Wails 的设计初衷就是**可 hack 的**。 +> 每个主要子系统都存在于你可以阅读、修改和发布的 Go 代码中。 +> 本页展示了当你: + +* 添加**服务**(文件服务器、KV 存储、自定义 IPC…) +* 创建**新的 CLI 命令**(`wails3 `) +* 扩展**运行时**(窗口 API、对话框、事件) +* 引入**平台功能**(Wayland、Apple Vision OS…) +* 保持**跨平台兼容性**而不淹没在 `//go:build` 标签中 + +时,从哪里开始以及如何保持跨平台。 + +--- + +## 1. 添加服务 + +服务是暴露给应用程序的后台 Go 组件,通过 `application.Context` 访问。 + +``` +internal/service/ +├── template/ # 新服务的样板代码 +│ ├── template.go +│ └── README.md +└── service.go # 注册 + 生命周期接口 +``` + +### 1.1 定义服务 + +```go +package chat + +type Service struct { + messages []string +} + +func New() *Service { return &Service{} } + +func (s *Service) Send(msg string) string { + s.messages = append(s.messages, msg) + return "ok" +} +``` + +### 1.2 实现 `service.Service` + +```go +func (s *Service) Init(ctx *application.Context) error { return nil } +func (s *Service) Shutdown() error { return nil } +``` + +### 1.3 注册生成器 + +*添加到* `internal/generator/collect/services.go` + +```go +services.Register("chat", chat.New) +``` + +> 现在 `wails3 generate` 会生成绑定,使 JS 可以调用 +> `window.backend.chat.Send("hi")`。 + +### 1.4 发布示例 + +复制 `v3/examples/services/` 并进行调整。 + +--- + +## 2. 编写新的 CLI 命令 + +CLI 逻辑位于 `internal/commands/` 下。 +每个命令都是**一个文件**,在 `init()` 中挂载自身。 + +### 2.1 创建文件 + +`v3/internal/commands/hello.go` + +```go +package commands + +import ( + "github.com/spf13/cobra" +) + +func init() { + Add(&cobra.Command{ + Use: "hello", + Short: "Prints Hello World", + RunE: func(cmd *cobra.Command, args []string) error { + cmd.Println("Hello Wails!") + return nil + }, + }) +} +``` + +`Add()` 在 `cmd/wails3/main.go` 中向根命令注册。 + +### 2.2 重新编译 CLI + +``` +go install ./v3/cmd/wails3 +wails3 hello +``` + +如果你的命令需要 **Taskfile** 集成,请重用 +`internal/commands/task_wrapper.go` 中的辅助函数。 + +--- + +## 3. 修改运行时 + +常见原因: + +* 新的窗口功能(`SetOpacity`、`Shake`…) +* 额外的对话框(`ColorPicker`) +* 系统级 API(屏幕亮度) + +### 3.1 公共 API + +添加到 `pkg/application/window.go`: + +```go +func (w *WebviewWindow) SetOpacity(o float32) { + w.ctx.Call("window:setOpacity", o) +} +``` + +### 3.2 消息处理器 + +创建 `messageprocessor_window_opacity.go`: + +```go +const MsgSetOpacity = "window:setOpacity" + +func init() { register(MsgSetOpacity, handleSetOpacity) } + +func handleSetOpacity(ctx *Context, params json.RawMessage) ([]byte, error) { + var req struct { + ID uint64 `json:"id"` + Opacity float32 `json:"o"` + } + json.Unmarshal(params, &req) + return nil, runtime.SetOpacity(req.ID, req.Opacity) +} +``` + +### 3.3 平台实现 + +``` +internal/runtime/ + webview_window_darwin.go + webview_window_linux.go + webview_window_windows.go +``` + +将 `SetOpacity()` 添加到每个文件,并通过构建标签进行保护。 +如果某个平台无法支持,请返回 `ErrCapability`。 + +### 3.4 功能标志 + +通过 `internal/capabilities` 暴露。 + +```go +const CapOpacity = "window:opacity" +``` + +运行时文件 `*_darwin.go` 等应在成功初始化时 `registerCapability(CapOpacity)`。 + +应用程序可以查询: + +```go +if application.HasCapability(application.CapOpacity) { ... } +``` + +--- + +## 4. 添加新的平台功能 + +示例:**Wayland** 剪贴板(在 Linux 上)。 + +1. 分叉 `internal/runtime/clipboard_linux.go`。 +2. 拆分文件: + * `clipboard_linux_x11.go` → `//go:build linux && !wayland` + * `clipboard_linux_wayland.go` → `//go:build linux && wayland` +3. 在 `internal/commands/dev.go` 中添加 CLI 标志 `--tags wayland` + (`goEnv.BuildTags += ",wayland"`)。 +4. 在 **Asset Server** 和 README 中记录。 + +> 保持默认构建标签最小化;将可选标签保留给小众功能。 + +--- + +## 5. 跨平台兼容性检查清单 + +| ✅ 步骤 | 原因 | +|---------|-----| +| 在所有平台文件中提供**每个**公共方法(即使是存根) | 确保在所有 OS/架构上构建通过 | +| 将平台特定内容隐藏在**功能**之后 | 让应用程序优雅降级 | +| 优先使用**纯 Go**,仅在需要时使用 CGO | 简化交叉编译 | +| 使用 `task matrix:test` 进行测试 | 在 Docker 中在 linux/mac/windows 上运行 `go test ./...` | +| 在 `docs/getting-started/installation.mdx` 中记录新的构建标签 | 用户必须知道这些标志 | + +--- + +## 6. 调试构建与迭代速度 + +* `wails3 dev -tags debug` 添加额外的日志钩子(`logger_dev*.go`)。 +* 使用 `task reload` 在不重启整个应用程序的情况下重新编译运行时。 +* 竞态检测器:`wails3 dev -race`(参见 `pkg/application/RACE.md`)。 + +--- + +## 7. 上游贡献 + +1. 打开一个**问题**来讨论想法和设计。 +2. 按照上述技术进行实现。 +3. 添加: + * 单元测试(`*_test.go`) + * 示例(`v3/examples//`) + * 文档(此文件或 API 参考) +4. 确保 `go vet`、`golangci-lint` 和 CI 矩阵通过。 + +--- + +### 快速链接 + +| 区域 | 位置 | +|------|----------| +| 服务框架 | `internal/service/` | +| CLI 核心 | `internal/commands/` | +| 运行时(按 OS) | `internal/runtime/` | +| 功能辅助函数 | `internal/capabilities/` | +| Taskfile DSL | `tasks/Taskfile.yml` | +| 开发矩阵测试 | `tasks/events/generate.go` | + +--- + +你现在拥有了让 Wails 按你意愿工作的**路线图**——添加服务、注入 CLI 魔法、黑客式修改运行时,或引入全新的 OS 功能。 +祝你扩展愉快! \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/contributing/getting-started.mdx b/docs/src/content/docs/zh-cn/contributing/getting-started.mdx new file mode 100644 index 00000000000..260b834564e --- /dev/null +++ b/docs/src/content/docs/zh-cn/contributing/getting-started.mdx @@ -0,0 +1,367 @@ +--- +title: 入门指南 +description: 如何开始为 Wails v3 做出贡献 +--- + +import { Steps, Tabs, TabItem } from '@astrojs/starlight/components'; + +## 欢迎,贡献者! + +感谢您对为 Wails 做出贡献的兴趣!本指南将帮助您完成首次贡献。 + +## 前置条件 + +在开始之前,请确保您已具备: + +- **Go 1.25+**([下载](https://go.dev/dl/)) +- **Node.js 20+** 和 **npm**([下载](https://nodejs.org/)) +- 已配置 GitHub 账户的 **Git** +- 对 Go 和 JavaScript/TypeScript 的基本熟悉 + +### 平台特定要求 + +**macOS:** +- Xcode Command Line Tools:`xcode-select --install` + +**Windows:** +- 建议使用 MSYS2 或类似的类 Unix 环境 +- WebView2 运行时(通常在 Windows 11 上预装) + +**Linux:** +- `gcc`、`pkg-config`、`libgtk-3-dev`、`libwebkit2gtk-4.0-dev` +- 通过以下命令安装:`sudo apt install build-essential pkg-config libgtk-3-dev libwebkit2gtk-4.0-dev`(Debian/Ubuntu) + +## 贡献流程概览 + +典型的贡献工作流遵循以下步骤: + +1. **Fork 并克隆** - 创建 Wails 仓库的副本 +2. **环境配置** - 构建 Wails CLI 并验证您的环境 +3. **创建分支** - 为您的更改创建功能分支 +4. **开发** - 按照我们的编码标准进行更改 +5. **测试** - 运行测试以确保一切正常 +6. **提交** - 使用清晰、规范的提交信息提交代码 +7. **提交 PR** - 提交拉取请求以供审查 +8. **迭代** - 回应反馈并进行调整 +9. **合并** - 一旦获得批准,您的更改将成为 Wails 的一部分! + +## 分步指南 + +选择您的贡献类型: + + + + + + +1. **查找或报告 Bug** + + - 检查 [GitHub Issues](https://github.com/wailsapp/wails/issues) 中是否已报告该 Bug + - 如果未报告,请创建一个包含复现步骤的新 Issue + - 在开始工作前等待确认 + +2. **Fork 并克隆** + + 在 [github.com/wailsapp/wails/fork](https://github.com/wailsapp/wails/fork) Fork 仓库 + + 克隆您的 Fork: + ```bash + git clone https://github.com/YOUR_USERNAME/wails.git + cd wails + git remote add upstream https://github.com/wailsapp/wails.git + ``` + +3. **构建并验证** + + 构建 Wails 并验证您能否复现该 Bug: + ```bash + cd v3 + go build -o ../wails3 ./cmd/wails3 + + # 复现 Bug 以理解其成因 + ``` + +4. **创建 Bug 修复分支** + + 为您的修复创建分支: + ```bash + git checkout -b fix/issue-123-window-crash + ``` + +5. **修复 Bug** + + - 进行修复 Bug 所需的最小更改 + - 不要重构无关代码 + - 添加或更新测试以防止回归 + + ```bash + # 进行您的更改 + # 在 *_test.go 文件中添加测试 + ``` + +6. **测试您的修复** + + 运行测试以确保修复有效: + ```bash + go test ./... + + # 测试特定包 + go test ./pkg/application -v + + # 使用竞态检测器运行 + go test ./... -race + ``` + +7. **提交您的修复** + + 使用清晰的提交信息提交: + ```bash + git commit -m "fix: prevent window crash when closing during initialization + + Fixes #123" + ``` + +8. **提交拉取请求** + + 推送并创建 PR: + ```bash + git push origin fix/issue-123-window-crash + ``` + + 在您的 PR 描述中: + - 解释 Bug 及其根本原因 + - 描述您的修复方案 + - 引用 Issue:“Fixes #123” + - 包含修复前后的行为对比 + +9. **回应反馈** + + 处理审查意见并根据需要更新您的 PR。 + + + + + + + + +1. **讨论功能** + + - 打开 [GitHub Discussion](https://github.com/wailsapp/wails/discussions) 或 Issue + - 描述您想要添加的内容及原因 + - 在实施前等待维护者的反馈 + - 确保其符合 Wails 的目标 + +2. **Fork 并克隆** + + 在 [github.com/wailsapp/wails/fork](https://github.com/wailsapp/wails/fork) Fork 仓库 + + 克隆您的 Fork: + ```bash + git clone https://github.com/YOUR_USERNAME/wails.git + cd wails + git remote add upstream https://github.com/wailsapp/wails.git + ``` + +3. **配置开发环境** + + 构建 Wails 并验证您的环境: + ```bash + cd v3 + go build -o ../wails3 ./cmd/wails3 + + # 运行测试以确保一切正常 + go test ./... + ``` + +4. **创建功能分支** + + 创建一个描述性的分支: + ```bash + git checkout -b feat/window-transparency-support + ``` + +5. **实现功能** + + - 遵循我们的 [编码标准](/zh-cn/contributing/standards) + - 保持更改专注于该功能 + - 编写清晰、有文档的代码 + - 添加全面的测试 + + ```bash + # 示例:添加新的窗口方法 + # 1. 添加到 window.go 接口 + # 2. 在平台文件 (darwin, windows, linux) 中实现 + # 3. 添加测试 + # 4. 更新文档 + ``` + +6. **彻底测试** + + 测试您的功能: + ```bash + # 单元测试 + go test ./pkg/application -v + + # 集成测试 - 创建一个测试应用 + cd .. + ./wails3 init -n feature-test + cd feature-test + # 使用新功能添加代码 + ../wails3 dev + ``` + +7. **记录您的功能** + + - 为所有公共 API 添加文档字符串 + - 更新 `/docs` 中的相关文档 + - 如有必要,添加示例 + +8. **使用规范提交** + + 使用规范提交(conventional commits): + ```bash + git commit -m "feat: add window transparency support + + - Add SetTransparent() method to Window API + - Implement for macOS, Windows, and Linux + - Add tests and documentation + + Closes #456" + ``` + +9. **提交拉取请求** + + 推送并创建 PR: + ```bash + git push origin feat/window-transparency-support + ``` + + 在您的 PR 中: + - 描述功能及使用场景 + - 展示示例或截图 + - 列出任何破坏性更改 + - 引用相关的 Discussion/Issue + +10. **根据审查结果迭代** + + 维护者可能会要求更改。请保持耐心和协作精神。 + + + + + + + + +1. **识别文档需求** + + - 在使用 Wails 时发现文档过时? + - 注意到缺少示例或解释? + - 想要修复拼写错误或提高清晰度? + - 查看 [文档 Issues](https://github.com/wailsapp/wails/labels/documentation) + +2. **Fork 并克隆** + + 在 [github.com/wailsapp/wails/fork](https://github.com/wailsapp/wails/fork) Fork 仓库 + + 克隆您的 Fork: + ```bash + git clone https://github.com/YOUR_USERNAME/wails.git + cd wails + git remote add upstream https://github.com/wailsapp/wails.git + ``` + +3. **配置文档环境** + + 文档位于 `/docs`,使用 Astro 构建: + ```bash + cd docs + npm install + npm run dev + ``` + + 打开 http://localhost:4321/ 以实时预览更改。 + +4. **创建文档分支** + + 为您的更改创建分支: + ```bash + git checkout -b docs/improve-window-api-examples + ``` + +5. **进行更改** + + 文档文件位于 `/docs/src/content/docs/`: + ```bash + # 编辑 MDX 文件 + # 在浏览器中检查预览 + # 确保格式正确 + ``` + + **最佳实践:** + - 使用清晰、简洁的语言 + - 包含实用的代码示例 + - 添加指向相关章节的链接 + - 检查拼写和语法 + - 测试所有代码示例 + +6. **验证您的更改** + + 检查实时预览并确保: + - 链接正常工作 + - 代码示例准确无误 + - 格式正确渲染 + - 没有损坏的图片或引用 + +7. **提交文档更改** + + 使用清晰的提交信息提交: + ```bash + git commit -m "docs: add practical examples to Window API guide + + - Add window positioning examples + - Include common patterns section + - Fix broken links to Event API" + ``` + +8. **提交拉取请求** + + 推送并创建 PR: + ```bash + git push origin docs/improve-window-api-examples + ```在你的 PR 中: +- 描述你改进的文档内容 +- 解释这些更改如何帮助用户 +- 如果涉及视觉变更,请附上截图 + +9. **处理评审反馈** + +文档相关的 PR 通常审查和合并速度很快! + + + + + + +## 寻找可处理的问题 + +- 查找 [`good first issue`](https://github.com/wailsapp/wails/labels/good%20first%20issue) 标签 +- 查看 [`help wanted`](https://github.com/wailsapp/wails/labels/help%20wanted) 问题 +- 浏览 [开放问题](https://github.com/wailsapp/wails/issues) 并申请认领 + +## 获取帮助 + +- **Discord:** 加入 [Wails Discord](https://discord.gg/JDdSxwjhGf) +- **讨论区:** 在 [GitHub Discussions](https://github.com/wailsapp/wails/discussions) 发帖 +- **问题:** 如果发现 bug 或有疑问,请提交 Issue + +## 行为准则 + +保持尊重、建设性和欢迎的态度。我们正在构建一个友好的社区,致力于共同创建优秀的软件。 + +## 下一步 + +- 设置你的 [开发环境](/zh-cn/contributing/setup) +- 阅读我们的 [编码规范](/zh-cn/contributing/standards) +- 探索 [技术文档](/zh-cn/contributing) \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/contributing/index.mdx b/docs/src/content/docs/zh-cn/contributing/index.mdx new file mode 100644 index 00000000000..f836c2cfd19 --- /dev/null +++ b/docs/src/content/docs/zh-cn/contributing/index.mdx @@ -0,0 +1,87 @@ +--- +title: 技术概览 +description: Wails v3 代码库的高级架构与路线图 +sidebar: + order: 1 +--- + +import { Card, CardGrid } from "@astrojs/starlight/components"; + +## 欢迎查阅 Wails v3 技术文档 + +本节**不**涉及社区指南或如何提交拉取请求。 +相反,它将深入探讨 **Wails v3 是如何构建的**,以便您能够快速熟悉代码库并自信地开始开发。 + +无论您计划修补运行时、扩展 CLI、制作新模板,还是仅仅想了解内部机制,接下来的页面都将提供您所需的技术背景。 + +--- + +## 高级架构 + + + + 每个 Wails 应用的核心都是编译为原生可执行文件的 Go 代码。 + 它负责应用程序逻辑、系统集成和性能关键操作。 + + + + UI 使用标准 Web 技术(React、Vue、Svelte、原生……)编写, + 由轻量级系统 WebView 渲染(Linux/macOS 上使用 WebKit,Windows 上使用 WebView2)。 + + + + 零拷贝、内存中的桥接层实现了 **Go⇄JavaScript** 调用,支持自动 + 类型转换、事件传播和错误转发。 + + + + `wails3` 协调项目创建、实时重载开发服务器、资源 + 打包、交叉编译和打包(deb、rpm、AppImage、msi、dmg……)。 + + + +--- + +## 架构概览 + +**Wails v3 – 端到端流程** + +{/* +TODO: Fix D2 diagram generation (triple quotes for multi-line strings) or embed as image. +The previous D2 code block was causing MDX parsing errors in the build pipeline. +*/} + +**[端到端流程图占位符]** + + +该图展示了 **端到端流程**: + +1. **CLI** 驱动生成、开发服务器、编译和打包。 +2. **绑定系统** 生成胶水代码,使 **Web 前端** 能够调用 **Go 后端**。 +3. 在开发期间,**资源服务器** 代理到框架开发服务器;在生产环境中,它提供嵌入的文件。 +4. 在运行时,**桌面运行时** 管理窗口和操作系统 API,而 **桥接层** 在 Go 和 JavaScript 之间传递消息。 + +--- + +## 本文档涵盖的内容 + +| 主题 | 重要性 | +| ----- | -------------- | +| **代码库布局** | `/v3` 目录映射及模块间的交互方式。 | +| **运行时内部机制** | 窗口管理、系统 API、消息处理器和平台适配层。 | +| **资源与开发服务器** | Web 资源在开发环境中的服务方式及在生产环境中的嵌入方式。 | +| **构建与打包流水线** | 基于 Taskfile 的工作流、跨平台编译和安装程序生成。 | +| **绑定系统** | 生成类型安全的 Go⇄TS 绑定的静态分析流水线。 | +| **模板系统** | 驱动 `wails init -t ` 的生成器架构。 | +| **测试与 CI** | 单元/集成测试框架、GitHub Actions、竞态检测器指南。 | +| **扩展 Wails** | 添加服务、模板或 CLI 子命令。 | + +每个后续页面都将通过具体的代码示例、图表和对相关源文件的引用来深入探讨这些领域。 + +--- + +:::note +前置要求:您应熟悉 **Go 1.25+**、基础 TypeScript 以及现代前端构建工具。如果您是 Go 新手,建议先浏览官方教程。 +::: + +祝您探索愉快——欢迎来到 Wails v3 的内部世界! \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/contributing/runtime-internals.mdx b/docs/src/content/docs/zh-cn/contributing/runtime-internals.mdx new file mode 100644 index 00000000000..7b41bb2430f --- /dev/null +++ b/docs/src/content/docs/zh-cn/contributing/runtime-internals.mdx @@ -0,0 +1,206 @@ +--- +title: 运行时内部机制 +description: 深入探讨 Wails v3 如何启动、运行并与操作系统通信 +sidebar: + order: 3 +--- + +**运行时**(runtime)是将普通 Go 函数转换为跨平台桌面应用程序的层。 +本文档解释了在追踪源代码时会遇到的各个组成部分。 + +--- + +## 1. 应用程序生命周期 + +| 阶段 | 代码路径 | 发生的情况 | +|-------|-----------|--------------| +| **引导** | `pkg/application/application.go:init()` | 注册构建时数据,创建全局 `application` 单例。 | +| **New()** | `application.New(...)` | 验证 `Options`,启动 **AssetServer**,初始化日志记录。 | +| **Run()** | `application.(*App).Run()` | 1. 调用平台 `mainthread.X()` 进入操作系统 UI 线程。
2. 启动 **runtime** (`internal/runtime`)。
3. 阻塞直到最后一个窗口关闭或调用 `Quit()`。 | +| **关闭** | `application.(*App).Quit()` | 广播 `application:shutdown` 事件,刷新日志,拆除窗口和服务。 | + +生命周期是严格的**单入口**:你可以创建多个窗口,但应用程序对象本身只初始化一次。 + +--- + +## 2. 窗口管理 + +### 公共 API + +```go +win := app.Window.New(&application.WebviewWindowOptions{ + Title: "Dashboard", + Width: 1280, + Height: 720, +}) +win.Show() +``` + +`app.Window.New()` 委托给 `internal/runtime/webview_window_*.go`,其中包含 +特定于平台的构造函数: + +``` +internal/runtime/ +├── webview_window_darwin.go +├── webview_window_linux.go +└── webview_window_windows.go +``` + +每个文件: + +1. 创建原生 webview (WKWebView, WebKitGTK, WebView2)。 +2. 注册 **Message Processor** 回调。 +3. 将 Wails 事件 (`WindowResized`, `Focus`, `DropFile`, …) 映射到运行时 + 事件 ID。 + +窗口由 `screenmanager.go` 跟踪,它提供 **查询 API**(所有显示器、DPI、活动窗口)并集中管理调整大小/移动的记录。 + +--- + +## 3. 消息处理管道 + +JavaScript 和 Go 之间的桥接由 `pkg/application/messageprocessor_*.go` 中的 **Message +Processor** 家族实现。 + +流程: + +1. **JavaScript** 调用 `window.runtime.Invoke("Greet", "Alice")`。 +2. 运行时序列化请求: + `{"t":"c","id":"123","m":"Greet","p":["Alice"]}` + (`t` = 类型, `c` = 调用)。 +3. **Go** 通过 webview 回调接收此 JSON。 +4. `messageprocessor_call.go` 在生成的表 (`application.bindings.go`) 中查找绑定的方法并执行它。 +5. 结果或错误被序列化回 JS,其中 `Promise` 解析。 + +专用处理器: + +| 文件 | 用途 | +|------|---------| +| `messageprocessor_window.go` | 窗口操作 (隐藏, 最大化, …) | +| `messageprocessor_dialog.go` | 原生对话框 (`OpenFile`, `MessageBox`, …) | +| `messageprocessor_clipboard.go` | 剪贴板读写 | +| `messageprocessor_events.go` | 事件订阅/发射 | +| `messageprocessor_browser.go` | 浏览器导航, 开发者工具 | + +处理器是**无状态**的——它们从随每条消息传递的 `ApplicationContext` 中获取所需的一切。 + +--- + +## 4. 事件系统 + +事件是跨三层分发的命名空间字符串: + +1. **应用程序事件**:全局生命周期 (`application:ready`, + `application:shutdown`)。 +2. **窗口事件**:每个窗口 (`window:focus`, `window:resize`)。 +3. **自定义事件**:用户定义 (`chat:new-message`)。 + +实现细节: + +* 常量是从 `internal/events/defaults.go` 生成的。 +* Go 端: + `app.On("window:focus", func(e application.WindowEvent) {...})` +* JS 端: + `window.runtime.EventsOn("chat:new-message", cb)` + +底层两者都映射到 `pkg/application/events.go` 中的同一个 **EventBus**。 +订阅者引用计数;当窗口关闭时,其回调会自动注销以避免泄漏。 + +--- + +## 5. 特定于平台的实现 + +条件编译保持公共 API 一致,同时隐藏操作系统的差异。 + +| 关注点 | Darwin | Linux | Windows | +|---------|--------|-------|---------| +| 主线程 | `mainthread_darwin.go` (Cgo 到 Foundation) | `mainthread_linux.go` (GTK) | `mainthread_windows.go` (Win32 `AttachThreadInput`) | +| 对话框 | `dialogs_darwin.*` (NSAlert) | `dialogs_linux.go` (GtkFileChooser) | `dialogs_windows.go` (IFileOpenDialog) | +| 剪贴板 | `clipboard_darwin.go` | `clipboard_linux.go` | `clipboard_windows.go` | +| 托盘图标 | `systemtray_darwin.*` | `systemtray_linux.go` (DBus) | `systemtray_windows.go` (Shell_NotifyIcon) | + +关键原则: + +* **除非不可避免,否则在 Windows/Linux 上不使用 Cgo**(性能、可移植性)。 +* 使用 **构建标签** (`//go:build darwin && !production`) 保持文件可读。 +* 通过 `internal/capabilities` 暴露 **功能**,以便更高层可以优雅地降级。 + +--- + +## 6. 文件指南 + +| 文件 | 你为什么要修改它 | +|------|--------------------| +| `internal/runtime/runtime_*.go` | 更改全局启动逻辑,添加调试钩子。 | +| `internal/runtime/webview_window_*.go` | 实现新的窗口提示或行为。 | +| `pkg/application/messageprocessor_*.go` | 添加一个新的可从 JS 调用的桥接命令。 | +| `pkg/application/events_*.go` | 扩展内置事件定义。 | +| `internal/assetserver/*` | 调整开发/生产环境资产处理。 | + +--- + +## 7. 调试技巧 + +* 使用 `WAILS_LOG_LEVEL=debug` 启动以打印跨越桥接器的每条消息。 +* 使用 `wails3 dev -verbose` 查看实时重载和资产请求。 +* 在 macOS 上,在 `lldb --` 下运行以尽早捕获 Objective-C 异常。 +* 对于 Windows Chromium 问题,启用 WebView2 调试日志: + `set WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--remote-debugging-port=9222` + +--- + +## 8. 扩展运行时 + +1. 在 `internal/capabilities` 中定义 **功能标志**。 +2. 使用构建标签在每个平台文件中实现该功能。 +3. 在 `pkg/application` 中添加公共 API。 +4. 如果 JS 需要调用它,注册新的消息类型或事件。 +5. 更新 `v3/examples/` 中至少一个使用该功能的示例。 + +遵循此检查清单,你将保持跨平台契约的完整性。 + +--- + +## 9. 拖放 + +文件拖放使用所有平台上的 **JavaScript 优先方法**。原生层拦截操作系统拖放事件,但实际的放置处理和 DOM 交互发生在 JavaScript 中。 + +### 流程 + +1. 用户从操作系统将文件拖到 Wails 窗口上 +2. 原生层检测到拖放并通知 JavaScript 以显示悬停效果 +3. 用户放置文件 +4. 原生层将文件路径 + 坐标发送给 JavaScript +5. JavaScript 找到放置目标元素 (`data-file-drop-target`) +6. JavaScript 将文件路径 + 元素详细信息发送给 Go 后端 +7. Go 发出带有完整上下文的 `WindowFilesDropped` 事件 + +### 平台实现 + +| 平台 | 原生层 | 关键挑战 | +|----------|--------------|---------------| +| **Windows** | WebView2 的内置拖放支持 | 坐标为 CSS 像素,无需转换 | +| **macOS** | NSWindow 拖放委托 | 将窗口相对坐标转换为 webview 相对坐标 | +| **Linux** | GTK3 拖放信号 | 必须区分文件拖放和内部 HTML5 拖放 | + +### Linux:区分拖放类型 + +GTK 和 WebKit 都想处理拖放事件。关键在于检查拖放目标类型: + +```c +static gboolean is_file_drag(GdkDragContext *context) { + GList *targets = gdk_drag_context_list_targets(context); + for (GList *l = targets; l != NULL; l = l->next) { + GdkAtom atom = GDK_POINTER_TO_ATOM(l->data); + gchar *name = gdk_atom_name(atom); + if (name && g_strcmp0(name, "text/uri-list") == 0) { + g_free(name); + return TRUE; // 外部文件拖放 + } + g_free(name); + } + return FALSE; // 内部 HTML5 拖放 +} +``` + +信号处理程序对内部拖放返回 `FALSE`(让 WebKit 处理它们),对文件拖放返回 `TRUE`(由我们自己处理)。你现在已经对运行时内部机制有了引导式了解。将这些知识与 **代码库布局** 图和 **资产服务器** 文档结合使用,即可自信地导航并进行有影响力的贡献。祝你编码愉快! \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/contributing/setup.mdx b/docs/src/content/docs/zh-cn/contributing/setup.mdx new file mode 100644 index 00000000000..89f9c7dd9ed --- /dev/null +++ b/docs/src/content/docs/zh-cn/contributing/setup.mdx @@ -0,0 +1,297 @@ +--- +title: 开发环境配置 +description: 为你的 Wails v3 开发配置开发环境 +--- + +## 开发环境配置 + +本指南将引导你完成 Wails v3 开发所需完整开发环境的设置。 + +## 必备工具 + +### Go 开发 + +1. **安装 Go 1.25 或更高版本:** + ```bash + # 从 https://go.dev/dl/ 下载 + go version # 验证安装 + ``` + +2. **配置 Go 环境:** + ```bash + # 添加到你的 shell 配置文件 (.bashrc, .zshrc 等) + export GOPATH=$HOME/go + export PATH=$PATH:$GOPATH/bin + ``` + +3. **安装实用的 Go 工具:** + ```bash + go install golang.org/x/tools/cmd/goimports@latest + go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + ``` + +### Node.js 和 npm + +用于构建文档和测试前端集成。 + +```bash +# 安装 Node.js 20+ 和 npm +node --version # 应为 20+ +npm --version +``` + +### 平台特定依赖 + +**macOS:** + +```bash +# 安装 Xcode 命令行工具 +xcode-select --install + +# 验证安装 +xcode-select -p # 应输出一个路径 +``` + +**Windows:** + +1. 安装 [MSYS2](https://www.msys2.org/) 以获得类 Unix 环境 +2. WebView2 运行时(Windows 11 预装,[下载](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) Windows 10 版本) +3. 可选:安装 [Git for Windows](https://git-scm.com/download/win) + +**Linux (Debian/Ubuntu):** + +```bash +sudo apt update +sudo apt install build-essential pkg-config libgtk-3-dev libwebkit2gtk-4.0-dev +``` + +**Linux (Fedora/RHEL):** + +```bash +sudo dnf install gcc pkg-config gtk3-devel webkit2gtk3-devel +``` + +**Linux (Arch):** + +```bash +sudo pacman -S base-devel gtk3 webkit2gtk +``` + +## 仓库设置 + +### 克隆和配置 + +```bash +# 克隆你的 fork +git clone https://github.com/YOUR_USERNAME/wails.git +cd wails + +# 添加上游远程仓库 +git remote add upstream https://github.com/wailsapp/wails.git + +# 验证远程仓库 +git remote -v +``` + +### 构建 Wails CLI + +```bash +# 进入 v3 目录 +cd v3 + +# 构建 CLI +go build -o ../wails3 ./cmd/wails3 + +# 测试构建 +cd .. +./wails3 version +``` + +### 添加到 PATH(可选) + +**Linux/macOS:** + +```bash +# 添加到 ~/.bashrc 或 ~/.zshrc +export PATH=$PATH:/path/to/wails +``` + +**Windows:** + +通过系统属性将 Wails 目录添加到你的 PATH 环境变量中。 + +## IDE 设置 + +### VS Code(推荐) + +1. **安装 VS Code:** [下载](https://code.visualstudio.com/) + +2. **安装扩展:** + - Go (by Go Team at Google) + - ESLint + - Prettier + - MDX (用于文档) + +3. **配置工作区设置** (`.vscode/settings.json`): + ```json + { + "go.useLanguageServer": true, + "go.lintTool": "golangci-lint", + "go.lintOnSave": "workspace", + "editor.formatOnSave": true, + "go.formatTool": "goimports" + } + ``` + +### GoLand + +1. **安装 GoLand:** [下载](https://www.jetbrains.com/go/) + +2. **配置:** + - 启用 Go 模块支持 + - 设置 `goimports` 的文件监听器 + - 配置代码风格以匹配项目规范 + +## 验证你的设置 + +运行以下命令以验证一切是否正常: + +```bash +# Go 版本检查 +go version + +# 构建 Wails +cd v3 +go build ./cmd/wails3 + +# 运行测试 +go test ./pkg/... + +# 创建一个测试应用 +cd .. +./wails3 init -n mytest -t vanilla +cd mytest +../wails3 dev +``` + +如果测试应用构建并运行成功,你的环境已准备就绪! + +## 运行测试 + +### 单元测试 + +```bash +cd v3 +go test ./... +``` + +### 特定包测试 + +```bash +go test ./pkg/application +go test ./pkg/events -v # 详细输出 +``` + +### 带覆盖率运行 + +```bash +go test ./... -coverprofile=coverage.out +go tool cover -html=coverage.out +``` + +### 带竞态检测器运行 + +```bash +go test ./... -race +``` + +## 处理文档 + +Wails 文档使用 Astro 和 Starlight 构建。 + +```bash +cd docs + +# 安装依赖 +npm install + +# 启动开发服务器 +npm run dev + +# 构建生产版本 +npm run build +``` + +文档将在 `http://localhost:4321/` 可用。 + +## 调试 + +### 调试 Go 代码 + +**VS Code:** + +创建 `.vscode/launch.json`: + +```json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug Wails CLI", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceFolder}/v3/cmd/wails3", + "args": ["dev"] + } + ] +} +``` + +**命令行:** + +```bash +# 使用 Delve 调试器 +go install github.com/go-delve/delve/cmd/dlv@latest +dlv debug ./cmd/wails3 -- dev +``` + +### 调试平台代码 + +平台特定的调试需要平台工具: + +- **macOS:** Xcode Instruments +- **Windows:** Visual Studio Debugger +- **Linux:** GDB + +## 常见问题 + +### "command not found: wails3" + +将 Wails 目录添加到你的 PATH,或者从项目根目录使用 `./wails3`。 + +### "webkit2gtk not found" (Linux) + +安装 WebKit2GTK 开发包: + +```bash +sudo apt install libwebkit2gtk-4.0-dev # Debian/Ubuntu +``` + +### 构建因 Go 模块错误而失败 + +```bash +cd v3 +go mod tidy +go mod download +``` + +### Windows 上的 "CGO_ENABLED" 错误 + +确保你的 PATH 中有 C 编译器(通过 MSYS2 的 MinGW-w64)。 + +## 下一步 + +- 查看 [编码规范](/zh-cn/contributing/standards) +- 探索 [技术文档](/zh-cn/contributing) +- 寻找一个待处理的问题:[适合新手的问题](https://github.com/wailsapp/wails/labels/good%20first%20issue) \ No newline at end of file diff --git a/docs/src/content/docs/zh-cn/contributing/standards.mdx b/docs/src/content/docs/zh-cn/contributing/standards.mdx new file mode 100644 index 00000000000..4b306b70947 --- /dev/null +++ b/docs/src/content/docs/zh-cn/contributing/standards.mdx @@ -0,0 +1,463 @@ +--- +title: 编码规范 +description: Wails v3 的代码风格、约定和最佳实践 +--- + +## 代码风格与约定 + +遵循一致的编码规范可以使代码库更易于阅读、维护和贡献。 + +## Go 代码规范 + +### 代码格式化 + +使用标准的 Go 格式化工具: + +```bash +# 格式化所有代码 +gofmt -w . + +# 使用 goimports 进行导入组织 +goimports -w . +``` + +**要求:** 所有 Go 代码在提交前必须通过 `gofmt` 和 `goimports` 检查。 + +### 命名约定 + +**包名:** +- 小写,尽可能使用单个单词 +- `package application`,`package events` +- 避免使用下划线或混合大小写 + +**导出名称:** +- 类型、函数、常量使用 PascalCase +- `type WebviewWindow struct`,`func NewApplication()` + +**非导出名称:** +- 内部类型、函数、变量使用 camelCase +- `type windowImpl struct`,`func createWindow()` + +**接口:** +- 按行为命名:`Reader`、`Writer`、`Handler` +- 单方法接口:名称以 `-er` 后缀结尾 + +```go +// 推荐 +type Closer interface { + Close() error +} + +// 避免 +type CloseInterface interface { + Close() error +} +``` + +### 错误处理 + +**始终检查错误:** + +```go +// 推荐 +result, err := doSomething() +if err != nil { + return fmt.Errorf("failed to do something: %w", err) +} + +// 错误 - 忽略错误 +result, _ := doSomething() +``` + +**使用错误包装:** + +```go +// 包装错误以提供上下文 +if err := validate(); err != nil { + return fmt.Errorf("validation failed: %w", err) +} +``` + +**在需要时创建自定义错误类型:** + +```go +type ValidationError struct { + Field string + Value string +} + +func (e *ValidationError) Error() string { + return fmt.Sprintf("invalid value %q for field %q", e.Value, e.Field) +} +``` + +### 注释与文档 + +**包注释:** + +```go +// Package application provides the core Wails application runtime. +// +// It handles window management, event dispatching, and service lifecycle. +package application +``` + +**导出声明:** + +```go +// NewApplication creates a new Wails application with the given options. +// +// The application must be started with Run() or RunWithContext(). +func NewApplication(opts Options) *Application { + // ... +} +``` + +**实现注释:** + +```go +// processEvent handles incoming events from the runtime. +// It dispatches to registered handlers and manages event lifecycle. +func (a *Application) processEvent(event *Event) { + // Validate event before processing + if event == nil { + return + } + + // Find and invoke handlers + // ... +} +``` + +### 函数与方法结构 + +**保持函数职责单一:** + +```go +// 推荐 - 单一职责 +func (w *Window) setTitle(title string) { + w.title = title + w.updateNativeTitle() +} + +// 错误 - 做了太多事情 +func (w *Window) updateEverything() { + w.setTitle(w.title) + w.setSize(w.width, w.height) + w.setPosition(w.x, w.y) + // ... 20 more operations +} +``` + +**使用早期返回:** + +```go +// 推荐 +func validate(input string) error { + if input == "" { + return errors.New("empty input") + } + + if len(input) > 100 { + return errors.New("input too long") + } + + return nil +} + +// 避免深层嵌套 +``` + +### 并发 + +**使用 context 进行取消:** + +```go +func (a *Application) RunWithContext(ctx context.Context) error { + select { + case <-ctx.Done(): + return ctx.Err() + case <-a.done: + return nil + } +} +``` + +**使用互斥锁保护共享状态:** + +```go +type SafeCounter struct { + mu sync.Mutex + count int +} + +func (c *SafeCounter) Increment() { + c.mu.Lock() + defer c.mu.Unlock() + c.count++ +} +``` + +**避免 goroutine 泄漏:** + +```go +// 推荐 - goroutine 有退出条件 +func (a *Application) startWorker(ctx context.Context) { + go func() { + for { + select { + case <-ctx.Done(): + return // Clean exit + case work := <-a.workChan: + a.process(work) + } + } + }() +} +``` + +### 测试 + +**测试文件命名:** + +```go +// 实现文件: window.go +// 测试文件: window_test.go +``` + +**表格驱动测试:** + +```go +func TestValidate(t *testing.T) { + tests := []struct { + name string + input string + wantErr bool + }{ + {"empty input", "", true}, + {"valid input", "hello", false}, + {"too long", strings.Repeat("a", 101), true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := validate(tt.input) + if (err != nil) != tt.wantErr { + t.Errorf("validate() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} +``` + +## JavaScript/TypeScript 规范 + +### 代码格式化 + +使用 Prettier 进行一致的格式化: + +```json +{ + "semi": false, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "es5" +} +``` + +### 命名约定 + +**变量和函数:** +- camelCase: `const userName = "John"` + +**类和类型:** +- PascalCase: `class WindowManager` + +**常量:** +- UPPER_SNAKE_CASE: `const MAX_RETRIES = 3` + +### TypeScript + +**使用显式类型:** + +```typescript +// 推荐 +function greet(name: string): string { + return `Hello, ${name}` +} + +// 避免隐式 any +function process(data) { // 错误 + return data +} +``` + +**定义接口:** + +```typescript +interface WindowOptions { + title: string + width: number + height: number +} + +function createWindow(options: WindowOptions): void { + // ... +} +``` + +## 提交信息格式 + +使用 [Conventional Commits](https://www.conventionalcommits.org/): + +``` +(): + + + +