Skip to content

feat: v1.3.0 - About menu, Sparkle auto-update, GitHub Actions CI/CD#20

Merged
hubo1989 merged 3 commits into
mainfrom
feat/v1.3.0
Feb 27, 2026
Merged

feat: v1.3.0 - About menu, Sparkle auto-update, GitHub Actions CI/CD#20
hubo1989 merged 3 commits into
mainfrom
feat/v1.3.0

Conversation

@hubo1989
Copy link
Copy Markdown
Owner

@hubo1989 hubo1989 commented Feb 27, 2026

Summary

This PR implements all features planned for v1.3.0:

About Menu

  • Create AboutView with app icon, version, copyright, license, and GitHub link
  • Create AcknowledgementsView for open source library credits
  • Create AboutWindowController for managing the about window lifecycle
  • Add "About ScreenTranslate" menu item to MenuBarController
  • Add localization for about window (English and Chinese)

Sparkle Auto-Update Framework

  • Integrate Sparkle SPM dependency
  • Add SPUStandardUpdaterController in AppDelegate
  • Connect "Check for Updates" button in About window to Sparkle
  • Add SUFeedURL to Info.plist for update feed

GitHub Actions CI/CD

  • Add release.yml workflow triggered by version tags (v*)
  • Automated Release build (universal binary)
  • DMG packaging
  • Sparkle appcast.xml generation
  • GitHub Release creation with DMG attachment

Documentation

  • Translate README to English (main README.md)
  • Preserve Chinese version as README_CN.md
  • Update docs/README.md with current features and structure

Test Plan

  • Build succeeds in Debug configuration
  • About window opens and displays correctly
  • Acknowledgements sheet shows Sparkle library
  • Check for Updates button triggers Sparkle updater
  • Localization works in both English and Chinese

Files Changed

  • ScreenTranslate/Features/About/AboutView.swift (new)
  • ScreenTranslate/Features/About/AboutWindowController.swift (new)
  • ScreenTranslate/Features/About/AcknowledgementsView.swift (new)
  • ScreenTranslate/Features/MenuBar/MenuBarController.swift (modified)
  • ScreenTranslate/App/AppDelegate.swift (modified)
  • ScreenTranslate/Resources/en.lproj/Localizable.strings (modified)
  • ScreenTranslate/Resources/zh-Hans.lproj/Localizable.strings (modified)
  • .github/workflows/release.yml (new)
  • README.md (translated to English)
  • README_CN.md (new - Chinese version)
  • docs/README.md (updated)

Summary by CodeRabbit

发布说明

  • 新功能

    • 添加应用"关于"窗口,展示版本信息、版权和许可详情
    • 添加检查更新功能
    • 添加开源库致谢窗口
    • 集成自动更新系统
  • 文档

    • README国际化支持(英文版本和新增中文版本)
    • 更新项目文档和技术栈信息
  • Chores

    • 建立发布工作流自动化

Hubert and others added 2 commits February 27, 2026 10:32
…ion improvements

About Menu:
- Create AboutView with app info, version, and license details
- Create AcknowledgementsView for open source library credits
- Create AboutWindowController for managing the about window
- Add About menu item to MenuBarController
- Add localization for about window (en/zh-Hans)

GitHub Actions:
- Add release.yml workflow for automated DMG builds on tag push
- Configure Sparkle appcast generation for auto-updates

Documentation:
- Translate README to English (main README.md)
- Keep Chinese version as README_CN.md
- Update docs/README.md with current features and structure
- Add link between English and Chinese versions

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Import Sparkle module in AppDelegate
- Add SPUStandardUpdaterController for managing updates
- Connect About window "Check for Updates" button to Sparkle
- Listen for checkForUpdates notification

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 27, 2026

Warning

Rate limit exceeded

@hubo1989 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 5 minutes and 31 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 261329b and 3611309.

📒 Files selected for processing (10)
  • .github/workflows/release.yml
  • README.md
  • README_CN.md
  • ScreenTranslate/App/AppDelegate.swift
  • ScreenTranslate/Features/About/AboutView.swift
  • ScreenTranslate/Features/About/AboutWindowController.swift
  • ScreenTranslate/Features/About/AcknowledgementsView.swift
  • ScreenTranslate/Resources/en.lproj/Localizable.strings
  • ScreenTranslate/Resources/zh-Hans.lproj/Localizable.strings
  • ScreenTranslate/Supporting Files/Info.plist
📝 Walkthrough

Walkthrough

此 PR 为 ScreenTranslate macOS 应用添加了自动发布工作流、Sparkle 更新框架集成、"关于"窗口 UI、应用内更新检查功能,并将 README 从中文翻译为英文,同时创建了中文版本的 README。

Changes

Cohort / File(s) Summary
GitHub Actions Release Workflow
.github/workflows/release.yml
新增自动发布工作流,在版本标签推送时触发,构建 DMG 包、生成 Sparkle appcast.xml,并通过 GitHub Releases 发布。
项目配置与更新集成
ScreenTranslate.xcodeproj/project.pbxproj, ScreenTranslate/Supporting Files/Info.plist
集成 Sparkle Swift 包依赖,添加构建框架链接;配置 plist 中的 SUFeedURL 指向 appcast 源。
关于窗口实现
ScreenTranslate/Features/About/AboutView.swift, ScreenTranslate/Features/About/AboutWindowController.swift, ScreenTranslate/Features/About/AcknowledgementsView.swift
新增 About 窗口 UI 组件,包括应用信息展示、更新检查按钮、开源库致谢列表和对应的窗口控制器。
应用集成与菜单
ScreenTranslate/App/AppDelegate.swift, ScreenTranslate/Features/MenuBar/MenuBarController.swift
AppDelegate 中集成 Sparkle 更新控制器并处理更新检查通知;菜单栏添加"About"菜单项。
本地化字符串
ScreenTranslate/Resources/en.lproj/Localizable.strings, ScreenTranslate/Resources/zh-Hans.lproj/Localizable.strings
为菜单、About 窗口及致谢面板添加英文和简体中文本地化字符串。
文档与国际化
README.md, README_CN.md, docs/README.md
将主 README 从中文翻译为英文,新增中文版 README_CN.md,更新项目文档以反映新增翻译及 OCR 功能。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 轻轻敲键盘,更新悄然至,
关于窗已开,致谢一一记,
中英双语舞,DMG 装进去,
Sparkle 闪闪亮,应用焕新衣!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题清晰地总结了PR的主要变更:v1.3.0版本包含三个核心功能(About菜单、Sparkle自动更新、GitHub Actions CI/CD),与所有更改内容完全相关。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/v1.3.0

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@hubo1989
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 27, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🧹 Nitpick comments (1)
ScreenTranslate/App/AppDelegate.swift (1)

25-25: 建议将 updaterController 改为惰性非可选,降低时序崩溃风险

当前使用 IUO,若未来有更早触发 checkForUpdates 的路径,会直接崩溃。这里可以改成惰性初始化并移除启动阶段的手动赋值。

♻️ 建议修改
-    private var updaterController: SPUStandardUpdaterController!
+    private lazy var updaterController = SPUStandardUpdaterController(
+        startingUpdater: true,
+        updaterDelegate: nil,
+        userDriverDelegate: nil
+    )
...
-        // Initialize Sparkle updater
-        updaterController = SPUStandardUpdaterController(
-            startingUpdater: true,
-            updaterDelegate: nil,
-            userDriverDelegate: nil
-        )

Also applies to: 56-60, 197-200

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ScreenTranslate/App/AppDelegate.swift` at line 25, 将隐式展开可选的 updaterController
改为惰性非可选并移除启动阶段的手动赋值:把 "private var updaterController:
SPUStandardUpdaterController!" 改为一个 lazy 非可选属性(例如 lazy private var
updaterController: SPUStandardUpdaterController = { ...
}())并在该闭包内完成原本在启动流程中创建/配置的逻辑;从 applicationDidFinishLaunching(或当前手动赋值的位置)删除对
updaterController 的显式赋值,确保所有对 updaterController 的调用(例如 checkForUpdates)不再使用强制解包或
IUO,以避免启动时的时序崩溃风险。
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/release.yml:
- Around line 11-14: 工作流缺少 permissions 声明,导致使用 softprops/action-gh-release@v2
的发布步骤可能因无写权限而失败;在顶层添加 permissions: with contents: write(即在 workflow 根对象下新增
permissions: { contents: write })以确保 release/upload 相关步骤有写入权限,参考 jobs/build 和使用的
action 名称 softprops/action-gh-release@v2 来定位需要权限保障的发布步骤并提交修改。
- Around line 47-74: The appcast currently writes enclosure url="${DMG_URL}"
with sparkle:edSignature="" and length="0", which will be rejected by Sparkle;
update the CI step that produces appcast.xml to sign the built DMG and set the
real byte size before writing the appcast: after building the DMG
(VERSION/DMS_URL), run your signing tool (e.g., sign_update or ed25519-cli) to
produce a Base64 Ed25519 signature and compute the file size (e.g., stat -f%z or
wc -c), then substitute those values into the enclosure attributes
(sparkle:edSignature and length) when creating appcast.xml (or switch to using
generate_appcast which does this automatically); also ensure the app bundle’s
Info.plist contains the matching SUPublicEDKey public key so Sparkle can verify
updates.
- Line 66: Replace the static use of github.event.head_commit.timestamp for the
<pubDate> element by generating an RFC-2822 timestamp at runtime (e.g., using
date -Ru) in a preceding step and injecting that generated value into the
<pubDate> field; add a step (e.g., "Generate pubDate" or similar) that runs date
-Ru and exposes the result as an output (e.g., pubDate) and then reference that
output where <pubDate>${{ github.event.head_commit.timestamp }}</pubDate>
currently appears so Sparkle can reliably parse the appcast.

In `@README_CN.md`:
- Around line 122-146: The code block in README_CN.md lacks a language specifier
and triggers MD040; update the fenced block that contains the project tree (the
block showing "ScreenTranslate/ ... Resources/") to use a plain text language
tag by changing the opening fence from ``` to ```text so the directory tree
renders consistently and lints cleanly; locate the block in README_CN.md that
contains the tree (the multi-line block starting with "ScreenTranslate/") and
replace its opening fence accordingly.
- Line 12: README_CN.md still references version "1.1.0" in the badges and
changelog; update all occurrences of "1.1.0" and "v1.1.0" to "1.3.0" / "v1.3.0"
respectively so the badge (the markdown image/link containing version text) and
the changelog heading (the "v..." entry in the release notes) match the PR
target; search for the literal tokens "1.1.0" and "v1.1.0" and replace them with
"1.3.0" and "v1.3.0" in README_CN.md (ensure both the badge alt/text and the
changelog headings are updated).

In `@README.md`:
- Line 12: Update the README.md version strings from 1.2.0 to 1.3.0: replace the
version badge text and URL (the markdown anchor/img snippet showing
"version-1.2.0" and alt text "Version") and update the changelog heading/entries
currently labeled "v1.2.0" (the changelog section starting at the "v1.2.0"
heading) so they reflect "v1.3.0"; ensure both the badge link and any changelog
headings/labels are consistently changed to 1.3.0.
- Around line 182-183: Update the terminology "translate and insert feature" to
the hyphenated form "translate-and-insert" throughout the README to match
existing docs; locate the text string "translate and insert feature" (and any
other occurrences of "translate and insert") and replace them with
"translate-and-insert" so the term is consistent.
- Around line 126-150: The fenced project-structure code block that starts with
"ScreenTranslate/" should declare a language to satisfy MD040; update the
opening fence from ``` to ```text for that block (the block containing the tree
listing like "ScreenTranslate/ ├── App/ ...") so markdownlint passes and
readability improves.

In `@ScreenTranslate/Features/About/AboutView.swift`:
- Around line 36-40: AboutView contains hardcoded user-facing strings (e.g.,
Text("ScreenTranslate"), Text("Version \(appVersion) (\(buildNumber))") and
other literals at the noted locations) which must be localized; replace each
literal in the AboutView SwiftUI view with localized keys using
LocalizedStringKey or NSLocalizedString (e.g., use
Text(LocalizedStringKey("about.title")) for the title and use String(format:
NSLocalizedString("about.version_format", comment: ""), appVersion, buildNumber)
for the version line), add corresponding keys to Localizable.strings (including
zh-Hans) and update any other hardcoded texts in AboutView to use those keys so
all user-facing strings are localized.

In `@ScreenTranslate/Features/About/AboutWindowController.swift`:
- Around line 44-47: In windowWillClose(_:) avoid clearing self.window
unconditionally from the queued async Task; instead, inside the Task (on
`@MainActor`) first obtain the window from notification.object (e.g. guard let
closed = notification.object as? NSWindow) and compare by identity to the
controller's current window (closed == self.window), and only set self.window =
nil if they match; this prevents an earlier close event's task from nulling a
newly opened window.

In `@ScreenTranslate/Features/About/AcknowledgementsView.swift`:
- Around line 73-80: Replace the forced unwrap of URL(string: item.url)! in the
Link initializer with a safe conditional: attempt to construct URL from item.url
and, if successful, use Link(destination: url) { Text(item.url) ... }. If URL
construction fails, render the same Text(item.url) (with .font(.caption),
.foregroundStyle(.primary or .secondary), .lineLimit(1),
.truncationMode(.middle)) and keep .buttonStyle(.plain) behavior so invalid URLs
degrade to plain text instead of crashing; update references in
AcknowledgementsView where Link and Text(item.url) are used.

In `@ScreenTranslate/Supporting` Files/Info.plist:
- Around line 35-36: The SUFeedURL value in Info.plist is using the wrong GitHub
path (/releases/download/latest/appcast.xml) so Sparkle cannot find the appcast;
update the SUFeedURL entry to use the correct GitHub releases pattern by
replacing the path segment to /releases/latest/download/appcast.xml so the
appcast.xml is served correctly (locate the SUFeedURL key in Info.plist and
change its string value accordingly).

---

Nitpick comments:
In `@ScreenTranslate/App/AppDelegate.swift`:
- Line 25: 将隐式展开可选的 updaterController 改为惰性非可选并移除启动阶段的手动赋值:把 "private var
updaterController: SPUStandardUpdaterController!" 改为一个 lazy 非可选属性(例如 lazy
private var updaterController: SPUStandardUpdaterController = { ...
}())并在该闭包内完成原本在启动流程中创建/配置的逻辑;从 applicationDidFinishLaunching(或当前手动赋值的位置)删除对
updaterController 的显式赋值,确保所有对 updaterController 的调用(例如 checkForUpdates)不再使用强制解包或
IUO,以避免启动时的时序崩溃风险。

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ce39412 and 261329b.

📒 Files selected for processing (13)
  • .github/workflows/release.yml
  • README.md
  • README_CN.md
  • ScreenTranslate.xcodeproj/project.pbxproj
  • ScreenTranslate/App/AppDelegate.swift
  • ScreenTranslate/Features/About/AboutView.swift
  • ScreenTranslate/Features/About/AboutWindowController.swift
  • ScreenTranslate/Features/About/AcknowledgementsView.swift
  • ScreenTranslate/Features/MenuBar/MenuBarController.swift
  • ScreenTranslate/Resources/en.lproj/Localizable.strings
  • ScreenTranslate/Resources/zh-Hans.lproj/Localizable.strings
  • ScreenTranslate/Supporting Files/Info.plist
  • docs/README.md

Comment thread .github/workflows/release.yml
Comment on lines +47 to +74
- name: Generate Sparkle Appcast
run: |
# Install generate_appcast if needed
# brew install --cask sparkle

# For now, create a basic appcast.xml
VERSION=${GITHUB_REF#refs/tags/v}
DMG_URL="https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/${{ env.PROJECT_NAME }}-${VERSION}.dmg"

cat > appcast.xml << EOF
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>${{ env.PROJECT_NAME }} Updates</title>
<link>https://github.com/${{ github.repository }}/releases</link>
<description>Most recent changes with links to updates.</description>
<language>en</language>
<item>
<title>Version ${VERSION}</title>
<pubDate>${{ github.event.head_commit.timestamp }}</pubDate>
<sparkle:version>${VERSION}</sparkle:version>
<sparkle:shortVersionString>${VERSION}</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>13.0</sparkle:minimumSystemVersion>
<enclosure url="${DMG_URL}" sparkle:edSignature="" length="0" type="application/octet-stream" />
</item>
</channel>
</rss>
EOF
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# 找到并查看 release.yml 文件
find . -name "release.yml" -type f

Repository: hubo1989/ScreenTranslate

Length of output: 99


🏁 Script executed:

# 获取 .github/workflows 目录的文件列表
git ls-files .github/workflows/

Repository: hubo1989/ScreenTranslate

Length of output: 97


🏁 Script executed:

# 读取 release.yml 文件内容,查看 47-74 行
cat -n .github/workflows/release.yml | sed -n '40,80p'

Repository: hubo1989/ScreenTranslate

Length of output: 2165


🌐 Web query:

Sparkle macOS edSignature signature verification requirements appcast

💡 Result:

For Sparkle (macOS) EdDSA / sparkle:edSignature verification, the practical requirements are:

  • Each update archive referenced by an <enclosure> must include:

    • sparkle:edSignature="…" (Base64 Ed25519 / EdDSA signature of the exact archive bytes you publish), and
    • length="…" (byte size of that archive). Sparkle’s sign_update tool outputs exactly these attributes, and generate_appcast can generate them automatically. [1]
  • Your app must ship the matching public key in Info.plist as SUPublicEDKey (Sparkle uses this to verify the sparkle:edSignature). [1][2]

  • The new app inside the update must also contain SUPublicEDKey (Sparkle supports key rotation but not key removal; missing the key in the new bundle causes validation failure). [2]

  • If you enable SURequireSignedFeed:

    • you must also sign the appcast and any external release notes (and include the corresponding sparkle:edSignature / sparkle:length where applicable). [1]
  • DSA signatures are legacy/deprecated; EdDSA (Ed25519) signatures are the current recommended mechanism. [3]

Sources: Sparkle “Publishing an update” docs (includes sign_update output examples and signed-feed notes) [1]; Sparkle GitHub discussion clarifying SUPublicEDKey presence in the updated bundle and generate_appcast behavior [2]; Ed25519/EdDSA compatibility note (WinSparkle) [3].


🌐 Web query:

Sparkle framework sparkle:edSignature length attribute requirements

💡 Result:

For Sparkle appcasts, when you add sparkle:edSignature="..." to an <enclosure>, you should also include the standard RSS length="..." attribute set to the exact size of the update archive in bytes (an integer). Sparkle’s sign_update tool outputs both values together specifically for you to copy into the <enclosure> element. [1]

Example output / usage (from Sparkle docs): sparkle:edSignature="…==" length="1623481" → add both attributes to <enclosure … />. [1]

If you’re signing release notes files (when using SURequireSignedFeed), sign_update outputs sparkle:edSignature="..." plus sparkle:length="..." (namespaced) for the sparkle:releaseNotesLink element. [1]

Sources: [1]


🏁 Script executed:

# 查看整个 release.yml 文件,检查是否有其他与签名相关的步骤
wc -l .github/workflows/release.yml && cat -n .github/workflows/release.yml | tail -20

Repository: hubo1989/ScreenTranslate

Length of output: 922


Sparkle appcast 缺少有效签名与真实文件大小,自动更新会失败。

第 70 行当前 sparkle:edSignature=""length="0" 会导致 Sparkle 框架无法验证更新。根据 Sparkle 规范,每个更新存档必须包含有效的 Ed25519 EdDSA 签名(Base64 编码)和准确的字节大小,否则客户端会拒绝应用更新。

应在 CI 流程中对构建的 DMG 进行签名,并获取实际文件大小:

  • 使用 sign_update 工具生成签名和大小,或
  • 使用 generate_appcast 自动生成有效的 appcast.xml,或
  • 手动计算 DMG 大小(stat -f%z)并使用 ed25519-cli 等工具签名

此外,应确保应用的 Info.plist 包含对应的 SUPublicEDKey 公钥,以便 Sparkle 进行验证。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release.yml around lines 47 - 74, The appcast currently
writes enclosure url="${DMG_URL}" with sparkle:edSignature="" and length="0",
which will be rejected by Sparkle; update the CI step that produces appcast.xml
to sign the built DMG and set the real byte size before writing the appcast:
after building the DMG (VERSION/DMS_URL), run your signing tool (e.g.,
sign_update or ed25519-cli) to produce a Base64 Ed25519 signature and compute
the file size (e.g., stat -f%z or wc -c), then substitute those values into the
enclosure attributes (sparkle:edSignature and length) when creating appcast.xml
(or switch to using generate_appcast which does this automatically); also ensure
the app bundle’s Info.plist contains the matching SUPublicEDKey public key so
Sparkle can verify updates.

Comment thread .github/workflows/release.yml Outdated
Comment thread README_CN.md Outdated
Comment thread README_CN.md Outdated
Comment thread README.md
Comment on lines +182 to +183
- ✨ Added translate and insert feature
- ✨ Menu bar shortcuts synced with settings
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

术语建议统一为 “translate-and-insert”。

Line [182] 当前写法为 “translate and insert feature”,建议加连字符以与文档中既有术语保持一致。

🧰 Tools
🪛 LanguageTool

[grammar] ~182-~182: Use a hyphen to join words.
Context: ... translation feature - ✨ Added translate and insert feature - ✨ Menu bar shortcut...

(QB_NEW_EN_HYPHEN)


[grammar] ~182-~182: Use a hyphen to join words.
Context: ...nslation feature - ✨ Added translate and insert feature - ✨ Menu bar shortcuts sy...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 182 - 183, Update the terminology "translate and
insert feature" to the hyphenated form "translate-and-insert" throughout the
README to match existing docs; locate the text string "translate and insert
feature" (and any other occurrences of "translate and insert") and replace them
with "translate-and-insert" so the term is consistent.

Comment thread ScreenTranslate/Features/About/AboutView.swift Outdated
Comment thread ScreenTranslate/Features/About/AboutWindowController.swift
Comment thread ScreenTranslate/Features/About/AcknowledgementsView.swift Outdated
Comment thread ScreenTranslate/Supporting Files/Info.plist Outdated
GitHub Actions:
- Add permissions: contents: write for release workflow
- Generate proper RFC-2822 pubDate using date -Ru
- Calculate real DMG file size for appcast enclosure

README:
- Update version badge from 1.2.0 to 1.3.0
- Add v1.3.0 changelog entry
- Add language specifier to code blocks (text)

AboutView:
- Localize all hardcoded user-facing strings
- Add new localization keys for app name, version format, etc.

AboutWindowController:
- Fix race condition in windowWillClose by checking window identity
- Use weak self capture to prevent retain cycles

AcknowledgementsView:
- Handle invalid URLs gracefully without forced unwrap

Info.plist:
- Fix SUFeedURL path to use correct /releases/latest/download/ format

AppDelegate:
- Make updaterController lazy to avoid initialization timing issues

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@hubo1989 hubo1989 merged commit 8c43252 into main Feb 27, 2026
1 check was pending
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant