Localize non-redacted notification titles and nearby bodies.

Redacted lock-screen copy was already localized; the preview-on path still hardcoded English for mentions, DMs, and nearby peer alerts.
This commit is contained in:
Ayush7614 2026-08-02 01:02:52 +05:30
parent 1f59e814f9
commit b5db1fc426
3 changed files with 1010 additions and 6 deletions

View File

@ -65869,6 +65869,941 @@
}
}
},
"notification.mention.title" : {
"comment" : "Lock-screen notification title when someone is mentioned; %@ is the sender nickname",
"extractionState" : "manual",
"localizations" : {
"ar" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"bn" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 du wurdest von %@ erwähnt"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 te ha mencionado %@"
}
},
"fa" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"fil" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 %@ t'a mentionné"
}
},
"he" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"hi" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 %@ ने आपका उल्लेख किया"
}
},
"id" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 sei stato menzionato da %@"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 %@さんにメンションされました"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 %@님이 회원님을 언급했습니다"
}
},
"ms" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"ne" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 je bent genoemd door %@"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 wspomniał o tobie %@"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 você foi mencionado por %@"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 вас упомянул(а) %@"
}
},
"sv" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 du nämndes av %@"
}
},
"ta" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"th" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 %@ senden bahsetti"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"ur" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"vi" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 you were mentioned by %@"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 %@ 提到了你"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "🫵 %@ 提到了你"
}
}
}
},
"notification.dm.title" : {
"comment" : "Lock-screen notification title for a direct message; %@ is the sender nickname",
"extractionState" : "manual",
"localizations" : {
"ar" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"bn" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM von %@"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 MD de %@"
}
},
"fa" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"fil" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM de %@"
}
},
"he" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"hi" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 %@ से DM"
}
},
"id" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM da %@"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 %@さんからのDM"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 %@님의 DM"
}
},
"ms" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"ne" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM van %@"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 PW od %@"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM de %@"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 ЛС от %@"
}
},
"sv" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM från %@"
}
},
"ta" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"th" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 %@ kişisinden DM"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"ur" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"vi" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 DM from %@"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 来自 %@ 的私信"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "🔒 來自 %@ 的私訊"
}
}
}
},
"notification.nearby.title" : {
"comment" : "Lock-screen notification title when mesh peers are nearby",
"extractionState" : "manual",
"localizations" : {
"ar" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"bn" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatter in der Nähe!"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 ¡bitchatters cerca!"
}
},
"fa" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"fil" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 des bitchatters à proximité !"
}
},
"he" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"hi" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 पास में bitchatter हैं!"
}
},
"id" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatter nelle vicinanze!"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 近くにbitchatterがいます!"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 근처에 bitchatter가 있어요!"
}
},
"ms" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"ne" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters in de buurt!"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatterzy w pobliżu!"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters por perto!"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 рядом есть bitchatters!"
}
},
"sv" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters i närheten!"
}
},
"ta" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"th" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 yakında bitchatter'lar var!"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"ur" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"vi" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 bitchatters nearby!"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 附近有 bitchatter!"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "👥 附近有 bitchatter!"
}
}
}
},
"notification.nearby.body.one" : {
"comment" : "Lock-screen notification body when exactly one mesh peer is nearby",
"extractionState" : "manual",
"localizations" : {
"ar" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"bn" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 Person in der Nähe"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 persona alrededor"
}
},
"fa" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"fil" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 personne à proximité"
}
},
"he" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"hi" : {
"stringUnit" : {
"state" : "translated",
"value" : "आसपास 1 व्यक्ति"
}
},
"id" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 persona intorno"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "周囲に1人"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "주변에 1명"
}
},
"ms" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"ne" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 persoon in de buurt"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 osoba w pobliżu"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 pessoa por perto"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 человек рядом"
}
},
"sv" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person i närheten"
}
},
"ta" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"th" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "etrafta 1 kişi"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"ur" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"vi" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 person around"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "附近有 1 人"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "附近有 1 人"
}
}
}
},
"notification.nearby.body.other" : {
"comment" : "Lock-screen notification body when multiple mesh peers are nearby; %lld is the peer count",
"extractionState" : "manual",
"localizations" : {
"ar" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"bn" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld Personen in der Nähe"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld personas alrededor"
}
},
"fa" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"fil" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld personnes à proximité"
}
},
"he" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"hi" : {
"stringUnit" : {
"state" : "translated",
"value" : "आसपास %lld व्यक्ति"
}
},
"id" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld persone intorno"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "周囲に%lld人"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "주변에 %lld명"
}
},
"ms" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"ne" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld personen in de buurt"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld osób w pobliżu"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld pessoas por perto"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld человек рядом"
}
},
"sv" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld personer i närheten"
}
},
"ta" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"th" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "etrafta %lld kişi"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"ur" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"vi" : {
"stringUnit" : {
"state" : "translated",
"value" : "%lld people around"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "附近有 %lld 人"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "附近有 %lld 人"
}
}
}
},
"notification.redacted.body" : {
"comment" : "Lock-screen notification body shown in place of the message text when message previews are hidden",
"extractionState" : "manual",

View File

@ -229,7 +229,20 @@ final class NotificationService {
}
func sendMentionNotification(from sender: String, message: String) {
let title = hidePreviews ? Redacted.mentionTitle : "🫵 you were mentioned by \(sender)"
let title: String
if hidePreviews {
title = Redacted.mentionTitle
} else {
title = String(
format: String(
localized: "notification.mention.title",
defaultValue: "🫵 you were mentioned by %@",
comment: "Lock-screen notification title when someone is mentioned; %@ is the sender nickname"
),
locale: .current,
sender
)
}
let body = hidePreviews ? Redacted.body : message
let identifier = "mention-\(UUID().uuidString)"
@ -237,7 +250,20 @@ final class NotificationService {
}
func sendPrivateMessageNotification(from sender: String, message: String, peerID: PeerID) {
let title = hidePreviews ? Redacted.directMessageTitle : "🔒 DM from \(sender)"
let title: String
if hidePreviews {
title = Redacted.directMessageTitle
} else {
title = String(
format: String(
localized: "notification.dm.title",
defaultValue: "🔒 DM from %@",
comment: "Lock-screen notification title for a direct message; %@ is the sender nickname"
),
locale: .current,
sender
)
}
let body = hidePreviews ? Redacted.body : message
let identifier = "private-\(UUID().uuidString)"
// Routing payload, not display copy: `userInfo` never reaches the lock
@ -260,8 +286,29 @@ final class NotificationService {
}
func sendNetworkAvailableNotification(peerCount: Int) {
let title = "👥 bitchatters nearby!"
let body = peerCount == 1 ? "1 person around" : "\(peerCount) people around"
let title = String(
localized: "notification.nearby.title",
defaultValue: "👥 bitchatters nearby!",
comment: "Lock-screen notification title when mesh peers are nearby"
)
let body: String
if peerCount == 1 {
body = String(
localized: "notification.nearby.body.one",
defaultValue: "1 person around",
comment: "Lock-screen notification body when exactly one mesh peer is nearby"
)
} else {
body = String(
format: String(
localized: "notification.nearby.body.other",
defaultValue: "%lld people around",
comment: "Lock-screen notification body when multiple mesh peers are nearby; %lld is the peer count"
),
locale: .current,
peerCount
)
}
// Fixed identifier so iOS updates the existing notification instead of creating new ones
let identifier = "network-available"

View File

@ -71,7 +71,18 @@ final class NotificationServiceTests: XCTestCase {
service.sendPrivateMessageNotification(from: "Alice", message: "hi", peerID: peerID)
let request = deliverer.requests.singleValue
XCTAssertEqual(request?.content.title, "🔒 DM from Alice")
XCTAssertEqual(
request?.content.title,
String(
format: String(
localized: "notification.dm.title",
defaultValue: "🔒 DM from %@",
comment: "Lock-screen notification title for a direct message; %@ is the sender nickname"
),
locale: .current,
"Alice"
)
)
XCTAssertEqual(request?.content.body, "hi")
XCTAssertEqual(request?.content.userInfo["peerID"] as? String, peerID.id)
XCTAssertEqual(request?.content.userInfo["senderName"] as? String, "Alice")
@ -114,7 +125,18 @@ final class NotificationServiceTests: XCTestCase {
XCTAssertTrue(deliverer.requests[0].identifier.hasPrefix("geo-activity-87yv-"))
XCTAssertEqual(deliverer.requests[1].identifier, "network-available")
XCTAssertEqual(deliverer.requests[1].content.interruptionLevel, .timeSensitive)
XCTAssertEqual(deliverer.requests[1].content.body, "2 people around")
XCTAssertEqual(
deliverer.requests[1].content.body,
String(
format: String(
localized: "notification.nearby.body.other",
defaultValue: "%lld people around",
comment: "Lock-screen notification body when multiple mesh peers are nearby; %lld is the peer count"
),
locale: .current,
2
)
)
}
}