Skip to content

Feature/add english translation - #83

Closed
CTristan wants to merge 7 commits into
MaaAssistantArknights:masterfrom
CTristan:feature/add-english-translation
Closed

Feature/add english translation#83
CTristan wants to merge 7 commits into
MaaAssistantArknights:masterfrom
CTristan:feature/add-english-translation

Conversation

@CTristan

@CTristan CTristan commented Feb 24, 2026

Copy link
Copy Markdown

Summary by Sourcery

在多个配置和工具视图中本地化用户可见文本,以支持英文和其他语言,同时保持后端使用的标识符不变。

新功能:

  • 引入本地化的可编辑购物清单:在界面上以用户语言显示物品名称,同时在数据持久化时保留中文名称以保证与后端的兼容性。

增强与改进:

  • 将设置、导航和任务相关视图(包括 roguelike、商城、基建、战斗、开局、连接、公招、奖励、抽卡、资源更新、日志、任务和侧边栏)中硬编码的中文界面文案替换为本地化字符串。
  • 添加物品名称本地化助手,用于在本地化显示名称与中文物品标识符之间进行映射,并将其用于商城配置摘要和可编辑列表。
  • 更新标签页标题、警告弹窗、工具提示和其他说明性文本,使用本地化 API 以支持多语言。
Original summary in English

Summary by Sourcery

Localize user-facing text across multiple configuration and utility views to support English and other languages while keeping backend-facing identifiers unchanged.

New Features:

  • Introduce localized editable shopping lists that display item names in the user’s language while persisting Chinese names for backend compatibility.

Enhancements:

  • Replace hard-coded Chinese UI strings with localized strings throughout settings, navigation, and task-related views, including roguelike, mall, infrastructure, fight, startup, connection, recruit, award, gacha, resource update, logs, tasks, and sidebar.
  • Add an item name localization helper to map between localized display names and Chinese item identifiers and use it for mall configuration summaries and editable lists.
  • Update tab labels, alerts, tooltips, and miscellaneous instructional texts to use localization APIs for multi-language support.

Signed-off-by: Chris Tristan <1764856+CTristan@users.noreply.github.com>
…tingsView

Signed-off-by: Chris Tristan <1764856+CTristan@users.noreply.github.com>
Signed-off-by: Chris Tristan <1764856+CTristan@users.noreply.github.com>
…d localization support

Signed-off-by: Chris Tristan <1764856+CTristan@users.noreply.github.com>
…MallSettingsView

Signed-off-by: Chris Tristan <1764856+CTristan@users.noreply.github.com>
Signed-off-by: Chris Tristan <1764856+CTristan@users.noreply.github.com>
Signed-off-by: Chris Tristan <1764856+CTristan@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 24, 2026 20:40

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - 我发现了 4 个问题,并给出了一些整体性的反馈:

  • 在多个地方你现在调用了 NSLocalizedString(String(localized: ...), comment: "")(例如 RoguelikeConfiguration.Theme.descriptionUtilityEntry.descriptionSidebarEntry.description),这会把已经本地化过的字符串当作查找键传入;这样会破坏本地化逻辑——应该在 NSLocalizedString 里保持原始 key,每个字符串只用一次 String(localized:)NSLocalizedString
  • ResourceUpdateView 中,错误文案使用了 String(localized: "Update failed: \(error.localizedDescription)"),这会把动态错误信息“烘焙”进本地化 key;建议使用带插值(例如 %@ 占位符)的静态格式化 key,这样翻译人员才能正确地本地化整句。
给 AI Agent 的提示
Please address the comments from this code review:

## Overall Comments
- 在多个地方你现在调用了 `NSLocalizedString(String(localized: ...), comment: "")`(例如 `RoguelikeConfiguration.Theme.description``UtilityEntry.description``SidebarEntry.description`),这会把已经本地化过的字符串当作查找键传入;这样会破坏本地化逻辑——应该在 `NSLocalizedString` 里保持原始 key,每个字符串只用一次 `String(localized:)``NSLocalizedString`-`ResourceUpdateView` 中,错误文案使用了 `String(localized: "Update failed: \(error.localizedDescription)")`,这会把动态错误信息“烘焙”进本地化 key;建议使用带插值(例如 `%@` 占位符)的静态格式化 key,这样翻译人员才能正确地本地化整句。

## Individual Comments

### Comment 1
<location path="MeoAsstMac/Navigation/UtilityContent.swift" line_range="97-106" />
<code_context>
         switch self {
         case .recruit:
-            return NSLocalizedString("公招词条", comment: "")
+            return NSLocalizedString(String(localized: "公招词条"), comment: "")
         case .depot:
-            return NSLocalizedString("仓库材料", comment: "")
+            return NSLocalizedString(String(localized: "仓库材料"), comment: "")
         case .oper:
-            return NSLocalizedString("干员列表", comment: "")
+            return NSLocalizedString(String(localized: "干员列表"), comment: "")
         case .video:
-            return NSLocalizedString("视频作业", comment: "")
+            return NSLocalizedString(String(localized: "视频作业"), comment: "")
         case .gacha:
-            return NSLocalizedString("干员寻访", comment: "")
+            return NSLocalizedString(String(localized: "干员寻访"), comment: "")
         case .minigame:
-            return NSLocalizedString("小游戏", comment: "")
+            return NSLocalizedString(String(localized: "小游戏"), comment: "")
         }
     }
</code_context>
<issue_to_address>
**issue (bug_risk):**`UtilityEntry` 的描述中使用 `String(localized:)` 嵌套在 `NSLocalizedString` 内,很可能会破坏本地化查找。

这里你先对字符串做了一次本地化,然后再把这个本地化后的值当作 `NSLocalizedString` 的 key 使用。由于这个 key 不会出现在 `.strings` 文件中,第二次查找实际上不会生效,而且也让逻辑变得更难理解。

建议二选一:
- 保持之前的写法 `NSLocalizedString("公招词条", comment: "")`,或者
- 去掉 `NSLocalizedString`,直接使用 `String(localized: "公招词条")`。

无论哪种方式,key 都应该是一个单一且稳定的字符串,以避免微妙的本地化问题。
</issue_to_address>

### Comment 2
<location path="MeoAsstMac/Navigation/Sidebar.swift" line_range="74-78" />
<code_context>
         switch self {
         case .daily:
-            return NSLocalizedString("一键长草", comment: "")
+            return NSLocalizedString(String(localized: "一键长草"), comment: "")
         case .copilot:
-            return NSLocalizedString("自动战斗", comment: "")
+            return NSLocalizedString(String(localized: "自动战斗"), comment: "")
         case .utility:
-            return NSLocalizedString("实用工具", comment: "")
+            return NSLocalizedString(String(localized: "实用工具"), comment: "")
         }
     }
</code_context>
<issue_to_address>
**issue (bug_risk):** `SidebarEntry` 描述中存在相同的“双重查找”本地化问题。

这些分支使用 `NSLocalizedString(String(localized: ...), comment: "")`,也就是把已经本地化过的字符串当作查找键传入,因此很可能找不到对应的 `.strings` 条目。

应只使用一次本地化调用,例如:

```swift
return String(localized: "一键长草")
```

或者保留原本的 `NSLocalizedString` 和原始 key,避免双重本地化以及错误的查找行为。
</issue_to_address>

### Comment 3
<location path="MeoAsstMac/Views/ResourceUpdateView.swift" line_range="50" />
<code_context>
             } else if let progress {
                 if let error {
-                    Text("更新失败:\(error.localizedDescription)")
+                    Text(String(localized: "Update failed: \(error.localizedDescription)"))
                         .font(.headline)
                         .frame(maxWidth: .infinity)
</code_context>
<issue_to_address>
**issue (bug_risk):** 在本地化 key 中插入 `error.localizedDescription` 会让这条字符串基本无法被本地化。

使用 `String(localized:)` 搭配动态消息(`"Update failed: \(error.localizedDescription)"`)时,整条字符串在运行时才拼接完成,因此永远不会匹配本地化资源中的 key,自然也就无法被真正本地化。catalog 中的 key 必须是稳定的,不能包含运行期内容。

例如:
```swift
Text("Update failed: \(error.localizedDescription)")
// 或者
Text(String(localized: "Update failed")) + Text(": \(error.localizedDescription)")
```
保持本地化 key 稳定的同时,仍然可以展示动态错误信息。
</issue_to_address>

### Comment 4
<location path="MeoAsstMac/Views/OperBoxView.swift" line_range="20-23" />
<code_context>
                 }
             } header: {
-                Text("已拥有干员:\(ownedOpers.count)")
+                Text(String(localized: "已拥有干员:") + "\(ownedOpers.count)")
             }

</code_context>
<issue_to_address>
**suggestion:** 使用 `LocalizedStringKey` 的插值来构建本地化的标题字符串,而不是手动拼接字符串。

将 `String(localized: ...)``"\(count)"` 进行字符串拼接会生成一个普通的 `String`,这会阻碍复数处理或特定语言的语序调整。

在 `LocalizedStringKey` 中使用插值,可以让整句保持可本地化状态,这样翻译人员就能根据需要移动或格式化数字,并更好地支持未来的非中文本地化。

建议实现方式:

```
            } header: {
                Text("已拥有干员:\(ownedOpers.count)")
            }

```

```
            } header: {
                Text("未拥有干员:\(unownedOpers.count)")
            }

```
</issue_to_address>

Sourcery 对开源项目免费——如果你觉得我们的评审有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据反馈改进后续的评审。
Original comment in English

Hey - I've found 4 issues, and left some high level feedback:

  • In several places you now call NSLocalizedString(String(localized: ...), comment: "") (e.g. RoguelikeConfiguration.Theme.description, UtilityEntry.description, SidebarEntry.description), which passes an already-localized string in as the lookup key; this will break localization—keep the raw key in NSLocalizedString and only use String(localized:) or NSLocalizedString once per string.
  • In ResourceUpdateView, the error text uses String(localized: "Update failed: \(error.localizedDescription)"), which bakes the dynamic error into the localization key; consider using a static format key with an interpolation (e.g. a %@ placeholder) so translators can localize the whole sentence properly.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In several places you now call `NSLocalizedString(String(localized: ...), comment: "")` (e.g. `RoguelikeConfiguration.Theme.description`, `UtilityEntry.description`, `SidebarEntry.description`), which passes an already-localized string in as the lookup key; this will break localization—keep the raw key in `NSLocalizedString` and only use `String(localized:)` or `NSLocalizedString` once per string.
- In `ResourceUpdateView`, the error text uses `String(localized: "Update failed: \(error.localizedDescription)")`, which bakes the dynamic error into the localization key; consider using a static format key with an interpolation (e.g. a `%@` placeholder) so translators can localize the whole sentence properly.

## Individual Comments

### Comment 1
<location path="MeoAsstMac/Navigation/UtilityContent.swift" line_range="97-106" />
<code_context>
         switch self {
         case .recruit:
-            return NSLocalizedString("公招词条", comment: "")
+            return NSLocalizedString(String(localized: "公招词条"), comment: "")
         case .depot:
-            return NSLocalizedString("仓库材料", comment: "")
+            return NSLocalizedString(String(localized: "仓库材料"), comment: "")
         case .oper:
-            return NSLocalizedString("干员列表", comment: "")
+            return NSLocalizedString(String(localized: "干员列表"), comment: "")
         case .video:
-            return NSLocalizedString("视频作业", comment: "")
+            return NSLocalizedString(String(localized: "视频作业"), comment: "")
         case .gacha:
-            return NSLocalizedString("干员寻访", comment: "")
+            return NSLocalizedString(String(localized: "干员寻访"), comment: "")
         case .minigame:
-            return NSLocalizedString("小游戏", comment: "")
+            return NSLocalizedString(String(localized: "小游戏"), comment: "")
         }
     }
</code_context>
<issue_to_address>
**issue (bug_risk):** Using `String(localized:)` inside `NSLocalizedString` likely breaks localization lookup for `UtilityEntry` descriptions.

Here you’re localizing the string first, then using that localized value as the `NSLocalizedString` key. Since that key won’t exist in the `.strings` file, the second lookup is effectively a no-op and makes the logic confusing.

Prefer either:
- Keeping the previous `NSLocalizedString("公招词条", comment: "")` style, or
- Dropping `NSLocalizedString` and just using `String(localized: "公招词条")`.

In both cases, the key should be a single, stable string to avoid subtle localization issues.
</issue_to_address>

### Comment 2
<location path="MeoAsstMac/Navigation/Sidebar.swift" line_range="74-78" />
<code_context>
         switch self {
         case .daily:
-            return NSLocalizedString("一键长草", comment: "")
+            return NSLocalizedString(String(localized: "一键长草"), comment: "")
         case .copilot:
-            return NSLocalizedString("自动战斗", comment: "")
+            return NSLocalizedString(String(localized: "自动战斗"), comment: "")
         case .utility:
-            return NSLocalizedString("实用工具", comment: "")
+            return NSLocalizedString(String(localized: "实用工具"), comment: "")
         }
     }
</code_context>
<issue_to_address>
**issue (bug_risk):** Same double-lookup localization issue for `SidebarEntry` descriptions.

These cases use `NSLocalizedString(String(localized: ...), comment: "")`, which passes an already-localized string as the lookup key and will likely miss the `.strings` entry.

Use a single localization call instead, e.g.:

```swift
return String(localized: "一键长草")
```

or keep `NSLocalizedString` with the original key to avoid double localization and incorrect lookups.
</issue_to_address>

### Comment 3
<location path="MeoAsstMac/Views/ResourceUpdateView.swift" line_range="50" />
<code_context>
             } else if let progress {
                 if let error {
-                    Text("更新失败:\(error.localizedDescription)")
+                    Text(String(localized: "Update failed: \(error.localizedDescription)"))
                         .font(.headline)
                         .frame(maxWidth: .infinity)
</code_context>
<issue_to_address>
**issue (bug_risk):** Interpolating `error.localizedDescription` inside the localization key makes this string effectively unlocalizable.

Using `String(localized:)` with a dynamic message (`"Update failed: \(error.localizedDescription)"`) means the full string will never match a key in the localization catalog, so it won’t actually be localized. The catalog key must be stable and not include runtime content.

For example:
```swift
Text("Update failed: \(error.localizedDescription)")
// or
Text(String(localized: "Update failed")) + Text(": \(error.localizedDescription)")
```
keeps the localized key stable while still showing the dynamic error text.
</issue_to_address>

### Comment 4
<location path="MeoAsstMac/Views/OperBoxView.swift" line_range="20-23" />
<code_context>
                 }
             } header: {
-                Text("已拥有干员:\(ownedOpers.count)")
+                Text(String(localized: "已拥有干员:") + "\(ownedOpers.count)")
             }

</code_context>
<issue_to_address>
**suggestion:** Build localized header strings using interpolation in `LocalizedStringKey` instead of manual string concatenation.

Concatenating `String(localized: ...)` with `"\(count)"` produces a plain `String`, which prevents proper handling of pluralization or language-specific word order.

Using interpolation in `LocalizedStringKey` keeps the whole sentence localizable so translators can move or format the number as needed and better support future non-Chinese localizations.

Suggested implementation:

```
            } header: {
                Text("已拥有干员:\(ownedOpers.count)")
            }

```

```
            } header: {
                Text("未拥有干员:\(unownedOpers.count)")
            }

```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +97 to 106
return NSLocalizedString(String(localized: "公招词条"), comment: "")
case .depot:
return NSLocalizedString("仓库材料", comment: "")
return NSLocalizedString(String(localized: "仓库材料"), comment: "")
case .oper:
return NSLocalizedString("干员列表", comment: "")
return NSLocalizedString(String(localized: "干员列表"), comment: "")
case .video:
return NSLocalizedString("视频作业", comment: "")
return NSLocalizedString(String(localized: "视频作业"), comment: "")
case .gacha:
return NSLocalizedString("干员寻访", comment: "")
return NSLocalizedString(String(localized: "干员寻访"), comment: "")
case .minigame:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk):UtilityEntry 的描述中使用 String(localized:) 嵌套在 NSLocalizedString 内,很可能会破坏本地化查找。

这里你先对字符串做了一次本地化,然后再把这个本地化后的值当作 NSLocalizedString 的 key 使用。由于这个 key 不会出现在 .strings 文件中,第二次查找实际上不会生效,而且也让逻辑变得更难理解。

建议二选一:

  • 保持之前的写法 NSLocalizedString("公招词条", comment: ""),或者
  • 去掉 NSLocalizedString,直接使用 String(localized: "公招词条")

无论哪种方式,key 都应该是一个单一且稳定的字符串,以避免微妙的本地化问题。

Original comment in English

issue (bug_risk): Using String(localized:) inside NSLocalizedString likely breaks localization lookup for UtilityEntry descriptions.

Here you’re localizing the string first, then using that localized value as the NSLocalizedString key. Since that key won’t exist in the .strings file, the second lookup is effectively a no-op and makes the logic confusing.

Prefer either:

  • Keeping the previous NSLocalizedString("公招词条", comment: "") style, or
  • Dropping NSLocalizedString and just using String(localized: "公招词条").

In both cases, the key should be a single, stable string to avoid subtle localization issues.

Comment on lines +74 to +78
return NSLocalizedString(String(localized: "一键长草"), comment: "")
case .copilot:
return NSLocalizedString("自动战斗", comment: "")
return NSLocalizedString(String(localized: "自动战斗"), comment: "")
case .utility:
return NSLocalizedString("实用工具", comment: "")
return NSLocalizedString(String(localized: "实用工具"), comment: "")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): SidebarEntry 描述中存在相同的“双重查找”本地化问题。

这些分支使用 NSLocalizedString(String(localized: ...), comment: ""),也就是把已经本地化过的字符串当作查找键传入,因此很可能找不到对应的 .strings 条目。

应只使用一次本地化调用,例如:

return String(localized: "一键长草")

或者保留原本的 NSLocalizedString 和原始 key,避免双重本地化以及错误的查找行为。

Original comment in English

issue (bug_risk): Same double-lookup localization issue for SidebarEntry descriptions.

These cases use NSLocalizedString(String(localized: ...), comment: ""), which passes an already-localized string as the lookup key and will likely miss the .strings entry.

Use a single localization call instead, e.g.:

return String(localized: "一键长草")

or keep NSLocalizedString with the original key to avoid double localization and incorrect lookups.

} else if let progress {
if let error {
Text("更新失败:\(error.localizedDescription)")
Text(String(localized: "Update failed: \(error.localizedDescription)"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): 在本地化 key 中插入 error.localizedDescription 会让这条字符串基本无法被本地化。

使用 String(localized:) 搭配动态消息("Update failed: \(error.localizedDescription)")时,整条字符串在运行时才拼接完成,因此永远不会匹配本地化资源中的 key,自然也就无法被真正本地化。catalog 中的 key 必须是稳定的,不能包含运行期内容。

例如:

Text("Update failed: \(error.localizedDescription)")
// 或者
Text(String(localized: "Update failed")) + Text(": \(error.localizedDescription)")

保持本地化 key 稳定的同时,仍然可以展示动态错误信息。

Original comment in English

issue (bug_risk): Interpolating error.localizedDescription inside the localization key makes this string effectively unlocalizable.

Using String(localized:) with a dynamic message ("Update failed: \(error.localizedDescription)") means the full string will never match a key in the localization catalog, so it won’t actually be localized. The catalog key must be stable and not include runtime content.

For example:

Text("Update failed: \(error.localizedDescription)")
// or
Text(String(localized: "Update failed")) + Text(": \(error.localizedDescription)")

keeps the localized key stable while still showing the dynamic error text.

Comment on lines +20 to 23
Text(String(localized: "已拥有干员:") + "\(ownedOpers.count)")
}

Section {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion: 使用 LocalizedStringKey 的插值来构建本地化的标题字符串,而不是手动拼接字符串。

String(localized: ...)"\(count)" 进行字符串拼接会生成一个普通的 String,这会阻碍复数处理或特定语言的语序调整。

LocalizedStringKey 中使用插值,可以让整句保持可本地化状态,这样翻译人员就能根据需要移动或格式化数字,并更好地支持未来的非中文本地化。

建议实现方式:

            } header: {
                Text("已拥有干员:\(ownedOpers.count)")
            }

            } header: {
                Text("未拥有干员:\(unownedOpers.count)")
            }

Original comment in English

suggestion: Build localized header strings using interpolation in LocalizedStringKey instead of manual string concatenation.

Concatenating String(localized: ...) with "\(count)" produces a plain String, which prevents proper handling of pluralization or language-specific word order.

Using interpolation in LocalizedStringKey keeps the whole sentence localizable so translators can move or format the number as needed and better support future non-Chinese localizations.

Suggested implementation:

            } header: {
                Text("已拥有干员:\(ownedOpers.count)")
            }

            } header: {
                Text("未拥有干员:\(unownedOpers.count)")
            }

@CTristan CTristan closed this Feb 24, 2026
@CTristan

Copy link
Copy Markdown
Author

Sorry, created this on accident.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the macOS SwiftUI UI text to use the string catalog-based localization system, with the goal of enabling English translations across the app.

Changes:

  • Replaced many hard-coded UI strings with String(localized:) (and related localized wrappers) in Views, Navigation, and Settings.
  • Updated labels/help text in toolbars and sidebars to be localizable.
  • Introduced several new English-keyed localization lookups in settings and dialogs.

Reviewed changes

Copilot reviewed 31 out of 32 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
MeoAsstMac/Views/VideoRecogView.swift Localizes instructional text for video recognition.
MeoAsstMac/Views/TaskTimerView.swift Localizes timer UI and the “prevent sleep” alert strings.
MeoAsstMac/Views/TaskButtons.swift Localizes task control button titles.
MeoAsstMac/Views/ResourceUpdateView.swift Localizes resource update status and error text.
MeoAsstMac/Views/RecruitView.swift Localizes recruitment configuration labels/toggles.
MeoAsstMac/Views/OperBoxView.swift Localizes owned/unowned operator section headers.
MeoAsstMac/Views/LogView.swift Localizes log table headers and toggle/help text.
MeoAsstMac/Views/GachaView.swift Localizes gacha warning and action buttons.
MeoAsstMac/Views/DepotView.swift Localizes copy/export UI text.
MeoAsstMac/Settings/UpdaterSettingsView.swift Localizes updater/resource update settings UI.
MeoAsstMac/Settings/SystemSettingsView.swift Localizes “prevent system sleep” setting text.
MeoAsstMac/Settings/GameSettingsView.swift Localizes client type picker label.
MeoAsstMac/Settings/ConnectionSettingsView.swift Localizes connection/touch mode and related tips.
MeoAsstMac/Navigation/UtilityDetail.swift Localizes placeholder text when nothing selected.
MeoAsstMac/Navigation/UtilityContent.swift Localizes toolbar actions and utility entry names.
MeoAsstMac/Navigation/TasksContent.swift Localizes toolbar actions/help for tasks list.
MeoAsstMac/Navigation/TaskDetail.swift Localizes “add task” toolbar label/help.
MeoAsstMac/Navigation/Sidebar.swift Localizes sidebar settings label and entry names.
MeoAsstMac/Navigation/MAADetail.swift Localizes placeholder text when no detail selected.
MeoAsstMac/Navigation/MAAContent.swift Localizes placeholder text when no sidebar selection.
MeoAsstMac/Navigation/CopilotDetail.swift Localizes copilot toolbar/actions/help text.
MeoAsstMac/Navigation/CopilotContent.swift Localizes copilot list headers and toolbar/actions/help.
MeoAsstMac/MeoAsstMacApp.swift Localizes settings tab labels.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

SecureField(String(localized: "CDK"), text: mirrorChyanCDK)
} else if resourceChannel == .github {
Text("可能需要设置系统代理。")
Text(String(localized: "System Proxy May Be Required"))

Copilot AI Feb 24, 2026

Copy link

Choose a reason for hiding this comment

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

The key "System Proxy May Be Required" currently only has an en localization entry in the string catalog (sourceLanguage is zh-Hans). This will display English in the zh-Hans UI unless you either revert to the original Chinese key (e.g. the previous sentence) or add a zh-Hans localization value for this key.

Suggested change
Text(String(localized: "System Proxy May Be Required"))
Text(String(localized: "可能需要系统代理"))

Copilot uses AI. Check for mistakes.
var body: some View {
if showNotice {
Text("请注意,这是真的抽卡!不是模拟!!!")
Text(String(localized: "Gacha Real Not Simulation"))

Copilot AI Feb 24, 2026

Copy link

Choose a reason for hiding this comment

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

The key "Gacha Real Not Simulation" only has an en localization entry in Localizable.xcstrings (sourceLanguage is zh-Hans). Using it here will make the zh-Hans UI show English instead of the original Chinese notice. Prefer keeping the original Chinese source string as the key or add a zh-Hans localization value for this English key.

Suggested change
Text(String(localized: "Gacha Real Not Simulation"))
Text(String(localized: "抽卡为真实操作,非模拟"))

Copilot uses AI. Check for mistakes.
Comment on lines +97 to +107
return NSLocalizedString(String(localized: "公招词条"), comment: "")
case .depot:
return NSLocalizedString("仓库材料", comment: "")
return NSLocalizedString(String(localized: "仓库材料"), comment: "")
case .oper:
return NSLocalizedString("干员列表", comment: "")
return NSLocalizedString(String(localized: "干员列表"), comment: "")
case .video:
return NSLocalizedString("视频作业", comment: "")
return NSLocalizedString(String(localized: "视频作业"), comment: "")
case .gacha:
return NSLocalizedString("干员寻访", comment: "")
return NSLocalizedString(String(localized: "干员寻访"), comment: "")
case .minigame:
return NSLocalizedString("小游戏", comment: "")
return NSLocalizedString(String(localized: "小游戏"), comment: "")

Copilot AI Feb 24, 2026

Copy link

Choose a reason for hiding this comment

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

description is currently double-localized: String(localized: ...) returns a localized value, then wrapping it in NSLocalizedString(...) treats that value as a lookup key. In non-zh-Hans locales this will likely bypass the intended translations and fall back to the already-localized (e.g. English) string. Use a single localization mechanism here (e.g. return String(localized: "公招词条") directly, or call NSLocalizedString with the original key).

Copilot uses AI. Check for mistakes.
Comment on lines +74 to +78
return NSLocalizedString(String(localized: "一键长草"), comment: "")
case .copilot:
return NSLocalizedString("自动战斗", comment: "")
return NSLocalizedString(String(localized: "自动战斗"), comment: "")
case .utility:
return NSLocalizedString("实用工具", comment: "")
return NSLocalizedString(String(localized: "实用工具"), comment: "")

Copilot AI Feb 24, 2026

Copy link

Choose a reason for hiding this comment

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

description is double-localized (NSLocalizedString(String(localized: ...))). This ends up looking up the already-localized value as a key and can break translations (especially for non-zh-Hans locales). Return String(localized: ...) directly (or use NSLocalizedString with the original key), but not both.

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +11
Text(String(localized: "Prevent System Sleep"))
Text(String(localized: "Prevent System Sleep Tip"))

Copilot AI Feb 24, 2026

Copy link

Choose a reason for hiding this comment

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

The keys "Prevent System Sleep" / "Prevent System Sleep Tip" currently only have en localization entries in Localizable.xcstrings (sourceLanguage is zh-Hans). Using them here will make the zh-Hans UI show English strings. Prefer reusing the previous Chinese source keys or add zh-Hans localizations for these keys.

Suggested change
Text(String(localized: "Prevent System Sleep"))
Text(String(localized: "Prevent System Sleep Tip"))
Text(String(localized: "防止系统睡眠"))
Text(String(localized: "防止系统睡眠提示"))

Copilot uses AI. Check for mistakes.
VStack {
if !shouldUpdate {
Text("无需更新资源")
Text(String(localized: "Resource update not needed"))

Copilot AI Feb 24, 2026

Copy link

Choose a reason for hiding this comment

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

The key "Resource update not needed" only has an en localization entry in Localizable.xcstrings (sourceLanguage is zh-Hans). This will show English in the zh-Hans UI. Prefer keeping the original Chinese source key ("无需更新资源") or add a zh-Hans localization value for this key.

Suggested change
Text(String(localized: "Resource update not needed"))
Text(String(localized: "无需更新资源"))

Copilot uses AI. Check for mistakes.
}
} header: {
Text("未拥有干员:\(unownedOpers.count)")
Text(String(localized: "未拥有干员:") + "\(unownedOpers.count)")

Copilot AI Feb 24, 2026

Copy link

Choose a reason for hiding this comment

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

Same issue as above: concatenating a localized prefix with the count limits localization flexibility. Prefer a single localized format string with a numeric placeholder (e.g. "未拥有干员:%lld").

Copilot uses AI. Check for mistakes.
Comment on lines +28 to 29
.alert(String(localized: "Allow Preventing System Sleep"),
isPresented: $showingAlertForPreventingSleep,

Copilot AI Feb 24, 2026

Copy link

Choose a reason for hiding this comment

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

Localizable.xcstrings has sourceLanguage = zh-Hans, and the key "Allow Preventing System Sleep" currently only has an en localization entry. Using it here will cause zh-Hans users to see the English key text. Prefer reusing the existing zh-Hans source key (e.g. the previous Chinese string) or add a zh-Hans localization value for this key in the string catalog.

Suggested change
.alert(String(localized: "Allow Preventing System Sleep"),
isPresented: $showingAlertForPreventingSleep,
.alert(String(localized: "允许防止系统休眠"),
isPresented: $showingAlertForPreventingSystemSleep,

Copilot uses AI. Check for mistakes.
Button(String(localized: "取消"), role: .cancel) {}
}, message: {
Text("日常任务定时执行会在系统休眠之后失效, 打开此功能可以阻止系统自动睡眠")
Text(String(localized: "Prevent System Sleep Tip"))

Copilot AI Feb 24, 2026

Copy link

Choose a reason for hiding this comment

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

The key "Prevent System Sleep Tip" currently has only an en localization entry in Localizable.xcstrings (sourceLanguage is zh-Hans), so zh-Hans users will see English here. Consider reverting to the original Chinese source string key or adding a zh-Hans localization value for this key in the string catalog.

Suggested change
Text(String(localized: "Prevent System Sleep Tip"))
Text(String(localized: "防止系统睡眠提示"))

Copilot uses AI. Check for mistakes.
Comment on lines +29 to +31
Toggle(String(localized: "Receive Beta Updates"), isOn: $useBetaChannel)

Toggle("自动检查更新", isOn: $automaticallyChecksForUpdates)
Toggle(String(localized: "Automatically Check for Updates"), isOn: $automaticallyChecksForUpdates)

Copilot AI Feb 24, 2026

Copy link

Choose a reason for hiding this comment

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

Localizable.xcstrings uses zh-Hans as the source language, but the key "Receive Beta Updates" (and several other new English keys introduced in this view) currently only has an en localization entry. This will make zh-Hans UI show English. Prefer keeping the original Chinese source keys (e.g. "接收开发版更新") or add zh-Hans localizations for the English keys.

Copilot uses AI. Check for mistakes.
@ChestnutLUO

Copy link
Copy Markdown
Contributor

@ChestnutLUO

Copy link
Copy Markdown
Contributor

Thanks for pull request you can check previous discussion on i18n by the link below:
#24 (comment)

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.

3 participants