diff --git a/translated_images/zh-MO/new-file-github.com.c886796d800e8056.webp b/translated_images/zh-MO/new-file-github.com.c886796d800e8056.webp new file mode 100644 index 000000000..00037acf1 Binary files /dev/null and b/translated_images/zh-MO/new-file-github.com.c886796d800e8056.webp differ diff --git a/translated_images/zh-MO/open-palette-menu.46dda01084738da8.webp b/translated_images/zh-MO/open-palette-menu.46dda01084738da8.webp new file mode 100644 index 000000000..8fb520096 Binary files /dev/null and b/translated_images/zh-MO/open-palette-menu.46dda01084738da8.webp differ diff --git a/translated_images/zh-MO/open-remote-repository.bd9c2598b8949e7f.webp b/translated_images/zh-MO/open-remote-repository.bd9c2598b8949e7f.webp new file mode 100644 index 000000000..00700557e Binary files /dev/null and b/translated_images/zh-MO/open-remote-repository.bd9c2598b8949e7f.webp differ diff --git a/translated_images/zh-MO/palette-menu.4946174e07f42622.webp b/translated_images/zh-MO/palette-menu.4946174e07f42622.webp new file mode 100644 index 000000000..90c79bc5c Binary files /dev/null and b/translated_images/zh-MO/palette-menu.4946174e07f42622.webp differ diff --git a/translated_images/zh-MO/partI-solution.36c53b48c9ffae2a.webp b/translated_images/zh-MO/partI-solution.36c53b48c9ffae2a.webp new file mode 100644 index 000000000..e7df45a1e Binary files /dev/null and b/translated_images/zh-MO/partI-solution.36c53b48c9ffae2a.webp differ diff --git a/translated_images/zh-MO/plant1.a876180d8659acb9.webp b/translated_images/zh-MO/plant1.a876180d8659acb9.webp new file mode 100644 index 000000000..0afdb8492 Binary files /dev/null and b/translated_images/zh-MO/plant1.a876180d8659acb9.webp differ diff --git a/translated_images/zh-MO/plant10.2f2c47804ae52dd3.webp b/translated_images/zh-MO/plant10.2f2c47804ae52dd3.webp new file mode 100644 index 000000000..a972d3197 Binary files /dev/null and b/translated_images/zh-MO/plant10.2f2c47804ae52dd3.webp differ diff --git a/translated_images/zh-MO/plant11.0ce0081b0ef17aa1.webp b/translated_images/zh-MO/plant11.0ce0081b0ef17aa1.webp new file mode 100644 index 000000000..83718f403 Binary files /dev/null and b/translated_images/zh-MO/plant11.0ce0081b0ef17aa1.webp differ diff --git a/translated_images/zh-MO/plant12.6b934c4312a00228.webp b/translated_images/zh-MO/plant12.6b934c4312a00228.webp new file mode 100644 index 000000000..abfcadc6c Binary files /dev/null and b/translated_images/zh-MO/plant12.6b934c4312a00228.webp differ diff --git a/translated_images/zh-MO/plant13.37d6ab2e2481421f.webp b/translated_images/zh-MO/plant13.37d6ab2e2481421f.webp new file mode 100644 index 000000000..77816483d Binary files /dev/null and b/translated_images/zh-MO/plant13.37d6ab2e2481421f.webp differ diff --git a/translated_images/zh-MO/plant14.908791477a46eb7f.webp b/translated_images/zh-MO/plant14.908791477a46eb7f.webp new file mode 100644 index 000000000..9b2eea637 Binary files /dev/null and b/translated_images/zh-MO/plant14.908791477a46eb7f.webp differ diff --git a/translated_images/zh-MO/plant2.9e45efea224115b0.webp b/translated_images/zh-MO/plant2.9e45efea224115b0.webp new file mode 100644 index 000000000..e6b517d90 Binary files /dev/null and b/translated_images/zh-MO/plant2.9e45efea224115b0.webp differ diff --git a/translated_images/zh-MO/plant3.06efdd0fa0c4b115.webp b/translated_images/zh-MO/plant3.06efdd0fa0c4b115.webp new file mode 100644 index 000000000..fa73f15cf Binary files /dev/null and b/translated_images/zh-MO/plant3.06efdd0fa0c4b115.webp differ diff --git a/translated_images/zh-MO/plant4.3b78072b427727c6.webp b/translated_images/zh-MO/plant4.3b78072b427727c6.webp new file mode 100644 index 000000000..be231012e Binary files /dev/null and b/translated_images/zh-MO/plant4.3b78072b427727c6.webp differ diff --git a/translated_images/zh-MO/plant5.8ec58b18ac336fa8.webp b/translated_images/zh-MO/plant5.8ec58b18ac336fa8.webp new file mode 100644 index 000000000..4e295e185 Binary files /dev/null and b/translated_images/zh-MO/plant5.8ec58b18ac336fa8.webp differ diff --git a/translated_images/zh-MO/plant6.ca4ff8372e6676b1.webp b/translated_images/zh-MO/plant6.ca4ff8372e6676b1.webp new file mode 100644 index 000000000..46a89a545 Binary files /dev/null and b/translated_images/zh-MO/plant6.ca4ff8372e6676b1.webp differ diff --git a/translated_images/zh-MO/plant7.194d5a42fcf5a88c.webp b/translated_images/zh-MO/plant7.194d5a42fcf5a88c.webp new file mode 100644 index 000000000..420dca0b9 Binary files /dev/null and b/translated_images/zh-MO/plant7.194d5a42fcf5a88c.webp differ diff --git a/translated_images/zh-MO/plant8.7b247809ab0eb492.webp b/translated_images/zh-MO/plant8.7b247809ab0eb492.webp new file mode 100644 index 000000000..9b4c15c2f Binary files /dev/null and b/translated_images/zh-MO/plant8.7b247809ab0eb492.webp differ diff --git a/translated_images/zh-MO/plant9.8fe614c01ded1b1e.webp b/translated_images/zh-MO/plant9.8fe614c01ded1b1e.webp new file mode 100644 index 000000000..893f89540 Binary files /dev/null and b/translated_images/zh-MO/plant9.8fe614c01ded1b1e.webp differ diff --git a/translated_images/zh-MO/player.137ee0e47f895ffc.webp b/translated_images/zh-MO/player.137ee0e47f895ffc.webp new file mode 100644 index 000000000..879c28a80 Binary files /dev/null and b/translated_images/zh-MO/player.137ee0e47f895ffc.webp differ diff --git a/translated_images/zh-MO/player.2887422f6982c3cd.webp b/translated_images/zh-MO/player.2887422f6982c3cd.webp new file mode 100644 index 000000000..879c28a80 Binary files /dev/null and b/translated_images/zh-MO/player.2887422f6982c3cd.webp differ diff --git a/translated_images/zh-MO/player.391fed427ede24f5.webp b/translated_images/zh-MO/player.391fed427ede24f5.webp new file mode 100644 index 000000000..879c28a80 Binary files /dev/null and b/translated_images/zh-MO/player.391fed427ede24f5.webp differ diff --git a/translated_images/zh-MO/player.3c4f50182552a73a.webp b/translated_images/zh-MO/player.3c4f50182552a73a.webp new file mode 100644 index 000000000..879c28a80 Binary files /dev/null and b/translated_images/zh-MO/player.3c4f50182552a73a.webp differ diff --git a/translated_images/zh-MO/player.47bc9de0714c723d.webp b/translated_images/zh-MO/player.47bc9de0714c723d.webp new file mode 100644 index 000000000..879c28a80 Binary files /dev/null and b/translated_images/zh-MO/player.47bc9de0714c723d.webp differ diff --git a/translated_images/zh-MO/player.57b3107c03012695.webp b/translated_images/zh-MO/player.57b3107c03012695.webp new file mode 100644 index 000000000..879c28a80 Binary files /dev/null and b/translated_images/zh-MO/player.57b3107c03012695.webp differ diff --git a/translated_images/zh-MO/player.606f85953e5e564e.webp b/translated_images/zh-MO/player.606f85953e5e564e.webp new file mode 100644 index 000000000..879c28a80 Binary files /dev/null and b/translated_images/zh-MO/player.606f85953e5e564e.webp differ diff --git a/translated_images/zh-MO/player.680ea4c619b54fe1.webp b/translated_images/zh-MO/player.680ea4c619b54fe1.webp new file mode 100644 index 000000000..879c28a80 Binary files /dev/null and b/translated_images/zh-MO/player.680ea4c619b54fe1.webp differ diff --git a/translated_images/zh-MO/player.bfe14f110bddf56d.webp b/translated_images/zh-MO/player.bfe14f110bddf56d.webp new file mode 100644 index 000000000..879c28a80 Binary files /dev/null and b/translated_images/zh-MO/player.bfe14f110bddf56d.webp differ diff --git a/translated_images/zh-MO/player.c99c25d54a615ca0.webp b/translated_images/zh-MO/player.c99c25d54a615ca0.webp new file mode 100644 index 000000000..879c28a80 Binary files /dev/null and b/translated_images/zh-MO/player.c99c25d54a615ca0.webp differ diff --git a/translated_images/zh-MO/player.dd24c1afa8c71e9b.webp b/translated_images/zh-MO/player.dd24c1afa8c71e9b.webp new file mode 100644 index 000000000..879c28a80 Binary files /dev/null and b/translated_images/zh-MO/player.dd24c1afa8c71e9b.webp differ diff --git a/translated_images/zh-MO/playerDamaged.181703f652fd5176.webp b/translated_images/zh-MO/playerDamaged.181703f652fd5176.webp new file mode 100644 index 000000000..00d3377d9 Binary files /dev/null and b/translated_images/zh-MO/playerDamaged.181703f652fd5176.webp differ diff --git a/translated_images/zh-MO/playerLeft.0f928412e66ba5d9.webp b/translated_images/zh-MO/playerLeft.0f928412e66ba5d9.webp new file mode 100644 index 000000000..0856babce Binary files /dev/null and b/translated_images/zh-MO/playerLeft.0f928412e66ba5d9.webp differ diff --git a/translated_images/zh-MO/playerRight.e4825f489e29f737.webp b/translated_images/zh-MO/playerRight.e4825f489e29f737.webp new file mode 100644 index 000000000..8d6696a22 Binary files /dev/null and b/translated_images/zh-MO/playerRight.e4825f489e29f737.webp differ diff --git a/translated_images/zh-MO/playground-choice.1d23ba7d407f4758.webp b/translated_images/zh-MO/playground-choice.1d23ba7d407f4758.webp new file mode 100644 index 000000000..2ed83a97b Binary files /dev/null and b/translated_images/zh-MO/playground-choice.1d23ba7d407f4758.webp differ diff --git a/translated_images/zh-MO/playground.d2b927122224ff8f.webp b/translated_images/zh-MO/playground.d2b927122224ff8f.webp new file mode 100644 index 000000000..8e8ccc0d1 Binary files /dev/null and b/translated_images/zh-MO/playground.d2b927122224ff8f.webp differ diff --git a/translated_images/zh-MO/preview.9215f0a010074476.webp b/translated_images/zh-MO/preview.9215f0a010074476.webp new file mode 100644 index 000000000..961270acf Binary files /dev/null and b/translated_images/zh-MO/preview.9215f0a010074476.webp differ diff --git a/translated_images/zh-MO/profiler.5a4a62479c5df01c.webp b/translated_images/zh-MO/profiler.5a4a62479c5df01c.webp new file mode 100644 index 000000000..d41978867 Binary files /dev/null and b/translated_images/zh-MO/profiler.5a4a62479c5df01c.webp differ diff --git a/translated_images/zh-MO/project-on-vscode.dev.e79815a9a95ee7fe.webp b/translated_images/zh-MO/project-on-vscode.dev.e79815a9a95ee7fe.webp new file mode 100644 index 000000000..f822f1b24 Binary files /dev/null and b/translated_images/zh-MO/project-on-vscode.dev.e79815a9a95ee7fe.webp differ diff --git a/translated_images/zh-MO/result.96ef01f607bf856a.webp b/translated_images/zh-MO/result.96ef01f607bf856a.webp new file mode 100644 index 000000000..dfe8ee660 Binary files /dev/null and b/translated_images/zh-MO/result.96ef01f607bf856a.webp differ diff --git a/translated_images/zh-MO/screen1.baccbba0f1f93364.webp b/translated_images/zh-MO/screen1.baccbba0f1f93364.webp new file mode 100644 index 000000000..e59d8f18b Binary files /dev/null and b/translated_images/zh-MO/screen1.baccbba0f1f93364.webp differ diff --git a/translated_images/zh-MO/screen2.123c82a831a1d14a.webp b/translated_images/zh-MO/screen2.123c82a831a1d14a.webp new file mode 100644 index 000000000..a1c40b2b5 Binary files /dev/null and b/translated_images/zh-MO/screen2.123c82a831a1d14a.webp differ diff --git a/translated_images/zh-MO/screenshot.0a1ee0d123df681b.webp b/translated_images/zh-MO/screenshot.0a1ee0d123df681b.webp new file mode 100644 index 000000000..c7fe086a3 Binary files /dev/null and b/translated_images/zh-MO/screenshot.0a1ee0d123df681b.webp differ diff --git a/translated_images/zh-MO/screenshot.e7a5ad659e364568.webp b/translated_images/zh-MO/screenshot.e7a5ad659e364568.webp new file mode 100644 index 000000000..022ebf330 Binary files /dev/null and b/translated_images/zh-MO/screenshot.e7a5ad659e364568.webp differ diff --git a/translated_images/zh-MO/screenshot_gray.0c796099a1f9f25e.webp b/translated_images/zh-MO/screenshot_gray.0c796099a1f9f25e.webp new file mode 100644 index 000000000..da8ac1d22 Binary files /dev/null and b/translated_images/zh-MO/screenshot_gray.0c796099a1f9f25e.webp differ diff --git a/translated_images/zh-MO/shield.1b9412b7ca6610ab.webp b/translated_images/zh-MO/shield.1b9412b7ca6610ab.webp new file mode 100644 index 000000000..a2e065ca1 Binary files /dev/null and b/translated_images/zh-MO/shield.1b9412b7ca6610ab.webp differ diff --git a/translated_images/zh-MO/snapshot.97750180ebcad737.webp b/translated_images/zh-MO/snapshot.97750180ebcad737.webp new file mode 100644 index 000000000..a4488b480 Binary files /dev/null and b/translated_images/zh-MO/snapshot.97750180ebcad737.webp differ diff --git a/translated_images/zh-MO/spa.268ec73b41f992c2.webp b/translated_images/zh-MO/spa.268ec73b41f992c2.webp new file mode 100644 index 000000000..7f35a28cd Binary files /dev/null and b/translated_images/zh-MO/spa.268ec73b41f992c2.webp differ diff --git a/translated_images/zh-MO/speedLine.5bcabb93f48b5ae1.webp b/translated_images/zh-MO/speedLine.5bcabb93f48b5ae1.webp new file mode 100644 index 000000000..57b77b342 Binary files /dev/null and b/translated_images/zh-MO/speedLine.5bcabb93f48b5ae1.webp differ diff --git a/translated_images/zh-MO/spritesheet.bec82852290b14ee.webp b/translated_images/zh-MO/spritesheet.bec82852290b14ee.webp new file mode 100644 index 000000000..02853f8a0 Binary files /dev/null and b/translated_images/zh-MO/spritesheet.bec82852290b14ee.webp differ diff --git a/translated_images/zh-MO/starBackground.a897b8acb1b0587d.webp b/translated_images/zh-MO/starBackground.a897b8acb1b0587d.webp new file mode 100644 index 000000000..1d99fb2ec Binary files /dev/null and b/translated_images/zh-MO/starBackground.a897b8acb1b0587d.webp differ diff --git a/translated_images/zh-MO/starBig.72e9c6d0d18f363d.webp b/translated_images/zh-MO/starBig.72e9c6d0d18f363d.webp new file mode 100644 index 000000000..917791333 Binary files /dev/null and b/translated_images/zh-MO/starBig.72e9c6d0d18f363d.webp differ diff --git a/translated_images/zh-MO/starSmall.ed78b961dbcd0898.webp b/translated_images/zh-MO/starSmall.ed78b961dbcd0898.webp new file mode 100644 index 000000000..bf86a6e91 Binary files /dev/null and b/translated_images/zh-MO/starSmall.ed78b961dbcd0898.webp differ diff --git a/translated_images/zh-MO/template.67ad477109d29a2b.webp b/translated_images/zh-MO/template.67ad477109d29a2b.webp new file mode 100644 index 000000000..0083ad2b1 Binary files /dev/null and b/translated_images/zh-MO/template.67ad477109d29a2b.webp differ diff --git a/translated_images/zh-MO/terrarium-final.0920f16e87c13a84.webp b/translated_images/zh-MO/terrarium-final.0920f16e87c13a84.webp new file mode 100644 index 000000000..dbe6b2a96 Binary files /dev/null and b/translated_images/zh-MO/terrarium-final.0920f16e87c13a84.webp differ diff --git a/translated_images/zh-MO/terrarium-final.2f07047ffc597d0a.webp b/translated_images/zh-MO/terrarium-final.2f07047ffc597d0a.webp new file mode 100644 index 000000000..126c622c4 Binary files /dev/null and b/translated_images/zh-MO/terrarium-final.2f07047ffc597d0a.webp differ diff --git a/translated_images/zh-MO/validation-error.8bd23e98d416c22f.webp b/translated_images/zh-MO/validation-error.8bd23e98d416c22f.webp new file mode 100644 index 000000000..be5aba0c3 Binary files /dev/null and b/translated_images/zh-MO/validation-error.8bd23e98d416c22f.webp differ diff --git a/translated_images/zh-MO/vs-code-index.e2986cf919471eb9.webp b/translated_images/zh-MO/vs-code-index.e2986cf919471eb9.webp new file mode 100644 index 000000000..ce67c407d Binary files /dev/null and b/translated_images/zh-MO/vs-code-index.e2986cf919471eb9.webp differ diff --git a/translated_images/zh-MO/webdev101-a11y.8ef3025c858d897a.webp b/translated_images/zh-MO/webdev101-a11y.8ef3025c858d897a.webp new file mode 100644 index 000000000..145ad1e89 Binary files /dev/null and b/translated_images/zh-MO/webdev101-a11y.8ef3025c858d897a.webp differ diff --git a/translated_images/zh-MO/webdev101-css.3f7af5991bf53a20.webp b/translated_images/zh-MO/webdev101-css.3f7af5991bf53a20.webp new file mode 100644 index 000000000..af6807b74 Binary files /dev/null and b/translated_images/zh-MO/webdev101-css.3f7af5991bf53a20.webp differ diff --git a/translated_images/zh-MO/webdev101-github.8846d7971abef6f9.webp b/translated_images/zh-MO/webdev101-github.8846d7971abef6f9.webp new file mode 100644 index 000000000..d22e61b21 Binary files /dev/null and b/translated_images/zh-MO/webdev101-github.8846d7971abef6f9.webp differ diff --git a/translated_images/zh-MO/webdev101-html.4389c2067af68e98.webp b/translated_images/zh-MO/webdev101-html.4389c2067af68e98.webp new file mode 100644 index 000000000..7502aa266 Binary files /dev/null and b/translated_images/zh-MO/webdev101-html.4389c2067af68e98.webp differ diff --git a/translated_images/zh-MO/webdev101-js-arrays.439d7528b8a29455.webp b/translated_images/zh-MO/webdev101-js-arrays.439d7528b8a29455.webp new file mode 100644 index 000000000..03f9f9642 Binary files /dev/null and b/translated_images/zh-MO/webdev101-js-arrays.439d7528b8a29455.webp differ diff --git a/translated_images/zh-MO/webdev101-js-datatypes.4cc470179730702c.webp b/translated_images/zh-MO/webdev101-js-datatypes.4cc470179730702c.webp new file mode 100644 index 000000000..96f507adc Binary files /dev/null and b/translated_images/zh-MO/webdev101-js-datatypes.4cc470179730702c.webp differ diff --git a/translated_images/zh-MO/webdev101-js-decisions.69e1b20f272dd1f0.webp b/translated_images/zh-MO/webdev101-js-decisions.69e1b20f272dd1f0.webp new file mode 100644 index 000000000..2a31b8da5 Binary files /dev/null and b/translated_images/zh-MO/webdev101-js-decisions.69e1b20f272dd1f0.webp differ diff --git a/translated_images/zh-MO/webdev101-js-functions.be049c4726e94f8b.webp b/translated_images/zh-MO/webdev101-js-functions.be049c4726e94f8b.webp new file mode 100644 index 000000000..7db4591b9 Binary files /dev/null and b/translated_images/zh-MO/webdev101-js-functions.be049c4726e94f8b.webp differ diff --git a/translated_images/zh-MO/webdev101-js.10280393044d7eaa.webp b/translated_images/zh-MO/webdev101-js.10280393044d7eaa.webp new file mode 100644 index 000000000..807e860ab Binary files /dev/null and b/translated_images/zh-MO/webdev101-js.10280393044d7eaa.webp differ diff --git a/translated_images/zh-MO/webdev101-programming.d6e3f98e61ac4bff.webp b/translated_images/zh-MO/webdev101-programming.d6e3f98e61ac4bff.webp new file mode 100644 index 000000000..a7a79cddc Binary files /dev/null and b/translated_images/zh-MO/webdev101-programming.d6e3f98e61ac4bff.webp differ diff --git a/translated_images/zh-MO/working-tree-pb.6cd43e5076f23ba3.webp b/translated_images/zh-MO/working-tree-pb.6cd43e5076f23ba3.webp new file mode 100644 index 000000000..f309c4327 Binary files /dev/null and b/translated_images/zh-MO/working-tree-pb.6cd43e5076f23ba3.webp differ diff --git a/translated_images/zh-MO/working-tree.c58eec08e6335c79.webp b/translated_images/zh-MO/working-tree.c58eec08e6335c79.webp new file mode 100644 index 000000000..8554d59cc Binary files /dev/null and b/translated_images/zh-MO/working-tree.c58eec08e6335c79.webp differ diff --git a/translations/ur/.co-op-translator.json b/translations/ur/.co-op-translator.json new file mode 100644 index 000000000..0a6303607 --- /dev/null +++ b/translations/ur/.co-op-translator.json @@ -0,0 +1,584 @@ +{ + "1-getting-started-lessons/1-intro-to-programming-languages/README.md": { + "original_hash": "d45ddcc54eb9232a76d08328b09d792e", + "translation_date": "2025-11-03T12:59:41+00:00", + "source_file": "1-getting-started-lessons/1-intro-to-programming-languages/README.md", + "language_code": "ur" + }, + "1-getting-started-lessons/1-intro-to-programming-languages/assignment.md": { + "original_hash": "17b8ec8e85d99e27dcb3f73842e583be", + "translation_date": "2025-10-20T20:45:48+00:00", + "source_file": "1-getting-started-lessons/1-intro-to-programming-languages/assignment.md", + "language_code": "ur" + }, + "1-getting-started-lessons/2-github-basics/README.md": { + "original_hash": "5c383cc2cc23bb164b06417d1c107a44", + "translation_date": "2025-11-25T11:50:03+00:00", + "source_file": "1-getting-started-lessons/2-github-basics/README.md", + "language_code": "ur" + }, + "1-getting-started-lessons/3-accessibility/README.md": { + "original_hash": "7f2c48e04754724123ea100a822765e5", + "translation_date": "2025-11-03T13:03:16+00:00", + "source_file": "1-getting-started-lessons/3-accessibility/README.md", + "language_code": "ur" + }, + "1-getting-started-lessons/3-accessibility/assignment.md": { + "original_hash": "e6d0f456dfc22afb41bbdefeb5ec179d", + "translation_date": "2025-10-20T20:48:34+00:00", + "source_file": "1-getting-started-lessons/3-accessibility/assignment.md", + "language_code": "ur" + }, + "1-getting-started-lessons/README.md": { + "original_hash": "770d9f83dddc841c19f210dee5fe0712", + "translation_date": "2025-10-03T13:25:49+00:00", + "source_file": "1-getting-started-lessons/README.md", + "language_code": "ur" + }, + "10-ai-framework-project/README.md": { + "original_hash": "3925b6a1c31c60755eaae4d578232c25", + "translation_date": "2025-11-03T13:07:43+00:00", + "source_file": "10-ai-framework-project/README.md", + "language_code": "ur" + }, + "10-ai-framework-project/solution/README.md": { + "original_hash": "d41d8cd98f00b204e9800998ecf8427e", + "translation_date": "2026-01-29T17:41:28+00:00", + "source_file": "10-ai-framework-project/solution/README.md", + "language_code": "ur" + }, + "2-js-basics/1-data-types/README.md": { + "original_hash": "672b0bb6e8b431075f3bdb7130590d2d", + "translation_date": "2025-11-03T12:52:12+00:00", + "source_file": "2-js-basics/1-data-types/README.md", + "language_code": "ur" + }, + "2-js-basics/1-data-types/assignment.md": { + "original_hash": "6fd645e97c48cd5eb5a3d290815ec8b5", + "translation_date": "2025-10-22T14:32:15+00:00", + "source_file": "2-js-basics/1-data-types/assignment.md", + "language_code": "ur" + }, + "2-js-basics/2-functions-methods/README.md": { + "original_hash": "71f7d7dafa1c7194d79ddac87f669ff9", + "translation_date": "2025-11-03T12:53:48+00:00", + "source_file": "2-js-basics/2-functions-methods/README.md", + "language_code": "ur" + }, + "2-js-basics/2-functions-methods/assignment.md": { + "original_hash": "8328f58f4593b4671656ff8f4b2edbd9", + "translation_date": "2025-10-22T14:32:55+00:00", + "source_file": "2-js-basics/2-functions-methods/assignment.md", + "language_code": "ur" + }, + "2-js-basics/3-making-decisions/README.md": { + "original_hash": "c688385d15dd3645e924ea0ffee8967f", + "translation_date": "2025-11-03T12:55:10+00:00", + "source_file": "2-js-basics/3-making-decisions/README.md", + "language_code": "ur" + }, + "2-js-basics/3-making-decisions/assignment.md": { + "original_hash": "ffe366b2d1f037b99fbadbe1dc81083d", + "translation_date": "2025-10-22T14:34:18+00:00", + "source_file": "2-js-basics/3-making-decisions/assignment.md", + "language_code": "ur" + }, + "2-js-basics/4-arrays-loops/README.md": { + "original_hash": "1710a50a519a6e4a1b40a5638783018d", + "translation_date": "2025-11-03T12:54:29+00:00", + "source_file": "2-js-basics/4-arrays-loops/README.md", + "language_code": "ur" + }, + "2-js-basics/4-arrays-loops/assignment.md": { + "original_hash": "8abcada0534e0fb3a7556ea3c5a2a8a4", + "translation_date": "2025-10-22T14:33:38+00:00", + "source_file": "2-js-basics/4-arrays-loops/assignment.md", + "language_code": "ur" + }, + "2-js-basics/README.md": { + "original_hash": "cc9e70a2f096c67389c8acff1521fc27", + "translation_date": "2025-08-25T21:31:58+00:00", + "source_file": "2-js-basics/README.md", + "language_code": "ur" + }, + "3-terrarium/1-intro-to-html/README.md": { + "original_hash": "3fcfa99c4897e051b558b5eaf1e8cc74", + "translation_date": "2025-11-03T13:16:50+00:00", + "source_file": "3-terrarium/1-intro-to-html/README.md", + "language_code": "ur" + }, + "3-terrarium/1-intro-to-html/assignment.md": { + "original_hash": "650e63282e1dfa032890fcf5c1c4119d", + "translation_date": "2025-10-22T14:56:03+00:00", + "source_file": "3-terrarium/1-intro-to-html/assignment.md", + "language_code": "ur" + }, + "3-terrarium/2-intro-to-css/README.md": { + "original_hash": "e39f3a4e3bcccf94639e3af1248f8a4d", + "translation_date": "2025-11-03T13:15:52+00:00", + "source_file": "3-terrarium/2-intro-to-css/README.md", + "language_code": "ur" + }, + "3-terrarium/2-intro-to-css/assignment.md": { + "original_hash": "bee6762d4092a13fc7c338814963f980", + "translation_date": "2025-10-22T14:54:16+00:00", + "source_file": "3-terrarium/2-intro-to-css/assignment.md", + "language_code": "ur" + }, + "3-terrarium/3-intro-to-DOM-and-closures/README.md": { + "original_hash": "973e48ad87d67bf5bb819746c9f8e302", + "translation_date": "2025-11-03T13:13:52+00:00", + "source_file": "3-terrarium/3-intro-to-DOM-and-closures/README.md", + "language_code": "ur" + }, + "3-terrarium/3-intro-to-DOM-and-closures/assignment.md": { + "original_hash": "947ca5ce7c94aee9c7de7034e762bc17", + "translation_date": "2025-10-22T14:53:12+00:00", + "source_file": "3-terrarium/3-intro-to-DOM-and-closures/assignment.md", + "language_code": "ur" + }, + "3-terrarium/README.md": { + "original_hash": "bc5c5550f79d10add90ce419ee34abb3", + "translation_date": "2026-01-06T11:01:29+00:00", + "source_file": "3-terrarium/README.md", + "language_code": "ur" + }, + "3-terrarium/solution/README.md": { + "original_hash": "6329fbe8bd936068debd78cca6f09c0a", + "translation_date": "2025-08-25T21:30:26+00:00", + "source_file": "3-terrarium/solution/README.md", + "language_code": "ur" + }, + "4-typing-game/README.md": { + "original_hash": "efa2ab875b8bb5a7883816506da6b6d2", + "translation_date": "2025-11-03T13:27:08+00:00", + "source_file": "4-typing-game/README.md", + "language_code": "ur" + }, + "4-typing-game/solution/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-26T00:54:31+00:00", + "source_file": "4-typing-game/solution/README.md", + "language_code": "ur" + }, + "4-typing-game/typing-game/README.md": { + "original_hash": "da8bc72041a2bb3826a54654ee1a8844", + "translation_date": "2025-11-03T13:28:28+00:00", + "source_file": "4-typing-game/typing-game/README.md", + "language_code": "ur" + }, + "4-typing-game/typing-game/assignment.md": { + "original_hash": "3eac59d70e2532a677a2ce6bf765485a", + "translation_date": "2025-10-22T15:07:02+00:00", + "source_file": "4-typing-game/typing-game/assignment.md", + "language_code": "ur" + }, + "5-browser-extension/1-about-browsers/README.md": { + "original_hash": "00aa85715e1efd4930c17a23e3012e69", + "translation_date": "2025-11-03T13:42:16+00:00", + "source_file": "5-browser-extension/1-about-browsers/README.md", + "language_code": "ur" + }, + "5-browser-extension/1-about-browsers/assignment.md": { + "original_hash": "b6897c02603d0045dd6d8256e8714baa", + "translation_date": "2025-10-22T15:16:12+00:00", + "source_file": "5-browser-extension/1-about-browsers/assignment.md", + "language_code": "ur" + }, + "5-browser-extension/2-forms-browsers-local-storage/README.md": { + "original_hash": "2b6203a48c48d8234e0948353b47d84e", + "translation_date": "2025-11-03T13:40:35+00:00", + "source_file": "5-browser-extension/2-forms-browsers-local-storage/README.md", + "language_code": "ur" + }, + "5-browser-extension/2-forms-browsers-local-storage/assignment.md": { + "original_hash": "25b8d28b8531352d4eb67291fd7824c4", + "translation_date": "2025-10-22T15:14:39+00:00", + "source_file": "5-browser-extension/2-forms-browsers-local-storage/assignment.md", + "language_code": "ur" + }, + "5-browser-extension/3-background-tasks-and-performance/README.md": { + "original_hash": "b275fed2c6fc90d2b9b6661a3225faa2", + "translation_date": "2025-11-03T13:38:52+00:00", + "source_file": "5-browser-extension/3-background-tasks-and-performance/README.md", + "language_code": "ur" + }, + "5-browser-extension/3-background-tasks-and-performance/assignment.md": { + "original_hash": "a203e560e58ccc6ba68bffc40c7c8676", + "translation_date": "2025-10-22T15:13:04+00:00", + "source_file": "5-browser-extension/3-background-tasks-and-performance/assignment.md", + "language_code": "ur" + }, + "5-browser-extension/README.md": { + "original_hash": "b121a279a6ab39878491f3e572673515", + "translation_date": "2025-08-25T23:26:02+00:00", + "source_file": "5-browser-extension/README.md", + "language_code": "ur" + }, + "5-browser-extension/solution/README.md": { + "original_hash": "fab4e6b4f0efcd587a9029d82991f597", + "translation_date": "2025-08-25T23:50:11+00:00", + "source_file": "5-browser-extension/solution/README.md", + "language_code": "ur" + }, + "5-browser-extension/solution/translation/README.es.md": { + "original_hash": "cbaf73f94a9ab4c680a10ef871e92948", + "translation_date": "2025-08-25T23:52:00+00:00", + "source_file": "5-browser-extension/solution/translation/README.es.md", + "language_code": "ur" + }, + "5-browser-extension/solution/translation/README.fr.md": { + "original_hash": "9361268ca430b2579375009e1eceb5e5", + "translation_date": "2025-08-25T23:57:21+00:00", + "source_file": "5-browser-extension/solution/translation/README.fr.md", + "language_code": "ur" + }, + "5-browser-extension/solution/translation/README.hi.md": { + "original_hash": "dd58ae1b7707034f055718c1b68bc8de", + "translation_date": "2025-08-25T23:53:44+00:00", + "source_file": "5-browser-extension/solution/translation/README.hi.md", + "language_code": "ur" + }, + "5-browser-extension/solution/translation/README.it.md": { + "original_hash": "9a6b22a2eff0f499b66236be973b24ad", + "translation_date": "2025-08-25T23:59:07+00:00", + "source_file": "5-browser-extension/solution/translation/README.it.md", + "language_code": "ur" + }, + "5-browser-extension/solution/translation/README.ja.md": { + "original_hash": "3f5e6821e0febccfc5d05e7c944d9e3d", + "translation_date": "2025-08-26T00:00:54+00:00", + "source_file": "5-browser-extension/solution/translation/README.ja.md", + "language_code": "ur" + }, + "5-browser-extension/solution/translation/README.ms.md": { + "original_hash": "21b364c158c8e4f698de65eeac16c9fe", + "translation_date": "2025-08-25T23:55:33+00:00", + "source_file": "5-browser-extension/solution/translation/README.ms.md", + "language_code": "ur" + }, + "5-browser-extension/start/README.md": { + "original_hash": "26fd39046d264ba185dcb086d3a8cf3e", + "translation_date": "2025-08-25T23:34:52+00:00", + "source_file": "5-browser-extension/start/README.md", + "language_code": "ur" + }, + "6-space-game/1-introduction/README.md": { + "original_hash": "a6332a7bb4d0be3bfd24199c83993777", + "translation_date": "2025-11-03T13:36:40+00:00", + "source_file": "6-space-game/1-introduction/README.md", + "language_code": "ur" + }, + "6-space-game/1-introduction/assignment.md": { + "original_hash": "c8fc39a014d08247c082878122e2ba73", + "translation_date": "2025-10-22T15:11:57+00:00", + "source_file": "6-space-game/1-introduction/assignment.md", + "language_code": "ur" + }, + "6-space-game/2-drawing-to-canvas/README.md": { + "original_hash": "7994743c5b21fdcceb36307916ef249a", + "translation_date": "2025-11-03T13:32:20+00:00", + "source_file": "6-space-game/2-drawing-to-canvas/README.md", + "language_code": "ur" + }, + "6-space-game/2-drawing-to-canvas/assignment.md": { + "original_hash": "87cd43afe5b69dbbffb5c4b209ea6791", + "translation_date": "2025-10-22T15:09:25+00:00", + "source_file": "6-space-game/2-drawing-to-canvas/assignment.md", + "language_code": "ur" + }, + "6-space-game/3-moving-elements-around/README.md": { + "original_hash": "8c55a2bd4bc0ebe4c88198fd563a9e09", + "translation_date": "2025-11-03T13:30:35+00:00", + "source_file": "6-space-game/3-moving-elements-around/README.md", + "language_code": "ur" + }, + "6-space-game/3-moving-elements-around/assignment.md": { + "original_hash": "c162b3b3a1cafc1483c8015e9b266f0d", + "translation_date": "2025-10-22T15:08:43+00:00", + "source_file": "6-space-game/3-moving-elements-around/assignment.md", + "language_code": "ur" + }, + "6-space-game/4-collision-detection/README.md": { + "original_hash": "039b4d8ce65f5edd82cf48d9c3e6728c", + "translation_date": "2025-11-03T13:35:53+00:00", + "source_file": "6-space-game/4-collision-detection/README.md", + "language_code": "ur" + }, + "6-space-game/4-collision-detection/assignment.md": { + "original_hash": "124efddbb65166cddb38075ad6dae324", + "translation_date": "2025-10-22T15:11:17+00:00", + "source_file": "6-space-game/4-collision-detection/assignment.md", + "language_code": "ur" + }, + "6-space-game/4-collision-detection/solution/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-25T22:28:03+00:00", + "source_file": "6-space-game/4-collision-detection/solution/README.md", + "language_code": "ur" + }, + "6-space-game/4-collision-detection/your-work/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-25T22:27:14+00:00", + "source_file": "6-space-game/4-collision-detection/your-work/README.md", + "language_code": "ur" + }, + "6-space-game/5-keeping-score/README.md": { + "original_hash": "2ed9145a16cf576faa2a973dff84d099", + "translation_date": "2025-11-03T13:37:22+00:00", + "source_file": "6-space-game/5-keeping-score/README.md", + "language_code": "ur" + }, + "6-space-game/5-keeping-score/assignment.md": { + "original_hash": "81f292dbda01685b91735e0398dc0504", + "translation_date": "2025-08-25T22:06:15+00:00", + "source_file": "6-space-game/5-keeping-score/assignment.md", + "language_code": "ur" + }, + "6-space-game/5-keeping-score/solution/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-25T22:08:15+00:00", + "source_file": "6-space-game/5-keeping-score/solution/README.md", + "language_code": "ur" + }, + "6-space-game/5-keeping-score/your-work/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-25T22:07:21+00:00", + "source_file": "6-space-game/5-keeping-score/your-work/README.md", + "language_code": "ur" + }, + "6-space-game/6-end-condition/README.md": { + "original_hash": "a4b78043f4d64bf3ee24e0689b8b391d", + "translation_date": "2025-11-03T13:33:58+00:00", + "source_file": "6-space-game/6-end-condition/README.md", + "language_code": "ur" + }, + "6-space-game/6-end-condition/assignment.md": { + "original_hash": "232d592791465c1678cab3a2bb6cd3e8", + "translation_date": "2025-10-22T15:10:11+00:00", + "source_file": "6-space-game/6-end-condition/assignment.md", + "language_code": "ur" + }, + "6-space-game/6-end-condition/solution/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-25T22:39:49+00:00", + "source_file": "6-space-game/6-end-condition/solution/README.md", + "language_code": "ur" + }, + "6-space-game/6-end-condition/your-work/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-25T22:39:00+00:00", + "source_file": "6-space-game/6-end-condition/your-work/README.md", + "language_code": "ur" + }, + "6-space-game/README.md": { + "original_hash": "c40a698395ee5102715f7880bba3f2e7", + "translation_date": "2025-08-25T22:01:25+00:00", + "source_file": "6-space-game/README.md", + "language_code": "ur" + }, + "6-space-game/solution/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-25T22:40:36+00:00", + "source_file": "6-space-game/solution/README.md", + "language_code": "ur" + }, + "7-bank-project/1-template-route/README.md": { + "original_hash": "351678bece18f07d9daa987a881fb062", + "translation_date": "2025-11-03T13:23:42+00:00", + "source_file": "7-bank-project/1-template-route/README.md", + "language_code": "ur" + }, + "7-bank-project/1-template-route/assignment.md": { + "original_hash": "df0dcecddcd28ea8cbf6ede0ad57d673", + "translation_date": "2025-10-22T15:03:16+00:00", + "source_file": "7-bank-project/1-template-route/assignment.md", + "language_code": "ur" + }, + "7-bank-project/2-forms/README.md": { + "original_hash": "7cbdbd132d39a2bb493e85bc2a9387cc", + "translation_date": "2025-11-03T13:26:00+00:00", + "source_file": "7-bank-project/2-forms/README.md", + "language_code": "ur" + }, + "7-bank-project/2-forms/assignment.md": { + "original_hash": "efb01fcafd2ef40c593a6e662fc938a8", + "translation_date": "2025-10-22T15:05:35+00:00", + "source_file": "7-bank-project/2-forms/assignment.md", + "language_code": "ur" + }, + "7-bank-project/3-data/README.md": { + "original_hash": "86ee5069f27ea3151389d8687c95fac9", + "translation_date": "2025-11-03T13:21:06+00:00", + "source_file": "7-bank-project/3-data/README.md", + "language_code": "ur" + }, + "7-bank-project/3-data/assignment.md": { + "original_hash": "d0a02cb117e91a5b5f24178080068a3d", + "translation_date": "2025-10-22T15:00:56+00:00", + "source_file": "7-bank-project/3-data/assignment.md", + "language_code": "ur" + }, + "7-bank-project/4-state-management/README.md": { + "original_hash": "b807b09df716dc48a2b750835bf8e933", + "translation_date": "2025-11-03T13:18:39+00:00", + "source_file": "7-bank-project/4-state-management/README.md", + "language_code": "ur" + }, + "7-bank-project/4-state-management/assignment.md": { + "original_hash": "50a7783473b39a2e0f133e271a102231", + "translation_date": "2025-10-22T14:58:15+00:00", + "source_file": "7-bank-project/4-state-management/assignment.md", + "language_code": "ur" + }, + "7-bank-project/README.md": { + "original_hash": "830359535306594b448db6575ce5cdee", + "translation_date": "2025-08-26T00:02:42+00:00", + "source_file": "7-bank-project/README.md", + "language_code": "ur" + }, + "7-bank-project/api/README.md": { + "original_hash": "9884f8c8a61cf56214450f8b16a094ce", + "translation_date": "2025-08-26T00:04:13+00:00", + "source_file": "7-bank-project/api/README.md", + "language_code": "ur" + }, + "7-bank-project/solution/README.md": { + "original_hash": "461aa4fc74c6b1789c3a13b5d82c0cd9", + "translation_date": "2025-08-26T00:39:14+00:00", + "source_file": "7-bank-project/solution/README.md", + "language_code": "ur" + }, + "8-code-editor/1-using-a-code-editor/README.md": { + "original_hash": "a9a3bcc037a447e2d8994d99e871cd9f", + "translation_date": "2025-11-03T12:56:53+00:00", + "source_file": "8-code-editor/1-using-a-code-editor/README.md", + "language_code": "ur" + }, + "8-code-editor/1-using-a-code-editor/assignment.md": { + "original_hash": "effe56ba51c38d7bdfad1ea38288666b", + "translation_date": "2025-10-22T14:36:54+00:00", + "source_file": "8-code-editor/1-using-a-code-editor/assignment.md", + "language_code": "ur" + }, + "9-chat-project/README.md": { + "original_hash": "2066c17078e9d18b5e309f31d8e8bc24", + "translation_date": "2025-11-03T13:10:45+00:00", + "source_file": "9-chat-project/README.md", + "language_code": "ur" + }, + "9-chat-project/solution/README.md": { + "original_hash": "cb549dcad8eea3221cb89793aeaa3bb3", + "translation_date": "2025-09-01T15:21:26+00:00", + "source_file": "9-chat-project/solution/README.md", + "language_code": "ur" + }, + "9-chat-project/solution/backend/README.md": { + "original_hash": "bcd2c2bbaae71151b1ed1b9170aa78af", + "translation_date": "2025-09-01T15:42:19+00:00", + "source_file": "9-chat-project/solution/backend/README.md", + "language_code": "ur" + }, + "9-chat-project/solution/backend/python/README.md": { + "original_hash": "0aaa930f076f2d83cc872ad157f8ffd3", + "translation_date": "2025-10-22T14:51:21+00:00", + "source_file": "9-chat-project/solution/backend/python/README.md", + "language_code": "ur" + }, + "9-chat-project/solution/frontend/README.md": { + "original_hash": "7746a470be8fc7f736eb1b43ebb710ee", + "translation_date": "2025-09-01T15:51:05+00:00", + "source_file": "9-chat-project/solution/frontend/README.md", + "language_code": "ur" + }, + "AGENTS.md": { + "original_hash": "a362efd06d64d4134a0cfe8515a86d34", + "translation_date": "2025-10-03T11:15:55+00:00", + "source_file": "AGENTS.md", + "language_code": "ur" + }, + "CODE_OF_CONDUCT.md": { + "original_hash": "b0a9b4cccd918195f58224d5793da1a6", + "translation_date": "2025-08-25T20:58:01+00:00", + "source_file": "CODE_OF_CONDUCT.md", + "language_code": "ur" + }, + "CONTRIBUTING.md": { + "original_hash": "777400e9f0336c7ee2f9a1200a88478f", + "translation_date": "2025-08-25T21:02:32+00:00", + "source_file": "CONTRIBUTING.md", + "language_code": "ur" + }, + "Git-Basics/README.md": { + "original_hash": "5cf5e1ed51455fefed4895fcc4d6ba2a", + "translation_date": "2025-10-03T15:46:23+00:00", + "source_file": "Git-Basics/README.md", + "language_code": "ur" + }, + "README.md": { + "original_hash": "490c83786552d7fab6390991517bef09", + "translation_date": "2026-01-29T17:43:12+00:00", + "source_file": "README.md", + "language_code": "ur" + }, + "SECURITY.md": { + "original_hash": "4ecc3bf2e27983d4c780be6f26ee6228", + "translation_date": "2025-08-25T21:00:13+00:00", + "source_file": "SECURITY.md", + "language_code": "ur" + }, + "SUPPORT.md": { + "original_hash": "c9d207ff77b4bb46e46dc2b607a8ec1a", + "translation_date": "2025-08-25T20:54:24+00:00", + "source_file": "SUPPORT.md", + "language_code": "ur" + }, + "_404.md": { + "original_hash": "ea9f0804bd62f46d9808e953ec7fc459", + "translation_date": "2025-08-25T20:59:04+00:00", + "source_file": "_404.md", + "language_code": "ur" + }, + "docs/_navbar.md": { + "original_hash": "3bd2f51ecf4ac9b39277cba748943793", + "translation_date": "2025-08-25T22:00:10+00:00", + "source_file": "docs/_navbar.md", + "language_code": "ur" + }, + "docs/_sidebar.md": { + "original_hash": "655c91b5979de46f1d70d97f0c5f1d14", + "translation_date": "2025-08-25T21:58:33+00:00", + "source_file": "docs/_sidebar.md", + "language_code": "ur" + }, + "for-teachers.md": { + "original_hash": "71009af209f81cc01a1f2d324200375f", + "translation_date": "2025-10-03T08:42:38+00:00", + "source_file": "for-teachers.md", + "language_code": "ur" + }, + "lesson-template/README.md": { + "original_hash": "0494be70ad7fadd13a8c3d549c23e355", + "translation_date": "2025-08-26T00:50:45+00:00", + "source_file": "lesson-template/README.md", + "language_code": "ur" + }, + "lesson-template/assignment.md": { + "original_hash": "b5f62ec256c7e43e771f0d3b4e1a9130", + "translation_date": "2025-08-26T00:52:01+00:00", + "source_file": "lesson-template/assignment.md", + "language_code": "ur" + }, + "memory-game/README.md": { + "original_hash": "ff47271e53637b2ba6ba72ad2b70f6d7", + "translation_date": "2025-10-03T11:53:51+00:00", + "source_file": "memory-game/README.md", + "language_code": "ur" + }, + "quiz-app/README.md": { + "original_hash": "5301875c55bb305e6046bed3a4fd06d2", + "translation_date": "2025-08-26T01:11:36+00:00", + "source_file": "quiz-app/README.md", + "language_code": "ur" + } +} \ No newline at end of file diff --git a/translations/zh-CN/.co-op-translator.json b/translations/zh-CN/.co-op-translator.json new file mode 100644 index 000000000..bf649cb68 --- /dev/null +++ b/translations/zh-CN/.co-op-translator.json @@ -0,0 +1,584 @@ +{ + "1-getting-started-lessons/1-intro-to-programming-languages/README.md": { + "original_hash": "d45ddcc54eb9232a76d08328b09d792e", + "translation_date": "2026-01-06T11:58:19+00:00", + "source_file": "1-getting-started-lessons/1-intro-to-programming-languages/README.md", + "language_code": "zh-CN" + }, + "1-getting-started-lessons/1-intro-to-programming-languages/assignment.md": { + "original_hash": "17b8ec8e85d99e27dcb3f73842e583be", + "translation_date": "2026-01-06T12:01:03+00:00", + "source_file": "1-getting-started-lessons/1-intro-to-programming-languages/assignment.md", + "language_code": "zh-CN" + }, + "1-getting-started-lessons/2-github-basics/README.md": { + "original_hash": "5c383cc2cc23bb164b06417d1c107a44", + "translation_date": "2026-01-06T12:01:16+00:00", + "source_file": "1-getting-started-lessons/2-github-basics/README.md", + "language_code": "zh-CN" + }, + "1-getting-started-lessons/3-accessibility/README.md": { + "original_hash": "7f2c48e04754724123ea100a822765e5", + "translation_date": "2026-01-06T11:54:52+00:00", + "source_file": "1-getting-started-lessons/3-accessibility/README.md", + "language_code": "zh-CN" + }, + "1-getting-started-lessons/3-accessibility/assignment.md": { + "original_hash": "e6d0f456dfc22afb41bbdefeb5ec179d", + "translation_date": "2026-01-06T11:57:51+00:00", + "source_file": "1-getting-started-lessons/3-accessibility/assignment.md", + "language_code": "zh-CN" + }, + "1-getting-started-lessons/README.md": { + "original_hash": "770d9f83dddc841c19f210dee5fe0712", + "translation_date": "2025-10-03T13:25:55+00:00", + "source_file": "1-getting-started-lessons/README.md", + "language_code": "zh-CN" + }, + "10-ai-framework-project/README.md": { + "original_hash": "3925b6a1c31c60755eaae4d578232c25", + "translation_date": "2026-01-06T11:03:16+00:00", + "source_file": "10-ai-framework-project/README.md", + "language_code": "zh-CN" + }, + "10-ai-framework-project/solution/README.md": { + "original_hash": "d41d8cd98f00b204e9800998ecf8427e", + "translation_date": "2026-01-29T17:41:28+00:00", + "source_file": "10-ai-framework-project/solution/README.md", + "language_code": "zh-CN" + }, + "2-js-basics/1-data-types/README.md": { + "original_hash": "672b0bb6e8b431075f3bdb7130590d2d", + "translation_date": "2026-01-06T11:12:57+00:00", + "source_file": "2-js-basics/1-data-types/README.md", + "language_code": "zh-CN" + }, + "2-js-basics/1-data-types/assignment.md": { + "original_hash": "6fd645e97c48cd5eb5a3d290815ec8b5", + "translation_date": "2026-01-06T11:14:42+00:00", + "source_file": "2-js-basics/1-data-types/assignment.md", + "language_code": "zh-CN" + }, + "2-js-basics/2-functions-methods/README.md": { + "original_hash": "71f7d7dafa1c7194d79ddac87f669ff9", + "translation_date": "2026-01-06T11:10:57+00:00", + "source_file": "2-js-basics/2-functions-methods/README.md", + "language_code": "zh-CN" + }, + "2-js-basics/2-functions-methods/assignment.md": { + "original_hash": "8328f58f4593b4671656ff8f4b2edbd9", + "translation_date": "2026-01-06T11:12:43+00:00", + "source_file": "2-js-basics/2-functions-methods/assignment.md", + "language_code": "zh-CN" + }, + "2-js-basics/3-making-decisions/README.md": { + "original_hash": "c688385d15dd3645e924ea0ffee8967f", + "translation_date": "2026-01-06T11:14:50+00:00", + "source_file": "2-js-basics/3-making-decisions/README.md", + "language_code": "zh-CN" + }, + "2-js-basics/3-making-decisions/assignment.md": { + "original_hash": "ffe366b2d1f037b99fbadbe1dc81083d", + "translation_date": "2026-01-06T11:17:04+00:00", + "source_file": "2-js-basics/3-making-decisions/assignment.md", + "language_code": "zh-CN" + }, + "2-js-basics/4-arrays-loops/README.md": { + "original_hash": "1710a50a519a6e4a1b40a5638783018d", + "translation_date": "2026-01-06T11:17:26+00:00", + "source_file": "2-js-basics/4-arrays-loops/README.md", + "language_code": "zh-CN" + }, + "2-js-basics/4-arrays-loops/assignment.md": { + "original_hash": "8abcada0534e0fb3a7556ea3c5a2a8a4", + "translation_date": "2026-01-06T11:19:25+00:00", + "source_file": "2-js-basics/4-arrays-loops/assignment.md", + "language_code": "zh-CN" + }, + "2-js-basics/README.md": { + "original_hash": "cc9e70a2f096c67389c8acff1521fc27", + "translation_date": "2025-08-23T22:36:41+00:00", + "source_file": "2-js-basics/README.md", + "language_code": "zh-CN" + }, + "3-terrarium/1-intro-to-html/README.md": { + "original_hash": "3fcfa99c4897e051b558b5eaf1e8cc74", + "translation_date": "2026-01-06T11:48:52+00:00", + "source_file": "3-terrarium/1-intro-to-html/README.md", + "language_code": "zh-CN" + }, + "3-terrarium/1-intro-to-html/assignment.md": { + "original_hash": "650e63282e1dfa032890fcf5c1c4119d", + "translation_date": "2026-01-06T11:50:29+00:00", + "source_file": "3-terrarium/1-intro-to-html/assignment.md", + "language_code": "zh-CN" + }, + "3-terrarium/2-intro-to-css/README.md": { + "original_hash": "e39f3a4e3bcccf94639e3af1248f8a4d", + "translation_date": "2026-01-06T11:53:01+00:00", + "source_file": "3-terrarium/2-intro-to-css/README.md", + "language_code": "zh-CN" + }, + "3-terrarium/2-intro-to-css/assignment.md": { + "original_hash": "bee6762d4092a13fc7c338814963f980", + "translation_date": "2026-01-06T11:54:36+00:00", + "source_file": "3-terrarium/2-intro-to-css/assignment.md", + "language_code": "zh-CN" + }, + "3-terrarium/3-intro-to-DOM-and-closures/README.md": { + "original_hash": "973e48ad87d67bf5bb819746c9f8e302", + "translation_date": "2026-01-06T11:50:49+00:00", + "source_file": "3-terrarium/3-intro-to-DOM-and-closures/README.md", + "language_code": "zh-CN" + }, + "3-terrarium/3-intro-to-DOM-and-closures/assignment.md": { + "original_hash": "947ca5ce7c94aee9c7de7034e762bc17", + "translation_date": "2026-01-06T11:52:45+00:00", + "source_file": "3-terrarium/3-intro-to-DOM-and-closures/assignment.md", + "language_code": "zh-CN" + }, + "3-terrarium/README.md": { + "original_hash": "bc5c5550f79d10add90ce419ee34abb3", + "translation_date": "2026-01-06T11:06:19+00:00", + "source_file": "3-terrarium/README.md", + "language_code": "zh-CN" + }, + "3-terrarium/solution/README.md": { + "original_hash": "6329fbe8bd936068debd78cca6f09c0a", + "translation_date": "2025-08-23T22:35:49+00:00", + "source_file": "3-terrarium/solution/README.md", + "language_code": "zh-CN" + }, + "4-typing-game/README.md": { + "original_hash": "efa2ab875b8bb5a7883816506da6b6d2", + "translation_date": "2026-01-06T11:05:33+00:00", + "source_file": "4-typing-game/README.md", + "language_code": "zh-CN" + }, + "4-typing-game/solution/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-24T00:17:41+00:00", + "source_file": "4-typing-game/solution/README.md", + "language_code": "zh-CN" + }, + "4-typing-game/typing-game/README.md": { + "original_hash": "da8bc72041a2bb3826a54654ee1a8844", + "translation_date": "2026-01-06T11:47:12+00:00", + "source_file": "4-typing-game/typing-game/README.md", + "language_code": "zh-CN" + }, + "4-typing-game/typing-game/assignment.md": { + "original_hash": "3eac59d70e2532a677a2ce6bf765485a", + "translation_date": "2026-01-06T11:48:41+00:00", + "source_file": "4-typing-game/typing-game/assignment.md", + "language_code": "zh-CN" + }, + "5-browser-extension/1-about-browsers/README.md": { + "original_hash": "00aa85715e1efd4930c17a23e3012e69", + "translation_date": "2026-01-06T11:36:28+00:00", + "source_file": "5-browser-extension/1-about-browsers/README.md", + "language_code": "zh-CN" + }, + "5-browser-extension/1-about-browsers/assignment.md": { + "original_hash": "b6897c02603d0045dd6d8256e8714baa", + "translation_date": "2026-01-06T11:37:53+00:00", + "source_file": "5-browser-extension/1-about-browsers/assignment.md", + "language_code": "zh-CN" + }, + "5-browser-extension/2-forms-browsers-local-storage/README.md": { + "original_hash": "2b6203a48c48d8234e0948353b47d84e", + "translation_date": "2026-01-06T11:32:52+00:00", + "source_file": "5-browser-extension/2-forms-browsers-local-storage/README.md", + "language_code": "zh-CN" + }, + "5-browser-extension/2-forms-browsers-local-storage/assignment.md": { + "original_hash": "25b8d28b8531352d4eb67291fd7824c4", + "translation_date": "2026-01-06T11:34:27+00:00", + "source_file": "5-browser-extension/2-forms-browsers-local-storage/assignment.md", + "language_code": "zh-CN" + }, + "5-browser-extension/3-background-tasks-and-performance/README.md": { + "original_hash": "b275fed2c6fc90d2b9b6661a3225faa2", + "translation_date": "2026-01-06T11:34:42+00:00", + "source_file": "5-browser-extension/3-background-tasks-and-performance/README.md", + "language_code": "zh-CN" + }, + "5-browser-extension/3-background-tasks-and-performance/assignment.md": { + "original_hash": "a203e560e58ccc6ba68bffc40c7c8676", + "translation_date": "2026-01-06T11:36:13+00:00", + "source_file": "5-browser-extension/3-background-tasks-and-performance/assignment.md", + "language_code": "zh-CN" + }, + "5-browser-extension/README.md": { + "original_hash": "b121a279a6ab39878491f3e572673515", + "translation_date": "2025-08-23T23:37:05+00:00", + "source_file": "5-browser-extension/README.md", + "language_code": "zh-CN" + }, + "5-browser-extension/solution/README.md": { + "original_hash": "fab4e6b4f0efcd587a9029d82991f597", + "translation_date": "2025-08-23T23:48:13+00:00", + "source_file": "5-browser-extension/solution/README.md", + "language_code": "zh-CN" + }, + "5-browser-extension/solution/translation/README.es.md": { + "original_hash": "cbaf73f94a9ab4c680a10ef871e92948", + "translation_date": "2025-08-23T23:49:06+00:00", + "source_file": "5-browser-extension/solution/translation/README.es.md", + "language_code": "zh-CN" + }, + "5-browser-extension/solution/translation/README.fr.md": { + "original_hash": "9361268ca430b2579375009e1eceb5e5", + "translation_date": "2025-08-23T23:51:49+00:00", + "source_file": "5-browser-extension/solution/translation/README.fr.md", + "language_code": "zh-CN" + }, + "5-browser-extension/solution/translation/README.hi.md": { + "original_hash": "dd58ae1b7707034f055718c1b68bc8de", + "translation_date": "2025-08-23T23:50:02+00:00", + "source_file": "5-browser-extension/solution/translation/README.hi.md", + "language_code": "zh-CN" + }, + "5-browser-extension/solution/translation/README.it.md": { + "original_hash": "9a6b22a2eff0f499b66236be973b24ad", + "translation_date": "2025-08-23T23:52:42+00:00", + "source_file": "5-browser-extension/solution/translation/README.it.md", + "language_code": "zh-CN" + }, + "5-browser-extension/solution/translation/README.ja.md": { + "original_hash": "3f5e6821e0febccfc5d05e7c944d9e3d", + "translation_date": "2025-08-23T23:53:33+00:00", + "source_file": "5-browser-extension/solution/translation/README.ja.md", + "language_code": "zh-CN" + }, + "5-browser-extension/solution/translation/README.ms.md": { + "original_hash": "21b364c158c8e4f698de65eeac16c9fe", + "translation_date": "2025-08-23T23:50:56+00:00", + "source_file": "5-browser-extension/solution/translation/README.ms.md", + "language_code": "zh-CN" + }, + "5-browser-extension/start/README.md": { + "original_hash": "26fd39046d264ba185dcb086d3a8cf3e", + "translation_date": "2025-08-23T23:41:12+00:00", + "source_file": "5-browser-extension/start/README.md", + "language_code": "zh-CN" + }, + "6-space-game/1-introduction/README.md": { + "original_hash": "a6332a7bb4d0be3bfd24199c83993777", + "translation_date": "2026-01-06T11:29:06+00:00", + "source_file": "6-space-game/1-introduction/README.md", + "language_code": "zh-CN" + }, + "6-space-game/1-introduction/assignment.md": { + "original_hash": "c8fc39a014d08247c082878122e2ba73", + "translation_date": "2026-01-06T11:30:50+00:00", + "source_file": "6-space-game/1-introduction/assignment.md", + "language_code": "zh-CN" + }, + "6-space-game/2-drawing-to-canvas/README.md": { + "original_hash": "7994743c5b21fdcceb36307916ef249a", + "translation_date": "2026-01-06T11:24:04+00:00", + "source_file": "6-space-game/2-drawing-to-canvas/README.md", + "language_code": "zh-CN" + }, + "6-space-game/2-drawing-to-canvas/assignment.md": { + "original_hash": "87cd43afe5b69dbbffb5c4b209ea6791", + "translation_date": "2026-01-06T11:25:39+00:00", + "source_file": "6-space-game/2-drawing-to-canvas/assignment.md", + "language_code": "zh-CN" + }, + "6-space-game/3-moving-elements-around/README.md": { + "original_hash": "8c55a2bd4bc0ebe4c88198fd563a9e09", + "translation_date": "2026-01-06T11:31:07+00:00", + "source_file": "6-space-game/3-moving-elements-around/README.md", + "language_code": "zh-CN" + }, + "6-space-game/3-moving-elements-around/assignment.md": { + "original_hash": "c162b3b3a1cafc1483c8015e9b266f0d", + "translation_date": "2026-01-06T11:32:45+00:00", + "source_file": "6-space-game/3-moving-elements-around/assignment.md", + "language_code": "zh-CN" + }, + "6-space-game/4-collision-detection/README.md": { + "original_hash": "039b4d8ce65f5edd82cf48d9c3e6728c", + "translation_date": "2026-01-06T11:22:28+00:00", + "source_file": "6-space-game/4-collision-detection/README.md", + "language_code": "zh-CN" + }, + "6-space-game/4-collision-detection/assignment.md": { + "original_hash": "124efddbb65166cddb38075ad6dae324", + "translation_date": "2026-01-06T11:23:55+00:00", + "source_file": "6-space-game/4-collision-detection/assignment.md", + "language_code": "zh-CN" + }, + "6-space-game/4-collision-detection/solution/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-23T23:03:54+00:00", + "source_file": "6-space-game/4-collision-detection/solution/README.md", + "language_code": "zh-CN" + }, + "6-space-game/4-collision-detection/your-work/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-23T23:03:24+00:00", + "source_file": "6-space-game/4-collision-detection/your-work/README.md", + "language_code": "zh-CN" + }, + "6-space-game/5-keeping-score/README.md": { + "original_hash": "2ed9145a16cf576faa2a973dff84d099", + "translation_date": "2026-01-06T11:28:05+00:00", + "source_file": "6-space-game/5-keeping-score/README.md", + "language_code": "zh-CN" + }, + "6-space-game/5-keeping-score/assignment.md": { + "original_hash": "81f292dbda01685b91735e0398dc0504", + "translation_date": "2025-08-23T22:53:29+00:00", + "source_file": "6-space-game/5-keeping-score/assignment.md", + "language_code": "zh-CN" + }, + "6-space-game/5-keeping-score/solution/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-23T22:54:32+00:00", + "source_file": "6-space-game/5-keeping-score/solution/README.md", + "language_code": "zh-CN" + }, + "6-space-game/5-keeping-score/your-work/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-23T22:54:04+00:00", + "source_file": "6-space-game/5-keeping-score/your-work/README.md", + "language_code": "zh-CN" + }, + "6-space-game/6-end-condition/README.md": { + "original_hash": "a4b78043f4d64bf3ee24e0689b8b391d", + "translation_date": "2026-01-06T11:25:54+00:00", + "source_file": "6-space-game/6-end-condition/README.md", + "language_code": "zh-CN" + }, + "6-space-game/6-end-condition/assignment.md": { + "original_hash": "232d592791465c1678cab3a2bb6cd3e8", + "translation_date": "2026-01-06T11:27:43+00:00", + "source_file": "6-space-game/6-end-condition/assignment.md", + "language_code": "zh-CN" + }, + "6-space-game/6-end-condition/solution/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-23T23:09:58+00:00", + "source_file": "6-space-game/6-end-condition/solution/README.md", + "language_code": "zh-CN" + }, + "6-space-game/6-end-condition/your-work/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-23T23:09:28+00:00", + "source_file": "6-space-game/6-end-condition/your-work/README.md", + "language_code": "zh-CN" + }, + "6-space-game/README.md": { + "original_hash": "c40a698395ee5102715f7880bba3f2e7", + "translation_date": "2025-08-23T22:51:01+00:00", + "source_file": "6-space-game/README.md", + "language_code": "zh-CN" + }, + "6-space-game/solution/README.md": { + "original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c", + "translation_date": "2025-08-23T23:10:27+00:00", + "source_file": "6-space-game/solution/README.md", + "language_code": "zh-CN" + }, + "7-bank-project/1-template-route/README.md": { + "original_hash": "351678bece18f07d9daa987a881fb062", + "translation_date": "2026-01-06T11:40:39+00:00", + "source_file": "7-bank-project/1-template-route/README.md", + "language_code": "zh-CN" + }, + "7-bank-project/1-template-route/assignment.md": { + "original_hash": "df0dcecddcd28ea8cbf6ede0ad57d673", + "translation_date": "2026-01-06T11:42:27+00:00", + "source_file": "7-bank-project/1-template-route/assignment.md", + "language_code": "zh-CN" + }, + "7-bank-project/2-forms/README.md": { + "original_hash": "7cbdbd132d39a2bb493e85bc2a9387cc", + "translation_date": "2026-01-06T11:38:09+00:00", + "source_file": "7-bank-project/2-forms/README.md", + "language_code": "zh-CN" + }, + "7-bank-project/2-forms/assignment.md": { + "original_hash": "efb01fcafd2ef40c593a6e662fc938a8", + "translation_date": "2026-01-06T11:40:21+00:00", + "source_file": "7-bank-project/2-forms/assignment.md", + "language_code": "zh-CN" + }, + "7-bank-project/3-data/README.md": { + "original_hash": "86ee5069f27ea3151389d8687c95fac9", + "translation_date": "2026-01-06T11:42:36+00:00", + "source_file": "7-bank-project/3-data/README.md", + "language_code": "zh-CN" + }, + "7-bank-project/3-data/assignment.md": { + "original_hash": "d0a02cb117e91a5b5f24178080068a3d", + "translation_date": "2026-01-06T11:44:49+00:00", + "source_file": "7-bank-project/3-data/assignment.md", + "language_code": "zh-CN" + }, + "7-bank-project/4-state-management/README.md": { + "original_hash": "b807b09df716dc48a2b750835bf8e933", + "translation_date": "2026-01-06T11:45:06+00:00", + "source_file": "7-bank-project/4-state-management/README.md", + "language_code": "zh-CN" + }, + "7-bank-project/4-state-management/assignment.md": { + "original_hash": "50a7783473b39a2e0f133e271a102231", + "translation_date": "2026-01-06T11:46:54+00:00", + "source_file": "7-bank-project/4-state-management/assignment.md", + "language_code": "zh-CN" + }, + "7-bank-project/README.md": { + "original_hash": "830359535306594b448db6575ce5cdee", + "translation_date": "2025-08-23T23:54:25+00:00", + "source_file": "7-bank-project/README.md", + "language_code": "zh-CN" + }, + "7-bank-project/api/README.md": { + "original_hash": "9884f8c8a61cf56214450f8b16a094ce", + "translation_date": "2025-08-23T23:55:10+00:00", + "source_file": "7-bank-project/api/README.md", + "language_code": "zh-CN" + }, + "7-bank-project/solution/README.md": { + "original_hash": "461aa4fc74c6b1789c3a13b5d82c0cd9", + "translation_date": "2025-08-24T00:10:23+00:00", + "source_file": "7-bank-project/solution/README.md", + "language_code": "zh-CN" + }, + "8-code-editor/1-using-a-code-editor/README.md": { + "original_hash": "a9a3bcc037a447e2d8994d99e871cd9f", + "translation_date": "2026-01-06T11:19:40+00:00", + "source_file": "8-code-editor/1-using-a-code-editor/README.md", + "language_code": "zh-CN" + }, + "8-code-editor/1-using-a-code-editor/assignment.md": { + "original_hash": "effe56ba51c38d7bdfad1ea38288666b", + "translation_date": "2026-01-06T11:21:50+00:00", + "source_file": "8-code-editor/1-using-a-code-editor/assignment.md", + "language_code": "zh-CN" + }, + "9-chat-project/README.md": { + "original_hash": "2066c17078e9d18b5e309f31d8e8bc24", + "translation_date": "2026-01-06T11:06:24+00:00", + "source_file": "9-chat-project/README.md", + "language_code": "zh-CN" + }, + "9-chat-project/solution/README.md": { + "original_hash": "cb549dcad8eea3221cb89793aeaa3bb3", + "translation_date": "2025-09-01T15:22:00+00:00", + "source_file": "9-chat-project/solution/README.md", + "language_code": "zh-CN" + }, + "9-chat-project/solution/backend/README.md": { + "original_hash": "bcd2c2bbaae71151b1ed1b9170aa78af", + "translation_date": "2025-09-01T15:42:23+00:00", + "source_file": "9-chat-project/solution/backend/README.md", + "language_code": "zh-CN" + }, + "9-chat-project/solution/backend/python/README.md": { + "original_hash": "0aaa930f076f2d83cc872ad157f8ffd3", + "translation_date": "2026-01-06T12:03:23+00:00", + "source_file": "9-chat-project/solution/backend/python/README.md", + "language_code": "zh-CN" + }, + "9-chat-project/solution/frontend/README.md": { + "original_hash": "7746a470be8fc7f736eb1b43ebb710ee", + "translation_date": "2025-09-01T15:51:09+00:00", + "source_file": "9-chat-project/solution/frontend/README.md", + "language_code": "zh-CN" + }, + "AGENTS.md": { + "original_hash": "a362efd06d64d4134a0cfe8515a86d34", + "translation_date": "2025-10-03T11:16:34+00:00", + "source_file": "AGENTS.md", + "language_code": "zh-CN" + }, + "CODE_OF_CONDUCT.md": { + "original_hash": "b0a9b4cccd918195f58224d5793da1a6", + "translation_date": "2025-08-23T22:20:05+00:00", + "source_file": "CODE_OF_CONDUCT.md", + "language_code": "zh-CN" + }, + "CONTRIBUTING.md": { + "original_hash": "777400e9f0336c7ee2f9a1200a88478f", + "translation_date": "2025-08-23T22:22:20+00:00", + "source_file": "CONTRIBUTING.md", + "language_code": "zh-CN" + }, + "Git-Basics/README.md": { + "original_hash": "5cf5e1ed51455fefed4895fcc4d6ba2a", + "translation_date": "2025-10-03T15:46:50+00:00", + "source_file": "Git-Basics/README.md", + "language_code": "zh-CN" + }, + "README.md": { + "original_hash": "490c83786552d7fab6390991517bef09", + "translation_date": "2026-01-29T17:44:53+00:00", + "source_file": "README.md", + "language_code": "zh-CN" + }, + "SECURITY.md": { + "original_hash": "4ecc3bf2e27983d4c780be6f26ee6228", + "translation_date": "2025-08-23T22:21:13+00:00", + "source_file": "SECURITY.md", + "language_code": "zh-CN" + }, + "SUPPORT.md": { + "original_hash": "c9d207ff77b4bb46e46dc2b607a8ec1a", + "translation_date": "2025-08-23T22:18:28+00:00", + "source_file": "SUPPORT.md", + "language_code": "zh-CN" + }, + "_404.md": { + "original_hash": "ea9f0804bd62f46d9808e953ec7fc459", + "translation_date": "2025-08-23T22:20:41+00:00", + "source_file": "_404.md", + "language_code": "zh-CN" + }, + "docs/_navbar.md": { + "original_hash": "3bd2f51ecf4ac9b39277cba748943793", + "translation_date": "2025-08-23T22:50:22+00:00", + "source_file": "docs/_navbar.md", + "language_code": "zh-CN" + }, + "docs/_sidebar.md": { + "original_hash": "655c91b5979de46f1d70d97f0c5f1d14", + "translation_date": "2025-08-23T22:49:23+00:00", + "source_file": "docs/_sidebar.md", + "language_code": "zh-CN" + }, + "for-teachers.md": { + "original_hash": "71009af209f81cc01a1f2d324200375f", + "translation_date": "2025-10-03T08:46:37+00:00", + "source_file": "for-teachers.md", + "language_code": "zh-CN" + }, + "lesson-template/README.md": { + "original_hash": "0494be70ad7fadd13a8c3d549c23e355", + "translation_date": "2025-08-24T00:15:43+00:00", + "source_file": "lesson-template/README.md", + "language_code": "zh-CN" + }, + "lesson-template/assignment.md": { + "original_hash": "b5f62ec256c7e43e771f0d3b4e1a9130", + "translation_date": "2025-08-24T00:16:24+00:00", + "source_file": "lesson-template/assignment.md", + "language_code": "zh-CN" + }, + "memory-game/README.md": { + "original_hash": "ff47271e53637b2ba6ba72ad2b70f6d7", + "translation_date": "2025-10-03T11:53:59+00:00", + "source_file": "memory-game/README.md", + "language_code": "zh-CN" + }, + "quiz-app/README.md": { + "original_hash": "5301875c55bb305e6046bed3a4fd06d2", + "translation_date": "2025-08-24T00:22:46+00:00", + "source_file": "quiz-app/README.md", + "language_code": "zh-CN" + } +} \ No newline at end of file diff --git a/translations/zh-CN/1-getting-started-lessons/1-intro-to-programming-languages/README.md b/translations/zh-CN/1-getting-started-lessons/1-intro-to-programming-languages/README.md new file mode 100644 index 000000000..df1ee5a3f --- /dev/null +++ b/translations/zh-CN/1-getting-started-lessons/1-intro-to-programming-languages/README.md @@ -0,0 +1,853 @@ +# 编程语言与现代开发工具简介 + +嗨,未来的开发者!👋 我能告诉你一件每天都会让我激动不已的事情吗?你即将发现,编程不仅仅是关于计算机——它是一种具有真正超能力的方式,能让你把最狂野的创意变成现实! + +你知道用自己最喜欢的应用时那种一切完美契合的时刻吗?当你点击一个按钮,发生了某种神奇的事情,让你忍不住惊叹“哇,他们到底是怎么做到的?”那么,就像你一样的人——可能正坐在他们最喜欢的咖啡馆,凌晨两点喝着第三杯浓咖啡——写出了创造那个魔法的代码。更震撼的是:到本课结束时,你不仅会理解他们是怎么做到的,还会急切想亲自尝试一番! + +听我说,我完全理解如果现在编程看起来让你感到害怕。当我刚开始时,我真的以为你得是某种数学天才,或者从五岁起就开始编程。但有件事彻底改变了我的看法:编程就像学习用一门新语言交谈。你从“你好”和“谢谢”开始,然后学会点咖啡,再到后面能谈天说地!只不过这次,你是在和计算机对话,而说实话?它们是你遇到过的最有耐心的对话伙伴——从不批评你的错误,并且永远乐意再试一次! + +今天,我们将探索那些让现代网页开发不仅可行而且极其上瘾的令人难以置信的工具。我说的是 Netflix、Spotify 和你最喜欢的独立应用工作室每天使用的同样的编辑器、浏览器和工作流程。最棒的是,这些专业级、行业标准的工具大多数是完全免费的! + +![Intro Programming](../../../../translated_images/zh-CN/webdev101-programming.d6e3f98e61ac4bff.webp) +> 速写笔记由 [Tomomi Imura](https://twitter.com/girlie_mac) 制作 + +```mermaid +journey + title 你今天的编程旅程 + section 发现 + 什么是编程: 5: You + 编程语言: 4: You + 工具概览: 5: You + section 探索 + 代码编辑器: 4: You + 浏览器与开发者工具: 5: You + 命令行: 3: You + section 练习 + 语言侦探: 4: You + 工具探索: 5: You + 社区连接: 5: You +``` +## 让我们看看你已经知道什么! + +在我们进入有趣的内容之前,我很好奇——你已经对这个编程世界了解多少?听着,如果你看着这些问题想“我完全一点头绪都没有”,这不仅没关系,还非常完美!这意味着你正处在绝佳的起点。把这个测验想象成锻炼前的拉伸运动——我们只是让大脑先热身! + +[参加课前测验](https://forms.office.com/r/dru4TE0U9n?origin=lprLink) + +## 我们即将一起踏上的冒险之旅 + +好了,我真的非常激动要和你一同探索今天的内容!说真的,我真希望能看到你那些概念“恍然大悟”时的表情。我们将一起经历这段不可思议的旅程: + +- **什么是编程(以及为什么它超酷!)**——我们将发现代码究竟是如何成为无形的魔法,驱动你周围所有事物,从那闹钟怎样知道今天是周一,到算法如何完美推荐你喜欢的 Netflix 内容 +- **编程语言和它们令人惊讶的个性**——想象参加一个派对,每个人都有完全不同的超能力和解决问题的方式。这就是编程语言的世界,你一定会喜欢认识它们! +- **数字魔法发生的基本构建块**——把它们当作终极创意的乐高积木。一旦你理解这些零件是如何拼合的,你会发现你完全可以构建任何你想象中的东西 +- **能让你感觉像拿到巫师魔杖的专业工具**——我一点都不夸张,这些工具真的会让你感觉拥有超能力,更棒的是?它们正是专业人士使用的工具! + +> 💡 **温馨提示**:今天别想着把所有内容都记住!此刻,我只希望你感受到可能性的火花。细节会随着我们的实践自然沉淀——这才是真正的学习过程! + +> 你也可以在 [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101/introduction-programming/?WT.mc_id=academic-77807-sagibbon) 上学习本课程! + +## 那么,什么是*编程*? + +好,让我们来攻克这个价值百万美元的问题:编程究竟是什么? + +我来给你讲一个让我完全改变看法的故事。上周,我试图向我妈妈解释如何使用我们的新智能电视遥控器。我发现自己说着“按那个红色按钮,不是大红按钮,是左边的小红按钮……不,你那边的左边……好了,现在按住两秒,不是一秒,也不是三秒……”是不是很熟悉?😅 + +这就是编程!它是向一个非常强大的对象给出极其详细、逐步的指令的艺术,但必须清楚准确。只不过你不是向妈妈(她可能会问“哪个红色按钮?!”)解释,而是向计算机(它只做你说的,即使不完全是你想要的)。 + +当我第一次学会这点时,真是震惊到不行:计算机其实很简单。它们字面上只懂两种东西——1和0,也就是“是”和“否”或“开”和“关”。就是这么简单!但魔幻的地方在这里——我们不必像电影《黑客帝国》一样说1和0。这时,**编程语言**就派上用场了。它们就像世界上最棒的翻译官,把你完全正常的人类想法转换成计算机语言。 + +每天早上醒来,这点仍然让我激动不已:你生活中所有的数字事物,最初都是像你一样的人,可能穿着睡衣,手拿咖啡,在笔记本上敲代码。那个让你看起来完美无瑕的 Instagram 滤镜?有人写了那段代码。带你发现新歌的推荐算法?开发者设计了它。帮助你和朋友均摊晚餐账单的应用?没错,有人想着“真烦人,我一定能改进它”,结果……他们做到了! + +学会编程,你不仅仅是习得一项新技能——你正在加入这样一个令人敬佩的群体,这群解决问题的人用他们的每一天思考,“如果我能造出点东西,让某个人的一天更美好一点,会怎么样?”说真的,有什么比这更酷的吗? + +✅ **趣味小调查**:闲暇时看看这个超酷的内容——你认为世界上第一位计算机程序员是谁?提示:她可能不是你想象中的那样!这位人士背后的故事极其精彩,说明编程从一开始就是关于创造性解决问题和跳出框架思考。 + +### 🧠 **情绪检查:你感觉如何?** + +**花点时间想想:** +- “向计算机下指令”的想法你现在能理解了吗? +- 你能想到想用编程自动化的日常任务吗? +- 关于编程,你脑海中冒出了哪些问题? + +> **记住**:某些概念暂时模糊完全正常。学编程就像学新语言——需要时间让大脑建立神经回路。你做得很棒! + +## 编程语言就像不同风味的魔法 + +嗯,这听起来可能有点怪,但请坚持听我说——编程语言很像不同类型的音乐。想想看:有爵士乐,流畅且即兴;摇滚,强劲直接;古典,优雅而有结构;还有嘻哈,创意和富于表现力。每种风格都有自己的气质和热情的拥护者社区,同时适合不同的心情和场合。 + +编程语言也是一样!你不会用同一种语言去造一个有趣的手机游戏和处理庞大的气候数据,就像你不会在瑜伽课上听死亡金属(嗯,大多数瑜伽课都是这样!😄)。 + +但每次一想到这点,我都震惊不已:这些语言就像世界上最耐心、最聪明的口译员坐在你旁边。你可以用适合你人脑的方式表达想法,语言帮你完成把这些转换成计算机说的1和0的复杂工作。这就像拥有一个在“人类创造力”和“计算机逻辑”两种语言之间流利切换的朋友——他们永不疲倦,不用喝咖啡休息,也从不因为你重复问同一个问题而评价你! + +### 流行编程语言及其用途 + +```mermaid +mindmap + root((编程语言)) + Web Development + JavaScript + 前端魔法 + 互动网站 + TypeScript + JavaScript + 类型 + 企业应用 + Data & AI + Python + 数据科学 + 机器学习 + 自动化 + R + 统计 + 研究 + Mobile Apps + Java + 安卓 + 企业 + Swift + iOS + 苹果生态系统 + Kotlin + 现代安卓 + 跨平台 + Systems & Performance + C++ + 游戏 + 性能关键 + Rust + 内存安全 + 系统编程 + Go + 云服务 + 可扩展后端 +``` +| 语言 | 最适合 | 为什么受欢迎 | +|------|--------|--------------| +| **JavaScript** | 网页开发,用户界面 | 在浏览器中运行,驱动互动网站 | +| **Python** | 数据科学,自动化,人工智能 | 易读易学,拥有强大库支持 | +| **Java** | 企业应用,安卓应用 | 跨平台,适合大型系统 | +| **C#** | Windows 应用,游戏开发 | 微软生态圈支持强大 | +| **Go** | 云服务,后端系统 | 快速简单,专为现代计算设计 | + +### 高级语言 vs 低级语言 + +说实话,这是我刚开始学时觉得最烧脑的概念,所以我要分享一个让我顿悟的比喻——希望对你也有帮助! + +想象你去一个不会说语言的国家,急需找厕所(我们都经历过,对吧?😅): + +- **低级编程**就像学得那么好本地方言,能和街角卖水果的奶奶聊文化典故、本地俚语和只有当地人懂的笑话。超厉害且高效……如果你流利的话!但当你只是想找个厕所时,简直头大。 + +- **高级编程**就像有一个很棒的本地朋友完全懂你。你用英语说“我急需找厕所”,朋友帮你翻译文化差异,给你解释得非常清楚,适合不懂当地文化的你。 + +编程术语来说: +- **低级语言**(如汇编或C)让你能和计算机硬件进行极其细致的对话,但你得像机器一样思考……嗯,这对脑力是很大考验! +- **高级语言**(如 JavaScript、Python 或 C#)让你像人类一样思考,它们在幕后处理所有机器语言。更棒的是,它们有超友好的社区,里面的人都记得刚入门的艰难,真心想帮助你! + +你猜我推荐你先学哪个?😉 高级语言就像有了辅助轮,虽然你可能永远不会想摘掉,因为它让整体验更愉快! + +```mermaid +flowchart TB + A["👤 人类思维:
'我想计算斐波那契数列'"] --> B{选择语言级别} + + B -->|高级| C["🌟 JavaScript/Python
易读易写"] + B -->|低级| D["⚙️ 汇编/C
直接硬件控制"] + + C --> E["📝 写:fibonacci(10)"] + D --> F["📝 写:mov r0,#00
sub r0,r0,#01"] + + E --> G["🤖 计算机理解:
翻译器处理复杂性"] + F --> G + + G --> H["💻 相同结果:
0, 1, 1, 2, 3, 5, 8, 13..."] + + style C fill:#e1f5fe + style D fill:#fff3e0 + style H fill:#e8f5e8 +``` +### 让我给你展示为什么高级语言更友好 + +好了,我马上给你看点东西,完美展示我为什么爱上高级语言。但先请你答应我一个条件。看到第一段代码示例时,不要慌张!它看起来吓人正是我要说明的点! + +我们将看同一任务用两种完全不同风格写成的代码。它们都会产生所谓的斐波那契数列——这是一个漂亮的数学模式,每个数字是前两个数字之和:0,1,1,2,3,5,8,13……(趣味事实:你会在大自然无处不在地发现这个模式——向日葵的种子螺旋,松果的形状,甚至银河的形成!) + +准备好看差别了吗?走起! + +**高级语言(JavaScript)——人类友好:** + +```javascript +// 第一步:基本斐波那契设置 +const fibonacciCount = 10; +let current = 0; +let next = 1; + +console.log('Fibonacci sequence:'); +``` + +**这段代码做了什么:** +- **声明**一个常量,用来指定我们想生成多少个斐波那契数 +- **初始化**两个变量,用于跟踪数列中的当前值和下一个值 +- **设置**起始值(0和1),定义斐波那契序列 +- **显示**一个标题消息,标示我们的输出 + +```javascript +// 第2步:用循环生成序列 +for (let i = 0; i < fibonacciCount; i++) { + console.log(`Position ${i + 1}: ${current}`); + + // 计算序列中的下一个数字 + const sum = current + next; + current = next; + next = sum; +} +``` + +**代码运行过程中:** +- **用`for`循环**遍历序列中的每个位置 +- **打印**每个数字及其位置,使用模板字符串格式化 +- **计算**下一个斐波那契数,方法是加上当前数和下一个数 +- **更新**跟踪变量,进入下一次循环 + +```javascript +// 第3步:现代函数式方法 +const generateFibonacci = (count) => { + const sequence = [0, 1]; + + for (let i = 2; i < count; i++) { + sequence[i] = sequence[i - 1] + sequence[i - 2]; + } + + return sequence; +}; + +// 使用示例 +const fibSequence = generateFibonacci(10); +console.log(fibSequence); +``` + +**上述代码中:** +- **创建**了一个可复用函数,使用现代箭头函数语法 +- **构建**了一个数组来存储完整序列,而不是逐个展示 +- **使用**数组索引根据前面的值计算新数 +- **返回**完整序列,方便在程序其他部分灵活使用 + +**低级语言(ARM 汇编)——计算机友好:** + +```assembly + area ascen,code,readonly + entry + code32 + adr r0,thumb+1 + bx r0 + code16 +thumb + mov r0,#00 + sub r0,r0,#01 + mov r1,#01 + mov r4,#10 + ldr r2,=0x40000000 +back add r0,r1 + str r0,[r2] + add r2,#04 + mov r3,r0 + mov r0,r1 + mov r1,r3 + sub r4,#01 + cmp r4,#00 + bne back + end +``` + +注意,JavaScript 版本读起来几乎像英语指令,而汇编使用的是直接控制处理器的神秘命令。它们完成的是完全相同的任务,但高级语言更易于人类理解、编写和维护。 + +**你会注意到的主要区别:** +- **可读性**:JavaScript 用像 `fibonacciCount` 这样的描述性名称,而汇编使用像 `r0`、`r1` 这样晦涩的标签 +- **注释**:高级语言鼓励解释性注释,使代码具备自我说明性 +- **结构**:JavaScript 的逻辑流程与人类逐步思考问题的方式相匹配 +- **维护**:针对不同需求更新 JavaScript 版本简单明了 + +✅ **关于斐波那契数列**:这个绝美的数字模式(每个数字都是前两个数字之和:0, 1, 1, 2, 3, 5, 8……)在自然界里无处不在!你会在向日葵的螺旋、松果的排列、鹦螺壳的弯曲方式,甚至树枝的生长方式中发现它。数学和代码帮我们理解并重现自然界用来创造美丽的模式,真是令人震撼! + +## 构成魔法的基石 + +好了,现在你已经看到了编程语言的实际运作,让我们分解构成所有程序的基础部分。把它们看作你最喜欢的食谱中的基本成分——只要你了解每个成分的作用,就能在几乎任何语言中读写代码! + +这有点像学习编程的语法。还记得你在学校学名词、动词和如何组成句子吗?编程也有自己的语法版本,说实话,比英语语法更加合乎逻辑和宽容!😄 + +### 语句:一步步的指令 + +先从**语句**开始——它们就像你和电脑对话中的单句。每条语句告诉电脑做一件具体的事,就像给出方向指令:“这里左转”、“红绿灯处停下”、“在那个地方停车”。 + +我喜欢语句的地方是它们通常很易读。看看这个: + +```javascript +// 执行单个操作的基本语句 +const userName = "Alex"; +console.log("Hello, world!"); +const sum = 5 + 3; +``` + +**这段代码做了什么:** +- **声明**一个常量变量存储用户的名字 +- **向控制台输出**问候消息 +- **计算**并存储一个数学运算的结果 + +```javascript +// 与网页交互的语句 +document.title = "My Awesome Website"; +document.body.style.backgroundColor = "lightblue"; +``` + +**一步步讲解发生了什么:** +- **修改**浏览器标签页显示的网页标题 +- **更改**整个页面主体的背景颜色 + +### 变量:程序的记忆系统 + +好,**变量**说实话是我最喜欢讲的概念之一,因为它们就像你每天使用的东西! + +想想你手机的联系人列表。你不会记住每个人的号码——你保存的是“妈妈”、“死党”或者“凌晨2点前送餐的披萨店”,然后让手机记住实际号码。变量就是这样!它们是带标签的容器,程序可以用名字存储信息,并在需要时取出。 + +更酷的是:变量会随着程序运行而改变(这也解释了它名字的意义)。就像你发现更好的披萨店会更新联系人一样,变量可以随着程序获取新信息或发生变化而更新! + +让我给你演示一下多么简单漂亮: + +```javascript +// 第一步:创建基本变量 +const siteName = "Weather Dashboard"; +let currentWeather = "sunny"; +let temperature = 75; +let isRaining = false; +``` + +**理解这些概念:** +- **用 `const` 存储不变的值**(比如网站名) +- **用 `let` 存储程序中会变化的值** +- **赋值不同的数据类型**:字符串(文本)、数字和布尔值(真/假) +- **选择描述性名称**,说明每个变量包含什么 + +```javascript +// 第2步:使用对象来分组相关数据 +const weatherData = { + location: "San Francisco", + humidity: 65, + windSpeed: 12 +}; +``` + +**上面代码中,我们:** +- **创建了一个对象**将相关的天气信息归类在一起 +- **将多条数据组织在一个变量名下** +- **用键值对清楚地标注每条信息** + +```javascript +// 第3步:使用和更新变量 +console.log(`${siteName}: Today is ${currentWeather} and ${temperature}°F`); +console.log(`Wind speed: ${weatherData.windSpeed} mph`); + +// 更新可变变量 +currentWeather = "cloudy"; +temperature = 68; +``` + +**逐一理解各部分:** +- **用模板字面量 `${}` 语法展示信息** +- **用点号访问对象属性**(如 `weatherData.windSpeed`) +- **更新用 `let` 声明的变量**以响应变化的情况 +- **组合多个变量创造有意义的消息** + +```javascript +// 第4步:使用现代解构赋值使代码更简洁 +const { location, humidity } = weatherData; +console.log(`${location} humidity: ${humidity}%`); +``` + +**你需要知道的是:** +- **用解构赋值提取对象中的特定属性** +- **自动创建与对象键同名的新变量** +- **避免重复点号访问简化代码** + +### 控制流:教你的程序学会思考 + +这里编程就开始绝对让人疯狂了!**控制流**本质上是教你的程序像你每天无意识做的那样,做出聪明的决策。 + +想象一下:今天早上你大概经历的是“如果下雨,我带伞;如果冷,我穿夹克;如果迟到,我就不吃早饭顺路买杯咖啡”。你的大脑自然地遵循这种如果-那么的逻辑,每天数十次! + +这就是让程序显得智能、有生命力的原因,而不是死板执行无聊脚本。它们可以识别情况,评估发生了什么,并做出恰当反应。就像赋予程序一个能适应和做选择的大脑! + +想看看这多美妙?我来给你演示: + +```javascript +// 第一步:基本条件逻辑 +const userAge = 17; + +if (userAge >= 18) { + console.log("You can vote!"); +} else { + const yearsToWait = 18 - userAge; + console.log(`You'll be able to vote in ${yearsToWait} year(s).`); +} +``` + +**这段代码做了什么:** +- **检查**用户年龄是否满足投票要求 +- **根据条件结果执行**不同代码块 +- **计算**并显示未满18岁距离投票资格的时间 +- **针对每种情形提供**具体且有用的反馈 + +```javascript +// 第2步:使用逻辑运算符的多个条件 +const userAge = 17; +const hasPermission = true; + +if (userAge >= 18 && hasPermission) { + console.log("Access granted: You can enter the venue."); +} else if (userAge >= 16) { + console.log("You need parent permission to enter."); +} else { + console.log("Sorry, you must be at least 16 years old."); +} +``` + +**分解这里发生的事情:** +- **使用 `&&`(且)运算符结合多个条件** +- **用 `else if` 创建多重情形的条件层级** +- **用最终的 `else` 处理所有可能案例** +- **为每种不同情况提供清晰、可行的反馈** + +```javascript +// 第3步:使用三元运算符的简洁条件语句 +const votingStatus = userAge >= 18 ? "Can vote" : "Cannot vote yet"; +console.log(`Status: ${votingStatus}`); +``` + +**你需要记住的:** +- **用三元运算符 (`? :`) 处理简单的二选一条件** +- **写条件,跟 `?`,接真值,再 `:`,最后假值** +- **在根据条件赋值时使用这个模式** + +```javascript +// 第4步:处理多个特定情况 +const dayOfWeek = "Tuesday"; + +switch (dayOfWeek) { + case "Monday": + case "Tuesday": + case "Wednesday": + case "Thursday": + case "Friday": + console.log("It's a weekday - time to work!"); + break; + case "Saturday": + case "Sunday": + console.log("It's the weekend - time to relax!"); + break; + default: + console.log("Invalid day of the week"); +} +``` + +**这段代码实现了以下功能:** +- **将变量的值匹配多个特定情况** +- **将类似情况归入一组(工作日与周末)** +- **找到匹配时执行相应代码块** +- **用 `default` 处理意外值** +- **用 `break` 语句阻止继续执行下一个情况** + +> 💡 **现实世界的比喻**:把控制流想象成世界上最有耐心的 GPS 指路。它可能告诉你“如果主街堵车,就走高速;如果高速施工,试试风景路”。程序用完全一样的条件逻辑智能响应各种情况,总是为用户提供最优体验。 + +### 🎯 **概念检测:构建块掌握情况** + +**来看看你对基础的掌握如何:** +- 你能用自己的话解释变量和语句的区别吗? +- 想一个现实场景,用 if-then 决策(像投票的例子) +- 编程逻辑中有什么让你感到惊讶的吗? + +**快速增强信心:** +```mermaid +flowchart LR + A["📝 语句
(指令)"] --> B["📦 变量
(存储)"] --> C["🔀 控制流
(决策)"] --> D["🎉 可用程序!"] + + style A fill:#ffeb3b + style B fill:#4caf50 + style C fill:#2196f3 + style D fill:#ff4081 +``` +✅ **接下来是什么**:我们将继续深入挖掘这些概念,一起度过一段绝妙的旅程!现在,只需专注于感受未来无限可能的兴奋。具体的技能和技巧随着我们的实践会自然而然地掌握——我保证这会比你想象的更有趣! + +## 工具箱 + +说实话,这部分我已经激动得坐不住了!🚀 我们要聊聊让你感觉像刚拿到数字飞船钥匙一样的神奇工具。 + +你知道厨师手中总有那些完美平衡、感觉像自己手臂延伸的刀具吗?或者音乐家那把碰即可歌唱的吉他?开发者也有属于自己的神奇工具,这些工具绝大多数竟然完全免费,真让人脑洞大开! + +我激动得都快跳起来了,因为这些工具彻底改变了我们构建软件的方式。我们聊的是 AI 驱动的编码助手,可以帮你写代码(不是开玩笑!),云端环境让你只要有 Wi-Fi 就能随时随地搭建完整应用,还有调试工具如此高级,简直就是给程序装上了透视眼。 + +而让我仍兴奋不已的是:这些不是“初学者工具”用着用着就会淘汰的。这就是 Google、Netflix 和你喜欢的那个独立应用工作室当下使用的同款专业级工具。用它们你会感觉自己像个大牛! + +```mermaid +graph TD + A["💡 你的想法"] --> B["⌨️ 代码编辑器
(VS Code)"] + B --> C["🌐 浏览器开发者工具
(测试与调试)"] + C --> D["⚡ 命令行
(自动化与工具)"] + D --> E["📚 文档
(学习与参考)"] + E --> F["🚀 惊艳的网页应用!"] + + B -.-> G["🤖 AI 助手
(GitHub Copilot)"] + C -.-> H["📱 设备测试
(响应式设计)"] + D -.-> I["📦 包管理器
(npm, yarn)"] + E -.-> J["👥 社区
(Stack Overflow)"] + + style A fill:#fff59d + style F fill:#c8e6c9 + style G fill:#e1f5fe + style H fill:#f3e5f5 + style I fill:#ffccbc + style J fill:#e8eaf6 +``` +### 代码编辑器和 IDE:你的新数字挚友 + +说说代码编辑器吧——它们绝对会成为你最喜欢呆的地方!把它想象成你的专属编码圣地,大部分时间你都在这里打造、完善你的数字作品。 + +现代编辑器的魔力在于:它们不仅是高级文本编辑器,更像有位天才、耐心的编码导师 24/7 坐在你身边。它们会先于你发现拼写错误,建议改进让你看起来像个大师,帮你理解代码每部分功能,有些甚至能预测你要输入啥,替你把话说完! + +我记得第一次发现自动补全时,简直像生活在未来。你一输入,它就说,“嘿,你是不是想调这个函数?刚好能满足你需要!”简直像个读心术编程伙伴! + +**它们为什么这么不可思议?** + +现代代码编辑器提供了丰富功能,大幅提升你的效率: + +| 功能 | 作用 | 帮助点 | +|---------|--------------|--------------| +| **语法高亮** | 给代码不同部分着色 | 让代码更容易阅读、发现错误 | +| **自动补全** | 你输入时给出建议 | 加速编程并减少拼写错误 | +| **调试工具** | 帮你找错并修正 | 节省大量排查问题的时间 | +| **扩展** | 添加专门功能 | 让编辑器适配各种技术需求 | +| **AI 助手** | 代码建议和解释 | 加速学习和提高生产力 | + +> 🎥 **视频资源**:想看看这些工具实际操作?查看这段[工具箱视频](https://youtube.com/watch?v=69WJeXGBdxg)获取全面概览。 + +#### 推荐的网络开发编辑器 + +**[Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon)**(免费) +- Web 开发者中最流行 +- 极佳的扩展生态系统 +- 内置终端和 Git 集成 +- **必装扩展**: + - [GitHub Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot) - AI 代码建议 + - [Live Share](https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare) - 实时协作 + - [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) - 自动格式化代码 + - [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) - 捕捉代码拼写错误 + +**[JetBrains WebStorm](https://www.jetbrains.com/webstorm/)**(收费,学生免费) +- 高级调试和测试工具 +- 智能代码补全 +- 内建版本控制 + +**云端 IDE**(不同价格) +- [GitHub Codespaces](https://github.com/features/codespaces) - 浏览器里完整的 VS Code +- [Replit](https://replit.com/) - 非常适合学习和共享代码 +- [StackBlitz](https://stackblitz.com/) - 极速全栈网页开发 + +> 💡 **入门小贴士**:先用 Visual Studio Code —— 它免费、业界广泛使用,且有庞大社区制作的教程和扩展。 + +### 网络浏览器:你的秘密开发实验室 + +准备好被彻底震撼了吗!你平常用浏览器刷社媒、看视频,对吧?实际上它们一直藏着个神奇的开发者实验室,等你去发现! + +每次你右键点击网页选“检查元素”,就打开了一个隐藏的开发者工具世界,这些工具比我以前花大钱买的专业软件都强大多了。就像发现自己平常用的厨房背后藏着一间专业大厨的实验室! +第一次有人给我展示浏览器开发者工具时,我光是点击四处查看,就花了大约三个小时不停地惊呼:“等等,它居然还能做这个?!”你真的可以实时编辑任何网站,准确看到加载速度,测试你的网站在不同设备上的展示效果,甚至像个专业人士一样调试 JavaScript。简直令人震惊! + +**浏览器是你秘密武器的原因:** + +当你创建一个网站或网络应用时,你需要看到它在现实中的外观和表现。浏览器不仅展示你的作品,还会提供性能、可访问性和潜在问题的详细反馈。 + +#### 浏览器开发者工具(DevTools) + +现代浏览器包含全面的开发套件: + +| 工具类别 | 功能 | 示例用途 | +|---------------|--------------|------------------| +| **元素检查器** | 实时查看和编辑 HTML/CSS | 调整样式以立即查看效果 | +| **控制台** | 查看错误信息和测试 JavaScript | 调试问题和尝试代码 | +| **网络监视器** | 跟踪资源加载情况 | 优化性能和加载时间 | +| **可访问性检查器** | 测试包容性设计 | 确保网站对所有用户友好 | +| **设备模拟器** | 在不同屏幕尺寸上预览 | 无需多设备即可测试响应式设计 | + +#### 推荐用于开发的浏览器 + +- **[Chrome](https://developers.google.com/web/tools/chrome-devtools/)** – 行业标准的 DevTools,拥有丰富文档 +- **[Firefox](https://developer.mozilla.org/docs/Tools)** – 出色的 CSS Grid 和可访问性工具 +- **[Edge](https://docs.microsoft.com/microsoft-edge/devtools-guide-chromium/?WT.mc_id=academic-77807-sagibbon)** – 基于 Chromium,集成微软开发资源 + +> ⚠️ **重要测试提示**:务必在多个浏览器中测试你的网页!Chrome 完美运行的东西,在 Safari 或 Firefox 上可能会不同。专业开发者会在所有主流浏览器中测试,以确保一致的用户体验。 + + +### 命令行工具:开发者超级力量之门 + +好吧,让我们对命令行有个完全坦诚的时刻,我想让你听听一个真正懂它的人的心声。刚看到它那一刻——黑屏闪烁的文字——我心里真的是想,“不行,绝对不行!这看起来像80年代黑客电影里的东西,我肯定不够聪明用它!”😅 + +但我当时希望有人告诉我的是,现在我也要告诉你:命令行一点都不可怕——它其实就像是和你的电脑直接对话。就好比点外卖的时候用带图标和菜单的漂亮 APP(方便又简单),和走进你最爱的本地餐厅,厨师知道你喜欢啥,随口说一句“给我来点惊喜”,马上端上一道绝妙的菜。这是两种截然不同的体验。 + +命令行是开发者感觉自己像绝对巫师的地方。你输入几个看似魔法的词(其实就是命令,但感觉魔法满满),按回车,噔!你就能创建整个项目结构,安装全球厉害的工具,或者部署你的应用供数百万用户访问。尝到这种力量后,真是停不下来! + +**为什么命令行会成为你最喜欢的工具:** + +虽然图形界面适合很多任务,命令行却在自动化、精确和速度上占优势。许多开发工具主要通过命令行运行,学会高效使用它们能极大提升你的工作效率。 + +```bash +# 第一步:创建并进入项目目录 +mkdir my-awesome-website +cd my-awesome-website +``` + +**这段代码做了什么:** +- **创建** 一个名为 “my-awesome-website” 的新目录作为项目 +- **进入** 新建的目录开始工作 + +```bash +# 第2步:使用 package.json 初始化项目 +npm init -y + +# 安装现代开发工具 +npm install --save-dev vite prettier eslint +npm install --save-dev @eslint/js +``` + +**逐步讲解:** +- 用 `npm init -y` **初始化** 一个新的 Node.js 项目,使用默认配置 +- **安装** Vite 作为现代构建工具,支持快速开发和生产构建 +- **添加** Prettier 用于自动格式化代码,ESLint 用于代码质量检查 +- 使用 `--save-dev` 标记为开发时依赖 + +```bash +# 第3步:创建项目结构和文件 +mkdir src assets +echo 'My Site

Hello World

' > index.html + +# 启动开发服务器 +npx vite +``` + +**上述步骤中,我们:** +- **整理** 项目结构,创建源码和资源文件夹 +- **生成** 了带有正确文档结构的基础 HTML 文件 +- **启动** 了 Vite 开发服务器,实现热重载和模块替换 + +#### 网络开发必备命令行工具 + +| 工具 | 目的 | 你为什么需要它 | +|------|---------|-----------------| +| **[Git](https://git-scm.com/)** | 版本控制 | 跟踪变更,协作,备份工作 | +| **[Node.js & npm](https://nodejs.org/)** | JavaScript 运行时及包管理器 | 浏览器外运行 JS,安装现代开发工具 | +| **[Vite](https://vitejs.dev/)** | 构建工具和开发服务器 | 超快速开发,支持热模块替换 | +| **[ESLint](https://eslint.org/)** | 代码质量 | 自动发现和修复 JS 问题 | +| **[Prettier](https://prettier.io/)** | 代码格式化 | 保持代码格式一致,易于阅读 | + +#### 平台专属选项 + +**Windows:** +- **[Windows Terminal](https://docs.microsoft.com/windows/terminal/?WT.mc_id=academic-77807-sagibbon)** – 现代功能丰富的终端 +- **[PowerShell](https://docs.microsoft.com/powershell/?WT.mc_id=academic-77807-sagibbon)** 💻 – 强大的脚本环境 +- **[命令提示符](https://docs.microsoft.com/windows-server/administration/windows-commands/?WT.mc_id=academic-77807-sagibbon)** 💻 – 传统 Windows 命令行 + +**macOS:** +- **[Terminal](https://support.apple.com/guide/terminal/)** 💻 – 系统自带终端应用 +- **[iTerm2](https://iterm2.com/)** – 功能增强的终端 + +**Linux:** +- **[Bash](https://www.gnu.org/software/bash/)** 💻 – 标准 Linux shell +- **[KDE Konsole](https://docs.kde.org/trunk5/en/konsole/konsole/index.html)** – 高级终端模拟器 + +> 💻 = 操作系统预装 + +> 🎯 **学习路线**:从基本命令开始,比如 `cd`(切换目录)、`ls` 或 `dir`(列出文件)、`mkdir`(创建文件夹)。练习现代工作流命令如 `npm install`、`git status`、`code .`(在 VS Code 打开当前目录)。随着熟悉,你会自然而然学到更高级的命令和自动化技巧。 + + +### 文档:你随时可用的学习导师 + +好了,告诉你一个让你作为初学者更安心的小秘密:即便是最有经验的开发者,也会花大量时间看文档。这不是因为他们不会写代码,而是聪明的表现! + +把文档想象成你可以24/7随时访问的、超耐心且知识渊博的老师。凌晨2点遇到难题?文档就像温暖的虚拟拥抱,给你正合适的答案。想学习某个大家都在讨论的新特性?文档有详细逐步示例。想弄懂某个功能为什么这样设计?文档乐意用让你豁然开朗的方式讲解! + +改变我认知的是:web 开发世界变化极快,没有人(真的没有)能把一切都记牢。我见过超过15年经验的大牛,都要查基础语法,你知道吗?这不丢人,而是聪明!重点不是完美记忆,而是知道在哪里快速找到可靠答案,并理解如何应用。 + +**真正的魔法发生在这里:** + +专业开发者大量时间看文档——不是因为没能力,而是技术迅速发展,持续学习必不可少。好文档不仅教你*如何*用,还解释*为什么*和*什么时候*用。 + +#### 重要文档资源 + +**[Mozilla Developer Network (MDN)](https://developer.mozilla.org/docs/Web)** +- 网页技术文档的黄金标准 +- 全面指南覆盖 HTML、CSS 和 JavaScript +- 含浏览器兼容性信息 +- 提供实用例子和互动演示 + +**[Web.dev](https://web.dev)**(谷歌出品) +- 现代网页开发最佳实践 +- 性能优化指南 +- 可访问性和包容性设计原则 +- 来自实际项目的案例研究 + +**[微软开发者文档](https://docs.microsoft.com/microsoft-edge/#microsoft-edge-for-developers)** +- Edge 浏览器开发资源 +- 渐进式网页应用指南 +- 跨平台开发见解 + +**[Frontend Masters 学习路径](https://frontendmasters.com/learn/)** +- 结构化学习课程 +- 行业专家视频教程 +- 动手编程练习 + +> 📚 **学习策略**:不要试图死记文档——而是学会高效浏览。收藏常用参考,练习用搜索快速找到具体信息。 + +### 🔧 **工具掌握度测验:你最认同什么?** + +**花点时间思考:** +- 你最想先试哪个工具?(没有错误答案!) +- 命令行还让你害怕吗?还是更好奇了? +- 能想象用浏览器 DevTools 探秘你喜欢的网站幕后吗? + +```mermaid +pie title "开发者使用工具的时间分配" + "代码编辑器" : 40 + "浏览器测试" : 25 + "命令行" : 15 + "阅读文档" : 15 + "调试" : 5 +``` +> **有趣见解**:大多数开发者大约40%的时间花在代码编辑器,其余时间用于测试、学习和解决问题。编程不仅是写代码——它是打造体验! + +✅ **思考题**:有件有趣的事想问你——你觉得构建网站的工具(开发)和设计外观的工具(设计)有什么不同?就像建筑师设计漂亮房子,和承包商实际建造房子,两者都重要,但工具箱不同!这样的思考能帮你更全面理解网站是如何诞生的。 + +## GitHub Copilot Agent 挑战 🚀 + +使用 Agent 模式完成以下挑战: + +**描述:** 探索现代代码编辑器或 IDE 的功能,展示它如何提升你作为网络开发者的工作流程。 + +**提示:** 选择一个代码编辑器或 IDE(如 Visual Studio Code、WebStorm 或云端 IDE)。列举三个功能或扩展,说明它们如何帮助你更高效地编写、调试或维护代码,并简要解释它们带来的好处。 + +--- + +## 🚀 挑战 + +**侦探,准备好第一个案子了吗?** + +现在你已经有了很棒的基础,我有一个冒险任务,将帮你领略编程世界的多样与魅力。听好了,这不涉及写代码,所以别紧张!把自己当作编程语言侦探,接下你的第一个激动人心的案子! + +**你的任务,如果你愿意接受:** +1. **成为语言探险家**:挑选三种来自截然不同领域的编程语言 —— 比如一种建网站,一种写移动应用,还有一种给科学家用来数据处理。找出它们都完成同样简单任务的示例。保证你会惊叹同样的事一个用法大不相同! + +2. **揭示它们的起源故事**:每种语言的特别之处在哪里?有趣的是—每种编程语言诞生时,发明者都想:“得有更好方式来解决这个具体问题。”你能找到这些问题吗?某些故事特别迷人! + +3. **认识社区**:看看每种语言社区的开放和热情程度。有些拥有数百万开发者分享经验和互助,另一些则小巧紧密且极具支持力。你会喜欢了解这些社区的独特个性! + +4. **跟随直觉**:哪种语言现在你感觉最容易上手?别纠结做“完美”选择——听从你的直觉!这里没有对错,你以后还能继续探索其他语言。 + +**额外侦探任务**:试着查查哪些主流网站或应用是用这些语言构建的。保证你会对 Instagram、Netflix 或那个让你停不下来的手机游戏背后的技术大吃一惊! + +> 💡 **记住**:今天你不是要成为任何语言的专家。你只是在熟悉这个“邻居”,为将来决定在哪里扎根做准备。慢慢来,玩得开心,保持好奇心! + +## 一起庆祝你的发现吧! + +哇哦,今天你吸收了这么多令人惊叹的信息!我真心期待看到你记住了多少这段精彩旅程。别忘了——这不是考核,不用追求完美。更像是为你即将探入的精彩世界学到的所有酷知识举行庆典! + +[参加课后测验](https://ff-quizzes.netlify.app/web/) +## 复习与自学 + +**慢慢来,尽情探索和享受乐趣吧!** + +你今天已经学了很多内容,这值得骄傲!现在是有趣的部分了 —— 探索那些激发你好奇心的话题。记住,这不是作业 —— 这是一场冒险! + +**深入挖掘你感兴趣的内容:** + +**动手实践编程语言:** +- 访问你感兴趣的2-3个编程语言的官方网站。每种语言都有其独特的个性和故事! +- 试试一些在线代码游乐场,比如 [CodePen](https://codepen.io/)、[JSFiddle](https://jsfiddle.net/) 或 [Replit](https://replit.com/)。不要害怕尝试 —— 你不会弄坏任何东西! +- 了解你喜欢的语言是如何诞生的。说真的,有些起源故事很有趣,会帮助你理解这些语言为何如此设计。 + +**熟悉你的新工具:** +- 如果还没下载 Visual Studio Code,赶快下载 —— 它是免费的,你一定会喜欢! +- 花几分钟浏览一下扩展市场。它就像你代码编辑器的应用商店! +- 打开浏览器的开发者工具,随便点击看看。别担心全懂 —— 先熟悉一下界面和功能就好。 + +**加入社区:** +- 关注一些开发者社区,比如 [Dev.to](https://dev.to/)、[Stack Overflow](https://stackoverflow.com/) 或 [GitHub](https://github.com/)。编程社区对新手非常友好! +- 在 YouTube 上看一些适合初学者的编程视频。有很多很棒的创作者曾经也和你一样刚刚起步。 +- 考虑参加本地聚会或者在线社区。相信我,开发者们都很乐于帮助新手! + +> 🎯 **听着,我希望你记住**:你不需要一夜之间成为编程高手!现在,你只是开始认识这个你即将加入的精彩新世界。慢慢来,享受这段旅程,记住 —— 每一个你敬佩的开发者,曾经也正坐在你现在的位置,既兴奋又可能有点不知所措。这完全正常,这意味着你正在正确的道路上! + + + +## 任务 + +[阅读文档](assignment.md) + +> 💡 **任务小提示**:我很想看到你去探索一些我们还没讲过的工具!跳过已经讨论过的编辑器、浏览器和命令行工具 —— 外面还有一个庞大而精彩的开发工具宇宙等待你去发现。找那些活跃维护、有生机且乐于助人的社区支持的工具(它们通常有最好的教程和最热心的人们,当你卡住需要帮助时能手把手支持你)。 + +--- + +## 🚀 你的编程之旅时间表 + +### ⚡ **接下来5分钟内你可以做的事** +- [ ] 收藏2-3个你感兴趣的编程语言官网 +- [ ] 如果没下载,安装 Visual Studio Code +- [ ] 打开浏览器开发者工具(F12),随意点击浏览任意网站 +- [ ] 加入一个编程社区(Dev.to、Reddit 的 r/webdev,或 Stack Overflow) + +### ⏰ **这1小时内你可以完成的任务** +- [ ] 完成课后测验并反思答案 +- [ ] 配置 VS Code 并安装 GitHub Copilot 扩展 +- [ ] 在线用两种不同编程语言写一个“Hello World”示例 +- [ ] 观看一段“开发者的一天”视频 +- [ ] 开始你的编程语言侦探工作(挑战内容) + +### 📅 **你的一周冒险计划** +- [ ] 完成作业,探索3个新的开发工具 +- [ ] 关注5个开发者或编程账号(社交媒体) +- [ ] 在 CodePen 或 Replit 上尝试做一个小作品(哪怕只是“Hello, [你的名字]!”) +- [ ] 阅读一篇关于某人编程历程的开发者博客 +- [ ] 加入一次线上聚会或观看编程讲座 +- [ ] 开始选定的语言的在线教程学习 + +### 🗓️ **你一个月的转变计划** +- [ ] 做出你的第一个小项目(就算简单网页也行!) +- [ ] 参与开源项目贡献(从文档修正开始) +- [ ] 指导一个刚开始编程的人 +- [ ] 创建你的开发者个人作品网站 +- [ ] 结识本地开发者社区或学习小组 +- [ ] 开始规划下一个学习目标 + +### 🎯 **最终反思签到** + +**继续之前,花点时间庆祝一下:** +- 今天编程中,哪些事情让你感到兴奋? +- 你想先探索哪个工具或概念? +- 对开始这段编程旅程,你的感觉如何? +- 有什么问题是你现在想问开发者的吗? + +```mermaid +journey + title 你的自信心建立之旅 + section 今天 + 好奇: 3: You + 不知所措: 4: You + 兴奋: 5: You + section 本周 + 探索: 4: You + 学习: 5: You + 连接: 4: You + section 下个月 + 建立: 5: You + 自信: 5: You + 帮助他人: 5: You +``` +> 🌟 **记住**:每个专家都曾是初学者。每个高级开发者都曾和你一样——既兴奋又有点不知所措,当然也充满了无限好奇。你身处伟大的同行中,这段旅程将会非常精彩。欢迎来到奇妙的编程世界! 🎉 + +--- + + +**免责声明**: +本文件由 AI 翻译服务 [Co-op Translator](https://github.com/Azure/co-op-translator) 翻译完成。尽管我们力求准确,但请注意自动翻译可能存在错误或不准确之处。原始文件的母语版本应视为权威来源。对于重要信息,建议采用专业人工翻译。因使用本翻译内容而引起的任何误解或错误理解,我们概不负责。 + \ No newline at end of file diff --git a/translations/zh-CN/1-getting-started-lessons/1-intro-to-programming-languages/assignment.md b/translations/zh-CN/1-getting-started-lessons/1-intro-to-programming-languages/assignment.md new file mode 100644 index 000000000..f0192ae80 --- /dev/null +++ b/translations/zh-CN/1-getting-started-lessons/1-intro-to-programming-languages/assignment.md @@ -0,0 +1,69 @@ +# Assignment: 探索现代网络开发工具 + +## Instructions + +网络开发生态系统包含数百种专门的工具,帮助开发者高效地构建、测试和维护应用程序。你的任务是研究并了解补充本课所涵盖内容的工具。 + +**你的任务:**选择**三个工具**,这些工具**未在本课中涵盖**(避免选择已列出的代码编辑器、浏览器或命令行工具)。重点关注解决现代网站开发工作流中特定问题的工具。 + +**针对每个工具,请提供:** + +1. **工具名称和类别**(例如“Figma - 设计工具”或“Jest - 测试框架”) +2. **用途和优势** - 用2-3句话解释为什么网络开发者会使用该工具以及它解决了哪些问题 +3. **官方文档链接** - 提供该工具的官方文档或网站链接(而非仅教程网站) +4. **实际应用场景** - 简要说明该工具如何融入专业开发工作流程 + +## 建议的工具类别 + +可以考虑探索以下类别的工具: + +| 类别 | 示例 | 功能描述 | +|----------|----------|--------------| +| **构建工具** | Vite, Webpack, Parcel, esbuild | 打包和优化生产代码,提供快速开发服务器 | +| **测试框架** | Vitest, Jest, Cypress, Playwright | 确保代码正确运行,及早捕获缺陷 | +| **设计工具** | Figma, Adobe XD, Penpot | 协作创建原型、模型和设计系统 | +| **部署平台** | Netlify, Vercel, Cloudflare Pages | 自动化CI/CD托管和分发网站 | +| **版本控制** | GitHub, GitLab, Bitbucket | 管理代码更改、协作与项目流程 | +| **CSS框架** | Tailwind CSS, Bootstrap, Bulma | 利用预构建组件库加速样式开发 | +| **包管理器** | npm, pnpm, Yarn | 安装和管理代码库依赖 | +| **无障碍工具** | axe-core, Lighthouse, Pa11y | 测试包容性设计和WCAG合规性 | +| **API开发** | Postman, Insomnia, Thunder Client | 开发过程中测试和编写API文档 | + +## 格式要求 + +**每个工具:** +``` +### [Tool Name] - [Category] + +**Purpose:** [2-3 sentences explaining why developers use this tool] + +**Documentation:** [Official website/documentation link] + +**Workflow Integration:** [1 sentence about how it fits into development process] +``` + +## 质量指导原则 + +- **选择当前工具**:选择2025年仍在积极维护且广泛使用的工具 +- **聚焦价值**:解释具体优势,而非仅描述功能 +- **专业背景**:考虑团队使用的工具,而非仅限个人爱好者 +- **多样化选择**:从不同类别中挑选,展示生态多样性 +- **现代相关性**:优先符合当前网络开发趋势和最佳实践的工具 + +## 评分标准 + +| 优秀 | 良好 | 需改进 | +|-----------|------|-------------------| +| **清晰解释为何开发者使用该工具及解决的问题** | **解释了工具作用但缺少价值上下文** | **仅列出工具名称,未解释用途或优势** | +| **为所有工具提供官方文档链接** | **大多为官方链接,含少量教程网站** | **主要依赖教程网站,缺少官方文档** | +| **选择当前被广泛专业使用、类别多样的工具** | **选择工具不错但类别较单一** | **选用过时工具或仅限某一类别** | +| **展示了解工具在开发流程中的应用** | **部分体现专业应用背景** | **仅聚焦工具功能,缺工作流上下文** | + +> 💡 **研究建议**:关注招聘网站中提及的网络开发工具,查看热门开发者调查,或分析GitHub上成功开源项目的依赖项! + +--- + + +**免责声明**: +本文件使用 AI 翻译服务 [Co-op Translator](https://github.com/Azure/co-op-translator) 进行翻译。虽然我们努力确保准确性,但请注意自动翻译可能包含错误或不准确之处。原始语言版本的文件应视为权威来源。对于重要信息,建议采用专业人工翻译。对于因使用本翻译而产生的任何误解或误释,我们不承担任何责任。 + \ No newline at end of file diff --git a/translations/zh-CN/1-getting-started-lessons/2-github-basics/README.md b/translations/zh-CN/1-getting-started-lessons/2-github-basics/README.md new file mode 100644 index 000000000..c0fd8b75f --- /dev/null +++ b/translations/zh-CN/1-getting-started-lessons/2-github-basics/README.md @@ -0,0 +1,767 @@ +# GitHub简介 + +嗨,未来的开发者!👋 准备好加入全球数百万程序员的行列了吗?我真心兴奋地向你介绍GitHub——把它想象成程序员的社交媒体平台,不过我们分享的不是午餐照片,而是代码,共同构建令人难以置信的东西! + +让我大开眼界的是:你手机上的每个应用、你访问的每个网站,以及你将学会使用的大多数工具,都是由开发团队在类似GitHub的平台上协作完成的。你喜欢的那个音乐应用?就有像你一样的人参与其中。那个让你爱不释手的游戏?没错,可能就是通过GitHub协作完成的。现在,你将学会如何成为这个惊人社区的一员! + +我知道一开始可能觉得信息量很大——说实话,我第一次看到GitHub页面时也懵了,“这到底是啥意思?”但事实是:每一个开发者都从你现在的位置开始。课程结束时,你将拥有自己的GitHub仓库(把它想象成云端的个人项目展示),你会知道如何保存工作,与他人分享,甚至为数百万用户使用的项目做贡献。 + +我们将一步步一起出发。没有急躁,没有压力——只有你我和一些即将成为你新朋友的酷炫工具! + +![Intro to GitHub](../../../../translated_images/zh-CN/webdev101-github.8846d7971abef6f9.webp) +> 速记图由 [Tomomi Imura](https://twitter.com/girlie_mac) 制作 + +```mermaid +journey + title 你今天的 GitHub 冒险 + section 安装设置 + 安装 Git: 4: You + 创建账户: 5: You + 第一个仓库: 5: You + section 精通 Git + 本地更改: 4: You + 提交与推送: 5: You + 分支管理: 4: You + section 协作 + 派生项目: 4: You + 拉取请求: 5: You + 开源项目: 5: You +``` +## 课前测验 +[课前测验](https://ff-quizzes.netlify.app) + +## 介绍 + +在开始真正令人兴奋的内容之前,先让你的电脑准备好迎接GitHub的魔法吧!把这看作是在创作杰作前整理好艺术用品——准备好合适的工具让整个过程更流畅、更有趣。 + +我会一步步带你完成每个设置步骤,保证过程没你想象的那么吓人。如果一开始没有立刻理解也没关系!我记得当初搭建第一个开发环境时,感觉自己像是在看古埃及象形文字。每个开发者都经历过你现在的阶段,怀疑自己是不是做对了。剧透一下:既然你来了这里学习,说明你已经在正确的路上了!🌟 + +这节课,我们会涵盖: + +- 追踪你在电脑上的工作 +- 与他人协作项目 +- 如何为开源软件做贡献 + +### 先决条件 + +让我们先让电脑准备好迎接GitHub的魔法!别担心——这只是一次性的设置,完成后整个编码之旅都会顺利。 + +好,先从基础开始!我们先检查电脑上是否已经安装了Git。Git基本上就像一个超级智能的助理,能记录你代码的每一次改动——比你两秒按一次Ctrl+S强多了(我们都有过!)。 + +在终端输入这个魔法命令看一下Git是否安装: +`git --version` + +如果还没安装Git,别着急!去[下载Git](https://git-scm.com/downloads)把它装上。安装完,我们需要正式介绍Git给你认识: + +> 💡 **首次设置**:这些命令告诉Git你的身份。每次提交都会附带这些信息,所以请选择你愿意公开分享的名字和邮箱。 + +```bash +git config --global user.name "your-name" +git config --global user.email "your-email" +``` + +你能通过输入以下命令检查Git是否已经配置: +```bash +git config --list +``` + +你还需要一个GitHub账户,一个代码编辑器(比如Visual Studio Code),并打开你的终端(命令提示符也可以)。 + +访问 [github.com](https://github.com/) ,如果还没有账户就创建一个,或者登录并完善你的个人资料。 + +💡 **现代建议**:考虑设置[SSH密钥](https://docs.github.com/en/authentication/connecting-to-github-with-ssh)或使用[GitHub CLI](https://cli.github.com/)实现无需密码的更便捷认证。 + +✅ GitHub不是唯一的代码仓库,但它是最知名的。 + +### 准备工作 + +你需要在本地(笔记本或PC)有一个包含代码项目的文件夹,并且在GitHub有一个公开仓库,这将作为学习如何为他人项目做贡献的范例。 + +### 保护你的代码安全 + +聊聊安全——别担心,我们不会让你听得头疼!把这些安全措施想象成锁车或锁门,是简单易养成的习惯,能保护你的辛勤成果。 + +我们将从一开始就用现代、安全的方式使用GitHub。这样你将培养出良好的习惯,这些习惯在你整个编码生涯都会发挥作用。 + +使用GitHub时,遵守安全最佳实践很重要: + +| 安全领域 | 最佳实践 | 为什么重要 | +|---------------|---------------|----------------| +| **身份认证** | 使用SSH密钥或个人访问令牌 | 密码不够安全,正被逐渐淘汰 | +| **两步验证** | 为GitHub账号启用2FA | 增加账户额外保护层 | +| **仓库安全** | 永远不要提交敏感信息 | API密钥和密码绝不能出现在公共仓库 | +| **依赖管理** | 启用Dependabot自动更新 | 保持依赖安全和最新 | + +> ⚠️ **重要安全提醒**:绝不可提交API密钥、密码和其他敏感信息到任何仓库。请使用环境变量和`.gitignore`文件保护敏感数据。 + +**现代认证配置示例:** + +```bash +# 生成 SSH 密钥(现代 ed25519 算法) +ssh-keygen -t ed25519 -C "your_email@example.com" + +# 设置 Git 使用 SSH +git remote set-url origin git@github.com:username/repository.git +``` + +> 💡 **专业提示**:SSH密钥无需重复输入密码,比传统认证方法更安全。 + +--- + +## 像专家一样管理你的代码 + +好了,真正令人兴奋的部分来了!🎉 我们将学习如何像专业人士那样追踪和管理代码,这真是我最喜欢教的内容之一,因为它改变游戏规则。 + +想象一下:你正在写一本精彩的故事,想保留每一稿、每个精彩修改和每一个“等一下,这简直是天才!”的瞬间。Git就是为你的代码做了这件事!它就像有一本了不起的时光笔记,记录一切——每一次击键、每一次改动、每一次“糟糕,坏掉了”的时刻,瞬间就能撤销。 + +说实话,一开始可能有点儿不知所措。我刚学Git时也想,“我为什么不能像以前那样只保存文件?”但相信我,一旦你适应了Git(肯定会的!),你会有那种灵光一闪的感觉:“没有Git我怎么写代码的?”就好像你一直只能走路,突然发现自己能飞了一样! + +假设你本地有个文件夹,里面有代码项目,你想用git版本控制系统来追踪进度。有些人把使用git比作写给未来自己的情书。数天、数周甚至数月后再看提交信息,你能回忆起当时为何做出某个决定,或者“回滚”某个改动——前提是你写了好的“提交消息”。 + +```mermaid +flowchart TD + A[📁 你的项目文件] --> B{这是一个 Git 仓库吗?} + B -->|否| C[git init] + B -->|是| D[进行更改] + C --> D + D --> E[git add .] + E --> F["git commit -m 'message'"] + F --> G[git push] + G --> H[🌟 GitHub 上的代码!] + + H --> I{想要协作吗?} + I -->|是| J[Fork & Clone] + I -->|否| D + J --> K[创建分支] + K --> L[进行更改] + L --> M[Pull Request] + M --> N[🎉 贡献中!] + + style A fill:#fff59d + style H fill:#c8e6c9 + style N fill:#ff4081,color:#fff +``` +### 任务:创建你的第一个仓库! + +> 🎯 **你的任务(我为你感到超级激动!)**:我们将一起创建你的第一个GitHub仓库!完成后,你将拥有在网络上的一个小角落,存放你的代码,并且你将完成第一次“提交”(开发者术语,意味着用超智能的方式保存工作)。 +> +> 这真是特别的时刻——你即将正式加入全球开发者社区!我还记得创建第一个仓库时的激动,“哇,我真的做到啦!” + +让我们一步步一起踏上这段旅程。每一步不要慌,慢慢来——没有谁在着急,保证每步都合情合理。记住,每个你敬佩的编码大神,都曾与你同坐在这里,准备创建他们的第一个仓库。多酷啊! + +> 观看视频 +> +> [![Git和GitHub基础视频](https://img.youtube.com/vi/9R31OUPpxU4/0.jpg)](https://www.youtube.com/watch?v=9R31OUPpxU4) + +**一起动手做:** + +1. **在GitHub上创建仓库**。登陆GitHub.com,找到那个醒目的绿色 **New** 按钮(或者右上角的 **+** 号)。点击,选择 **New repository**。 + + 操作步骤: + 1. 给你的仓库起个名字——起一个对你有意义的名字! + 1. 可以添加描述(帮助别人了解你的项目) + 1. 选定公开(所有人可见)或私有(仅你可见) + 1. 建议勾选添加README文件——它是项目的首页介绍 + 1. 点击 **Create repository**,庆祝一下——你刚刚创建了第一个仓库!🎉 + +2. **进入你的项目文件夹**。现在打开终端(别怕,其实没那么吓人!)。告诉电脑你的项目文件在哪儿,输入命令: + + ```bash + cd [name of your folder] + ``` + + **这里做了什么:** + - 我们实质上是在告诉电脑“带我到项目文件夹” + - 就像在桌面打开特定文件夹,只不过用文本命令做这件事 + - 把`[name of your folder]`替换成你项目文件夹的真实名称 + +3. **把你的文件夹变成Git仓库**。神奇时刻来了!输入: + + ```bash + git init + ``` + + **发生了什么(很酷!):** + - Git在你的项目里创建了一个隐藏的`.git`文件夹——你看不到它,但它就在那! + - 你的普通文件夹变成了一个能追踪每一次改动的“仓库” + - 就好像给文件夹赋予了超能力,能记住所有事情 + +4. **检查仓库当前状态**。看看Git此刻对你的项目有什么看法: + + ```bash + git status + ``` + + **理解Git告诉你的内容:** + + 你可能会看到类似这样的信息: + + ```output + Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + + modified: file.txt + modified: file2.txt + ``` + + **别慌!它的意思是:** + - 红色的文件是有改动但还没准备好保存的 + - 绿色的文件(如果看到)是已准备好保存的 + - Git会提示你下一步该做什么,很贴心 + + > 💡 **小贴士**:`git status`命令是你的好帮手!不懂时就问它,就像让Git告诉你“现在状况如何”。 + +5. **准备文件保存(也叫“暂存”)**: + + ```bash + git add . + ``` + + **刚刚做了什么:** + - 告诉Git“把所有文件都加到下一次保存里” + - `.`表示“这个文件夹下的所有东西” + - 现在你的文件已经“暂存”好,可以进行下一步 + + **想更挑剔地选择?** 你可以只添加特定文件: + + ```bash + git add [file or folder name] + ``` + + **为什么这样做?** + - 有时候你想把相关改动分批提交 + - 有利于把工作整理成有逻辑的小块 + - 让日后更容易理解改动内容和时间 + + **想撤销选择?** 可以这样取消暂存: + + ```bash + # 取消暂存所有内容 + git reset + + # 只取消暂存一个文件 + git reset [file name] + ``` + + 不用担心——这不会删掉你的内容,只是把文件从“准备提交”的列表里移除。 + +6. **永久保存工作(提交你的第一次commit!)**: + + ```bash + git commit -m "first commit" + ``` + + **🎉 恭喜你!你完成了第一次commit!** + + **发生了什么:** + - Git对所有暂存的文件做了“快照”,记录当前状态 + - 你的提交信息“first commit”说明了保存点的内容 + - Git给这个快照一个唯一ID,你随时能找到它 + - 你正式开始管理项目历史了! + + > 💡 **今后的提交信息**:写得更有描述性!别写“updated stuff”,试试“给首页添加联系表单”或“修复导航菜单bug”。未来的你会感谢自己的! + +7. **连接本地项目到GitHub**。现在你的项目只存在电脑里,连接到GitHub仓库,才能分享给全世界! + + 先打开你的GitHub仓库页面,复制URL。回到这里,输入: + + ```bash + git remote add origin https://github.com/username/repository_name.git + ``` + + (把这个URL换成你的仓库实际地址!) + + **刚刚做了什么:** + - 我们在你的本地项目和你的 GitHub 仓库之间建立了连接 + - “origin” 只是你的 GitHub 仓库的一个昵称——就像给你的手机添加联系人一样 + - 现在你的本地 Git 知道在你准备好分享代码时该把代码发送到哪里 + + 💡 **更简单的方法**:如果你安装了 GitHub CLI,可以用一条命令完成这一步: + ```bash + gh repo create my-repo --public --push --source=. + ``` + +8. **将代码上传到 GitHub**(激动人心的时刻!): + + ```bash + git push -u origin main + ``` + + **🚀 就是这一步!你正在把代码上传到 GitHub!** + + **发生了什么:** + - 你的提交正从电脑传送到 GitHub + - `-u` 参数建立了永久连接,方便以后推送 + - “main” 是你的主分支名称(类似主文件夹) + - 之后你只需输入 `git push` 来上传修改! + + 💡 **小提示**:如果分支叫其他名字(如 “master”),用那个名字替代。可用 `git branch --show-current` 查看当前名字。 + +9. **你的新日常编码节奏**(上瘾的时候到了!): + + 从现在开始,只要你修改项目,都遵循简单的三步流程: + + ```bash + git add . + git commit -m "describe what you changed" + git push + ``` + + **这将成为你的编码心跳:** + - 编写精彩代码 ✨ + - 用 `git add` 记录修改(“Git,关注这些改动!”) + - 用 `git commit` 并写清楚信息保存(未来的你会感谢现在的你!) + - 用 `git push` 分享给世界 🚀 + - 循环往复——真的,这会变得自然而然! + + 我喜欢这个流程,就像电子游戏里多保存点。喜欢刚写的修改?提交它!想试点冒险的改动?没问题——你总能回到最后一次提交! + + > 💡 **提示**:建议使用 `.gitignore` 文件避免不想追踪的文件出现在 GitHub 上——比如你存放的笔记文件,它不适合公开。你可以去 [.gitignore 模板](https://github.com/github/gitignore) 找模板,或用 [gitignore.io](https://www.toptal.com/developers/gitignore) 创建。 + +### 🧠 **第一次仓库提交:感觉如何?** + +**花点时间庆祝和回顾:** +- 第一次在 GitHub 看到自己的代码感觉怎么样? +- 哪一步最让你困惑?哪一步出乎意料地简单? +- 你能用自己的话解释 `git add`、`git commit` 和 `git push` 的区别吗? + +```mermaid +stateDiagram-v2 + [*] --> LocalFiles: 创建项目 + LocalFiles --> Staged: git add . + Staged --> Committed: git commit + Committed --> GitHub: git push + GitHub --> [*]: 成功!🎉 + + note right of Staged + 文件准备保存 + end note + + note right of Committed + 快照已创建 + end note +``` +> **记住**:即使是经验丰富的开发者也会忘记具体命令。让流程变成本能需要练习——你做得很棒! + +#### 现代 Git 工作流程 + +考虑采用这些现代实践: + +- **Conventional Commits(规范提交)**:用标准格式的提交信息如 `feat:`、`fix:`、`docs:` 等。了解更多请访问 [conventionalcommits.org](https://www.conventionalcommits.org/) +- **原子提交**:每次提交代表一个逻辑上的独立改动 +- **频繁提交**:多且带描述的提交代替少且庞大的提交 + +#### 提交信息 + +一个好的 Git 提交主题行能完成下面句子: +如果应用该提交,它将 <你的主题> + +主题用祈使句现在时态:“change”,不是 “changed” 或 “changes”。正文(可选)也用祈使句现在时。正文应说明改动的动机,并与之前的行为对比。你是在解释“为什么”,不是“怎么做”。 + +✅ 花几分钟逛逛 GitHub,能找到一个特别棒的提交信息吗?能找到特别简洁的吗?你觉得提交信息中最重要有用的信息是什么? + +## 与他人合作(有趣部分!) + +抓紧你的帽子,因为这里是 GitHub 真正神奇的时候!🪄 你已经学会管理自己的代码,现在我们进入我最喜欢的部分——与来自世界各地的优秀人才协作。 + +想象一下:你第二天醒来发现东京有人改进了你的代码;柏林有人修复了你一直卡住的 Bug;下午时,圣保罗的开发者添加了你从没想过的功能。这不是科幻——这只是 GitHub 世界里的普通一天! + +让我激动的是,你将学到的协作技能正是谷歌、微软和你喜欢的创业公司每天都在用的工作流程。这不仅仅是学一个酷工具——你学会了让整个软件世界协同工作的秘密语言。 + +说真的,一旦你体验过别人合并你的第一次拉取请求的激动,你会明白开发者为何对开源项目如此热情。这就像参与了全世界最大最有创意的团队项目! + +> 查看视频 +> +> [![Git and GitHub basics video](https://img.youtube.com/vi/bFCM-PC3cu8/0.jpg)](https://www.youtube.com/watch?v=bFCM-PC3cu8) + +把东西放到 GitHub 的主要原因就是让与其他开发者的协作成为可能。 + +```mermaid +flowchart LR + A[🔍 寻找项目] --> B[🍴 分叉代码库] + B --> C[📥 克隆到本地] + C --> D[🌿 创建分支] + D --> E[✏️ 进行修改] + E --> F[💾 提交更改] + F --> G[📤 推送分支] + G --> H[🔄 创建合并请求] + H --> I{维护者审查} + I -->|✅ 批准| J[🎉 合并!] + I -->|❓ 请求更改| K[📝 进行更新] + K --> F + J --> L[🧹 清理分支] + + style A fill:#e3f2fd + style J fill:#e8f5e8 + style L fill:#fff3e0 +``` +在你的仓库里,导航至 `Insights > Community`,查看你的项目如何对照推荐的社区标准进行比较。 + +想让你的仓库看起来专业且有吸引力?去仓库点击 `Insights > Community`。这个酷功能会显示你的项目与 GitHub 社区认可的“好仓库实践”相比的情况。 + +> 🎯 **让你的项目闪耀**:结构良好的仓库和完善的文档就像干净欢迎的店铺。它告诉大家你重视你的工作,也会让别人想来贡献! + +**一个棒仓库的要点:** + +| 应该添加的内容 | 重要性 | 对你的作用 | +|-------------|-------------------|---------------------| +| **描述** | 第一印象很重要! | 让人立刻知道项目做什么 | +| **README** | 项目的主页 | 就像对新访客的友好导览 | +| **贡献指南** | 表明欢迎帮助 | 让人知道如何参与贡献 | +| **行为准则** | 营造友好氛围 | 确保每个人都感到受欢迎 | +| **许可证** | 法律明确 | 让别人知道怎么使用你的代码 | +| **安全政策** | 表明你负责任 | 展示专业规范 | + +> 💡 **小窍门**:GitHub 提供了所有这些文件的模板。创建新仓库时,可以勾选自动生成这些文件。 + +**值得探索的现代 GitHub 功能:** + +🤖 **自动化 & CI/CD:** +- **GitHub Actions**:自动化测试和部署 +- **Dependabot**:依赖自动更新 + +💬 **社区 & 项目管理:** +- **GitHub Discussions**:议题以外的社区对话 +- **GitHub Projects**:看板式项目管理 +- **分支保护规则**:维护代码质量标准 + + +所有这些资源都能帮助新成员快速入职。新贡献者通常先看这些东西,再决定项目是否值得投入时间。 + +✅ README 虽然准备需要时间,但常被繁忙的维护者忽视。你能找到一个特别详细的 README 作为例子吗?提示:有些[工具能帮你创建优秀的 README](https://www.makeareadme.com/),可以试试。 + +### 任务:合并代码 + +贡献文档帮助别人参与项目。它说明你期待的贡献类型和流程。贡献者需要经过一系列步骤,才能在 GitHub 上为你的仓库做贡献: + +1. **Fork 你的仓库**。你可能希望别人 _fork_ 你的项目。Fork 是在他们的 GitHub 账号上创建你仓库的副本。 +1. **克隆**。然后他们将项目克隆到本地机器。 +1. **创建分支**。你会希望他们为自己的工作创建一个 _分支_。 +1. **把修改聚焦在一件事**。让贡献者每次专注一件事——这样更容易 _合并_ 他们的工作。假设他们写了 bug 修复、添加新功能并更新多个测试——如果你只能合并其中两个或一个怎么办? + +✅ 想想有哪些场景分支对写出和发布高质量代码特别关键? + +> 注意,成为你希望看到的改变,也为你自己的工作创建分支。任何提交都发生在你当前“签出”的分支上。用 `git status` 查看当前分支。 + +我们来看贡献者的工作流程。假设贡献者已经 _fork_ 和 _clone_ 了仓库,拥有一个可本地操作的 Git 仓库: + +1. **创建分支**。用命令 `git branch` 创建将用于贡献的分支: + + ```bash + git branch [branch-name] + ``` + + > 💡 **现代做法**:你也可以用一条命令创建并切换分支: + ```bash + git switch -c [branch-name] + ``` + +1. **切换到工作分支**。用 `git switch` 切换到指定分支并更新工作区: + + ```bash + git switch [branch-name] + ``` + + > 💡 **现代提示**:`git switch` 是替代 `git checkout` 修改分支的现代命令,更清晰也更安全适合新手。 + +1. **开始工作**。此时你添加修改。别忘了用下面命令告诉 Git: + + ```bash + git add . + git commit -m "my changes" + ``` + + > ⚠️ **提交信息质量**:确保给你的提交起个好名字,为自己和仓库维护者负责。具体说明你的改动! + +1. **与 `main` 分支合并**。完成工作后,你想把改动合并回 `main`。由于 `main` 可能已变动,先用以下命令更新它: + + ```bash + git switch main + git pull + ``` + + 接下来确保任何冲突,即 Git 无法轻松合并的情况发生在你的工作分支上。运行以下命令: + + ```bash + git switch [branch_name] + git merge main + ``` + + `git merge main` 命令将 `main` 的所有改动合入你的分支。希望你可以直接继续。如果不能,VS Code 会告诉你哪里有冲突,你只需编辑相关文件,决定哪些内容是正确的。 + + 💡 **现代替代**:考虑用 `git rebase` 保持历史清晰: + ```bash + git rebase main + ``` + 它将你的提交放到最新的 `main` 之上,创建线性历史。 + +1. **将你的工作推送到 GitHub**。推送工作到 GitHub 包含两步:推送分支到你的仓库,然后打开 PR(拉取请求)。 + + ```bash + git push --set-upstream origin [branch-name] + ``` + + 上面命令会在你的 fork 仓库上创建该分支。 + +### 🤝 **协作技能检测:准备好与他人合作了吗?** + +**看看你对协作的感觉如何:** +- 你现在理解 fork 和拉取请求的概念了吗? +- 关于分支工作你还想多练习什么? +- 你对向别人的项目贡献感觉如何? + +```mermaid +mindmap + root((Git 协作)) + Branching + Feature branches + Bug fix branches + Experimental work + Pull Requests + Code review + Discussion + Testing + Best Practices + Clear commit messages + Small focused changes + Good documentation +``` +> **信心提升**:你敬佩的每个开发者当年也曾紧张他们的第一次拉取请求。GitHub 社区对新手非常友好! + +1. **打开拉取请求(PR)**。接下来你要在 GitHub 上打开 PR。访问你的 fork 仓库,GitHub 会提示你是否创建新 PR,点击进入后可以修改提交信息标题,写更合适的描述。原仓库维护者会看到该 PR,_希望他们会喜欢并合并它_。你现在是贡献者,太棒了 :) + + 💡 **现代小贴士**:你也可以用 GitHub CLI 创建 PR: + ```bash + gh pr create --title "Your PR title" --body "Description of changes" + ``` + + 🔧 **PR 最佳实践**: + - 使用关键词关联相关 issues,如 “Fixes #123” + - 为界面改动添加截图 + - 指定特定评审人 + - 对进行中的工作使用草稿 PR + - 确保所有 CI 检查通过再请求评审 +1. **清理**。在你成功合并一个 PR 之后,进行_清理_工作被认为是一种良好习惯。你需要清理你的本地分支以及你推送到 GitHub 的分支。首先,用以下命令在本地删除它: + + ```bash + git branch -d [branch-name] + ``` + +确保接下来访问 Fork 的 GitHub 页面,删除你刚刚推送的远程分支。 + +“拉取请求”(Pull request)这个术语看起来有些奇怪,实际上你是想将你的变更推送到项目里。但项目维护者(项目所有者)或者核心团队需要先审查你的变更,才会将它合并到项目的“主”分支,所以你实际上是在请求维护者做出变更的决定。 + +拉取请求是一个比较和讨论某个分支引入的差异的地方,带有评审、评论、集成测试等等功能。一个好的拉取请求大致遵循提交信息的相同规则。当你的工作修复了某个问题时,你可以添加该问题追踪器中问题的引用。方法是用 `#` 加上你的问题编号。例如 `#97`。 + +🤞 希望所有检查都通过,项目所有者能将你的改动合并进项目 🤞 + +使用以下命令更新你当前本地工作分支,使其包含 GitHub 上对应远程分支的所有新提交: + +`git pull` + +## 为开源贡献(您改变世界的机会!) + +你准备好迎接将彻底震撼你心灵的事情了吗?🤯 让我们聊聊如何为开源项目做贡献——想到与您分享这些我都热血沸腾! + +这是你成为真正非凡事物一部分的机会。想象一下,改进数百万开发者每天使用的工具,或者修复你朋友喜欢的应用中的一个 bug。这不仅仅是梦想——这就是开源贡献的意义! + +让我每次想到都会激动的是:你学习过的每一个工具——代码编辑器、我们将探索的框架,甚至你现在用来阅读这篇文章的浏览器——最初都是由和你一样的人首次做出贡献而开始的。那个打造你最喜欢的 VS Code 插件的优秀开发者?他们也曾是一个初学者,用颤抖的手点下“创建拉取请求”,就像你即将做的那样。 + +最美妙的是:开源社区就像互联网最大的集体拥抱。大多数项目都会积极欢迎新人,而且有专门标记为“good first issue”(好入门问题)的任务,就是为像你这样的人准备的!维护者看到新贡献者会非常兴奋,因为他们记得自己的第一步。 + +```mermaid +flowchart TD + A[🔍 探索 GitHub] --> B[🏷️ 找到 “good first issue”] + B --> C[📖 阅读贡献指南] + C --> D[🍴 派生仓库] + D --> E[💻 设置本地环境] + E --> F[🌿 创建功能分支] + F --> G[✨ 做出你的贡献] + G --> H[🧪 测试你的更改] + H --> I[📝 写清晰的提交信息] + I --> J[📤 推送并创建 PR] + J --> K[💬 参与反馈交流] + K --> L[🎉 合并成功!你成为贡献者了!] + L --> M[🌟 寻找下一个问题] + + style A fill:#e1f5fe + style L fill:#c8e6c9 + style M fill:#fff59d +``` +你不仅仅是在学编程——你正在准备加入一个每天醒来都想着“我们如何让数字世界变得更好一点”的全球建设者家庭。欢迎加入!🌟 + +首先,让我们找到一个你感兴趣且想贡献变更的 GitHub 代码库(**repo**)。你需要把它的内容复制到你的电脑上。 + +✅ 一个很好的寻找“初学者友好”仓库的方法是[通过“good-first-issue”标签搜索](https://github.blog/2020-01-22-browse-good-first-issues-to-start-contributing-to-open-source/)。 + +![在本地复制仓库](../../../../translated_images/zh-CN/clone_repo.5085c48d666ead57.webp) + +有几种方式可以复制代码。一种是使用 HTTPS、SSH,或者 GitHub CLI(命令行界面)“克隆”仓库内容。 + +打开终端,输入以下命令克隆仓库: + +```bash +# 使用 HTTPS +git clone https://github.com/ProjectURL + +# 使用 SSH(需要设置 SSH 密钥) +git clone git@github.com:username/repository.git + +# 使用 GitHub CLI +gh repo clone username/repository +``` + +要开始项目工作,切换到相应文件夹: +`cd ProjectURL` + +你也可以用以下方式打开整个项目: +- **[GitHub Codespaces](https://github.com/features/codespaces)** —— GitHub 提供的带有浏览器中 VS Code 的云开发环境 +- **[GitHub Desktop](https://desktop.github.com/)** —— Git 操作的图形界面应用 +- **[GitHub.dev](https://github.dev)** —— 在任意 GitHub 仓库按 `.` 键打开浏览器中 VS Code +- 安装 GitHub Pull Requests 扩展的 VS Code + +最后,你也可以下载代码的压缩包。 + +### 关于 GitHub 的几点更多有趣内容 + +你可以给任何 GitHub 上的公共仓库加星、关注和/或“Fork”(派生)。你可以在右上角的下拉菜单中找到你加星的仓库。它就像收藏书签,但针对代码。 + +项目通常有一个问题追踪器,通常在 GitHub 的“Issues”标签页(除非另有说明),这是人们讨论与项目有关问题的地方。拉取请求页是人们讨论和复审正在进行的改动的地方。 + +项目还可能有论坛、邮件列表,或者像 Slack、Discord、IRC 这样的聊天频道。 + +🔧 **现代 GitHub 功能**: +- **GitHub Discussions** —— 内置社区讨论论坛 +- **GitHub Sponsors** —— 金融支持维护者 +- **安全标签** —— 漏洞报告与安全公告 +- **Actions 标签** —— 查看自动化工作流和 CI/CD 管道 +- **Insights 标签** —— 关于贡献者、提交和项目健康的数据分析 +- **Projects 标签** —— GitHub 内置的项目管理工具 + +✅ 试着熟悉你的新 GitHub 仓库,尝试编辑设置、为仓库添加信息、创建项目(如看板),以及设置 GitHub Actions 实现自动化。你可以做很多事情! + +--- + +## 🚀 挑战 + +好了,是时候检验你闪亮的新 GitHub 超能力了!🚀 这项挑战会让一切以最令人满意的方式水到渠成: + +找一个朋友(或者一直问你“你那些电脑玩意儿在干嘛”的亲戚)一起开始一场协作编程冒险!这才是真正的魔法所在——创建项目,让他们 Fork,创建几个分支,然后像专业人士一样合并变更。 + +我说实话——你们很可能会哈哈大笑(尤其是当你们俩试图同时改同一行代码时),也许会一起摸不着头脑,但你们肯定会有那些令人激动的“啊哈!”时刻,让所有学习都物有所值。而且,和别人分享第一次成功合并总是特别的——就像是对你来之不易进步的一次小小庆祝! + +还没有编程伙伴?没关系!GitHub 社区里有无数热情欢迎的成员,他们都记得自己刚开始时是什么样子。寻找带有“good first issue”标签的仓库——它们基本上是在说“嘿,初学者,来和我们一起学习吧!”多棒啊! + +## 课后测验 +[课后测验](https://ff-quizzes.netlify.app/web/en/) + +## 复习与持续学习 + +呼!🎉 看你——你刚刚像个绝对的高手一样掌握了 GitHub 基础!如果现在感觉大脑有点满,那很正常,老实说这其实是好现象。你刚刚学会的工具,我当初花了好几周才熟悉。 + +Git 和 GitHub 非常强大(真的非常强大),我认识的每个开发者——包括现在看起来像个高手的那帮人——都必须不断练习、跌跌撞撞才能完全掌握。你能完成这课说明你已经在向掌握开发者工具箱里最重要的东西迈进了。 + +这里有一些绝佳资源,帮你练习且变得更棒: + +- [开源软件贡献指南](https://opensource.guide/how-to-contribute/#how-to-submit-a-contribution) —— 你的改变之路地图 +- [Git 速查表](https://training.github.com/downloads/github-git-cheat-sheet/) —— 随时备查! + +记住:练习带来进步,不是完美!你用 Git 和 GitHub 越多,越觉得自然。GitHub 还推出了些很棒的交互课程,让你在安全环境中练习: + +- [GitHub 入门](https://github.com/skills/introduction-to-github) +- [使用 Markdown 交流](https://github.com/skills/communicate-using-markdown) +- [GitHub Pages](https://github.com/skills/github-pages) +- [管理合并冲突](https://github.com/skills/resolve-merge-conflicts) + +**想挑战现代工具?查看这些:** +- [GitHub CLI 文档](https://cli.github.com/manual/) —— 想成为命令行巫师必备 +- [GitHub Codespaces 文档](https://docs.github.com/en/codespaces) —— 云端编程! +- [GitHub Actions 文档](https://docs.github.com/en/actions) —— 自动化一切 +- [Git 最佳实践](https://www.atlassian.com/git/tutorials/comparing-workflows) —— 升级你的工作流玩法 + +## GitHub Copilot Agent 挑战 🚀 + +使用 Agent 模式完成下面的挑战: + +**描述:** 创建一个协作网页开发项目,展示你在本课中学到的完整 GitHub 工作流程。本挑战将帮助你在真实场景中练习仓库创建、协作功能以及现代 Git 工作流。 + +**提示:** 在 GitHub 创建一个新的公共仓库,名为“Web Development Resources”。仓库应包含结构良好的 README.md 文件,列出按类别组织的实用网页开发工具和资源(HTML、CSS、JavaScript 等)。为仓库设置合适的社区规范,包括许可协议、贡献指南和行为准则。创建至少两个功能分支:一个用于添加 CSS 资源,另一个用于 JavaScript 资源。分别在两个分支做提交,并附上描述性提交信息,然后创建拉取请求合并回主分支。启用 GitHub 诸如 Issues、Discussions 功能,并设置基础的 GitHub Actions 工作流,实现自动检查。 + +## 任务 + +你的任务,如果你愿意接受:完成 GitHub Skills 上的 [GitHub 入门](https://github.com/skills/introduction-to-github) 课程。这个交互式课程会让你在安全的引导环境中练习所学。完成还有酷炫徽章奖励!🏅 + +**准备好接受更多挑战?** +- 为你的 GitHub 账户设置 SSH 认证(告别密码!) +- 试用 GitHub CLI 进行日常 Git 操作 +- 创建包含 GitHub Actions 工作流的仓库 +- 通过 GitHub Codespaces 在云端编辑这个仓库 + +--- + +## 🚀 你的 GitHub 掌握时间线 + +### ⚡ **接下来 5 分钟能做的事** +- [ ] 给这个仓库及另外 3 个你感兴趣的项目加星 +- [ ] 为你的 GitHub 账户设置双因素认证 +- [ ] 为你的第一个仓库创建简单的 README +- [ ] 关注 5 位启发你的开发者 + +### 🎯 **本小时能完成的目标** +- [ ] 完成课后测验并反思你的 GitHub 学习之旅 +- [ ] 配置 SSH 密钥实现免密码登录 GitHub +- [ ] 做出你第一个有意义且带有良好提交信息的 commit +- [ ] 探索 GitHub“Explore”标签页,发现热门项目 +- [ ] 练习 Fork 仓库并做一些小改动 + +### 📅 **一周的 GitHub 冒险** +- [ ] 完成 GitHub Skills 课程(GitHub 入门,Markdown) +- [ ] 向开源项目提交第一个拉取请求 +- [ ] 搭建 GitHub Pages 展示你的作品 +- [ ] 参与你感兴趣项目的 GitHub Discussions +- [ ] 创建符合社区规范的仓库(README,授权等) +- [ ] 试用 GitHub Codespaces 云端开发 + +### 🌟 **一个月的转变** +- [ ] 向 3 个不同开源项目贡献代码 +- [ ] 指导 GitHub 新手(传帮带!) +- [ ] 配置自动化工作流(GitHub Actions) +- [ ] 构建展示你 GitHub 贡献的作品集 +- [ ] 参加 Hacktoberfest 或类似社区活动 +- [ ] 成为自己项目的维护者,吸引他人贡献 + +### 🎓 **最终 GitHub 掌握确认** + +**庆祝你的进步:** +- 你最喜欢 GitHub 的哪一点? +- 哪个协作功能让你最兴奋? +- 现在你对开源贡献有多自信? +- 你第一个想贡献的项目是什么? + +```mermaid +journey + title 你的 GitHub 信心旅程 + section 今天 + 紧张: 3: 你 + 好奇: 4: 你 + 兴奋: 5: 你 + section 本周 + 练习中: 4: 你 + 贡献中: 5: 你 + 连接中: 5: 你 + section 下个月 + 合作中: 5: 你 + 领导中: 5: 你 + 激励他人: 5: 你 +``` +> 🌍 **欢迎加入全球开发者社区!** 你现在拥有了与全球数百万开发者协作的工具。你的第一次贡献可能看上去很小,但请记住——每个重大开源项目都是从有人第一次提交代码开始的。问题不在于你是否能产生影响,而是哪个令人惊叹的项目会首先受益于你独特的视角!🚀 + +记住:每个专家都曾是初学者。你可以的!💪 + +--- + + +**免责声明**: +本文件使用 AI 翻译服务 [Co-op Translator](https://github.com/Azure/co-op-translator) 进行翻译。尽管我们努力确保准确性,但请注意自动翻译可能包含错误或不准确之处。原文以其母语版本为准。对于重要信息,建议采用专业人工翻译。因使用本翻译引起的任何误解或错误解读,我们概不负责。 + \ No newline at end of file diff --git a/translations/zh-CN/1-getting-started-lessons/3-accessibility/README.md b/translations/zh-CN/1-getting-started-lessons/3-accessibility/README.md new file mode 100644 index 000000000..eb88f37c3 --- /dev/null +++ b/translations/zh-CN/1-getting-started-lessons/3-accessibility/README.md @@ -0,0 +1,1491 @@ +# 创建无障碍网页 + +![无障碍知识全览](../../../../translated_images/zh-CN/webdev101-a11y.8ef3025c858d897a.webp) +> 草图笔记由 [Tomomi Imura](https://twitter.com/girlie_mac) 制作 + +```mermaid +journey + title 你的无障碍学习之旅 + section 基础 + 了解用户: 5: 你 + 测试工具: 4: 你 + POUR 原则: 5: 你 + section 技能提升 + 语义化 HTML: 4: 你 + 视觉设计: 5: 你 + ARIA 技术: 4: 你 + section 精通实践 + 键盘导航: 5: 你 + 表单无障碍: 4: 你 + 真实环境测试: 5: 你 +``` +## 课前测验 +[课前测验](https://ff-quizzes.netlify.app/web/) + +> 网络的力量在于它的普遍性。无论是否有残疾,人人都能访问是其核心要素。 +> +> \- Sir Timothy Berners-Lee,W3C 董事兼万维网发明者 + +这里有个可能会让你惊讶的事实:当你构建无障碍网站时,你不仅是在帮助残障人士——你实际上是在让网络对所有人更好用! + +你有没有注意到街角的轮椅斜坡?它们最初是为轮椅设计的,但现在同样方便推婴儿车的人、搬运员推货车、带滚轮行李的旅行者和骑自行车的人。这正是无障碍网页设计的原理——帮助某一群体的解决方案最终会惠及所有人。相当酷,对吧? + +在这节课中,我们将探讨如何创建真正适合所有人的网站,无论他们如何浏览网络。你将学习已经内置于网页标准中的实用技巧,动手使用测试工具,并了解无障碍如何让你的网站对所有用户都更易用。 + +课程结束时,你将有信心让无障碍成为开发工作流程中的自然一环。准备好探索那些用心设计如何为数十亿用户打开网络的大门了吗?开始吧! + +```mermaid +mindmap + root((网页无障碍)) + Users + Screen readers + Keyboard navigation + Voice control + Magnification + Technologies + HTML semantics + ARIA attributes + CSS focus indicators + Keyboard events + Benefits + Wider audience + Better SEO + Legal compliance + Universal design + Testing + Automated tools + Manual testing + User feedback + Real assistive tech +``` +> 你也可以在 [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101/accessibility/?WT.mc_id=academic-77807-sagibbon) 在线学习这堂课! + +## 了解辅助技术 + +在开始编码之前,让我们先花点时间了解不同能力的人们是如何体验网络的。这不仅仅是理论——理解这些真实的导航模式会让你成为更出色的开发者! + +辅助技术是非常了不起的工具,它们帮助残障人士以你可能想不到的方式与网站交互。一旦你掌握了这些技术的运作方式,创建无障碍网页体验就会变得更加直观。这就像学会用别人的视角来看你的代码。 + +### 屏幕阅读器 + +[屏幕阅读器](https://en.wikipedia.org/wiki/Screen_reader) 是复杂的技术,它们将数字文本转换成语音或盲文输出。虽然主要用于视障人士,但它们对有阅读障碍等学习障碍的用户也非常有帮助。 + +我喜欢把屏幕阅读器想象成一个非常聪明的讲解者在为你朗读书籍。它以合乎逻辑的顺序朗读内容,宣布交互元素如“按钮”或“链接”,并提供键盘快捷键以跳转页面。然而,屏幕阅读器只有在我们构建的网站具有正确结构和有意义的内容时,才能发挥作用。这就需要你作为开发者参与进来了! + +**各平台流行的屏幕阅读器:** +- **Windows**: [NVDA](https://www.nvaccess.org/about-nvda/)(免费且最受欢迎),[JAWS](https://webaim.org/articles/jaws/),[Narrator](https://support.microsoft.com/windows/complete-guide-to-narrator-e4397a0d-ef4f-b386-d8ae-c172f109bdb1/?WT.mc_id=academic-77807-sagibbon)(内置) +- **macOS/iOS**: [VoiceOver](https://support.apple.com/guide/voiceover/welcome/10)(内置且性能强大) +- **Android**: [TalkBack](https://support.google.com/accessibility/android/answer/6283677)(内置) +- **Linux**: [Orca](https://wiki.gnome.org/Projects/Orca)(免费开源) + +**屏幕阅读器浏览网页内容的方式:** + +屏幕阅读器为有经验的用户提供多种高效的导航方式: +- **顺序阅读**:从上到下读取内容,就像看书一样 +- **地标导航**:在页面章节间跳转(头部,导航,主内容,页脚) +- **标题导航**:跳转标题,以了解页面结构 +- **链接列表**:生成所有链接的列表,快速访问 +- **表单控件**:直接在输入框和按钮间导航 + +> 💡 **让人惊讶的是**:68% 的屏幕阅读器用户主要通过标题导航 ([WebAIM 调查](https://webaim.org/projects/screenreadersurvey9/#finding))。这意味着你的标题结构就像用户的导航图——当你弄对了,它们能帮助用户更快地找到内容! + +### 构建你的测试工作流程 + +好消息是——有效的无障碍测试不必让人望而生畏!你需要结合自动化工具(它们非常擅长捕捉明显的问题)和一些手动测试。以下是我发现的一个体系化方法,能最大限度地发现问题且不会占用你太多时间: + +**必备的手动测试工作流程:** + +```mermaid +flowchart TD + A[🚀 开始测试] --> B{⌨️ 键盘导航} + B --> C[通过 Tab 键浏览所有交互元素] + C --> D{🎧 屏幕阅读器测试} + D --> E[使用 NVDA/VoiceOver 测试] + E --> F{🔍 放大测试} + F --> G[放大至 200% 并测试功能] + G --> H{🎨 颜色/对比度检查} + H --> I[验证所有文本满足对比度要求] + I --> J{👁️ 聚焦管理} + J --> K[确保聚焦指示器可见] + K --> L[✅ 测试完成] + + style A fill:#e3f2fd + style L fill:#e8f5e8 + style B fill:#fff3e0 + style D fill:#f3e5f5 + style F fill:#e0f2f1 + style H fill:#fce4ec + style J fill:#e8eaf6 +``` +**逐步测试检查表:** +1. **键盘导航**:仅使用 Tab、Shift+Tab、Enter、空格键和方向键操作 +2. **屏幕阅读器测试**:启动 NVDA、VoiceOver 或 Narrator,闭眼操作导航 +3. **缩放测试**:分别测验 200% 和 400% 缩放级别 +4. **颜色对比检查**:检查所有文本和 UI 组件 +5. **焦点指示测试**:确保所有交互元素都有可见焦点样式 + +✅ **从 Lighthouse 开始**:打开浏览器开发者工具,运行 Lighthouse 无障碍审计,再用结果指导手动测试重点。 + +### 缩放和放大工具 + +你知道吗,当文本太小而你在手机上捏合放大,或者在强光下眯眼看笔记本时?很多用户每天都依赖放大工具让内容可读。这包括视力低下者、老年人,以及任何曾尝试在户外阅读网页的人。 + +现代缩放技术不仅是放大而已。了解这些工具的工作原理有助于你设计出响应式页面,无论放大多少倍都保持功能性和美观。 + +**现代浏览器的缩放能力:** +- **页面缩放**:成比例缩放所有内容(文本、图片、布局)——这是首选方法 +- **仅文本缩放**:只放大字体大小,保持原有布局 +- **捏合缩放**:移动端手势支持临时放大 +- **浏览器支持**:所有现代浏览器支持最多 500% 缩放且不影响功能 + +**专用放大软件:** +- **Windows**: [放大镜](https://support.microsoft.com/windows/use-magnifier-to-make-things-on-the-screen-easier-to-see-414948ba-8b1c-d3bd-8615-0e5e32204198)(内置),[ZoomText](https://www.freedomscientific.com/training/zoomtext/getting-started/) +- **macOS/iOS**: [Zoom](https://www.apple.com/accessibility/mac/vision/)(内置,带高级功能) + +> ⚠️ **设计要点**:WCAG 要求内容在放大到 200% 时仍保持功能。此时应尽量避免横向滚动,所有交互元素都应保持可访问。 + +✅ **测试响应式设计**:将浏览器缩放至 200% 和 400%。你的布局是否优雅适应?是否能使用全部功能且无需过度滚动? + +## 现代无障碍测试工具 + +了解了人们如何用辅助技术浏览网页后,我们来看看帮助你构建和测试无障碍网站的工具。 + +简单来说:自动化工具擅长发现明显问题(比如缺少替代文本),而手动测试帮助你确保网站在真实使用中感觉良好。二者结合,让你有信心网站惠及所有人。 + +### 颜色对比测试 + +好消息是:颜色对比是最常见的无障碍问题之一,但也是最容易修正的。良好的对比度惠及所有人——从视障用户到在海滩上看手机的人。 + +**WCAG 对比度要求:** + +| 文本类型 | WCAG AA(最低要求) | WCAG AAA(增强要求) | +|-----------|--------------------|---------------------| +| **普通文本**(小于18pt) | 4.5:1 对比度 | 7:1 对比度 | +| **大号文本**(18pt及以上或14pt加粗) | 3:1 对比度 | 4.5:1 对比度 | +| **UI 组件**(按钮,表单边框) | 3:1 对比度 | 3:1 对比度 | + +**必备测试工具:** +- [Colour Contrast Analyser](https://www.tpgi.com/color-contrast-checker/) - 桌面应用带取色器 +- [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/) - 网站工具即时反馈 +- [Stark](https://www.getstark.co/) - 针对 Figma, Sketch, Adobe XD 的设计插件 +- [Accessible Colors](https://accessible-colors.com/) - 查找可访问的配色方案 + +✅ **打造更好的色彩方案**:从品牌颜色出发,使用对比度工具创建无障碍变体。将它们作为设计系统的无障碍色彩标记记录下来。 + +### 全面无障碍审计 + +最有效的无障碍测试是结合多种方法。没有单一工具能发现所有问题,因此建立多元测试流程能确保覆盖全面。 + +**基于浏览器的测试(集成在开发者工具中):** +- **Chrome/Edge**:Lighthouse 无障碍审计 + 无障碍面板 +- **Firefox**:带详细树视图的无障碍检查器 +- **Safari**:Web Inspector 审计标签页 + VoiceOver 模拟 + +**专业测试插件:** +- [axe DevTools](https://www.deque.com/axe/devtools/) - 行业内标准的自动测试工具 +- [WAVE](https://wave.webaim.org/extension/) - 可视反馈与错误高亮 +- [Accessibility Insights](https://accessibilityinsights.io/) - 微软的综合测试套件 + +**命令行和 CI/CD 集成:** +- [axe-core](https://github.com/dequelabs/axe-core) - 用于自动测试的 JS 库 +- [Pa11y](https://pa11y.org/) - 命令行无障碍测试工具 +- [Lighthouse CI](https://github.com/GoogleChrome/lighthouse-ci) - 自动无障碍评分 + +> 🎯 **测试目标**:力争 Lighthouse 无障碍得分至少 95 分。记住,自动工具只能发现约 30-40% 的无障碍问题——手动测试依然不可少! + +### 🧠 **测试技能自测:准备找问题了吗?** + +**来看看你对无障碍测试的感觉:** +- 目前你觉得哪个测试方式最容易上手? +- 你能想象只用键盘导航一天吗? +- 你曾在线上遇到过哪些无障碍障碍? + +```mermaid +pie title "不同方法捕捉到的无障碍问题" + "自动化工具" : 35 + "人工测试" : 40 + "用户反馈" : 25 +``` +> **增强信心**:专业无障碍测试员正是使用上述组合方法。你正在学习行业标准的实践! + +## 从根基开始构建无障碍 + +无障碍成功的关键是从一开始就将它构建进你的基础。虽然可能会想“我以后再加无障碍”,但这就像房子建好后再加坡道。可能吗?可以。但容易吗?不太。 + +把无障碍想象成房屋规划——在初期建筑设计时包含轮椅通道,要远比事后改造轻松很多。 + +### POUR 原则:你的无障碍基石 + +《网页内容无障碍指南》(WCAG) 建立在四个基本原则之上,简称 POUR。别担心,这些并非枯燥的学术概念,而是实用指南,帮助你制作适合所有人的内容。 + +掌握了 POUR,做无障碍相关决策会更加顺畅。这就像有一个心理清单指导你的设计选择。我们来逐条拆解: + +```mermaid +flowchart LR + A[🔍 可感知的
用户能感知到吗?] --> B[🎮 可操作的
用户能使用吗?] + B --> C[📖 可理解的
用户能理解吗?] + C --> D[💪 稳定的
它能在任何地方工作吗?] + + A1[替代文本
字幕
对比度] --> A + B1[键盘访问
无癫痫发作
时间限制] --> B + C1[清晰的语言
可预测的
错误帮助] --> C + D1[有效代码
兼容
面向未来] --> D + + style A fill:#e1f5fe + style B fill:#e8f5e8 + style C fill:#fff3e0 + style D fill:#f3e5f5 +``` +**🔍 可感知(Perceivable)**:信息必须以用户能通过其感官感知的方式呈现 + +- 为非文本内容(图片、视频、音频)提供文本替代 +- 确保所有文本和 UI 组件有足够的颜色对比度 +- 为多媒体内容提供字幕和文字稿 +- 设计内容在放大至 200% 时仍保持功能 +- 使用多重感官属性(不仅仅是颜色)传达信息 + +**🎮 可操作(Operable)**:所有界面组件必须可通过可用输入方式操作 + +- 使所有功能可通过键盘导航访问 +- 给用户充足时间阅读和交互 +- 避免引发癫痫或前庭障碍的内容 +- 通过清晰结构和地标帮助用户高效导航 +- 确保交互元素有足够触控面积(至少44像素) + +**📖 可理解(Understandable)**:信息和界面操作必须清晰且易懂 + +- 使用适合目标用户的清晰简洁语言 +- 保证内容出现和操作方式可预测、一致 +- 为用户输入提供清晰的指引和错误提示 +- 帮助用户理解并纠正表单错误 +- 通过合理的阅读顺序和信息层级组织内容 + +**💪 稳健(Robust)**:内容必须在不同技术和辅助设备中可靠工作 + +- **使用有效且语义化的 HTML 作为基础** +- **确保兼容当前和未来的辅助技术** +- **遵循网页标准和最佳实践的标记规范** +- **在不同浏览器、设备和辅助工具上进行测试** +- **构建内容结构,以便在不支持高级功能时可优雅降级** + +### 🎯 **POUR 原则检查:让它深入人心** + +**对基础的快速反思:** +- 你能想到哪些网站功能未能满足每个 POUR 原则吗? +- 作为开发者,哪个原则对你来说最自然? +- 这些原则如何改善所有人的设计,而不仅仅是残障用户? + +```mermaid +quadrantChart + title POUR 原则影响矩阵 + x-axis 低投入 --> 高投入 + y-axis 低影响 --> 高影响 + quadrant-1 快速胜利 + quadrant-2 重大项目 + quadrant-3 后续考虑 + quadrant-4 战略重点 + + Alt Text: [0.2, 0.9] + Color Contrast: [0.3, 0.8] + Semantic HTML: [0.4, 0.9] + Keyboard Nav: [0.6, 0.8] + ARIA Complex: [0.8, 0.7] + Screen Reader Testing: [0.7, 0.6] +``` +> **记住**:从高影响、低难度的改进开始。语义化 HTML 和 alt 文本能以最低的努力带来最大的无障碍提升! + +## 创建无障碍的视觉设计 + +良好的视觉设计和无障碍是相辅相成的。当你以无障碍为设计出发点时,你常常会发现这些限制会带来更简洁、更优雅的解决方案,惠及所有用户。 + +让我们探讨如何创建对所有人都友好的视觉设计,无论他们的视觉能力如何,也无论他们在何种条件下浏览内容。 + +### 颜色和视觉无障碍策略 + +颜色是强有力的沟通手段,但不应成为传达重要信息的唯一方式。超越颜色的设计创造了更强健、更包容的体验,适用性更广。 + +**考虑色觉差异进行设计:** + +约有 8% 的男性和 0.5% 的女性存在某种形式的色觉差异(通常称为“色盲”)。最常见的类型有: +- **红绿色盲(Deuteranopia)**:难以区分红色和绿色 +- **红色弱视(Protanopia)**:红色看起来更加暗淡 +- **蓝黄色盲(Tritanopia)**:难以区分蓝色和黄色(罕见) + +**包容性色彩策略:** + +```css +/* ❌ Bad: Using only color to indicate status */ +.error { color: red; } +.success { color: green; } + +/* ✅ Good: Color plus icons and context */ +.error { + color: #d32f2f; + border-left: 4px solid #d32f2f; +} +.error::before { + content: "⚠️"; + margin-right: 8px; +} + +.success { + color: #2e7d32; + border-left: 4px solid #2e7d32; +} +.success::before { + content: "✅"; + margin-right: 8px; +} +``` + +**超越基础对比度要求:** +- 使用色盲模拟器测试你的配色 +- 结合使用图案、纹理或形状与颜色编码 +- 确保交互状态无需色彩也能区分 +- 考虑设计在高对比度模式下的表现 + +✅ **测试你的颜色无障碍性**:使用诸如 [Coblis](https://www.color-blindness.com/coblis-color-blindness-simulator/) 之类的工具查看不同色觉用户如何看到你的网站。 + +### 焦点指示器和交互设计 + +焦点指示器是数字世界中的光标——它向键盘用户显示他们在页面上的位置。设计良好的焦点指示器通过使交互清晰且可预测来提升所有用户的体验。 + +**现代焦点指示器最佳实践:** + +```css +/* Enhanced focus styles that work across browsers */ +button:focus-visible { + outline: 2px solid #0066cc; + outline-offset: 2px; + box-shadow: 0 0 0 4px rgba(0, 102, 204, 0.25); +} + +/* Remove focus outline for mouse users, preserve for keyboard users */ +button:focus:not(:focus-visible) { + outline: none; +} + +/* Focus-within for complex components */ +.card:focus-within { + box-shadow: 0 0 0 3px rgba(74, 144, 164, 0.5); + border-color: #4A90A4; +} + +/* Ensure focus indicators meet contrast requirements */ +.custom-focus:focus-visible { + outline: 3px solid #ffffff; + outline-offset: 2px; + box-shadow: 0 0 0 6px #000000; +} +``` + +**焦点指示器要求:** +- **可见性**:必须与周围元素保持至少 3:1 的对比度 +- **宽度**:元素周围必须至少有 2px 的厚度 +- **持续性**:焦点移动到别处之前需要一直可见 +- **区分性**:必须与其他 UI 状态有明显视觉差异 + +> 💡 **设计建议**:优秀的焦点指示器通常结合使用轮廓、盒阴影和颜色变化,以确保在不同背景和场景下都能清晰可见。 + +✅ **审查焦点指示器**:用 Tab 键遍历你的网站,记录哪些元素有清晰的焦点指示器。有没有难以看清或完全缺失的? + +### 语义 HTML:无障碍的基础 + +语义 HTML 就像为你的网页提供一套 GPS 系统。当你为 HTML 元素赋予正确的语义时,基本上为屏幕阅读器、键盘和其他辅助工具提供了详细的导航路线图,帮助用户高效浏览。 + +我特别喜欢这个比喻:语义 HTML 的区别就像一个有明确类别和指示牌的图书馆,与一个书籍乱扔的仓库。两者虽然都有书,但你更愿意在哪个地方找书?没错! + +```mermaid +flowchart TD + A[🏠 HTML 文档] --> B[📰 头部] + A --> C[🧭 导航] + A --> D[📄 主要内容] + A --> E[📋 页脚] + + B --> B1[h1:网站名称
标志与品牌] + C --> C1[ul:导航
主要链接] + D --> D1[article:内容
section:子部分] + D --> D2[aside:侧边栏
相关内容] + E --> E1[nav:页脚链接
版权信息] + + D1 --> D1a[h1:页面标题
h2:主要部分
h3:子部分] + + style A fill:#e3f2fd + style B fill:#e8f5e8 + style C fill:#fff3e0 + style D fill:#f3e5f5 + style E fill:#e0f2f1 +``` +**构建无障碍页面结构的基本模块:** + +```html + +
+

Your Site Name

+ +
+ +
+
+
+

Article Title

+

Published on

+
+ +
+

First Section

+

Content that relates to this section...

+
+ +
+

Second Section

+

More related content...

+
+
+ + +
+ + +``` + +**语义 HTML 如何改变无障碍体验:** + +| 语义元素 | 作用 | 屏幕阅读器优势 | +|------------------|---------|----------------------| +| `
` | 页面或区域的页眉 | “横幅地标” - 快速导航至顶部 | +| `