Chuyển tới nội dung chính

Phát triển


Hướng dẫn phát triển

Chỉ chỉnh sửa tiếng Anh; bản dịch sẽ được đồng bộ

Cập nhật tài liệu chỉ dưới website/docs (tiếng Anh). Bản dịch dưới website/i18n/<locale>/… được tạo tự động và không nên chỉnh sửa thủ công. Dùng các tác vụ dịch (vd., make translate_web_docs_batch) để làm mới nội dung bản địa hóa.

Điều kiện tiên quyết

  • Node.js 22+ và npm (đã thử với Node 22)
  • Thunderbird 128 ESR hoặc mới hơn (để kiểm thử thủ công)

Bố cục dự án (tổng quan)

  • Gốc: script đóng gói distribution_zip_packer.sh, tài liệu, ảnh chụp màn hình
  • sources/: mã tiện ích chính (background, giao diện options/popup, manifest, biểu tượng)
  • tests/: bộ kiểm thử Vitest
  • website/: tài liệu Docusaurus (có i18n dưới website/i18n/de/...)

Cài đặt & Công cụ

  • Cài đặt phụ thuộc ở thư mục gốc: npm ci
  • Tài liệu (tuỳ chọn): cd website && npm ci
  • Xem các mục tiêu: make help

Phát triển trực tiếp (web‑ext run)

  • Vòng lặp nhanh trên Firefox Desktop (chỉ kiểm thử giao diện cơ bản):
  • npx web-ext run --source-dir sources --target=firefox-desktop
  • Chạy trong Thunderbird (khuyến nghị cho MailExtensions):
  • npx web-ext run --source-dir sources --start-url about:addons --firefox-binary "$(command -v thunderbird || echo /path/to/thunderbird)"
  • Mẹo:
  • Giữ mở Bảng điều khiển lỗi của Thunderbird (Tools → Developer Tools → Error Console).
  • Trang sự kiện MV3 sẽ tạm dừng khi nhàn rỗi; hãy tải lại tiện ích sau khi thay đổi mã, hoặc để web‑ext tự động tải lại.
  • Một số hành vi chỉ có trên Firefox khác biệt; luôn xác minh trên Thunderbird để đảm bảo tương đồng API.
  • Đường dẫn nhị phân Thunderbird (ví dụ):
  • Linux: thunderbird (ví dụ: /usr/bin/thunderbird)
  • macOS: /Applications/Thunderbird.app/Contents/MacOS/thunderbird
  • Windows: "C:\\Program Files\\Mozilla Thunderbird\\thunderbird.exe"
  • Cô lập hồ sơ: Sử dụng một hồ sơ Thunderbird riêng cho phát triển để tránh ảnh hưởng thiết lập hàng ngày của bạn.

Mục tiêu Make (theo thứ tự bảng chữ cái)

Makefile tiêu chuẩn hóa các luồng phát triển phổ biến. Chạy make help bất cứ lúc nào để xem tóm tắt một dòng cho từng mục tiêu.

Mẹo: chạy make không kèm mục tiêu sẽ mở menu Whiptail đơn giản để chọn mục tiêu.

Mục tiêuMô tả một dòng
cleanXóa các tạo phẩm build/preview cục bộ (tmp/, web-local-preview/, website/build/).
commitĐịnh dạng, chạy kiểm thử (bao gồm i18n), cập nhật changelog, commit & push.
eslintChạy ESLint qua cấu hình phẳng (npm run -s lint:eslint).
helpLiệt kê tất cả mục tiêu với tài liệu một dòng (đã sắp xếp).
lintweb‑ext lint trên sources/ (manifest tạm; bỏ qua ZIP; không gây lỗi dừng).
menuMenu tương tác để chọn mục tiêu và tham số tùy chọn.
packXây dựng ZIP cho ATN & LOCAL (chạy linter; gọi script đóng gói).
prettierĐịnh dạng kho tại chỗ (ghi thay đổi).
prettier_checkPrettier ở chế độ kiểm tra (không ghi); thất bại nếu cần định dạng lại.
prettier_writeBí danh cho prettier.
testPrettier (ghi), ESLint, rồi Vitest (coverage nếu đã cấu hình).
test_i18nChỉ kiểm thử i18n: placeholder/tương đồng của tiện ích + tương đồng website.
translate_appBí danh cho translation_app.
translation_appDịch chuỗi giao diện ứng dụng từ sources/_locales/en/messages.json.
translate_web_docs_batchDịch tài liệu website qua OpenAI Batch API (ưu tiên).
translate_web_docs_syncDịch tài liệu website đồng bộ (cũ, không dùng batch).
translate_web_indexBí danh cho translation_web_index.
translation_web_indexDịch giao diện trang chủ/thanh điều hướng/chân trang (website/i18n/en/code.json → .../<lang>/code.json).
web_buildBuild tài liệu ra website/build (hỗ trợ --locales / BUILD_LOCALES).
web_build_linkcheckKiểm tra liên kết an toàn ngoại tuyến (bỏ qua HTTP[S] từ xa).
web_build_local_previewXem thử gh‑pages cục bộ; tự phục vụ trên 8080–8090; tùy chọn kiểm thử/kiểm tra liên kết.
web_push_githubĐẩy website/build lên nhánh gh-pages.

Cú pháp cho tùy chọn

  • Dùng make <command> OPTS="…" để truyền tùy chọn (khuyến nghị dùng dấu ngoặc kép). Mỗi mục tiêu bên dưới có ví dụ sử dụng.

--

Mẹo build theo locale

  • Build một tập con locale: đặt BUILD_LOCALES="en de" hoặc truyền OPTS="--locales en,de" cho các target web.
  • Xem thử một locale cụ thể: http://localhost:<port>/Thunderbird-Reply-with-Attachments/de/.

Build & Đóng gói

  • Build ZIP: make pack
  • Tạo ZIP ATN và LOCAL ở thư mục gốc repo (không chỉnh sửa tạo phẩm bằng tay)
  • Mẹo: cập nhật phiên bản ở cả sources/manifest_ATN.jsonsources/manifest_LOCAL.json trước khi đóng gói
  • Cài thủ công (dev): Thunderbird → Tools → Add‑ons and Themes → bánh răng → Install Add‑on From File… → chọn ZIP đã build

Kiểm thử

  • Toàn bộ bộ kiểm thử: make test (Vitest)
  • Độ bao phủ (tuỳ chọn):
  • npm i -D @vitest/coverage-v8
  • Chạy make test; mở coverage/index.html để xem báo cáo HTML
  • Chỉ i18n: make test_i18n (khóa UI/placeholder/tiêu đề + tương đồng website theo locale theo tài liệu với kiểm tra id/title/sidebar_label)

Gỡ lỗi & Nhật ký

  • Bảng điều khiển lỗi: Tools → Developer Tools → Error Console
  • Bật/tắt log chi tiết khi chạy:
  • Bật: messenger.storage.local.set({ debug: true })
  • Tắt: messenger.storage.local.set({ debug: false })
  • Log hiển thị khi soạn/gửi phản hồi

Tài liệu (website)

  • Máy chủ dev: cd website && npm run start
  • Build site tĩnh: cd website && npm run build
  • Lệnh Make tương đương (theo ABC): make web_build, make web_build_linkcheck, make web_build_local_preview, make web_push_github
  • Ví dụ sử dụng:
  • Chỉ EN, bỏ qua kiểm thử/kiểm tra liên kết, không push: make web_build_local_preview OPTS="--locales en --no-test --no-link-check --dry-run"
  • Tất cả locale, kèm kiểm thử/kiểm tra liên kết, rồi push: make web_build_local_preview && make web_push_github
  • Trước khi xuất bản, chạy kiểm tra liên kết an toàn ngoại tuyến: make web_build_linkcheck.
  • i18n: Tiếng Anh ở website/docs/*.md; Tiếng Đức ở website/i18n/de/docusaurus-plugin-content-docs/current/*.md
  • Tìm kiếm: Nếu biến môi trường Algolia DocSearch được thiết lập trong CI (DOCSEARCH_APP_ID, DOCSEARCH_API_KEY, DOCSEARCH_INDEX_NAME), site sẽ dùng tìm kiếm Algolia; nếu không sẽ dùng tìm kiếm cục bộ. Ở trang chủ, nhấn / hoặc Ctrl+K để mở hộp tìm kiếm.

  • website/src/pages/donate.js
  • Route: /donate (và /<locale>/donate)
  • Hành vi:
  • Nếu route hiện tại có locale (ví dụ: /de/donate), hãy dùng nó
  • Nếu không, chọn khớp tốt nhất từ navigator.languages so với các locale đã cấu hình; nếu không có thì dùng locale mặc định
  • Chuyển hướng đến:
  • en/docs/donation
  • khác → /<locale>/docs/donation
  • Dùng useBaseUrl để xử lý baseUrl đúng
  • Bao gồm meta refresh + liên kết noscript như phương án dự phòng


Mẹo xem thử

  • Dừng xem thử Node một cách sạch sẽ: mở http://localhost:<port>/__stop (in ra sau Local server started).
  • Nếu hình ảnh không tải trong MDX/JSX, dùng useBaseUrl('/img/...') để tuân theo baseUrl của site.
  • Bản xem thử khởi động trước; kiểm tra liên kết chạy sau và không chặn (liên kết ngoài hỏng sẽ không dừng xem thử).
  • URL xem thử ví dụ: http://localhost:<port>/Thunderbird-Reply-with-Attachments/ (in ra sau “Local server started”).
  • Liên kết ngoài trong kiểm tra liên kết: Một số trang ngoài (vd., addons.thunderbird.net) chặn trình thu thập tự động và có thể hiển thị 403 trong kiểm tra. Bản xem thử vẫn khởi động; có thể bỏ qua an toàn.

Dịch Website

Những gì bạn có thể dịch

  • Chỉ giao diện website: trang chủ, thanh điều hướng, chân trang và các chuỗi UI khác. Nội dung tài liệu hiện vẫn chỉ tiếng Anh.

Chỉnh ở đâu

  • Sửa website/i18n/<locale>/code.json (dùng en làm tham chiếu). Giữ nguyên các placeholder như {year}, {slash}, {ctrl}, {k}, {code1}.

Tạo hoặc làm mới tệp

  • Tạo stub còn thiếu cho mọi locale: npm --prefix website run i18n:stubs
  • Ghi đè stub từ tiếng Anh (sau khi thêm chuỗi mới): npm --prefix website run i18n:stubs:force
  • Cách thay thế cho một locale: npx --prefix website docusaurus write-translations --locale <locale>

Dịch chuỗi UI trang chủ/thanh điều hướng/chân trang (OpenAI)

  • Thiết lập thông tin xác thực một lần (shell hoặc .env):
  • export OPENAI_API_KEY=sk-...
  • Tuỳ chọn: export OPENAI_MODEL=gpt-4o-mini
  • Một lần (tất cả locale, bỏ qua en): make translate_web_index
  • Giới hạn cho một số locale: make translate_web_index OPTS="--locales de,fr"
  • Ghi đè giá trị hiện có: make translate_web_index OPTS="--force"

Xác thực & thử lại

  • Script dịch xác thực cấu trúc JSON, giữ nguyên placeholder trong ngoặc nhọn và đảm bảo URL không thay đổi.
  • Nếu xác thực thất bại, nó thử lại kèm phản hồi tối đa 2 lần trước khi giữ nguyên giá trị hiện có.

Xem thử locale của bạn

  • Máy chủ dev: npm --prefix website run start
  • Truy cập http://localhost:3000/<locale>/Thunderbird-Reply-with-Attachments/

Gửi lên

  • Mở PR với các tệp code.json đã chỉnh sửa. Giữ thay đổi tập trung và kèm ảnh chụp nhanh khi có thể.

Mẹo Bảo mật & Cấu hình

  • Không commit sources/manifest.json (được tạo tạm thời bởi quá trình build)
  • Giữ browser_specific_settings.gecko.id ổn định để bảo toàn kênh cập nhật

Lưu giữ Thiết lập

  • Lưu trữ: Mọi thiết lập người dùng nằm trong storage.local và tồn tại qua các lần cập nhật tiện ích.
  • Cài đặt: Giá trị mặc định chỉ áp dụng khi một khóa hoàn toàn thiếu (undefined).
  • Cập nhật: Quá trình di trú chỉ điền các khóa còn thiếu; không bao giờ ghi đè giá trị hiện có.
  • Đánh dấu schema: settingsVersion (hiện là 1).
  • Các khóa và mặc định:
  • blacklistPatterns: string[]['*intern*', '*secret*', '*passwor*']
  • confirmBeforeAdd: booleanfalse
  • confirmDefaultChoice: 'yes'|'no''yes'
  • warnOnBlacklistExcluded: booleantrue
  • Mã: xem sources/background.jsinitializeOrMigrateSettings()SCHEMA_VERSION.

Quy trình dev (thêm một thiết lập mới)

  • Tăng SCHEMA_VERSION trong sources/background.js.
  • Thêm khóa mới + mặc định vào đối tượng DEFAULTS trong initializeOrMigrateSettings().
  • Dùng quy tắc "only-if-undefined" khi gieo giá trị mặc định; không ghi đè giá trị hiện có.
  • Nếu thiết lập hiển thị với người dùng, kết nối nó trong sources/options.js và thêm chuỗi bản địa hóa.
  • Thêm/điều chỉnh kiểm thử (xem tests/background.settings.migration.test.js).

Mẹo kiểm thử thủ công

  • Mô phỏng cài đặt mới: xóa thư mục dữ liệu của tiện ích hoặc bắt đầu với hồ sơ mới.
  • Mô phỏng cập nhật: đặt settingsVersion thành 0 trong storage.local rồi tải lại; xác nhận giá trị hiện có không đổi và chỉ các khóa thiếu được thêm vào.

Khắc phục sự cố

  • Đảm bảo Thunderbird là 128 ESR hoặc mới hơn
  • Dùng Bảng điều khiển lỗi cho vấn đề khi chạy
  • Nếu các thiết lập lưu trữ có vẻ không áp dụng đúng, hãy khởi động lại Thunderbird và thử lại. (Thunderbird có thể lưu trạng thái giữa các phiên; khởi động lại sẽ đảm bảo tải thiết lập mới.)

CI & Độ bao phủ

  • GitHub Actions (CI — Tests) chạy vitest với ngưỡng độ bao phủ (85% dòng/hàm/nhánh/mệnh đề). Nếu không đạt ngưỡng, job sẽ thất bại.
  • Workflow tải lên tạo phẩm coverage-html kèm báo cáo HTML; tải về từ trang chạy (Actions → lần chạy mới nhất → Artifacts).

Đóng góp

  • Xem CONTRIBUTING.md để biết hướng dẫn nhánh/commit/PR
  • Mẹo: Tạo một hồ sơ phát triển Thunderbird riêng để kiểm thử nhằm tránh ảnh hưởng hồ sơ hằng ngày.

Bản dịch

  • Chạy các tác vụ dịch lớn “tất cả → tất cả” có thể chậm và tốn kém. Bắt đầu với một tập con (vd., vài tài liệu và 1–2 locale), xem lại kết quả, rồi mở rộng.

  • Chính sách thử lại: các tác vụ dịch thử tối đa 3 lần với backoff lũy tiến khi lỗi API; xem scripts/translate_web_docs_batch.jsscripts/translate_web_docs_sync.js.

Ảnh chụp màn hình cho tài liệu

  • Lưu ảnh dưới website/static/img/.

  • Tham chiếu chúng trong MD/MDX qua useBaseUrl('/img/<filename>') để đường dẫn hoạt động với baseUrl của site.

  • Sau khi thêm hoặc đổi tên ảnh dưới website/static/img/, xác nhận mọi tham chiếu vẫn dùng useBaseUrl('/img/…') và hiển thị trong bản xem thử cục bộ. Favicon

  • Tệp favicon.ico đa kích thước được tạo tự động trong mọi đường build (Make + script) qua website/scripts/build-favicon.mjs.

  • Không cần thao tác thủ công; chỉ cần cập nhật icon-*.png là đủ. Mẹo rà soát

  • Giữ nguyên id ở front‑matter trong tài liệu đã dịch; chỉ dịch titlesidebar_label nếu có.

clean

  • Mục đích: xóa tạo phẩm build/preview cục bộ.
  • Cách dùng: make clean
  • Xóa (nếu có):
  • tmp/
  • web-local-preview/
  • website/build/

commit

  • Mục đích: định dạng, kiểm thử, cập nhật changelog, commit và push.
  • Cách dùng: make commit
  • Chi tiết: chạy Prettier (ghi), make test, make test_i18n; nối thêm changelog khi có khác biệt đã stage; push lên origin/<branch>.

eslint

  • Mục đích: chạy ESLint qua cấu hình phẳng.
  • Cách dùng: make eslint

help

  • Mục đích: liệt kê tất cả mục tiêu với tài liệu một dòng.
  • Cách dùng: make help

lint

  • Mục đích: lint MailExtension bằng web-ext.
  • Cách dùng: make lint
  • Ghi chú: sao chép tạm sources/manifest_LOCAL.jsonsources/manifest.json; bỏ qua ZIP đã build; cảnh báo không làm hỏng pipeline.

menu

  • Mục đích: menu tương tác để chọn mục tiêu Make và tham số tùy chọn.
  • Cách dùng: chạy make không kèm tham số.
  • Ghi chú: nếu không có whiptail, menu sẽ dùng make help.

pack

  • Mục đích: build ZIP ATN và LOCAL (phụ thuộc lint).
  • Cách dùng: make pack
  • Mẹo: tăng phiên bản ở cả sources/manifest_*.json trước khi đóng gói.

prettier

  • Mục đích: định dạng repo tại chỗ.
  • Cách dùng: make prettier

prettier_check

  • Mục đích: kiểm tra định dạng (không ghi).
  • Cách dùng: make prettier_check

prettier_write

  • Mục đích: bí danh cho prettier.
  • Cách dùng: make prettier_write

test

  • Mục đích: chạy Prettier (ghi), ESLint, rồi Vitest (coverage nếu đã cài).
  • Cách dùng: make test

test_i18n

  • Mục đích: kiểm thử tập trung i18n cho chuỗi tiện ích và tài liệu website.
  • Cách dùng: make test_i18n
  • Chạy: npm run test:i18nnpm run -s test:website-i18n.

translate_app / translation_app

  • Mục đích: dịch chuỗi UI tiện ích từ EN sang các locale khác.
  • Cách dùng: make translation_app OPTS="--locales all|de,fr"
  • Ghi chú: giữ nguyên cấu trúc khóa và placeholder; ghi log vào translation_app.log. Dạng script: node scripts/translate_app.js --locales ….

translate_web_docs_batch / translate_web_docs_sync

  • Mục đích: dịch tài liệu website từ website/docs/*.md sang website/i18n/<locale>/....
  • Ưu tiên: translate_web_docs_batch (OpenAI Batch API)
    • Cách dùng (cờ): make translate_web_docs_batch OPTS="--files <doc1,doc2|all> --locales <lang1,lang2|all>"
    • Vị trí tham số kiểu cũ vẫn chấp nhận: OPTS="<doc|all> <lang|all>"
  • Hành vi: dựng JSONL, tải lên, thăm dò mỗi 30s, tải kết quả, ghi tệp.
  • Lưu ý: một job batch có thể mất tới 24 giờ để hoàn tất (theo cửa sổ batch của OpenAI). Bảng điều khiển hiển thị thời gian đã trôi qua ở mỗi lần thăm dò.
  • Môi trường: OPENAI_API_KEY (bắt buộc), tùy chọn OPENAI_MODEL, OPENAI_TEMPERATURE, OPENAI_BATCH_WINDOW (mặc định 24h), BATCH_POLL_INTERVAL_MS.
  • Bản cũ: translate_web_docs_sync
    • Cách dùng (cờ): make translate_web_docs_sync OPTS="--files <doc1,doc2|all> --locales <lang1,lang2|all>"
    • Vị trí tham số kiểu cũ vẫn chấp nhận: OPTS="<doc|all> <lang|all>"
  • Hành vi: yêu cầu đồng bộ theo từng cặp (không gom batch).
  • Ghi chú: Nhắc tương tác khi bỏ qua OPTS. Cả hai chế độ đều giữ nguyên khối mã/mã inline và giữ id ở front‑matter không đổi; log vào translation_web_batch.log (batch) hoặc translation_web_sync.log (sync).

translate_web_index / translation_web_index

  • Mục đích: dịch chuỗi UI website (trang chủ, thanh điều hướng, chân trang) từ website/i18n/en/code.json sang tất cả locale dưới website/i18n/<locale>/code.json (loại trừ en).
  • Cách dùng: make translate_web_index hoặc make translate_web_index OPTS="--locales de,fr [--force]"
  • Yêu cầu: export OPENAI_API_KEY (tùy chọn: OPENAI_MODEL=gpt-4o-mini).
  • Hành vi: xác thực cấu trúc JSON, giữ nguyên placeholder ngoặc nhọn, giữ URL không đổi và thử lại kèm phản hồi khi lỗi xác thực.

web_build

  • Mục đích: build site tài liệu ra website/build.
  • Cách dùng: make web_build OPTS="--locales en|de,en|all" (hoặc đặt BUILD_LOCALES="en de")
  • Bên trong: node ./node_modules/@docusaurus/core/bin/docusaurus.mjs build [--locale …].
  • Phụ thuộc: chạy npm ci trong website/ chỉ khi thiếu website/node_modules/@docusaurus.

web_build_linkcheck

  • Mục đích: kiểm tra liên kết an toàn ngoại tuyến.
  • Cách dùng: make web_build_linkcheck OPTS="--locales en|all"
  • Ghi chú: build ra tmp_linkcheck_web_pages; viết lại baseUrl của GH Pages thành /; bỏ qua liên kết HTTP(S) từ xa.

web_build_local_preview

  • Mục đích: xem thử gh‑pages cục bộ với tuỳ chọn kiểm thử/kiểm tra liên kết.
  • Cách dùng: make web_build_local_preview OPTS="--locales en|all [--no-test] [--no-link-check] [--dry-run] [--no-serve]"
  • Hành vi: thử máy chủ xem thử Node trước (scripts/preview-server.mjs, hỗ trợ /__stop), dự phòng python3 -m http.server; phục vụ trên 8080–8090; PID tại web-local-preview/.server.pid.

web_push_github

  • Mục đích: đẩy website/build lên nhánh gh-pages.
  • Cách dùng: make web_push_github

Mẹo: đặt NPM=… để ghi đè trình quản lý gói mà Makefile dùng (mặc định npm).