build(apple): flag raw string literals in SwiftUI initializers

The typed-resource rules missed a bare string literal passed as the leading arg of
a view initializer (e.g. Label("send_stop_sharing", …)), which is an implicit
LocalizedStringKey. Add a rule covering Text/Label/Button/Section/Picker/etc.
(empty labels allowed). Fixes the two dynamic-content Text sites it surfaced by
switching them to Text(verbatim:).
This commit is contained in:
2026-07-24 19:42:40 +02:00
parent b66cb8c1f1
commit 3abd4d0cfd
3 changed files with 9 additions and 2 deletions

View File

@@ -25,3 +25,10 @@ custom_rules:
regex: 'system(Name|Image):\s*"' regex: 'system(Name|Image):\s*"'
message: "Use SFSafeSymbols: Image(systemSymbol:) or systemSymbol:." message: "Use SFSafeSymbols: Image(systemSymbol:) or systemSymbol:."
severity: warning severity: warning
raw_swiftui_string_literal:
name: "Raw SwiftUI string"
# A non-empty string literal as the leading arg of a view initializer is an
# implicit LocalizedStringKey. Empty labels (e.g. Picker("", …)) are allowed.
regex: '\b(Text|Label|Button|Toggle|Link|NavigationLink|Section|Picker|Stepper|TextField|SecureField|DisclosureGroup|Menu|GroupBox)\("[^"]'
message: "Pass a typed L10n.* accessor (or Text(verbatim:)), not a raw string literal."
severity: warning

View File

@@ -112,7 +112,7 @@ private struct DetailDestination: View {
} }
Spacer() Spacer()
if count > 0 { if count > 0 {
Text("\(count)") Text(verbatim: "\(count)")
.font(.footnote) .font(.footnote)
.foregroundStyle(.secondary) .foregroundStyle(.secondary)
} }

View File

@@ -42,7 +42,7 @@ struct ProgressRow: View {
label.font(.subheadline).lineLimit(1) label.font(.subheadline).lineLimit(1)
Spacer() Spacer()
if let progress { if let progress {
Text("\(Int(progress * 100))%").font(.caption).foregroundStyle(.secondary) Text(verbatim: "\(Int(progress * 100))%").font(.caption).foregroundStyle(.secondary)
} }
} }
if let detail { if let detail {