fix(styles): resolve style captions through in-app language
Style card descriptions were passed to Text as raw String keys, so they never went through AppL10n. Resolve them (and the editor title) with the in-app UI language override, matching the rest of the host app. Co-authored-by: Rocky <hkgood@users.noreply.github.com>
This commit is contained in:
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **Style card captions**: resolve each built-in style’s short description through the in-app language override, so switching App Language updates the caption instead of showing a localization key or the system language. / **风格卡片说明**:内置风格的说明小字改为走应用内语言设置;切换 App 语言后说明会跟着变,而不再显示本地化 key 或跟随系统语言。
|
||||||
|
|
||||||
## [2.2.0] - 2026-09-18
|
## [2.2.0] - 2026-09-18
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -196,9 +196,11 @@ struct PersonalReplyStyleSection: View {
|
|||||||
Image(systemName: "arrow.clockwise")
|
Image(systemName: "arrow.clockwise")
|
||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
isGenerating
|
AppL10n.string(
|
||||||
? "personalReplyStyle.regenerating"
|
isGenerating
|
||||||
: "personalReplyStyle.regenerate"
|
? "personalReplyStyle.regenerating"
|
||||||
|
: "personalReplyStyle.regenerate"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.font(TypeStyle.bodyEmph)
|
.font(TypeStyle.bodyEmph)
|
||||||
|
|||||||
@@ -169,7 +169,10 @@ struct PolishStylesView: View {
|
|||||||
.foregroundStyle(palette.textPrimary)
|
.foregroundStyle(palette.textPrimary)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
.padding(.trailing, 32)
|
.padding(.trailing, 32)
|
||||||
Text(descriptionKey(for: pack))
|
// AppL10n honors Settings → App Language; Text(String) would
|
||||||
|
// show the raw key, and a bare LocalizedStringKey would follow
|
||||||
|
// the system language instead (see Scripts/check_l10n_keys.sh).
|
||||||
|
Text(AppL10n.string(descriptionKey(for: pack), language: config.uiLanguage))
|
||||||
.font(TypeStyle.caption2)
|
.font(TypeStyle.caption2)
|
||||||
.foregroundStyle(palette.textTertiary)
|
.foregroundStyle(palette.textTertiary)
|
||||||
.lineLimit(2)
|
.lineLimit(2)
|
||||||
@@ -229,19 +232,11 @@ struct PolishStylesView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Host-bundle caption keys. Resolved at the render site with `AppL10n`
|
||||||
|
/// so Settings → App Language wins over the launch-time system locale.
|
||||||
private func descriptionKey(for pack: PolishStylePack) -> String {
|
private func descriptionKey(for pack: PolishStylePack) -> String {
|
||||||
guard pack.kind == .builtin else { return "polishStyles.custom.description" }
|
guard pack.kind == .builtin else { return "polishStyles.custom.description" }
|
||||||
switch pack.id {
|
return "polishStyles.\(pack.id.dropFirst("builtin.".count)).description"
|
||||||
case "builtin.structured": return "polishStyles.structured.description"
|
|
||||||
case "builtin.formal": return "polishStyles.formal.description"
|
|
||||||
case "builtin.dating": return "polishStyles.dating.description"
|
|
||||||
case "builtin.chat": return "polishStyles.chat.description"
|
|
||||||
case "builtin.flex": return "polishStyles.flex.description"
|
|
||||||
case "builtin.corp": return "polishStyles.corp.description"
|
|
||||||
case "builtin.diba": return "polishStyles.diba.description"
|
|
||||||
case "builtin.xhs": return "polishStyles.xhs.description"
|
|
||||||
default: return "polishStyles.light.description"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func reload() {
|
private func reload() {
|
||||||
@@ -464,7 +459,9 @@ struct PolishStyleEditorSheet: View {
|
|||||||
Text(AppL10n.string("polishStyles.editor.hint"))
|
Text(AppL10n.string("polishStyles.editor.hint"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle(isNew ? "polishStyles.add" : "polishStyles.edit")
|
.navigationTitle(
|
||||||
|
AppL10n.string(isNew ? "polishStyles.add" : "polishStyles.edit")
|
||||||
|
)
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .cancellationAction) {
|
ToolbarItem(placement: .cancellationAction) {
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// PolishStylesL10nTests.swift
|
||||||
|
// OSGKeyboard · Tests
|
||||||
|
//
|
||||||
|
// Style-card captions live in the host Localizable.strings table and must be
|
||||||
|
// resolved through AppL10n so the in-app language override wins.
|
||||||
|
|
||||||
|
@testable import OSGKeyboard
|
||||||
|
@testable import OSGKeyboardShared
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
final class PolishStylesL10nTests: XCTestCase {
|
||||||
|
func testBuiltinStyleCardDescriptionsHonorInAppLanguage() {
|
||||||
|
let slugs = PolishStylePackCatalog.builtins.map {
|
||||||
|
String($0.id.dropFirst("builtin.".count))
|
||||||
|
} + ["custom"]
|
||||||
|
|
||||||
|
for slug in slugs {
|
||||||
|
let key = "polishStyles.\(slug).description"
|
||||||
|
let english = AppL10n.string(key, language: .english)
|
||||||
|
let chinese = AppL10n.string(key, language: .chinese)
|
||||||
|
XCTAssertNotEqual(english, key, "missing English copy for \(key)")
|
||||||
|
XCTAssertNotEqual(chinese, key, "missing Chinese copy for \(key)")
|
||||||
|
XCTAssertNotEqual(english, chinese, "\(key) is not bilingual")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user