Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions Strand/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
@@ -1,6 +1,52 @@
{
"sourceLanguage": "en",
"strings": {
"Night": {
"localizations": {
"de": {
"stringUnit": {
"state": "translated",
"value": "Nacht"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "Noche"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Nuit"
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "Notte"
}
},
"pt-PT": {
"stringUnit": {
"state": "translated",
"value": "Noite"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "夜间"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "夜間"
}
}
}
},
"": {
"localizations": {
"de": {
Expand Down
17 changes: 13 additions & 4 deletions Strand/Screens/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -249,10 +249,17 @@ struct SettingsView: View {
/// iOS 16+ and macOS 13+ (NOOP's floor), so the same control serves both platforms — no
/// availability gating needed. The photo is stored only on this device (NOOP is fully offline).
private var profilePhotoCard: some View {
SettingsSection(
// #153: resolve the whole blurb through `String(localized:)` first, then hand SwiftUI the plain
// String via `LocalizedStringKey(_:)`. Interpolating `Platform.deviceNounPhrase` (itself an
// already-resolved localized String) straight into the `blurb:` `LocalizedStringKey` literal
// confused SwiftUI's text-measurement pass — the blurb rendered with zero trailing margin and
// clipped to the card edge instead of wrapping inside the card padding. The localization key is
// unchanged (`…Stored only on %@…`), so the existing translations still apply.
let blurbText = String(localized: "Optional. Add a photo for the avatar in the top-left. Stored only on \(Platform.deviceNounPhrase). NOOP is offline, so it's never uploaded.")
return SettingsSection(
icon: "person.crop.circle",
title: "Profile photo",
blurb: "Optional. Add a photo for the avatar in the top-left. Stored only on \(Platform.deviceNounPhrase). NOOP is offline, so it's never uploaded."
blurb: LocalizedStringKey(blurbText)
) {
HStack(spacing: 16) {
ProfileAvatarView(imageData: profile.avatarImageData, size: 64)
Expand All @@ -270,7 +277,6 @@ struct SettingsView: View {
.accessibilityHint("Reverts to the default profile icon")
}
}
.frame(maxWidth: .infinity)
}
}
// Load the picked photo's bytes, then hand them to the store (which downscales + persists).
Expand Down Expand Up @@ -889,7 +895,10 @@ struct SettingsView: View {
// re-baselines (like a sleep edit).
FormRow(label: "HRV window") {
Picker("HRV window", selection: $hrvWindowRaw) {
Text("Whole night").tag(HrvWindow.whole.rawValue)
// #153: "Night" (not "Whole night") — a single short word so the two-segment
// control doesn't truncate once it sizes to the row (some locales' longer
// translations overflowed), matching the Temperature/Theme pickers above.
Text("Night").tag(HrvWindow.whole.rawValue)
Text("Deep sleep").tag(HrvWindow.deep.rawValue)
}
.labelsHidden()
Expand Down
4 changes: 3 additions & 1 deletion android/app/src/main/java/com/noop/ui/SettingsScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1355,7 +1355,9 @@ fun SettingsScreen(
SegmentedPillControl(
items = listOf(HrvWindow.WHOLE_NIGHT, HrvWindow.DEEP_SLEEP),
selection = hrvWindow,
label = { if (it == HrvWindow.DEEP_SLEEP) "Deep sleep" else "Whole night" },
// #153: "Night" (not "Whole night") so the two-segment pill reads the same as the iOS
// picker and stays short — keeps the label consistent across platforms.
label = { if (it == HrvWindow.DEEP_SLEEP) "Deep sleep" else "Night" },
onSelect = {
hrvWindow = it
UnitPrefs.setHrvWindow(context, it)
Expand Down