From eb42452b9e13602f16a9b9500d837365a0561afc Mon Sep 17 00:00:00 2001
From: paradix86 <2883806+paradix86@users.noreply.github.com>
Date: Sat, 26 Sep 2026 11:30:06 +0200
Subject: [PATCH 1/2] i18n(android): translate the Settings screen's hardcoded
copy
Settings still rendered about 90 English literals from SettingsScreen.kt,
SettingsLogic.kt and SettingsComponents.kt regardless of locale: card
blurbs, button labels, toggle details, toasts, screen-reader text, the
strap status pill and detail, the sex options and the "Settings" overline.
They now resolve through string resources: 96 new keys, translated into
all nine locales, and 14 literals reuse existing keys with identical
English. strapStatusTitle/strapStatusDetail become strapStatusTitleRes/
strapStatusDetailRes returning @StringRes, following spo2MissingCaptionRes,
so the branches stay testable on the JVM; StrapStatusDetailTest keeps its
wording checks by reading the English values from values/strings.xml.
Left in English on purpose: the "NOOP" wordmark, the support email
subject, and four strings inside the 5/MG card that is compiled out
(if (false && ...)).
The Android i18n baseline drops the 26 SettingsScreen.kt entries this
extracts.
---
Tools/i18n_audit_baseline.json | 100 ---------
.../java/com/noop/ui/DataSourcesScreen.kt | 2 +-
.../java/com/noop/ui/SettingsComponents.kt | 2 +-
.../main/java/com/noop/ui/SettingsLogic.kt | 48 ++--
.../main/java/com/noop/ui/SettingsScreen.kt | 208 +++++++++---------
.../app/src/main/res/values-de/strings.xml | 96 ++++++++
.../app/src/main/res/values-es/strings.xml | 96 ++++++++
.../app/src/main/res/values-fr/strings.xml | 96 ++++++++
.../app/src/main/res/values-it/strings.xml | 96 ++++++++
.../app/src/main/res/values-pl/strings.xml | 96 ++++++++
.../src/main/res/values-pt-rPT/strings.xml | 96 ++++++++
.../app/src/main/res/values-ru/strings.xml | 96 ++++++++
.../app/src/main/res/values-zh/strings.xml | 96 ++++++++
android/app/src/main/res/values/strings.xml | 96 ++++++++
.../java/com/noop/ui/StrapStatusDetailTest.kt | 69 +++++-
15 files changed, 1053 insertions(+), 240 deletions(-)
diff --git a/Tools/i18n_audit_baseline.json b/Tools/i18n_audit_baseline.json
index 0d2602780a..abe21ea191 100644
--- a/Tools/i18n_audit_baseline.json
+++ b/Tools/i18n_audit_baseline.json
@@ -472,50 +472,6 @@
"android/app/src/main/java/com/noop/ui/PipBar.kt",
"$label: $valueText $unit"
],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Auto · ${profile.hrMaxAuto} bpm (Tanaka)"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Background image"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Blood Oxygen: strap estimate"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Browse files"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Change photo"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Choose from Photos"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Choose photo"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Fill"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Fit"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Let the background show through every card. Tune how much just below."
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Manual override"
- ],
[
"android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
"Needs the full encrypted bond: close the official WHOOP app and pair the strap to NOOP first (a live-HR-only link can't carry the unlock)."
@@ -524,62 +480,6 @@
"android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
"Put the strap on first. The deep stream is on-wrist only."
],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Re-scan"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Recent"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Remove image"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Replace from Photos"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Scaling"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Scores today's hour-by-hour stress timeline against YOUR own cross-day baseline "
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Searching…"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Show custom background"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Sleep chart"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Stress: personal daytime baseline"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Stretch"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Surfaces your strap's nightly SpO₂ estimate in the Blood Oxygen tile when no "
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Tile"
- ],
- [
- "android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
- "Transparent cards"
- ],
[
"android/app/src/main/java/com/noop/ui/SettingsScreen.kt",
"Wear the strap, tap once, then let it sync and share your strap log."
diff --git a/android/app/src/main/java/com/noop/ui/DataSourcesScreen.kt b/android/app/src/main/java/com/noop/ui/DataSourcesScreen.kt
index 03bc1ae5e2..b3feb01887 100644
--- a/android/app/src/main/java/com/noop/ui/DataSourcesScreen.kt
+++ b/android/app/src/main/java/com/noop/ui/DataSourcesScreen.kt
@@ -897,7 +897,7 @@ fun DataSourcesScreen(vm: AppViewModel) {
subtitle = uiString(R.string.data_sources_whoop_live_subtitle),
) {
val (label, tone) = when {
- // encryptedBond, not bonded — see strapStatusTitle. A 5/MG streaming over the open
+ // encryptedBond, not bonded — see strapStatusTitleRes. A 5/MG streaming over the open
// profile has bonded == true with no pairing at all, and after #1635 hello suppression it
// stays there for good rather than passing through.
//
diff --git a/android/app/src/main/java/com/noop/ui/SettingsComponents.kt b/android/app/src/main/java/com/noop/ui/SettingsComponents.kt
index 74aa1b8f06..bccfc6725e 100644
--- a/android/app/src/main/java/com/noop/ui/SettingsComponents.kt
+++ b/android/app/src/main/java/com/noop/ui/SettingsComponents.kt
@@ -111,7 +111,7 @@ internal fun SettingsCard(
NoopCard(padding = 20.dp, tint = Palette.accent) {
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
- Overline("Settings")
+ Overline(uiString(R.string.nav_settings))
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(10.dp),
diff --git a/android/app/src/main/java/com/noop/ui/SettingsLogic.kt b/android/app/src/main/java/com/noop/ui/SettingsLogic.kt
index 2e74b5ae14..2e54b95a49 100644
--- a/android/app/src/main/java/com/noop/ui/SettingsLogic.kt
+++ b/android/app/src/main/java/com/noop/ui/SettingsLogic.kt
@@ -1,6 +1,8 @@
package com.noop.ui
import android.content.SharedPreferences
+import androidx.annotation.StringRes
+import com.noop.R
import kotlin.math.roundToInt
// MARK: - Waist stepper (optional VO₂max input)
@@ -40,19 +42,23 @@ internal fun waistInchesStep(current: Double, up: Boolean): Double {
* It is not cosmetic. The encrypted bond gates buzz, alarms, double-tap and history sync, and Settings
* already says so a few rows further down ("Needs the full encrypted bond…"). A green "Bonded · streaming"
* above that contradicts it on the same screen.
+ *
+ * Returns a string resource rather than text so the branch stays testable in a plain JVM test, where
+ * [uiString] has no Application to resolve through.
*/
-internal fun strapStatusTitle(encryptedBond: Boolean, bonded: Boolean, connected: Boolean): String = when {
- encryptedBond && connected -> "Bonded · streaming"
- encryptedBond -> "Bonded · idle"
- bonded && connected -> "Live HR (not fully paired)"
- connected -> "Connected"
+@StringRes
+internal fun strapStatusTitleRes(encryptedBond: Boolean, bonded: Boolean, connected: Boolean): Int = when {
+ encryptedBond && connected -> R.string.onboarding_state_bonded_streaming
+ encryptedBond -> R.string.l10n_settings_logic_bonded_idle_1930284f
+ bonded && connected -> R.string.l10n_settings_logic_live_hr_not_fully_paired_6fd6ddb1
+ connected -> R.string.recording_chip_title_connected
// No `bonded`-only idle arm: without an encrypted bond there was never a pairing to be idle from,
// and labelling that "Paired" would be the same overclaim this change exists to remove. The 5/MG
// shortcut's `bonded` is cleared on disconnect anyway, so the honest answer here is Disconnected.
- else -> "Disconnected"
+ else -> R.string.l10n_settings_logic_disconnected_771e05f2
}
-/** Positive ONLY for a real encrypted bond on a live link — see [strapStatusTitle]. A live-HR-only link
+/** Positive ONLY for a real encrypted bond on a live link — see [strapStatusTitleRes]. A live-HR-only link
* is a warning, not a success: it works, but the pairing-gated features do not. */
internal fun strapTone(encryptedBond: Boolean, bonded: Boolean, connected: Boolean): StrandTone = when {
encryptedBond && connected -> StrandTone.Positive
@@ -60,19 +66,21 @@ internal fun strapTone(encryptedBond: Boolean, bonded: Boolean, connected: Boole
else -> StrandTone.Critical
}
-// `internal` (not private) so the unit test in the same package can assert the scanning branch.
-internal fun strapStatusDetail(
+// `internal` (not private) so the unit test in the same package can assert the scanning branch. A string
+// resource for the same reason as [strapStatusTitleRes].
+@StringRes
+internal fun strapStatusDetailRes(
encryptedBond: Boolean,
bonded: Boolean,
connected: Boolean,
scanning: Boolean,
-): String = when {
- scanning -> "Searching for your WHOOP… make sure it's charged, on your wrist, and the official WHOOP app isn't connected to it."
- encryptedBond && connected -> "Your strap is paired and sending data. Open Live for a real-time heart rate."
- bonded && connected -> "Live heart rate is streaming, but your strap is not fully paired. The encrypted pairing is what carries motion, skin temperature, SpO₂ and respiratory rate — without it, sleep is staged from heart rate alone. Buzz, alarms and history sync need it too."
- connected -> "Connected. Finishing the secure pairing handshake…"
- bonded -> "Previously paired but not currently connected. Re-scan to reconnect."
- else -> "No strap connected. Put your WHOOP nearby and tap Re-scan to pair."
+): Int = when {
+ scanning -> R.string.l10n_settings_logic_searching_for_your_whoop_make_sure_7be37c50
+ encryptedBond && connected -> R.string.l10n_settings_logic_your_strap_is_paired_and_sending_ef06dfd4
+ bonded && connected -> R.string.l10n_settings_logic_live_heart_rate_is_streaming_but_934807fc
+ connected -> R.string.l10n_settings_logic_connected_finishing_the_secure_pairing_handshake_1e56d362
+ bonded -> R.string.l10n_settings_logic_previously_paired_but_not_currently_connected_0a84a072
+ else -> R.string.l10n_settings_logic_no_strap_connected_put_your_whoop_61a155c1
}
internal fun batteryTone(pct: Double): StrandTone = when {
@@ -83,12 +91,12 @@ internal fun batteryTone(pct: Double): StrandTone = when {
// MARK: - Sex options
-internal data class SexOption(val tag: String, val label: String)
+internal data class SexOption(val tag: String, @StringRes val labelRes: Int)
internal val SEX_OPTIONS = listOf(
- SexOption("male", "Male"),
- SexOption("female", "Female"),
- SexOption("nonbinary", "Non-binary"),
+ SexOption("male", R.string.onboarding_male),
+ SexOption("female", R.string.onboarding_female),
+ SexOption("nonbinary", R.string.l10n_settings_logic_non_binary_dc82a40c),
)
// MARK: - Advanced disclosure persistence (S3)
diff --git a/android/app/src/main/java/com/noop/ui/SettingsScreen.kt b/android/app/src/main/java/com/noop/ui/SettingsScreen.kt
index 6f8df9a8b0..0bf3436e9d 100644
--- a/android/app/src/main/java/com/noop/ui/SettingsScreen.kt
+++ b/android/app/src/main/java/com/noop/ui/SettingsScreen.kt
@@ -771,10 +771,9 @@ fun SettingsScreen(
// during a restore, which is the one moment the original is gone. The second
// sentence is the refusal's own wording, reused so this adds no untranslated copy.
val note = if (outcome.overRestoreCeiling) {
- "Backup exported. The backup archive is too large to restore safely — " +
- "restoring it will ask you to confirm."
+ uiString(R.string.l10n_settings_screen_backup_exported_the_backup_archive_is_a3da19f4)
} else {
- "Backup exported. Copy this file to your new phone and use Import there to restore everything."
+ uiString(R.string.l10n_settings_screen_backup_exported_copy_this_file_to_9495b34e)
}
Toast.makeText(context, note, Toast.LENGTH_LONG).show()
},
@@ -782,7 +781,7 @@ fun SettingsScreen(
// The EXPORT-side integrity refusal lands here (#1014): a corrupt store is caught
// before it is archived, and the message names the CSV route that still works. That
// is a next step, so it needs the dialog for the same reason the import failures do.
- backupFailure = "Backup problem: ${e.message}"
+ backupFailure = uiString(R.string.l10n_settings_screen_backup_problem_1df82e8c, e.message.toString())
},
)
}
@@ -804,12 +803,12 @@ fun SettingsScreen(
onSuccess = { msg ->
Toast.makeText(
context,
- "$msg Re-import it via Data sources → WHOOP import, on Android or Mac.",
+ uiString(R.string.l10n_settings_screen_re_import_it_via_data_sources_6aaa6753, msg),
Toast.LENGTH_LONG,
).show()
},
onFailure = { e ->
- Toast.makeText(context, "CSV export problem: ${e.message}", Toast.LENGTH_LONG).show()
+ Toast.makeText(context, uiString(R.string.l10n_settings_screen_csv_export_problem_8632cbaf, e.message.toString()), Toast.LENGTH_LONG).show()
},
)
}
@@ -827,7 +826,7 @@ fun SettingsScreen(
when (result) {
is DataBackup.ImportResult.NeedsRestart -> Toast.makeText(
context,
- "Backup imported. Fully close and reopen NOOP for it to take effect.",
+ uiString(R.string.l10n_settings_screen_backup_imported_fully_close_and_reopen_8c17637d),
Toast.LENGTH_LONG,
).show()
is DataBackup.ImportResult.Failed -> backupFailure = result.message
@@ -852,7 +851,7 @@ fun SettingsScreen(
ProfileAvatarStore.setAvatarFromUri(context, uri)
}
if (!ok) {
- Toast.makeText(context, "Couldn't use that photo. Try another.", Toast.LENGTH_LONG).show()
+ Toast.makeText(context, uiString(R.string.l10n_settings_screen_couldn_t_use_that_photo_try_18755a7c), Toast.LENGTH_LONG).show()
}
}
}
@@ -865,7 +864,7 @@ fun SettingsScreen(
scope.launch {
val ok = withContext(Dispatchers.IO) { BackgroundImageStore.setImageFromUri(context, uri) }
if (!ok) {
- Toast.makeText(context, "Couldn't use that image. Try another.", Toast.LENGTH_LONG).show()
+ Toast.makeText(context, uiString(R.string.l10n_settings_screen_couldn_t_use_that_image_try_311dd42c), Toast.LENGTH_LONG).show()
}
}
}
@@ -878,7 +877,7 @@ fun SettingsScreen(
ScreenScaffold(
title = uiString(R.string.l10n_settings_screen_settings_c7f73bb5),
- subtitle = "Your numbers, your strap, and how NOOP works. All on this phone.",
+ subtitle = uiString(R.string.l10n_settings_screen_your_numbers_your_strap_and_how_5aad55af),
// LIQUID SKY BACKDROP (the pilot pattern — LiquidScreenSky.kt): the static time-of-day sky settles
// into the theme canvas behind the top of the list, exactly like the liquid Today. This is a long,
// scroll-heavy list with NO hero gauge, so the liquid finish here is just the sky + liquidPress on
@@ -919,7 +918,7 @@ fun SettingsScreen(
SettingsCard(
icon = Icons.Outlined.AccountCircle,
title = uiString(R.string.l10n_settings_screen_profile_photo_33f385bb),
- blurb = "Optional. Add a photo for the avatar in the top-left. Stored only on this phone. NOOP is offline, so it's never uploaded.",
+ blurb = uiString(R.string.l10n_settings_screen_optional_add_a_photo_for_the_aee66863),
) {
Row(
modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp),
@@ -933,7 +932,7 @@ fun SettingsScreen(
) {
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
NoopButton(
- text = if (ProfileAvatarStore.hasAvatar) "Change photo" else "Choose photo",
+ text = if (ProfileAvatarStore.hasAvatar) uiString(R.string.l10n_settings_screen_change_photo_ed5690c3) else uiString(R.string.l10n_settings_screen_choose_photo_4a7eded8),
kind = NoopButtonKind.Secondary,
modifier = Modifier.weight(1f),
onClick = {
@@ -959,13 +958,13 @@ fun SettingsScreen(
SettingsCard(
icon = Icons.Outlined.Person,
title = uiString(R.string.l10n_settings_screen_profile_ff4fc027),
- blurb = "These power your heart-rate zones, calorie estimates and recovery baselines. Keep them accurate.",
+ blurb = uiString(R.string.l10n_settings_screen_these_power_your_heart_rate_zones_6d5e1ab1),
) {
Column {
SettingsFormRow(label = uiString(R.string.l10n_settings_screen_age_ff9f1ff3)) {
StepperField(
value = profile.age.toString(),
- accessibility = "Age, ${profile.age} years",
+ accessibility = uiString(R.string.l10n_settings_screen_age_years_77385403, profile.age),
// #146: age is derived from a stored date of birth, so it advances on its own. The
// stepper re-anchors the DOB via setAge (which clamps to 13..100 — age feeds the
// Fitness Age + Vitality engines that gate on age > 0, so it must never go 0/negative).
@@ -978,7 +977,7 @@ fun SettingsScreen(
SegmentedPillControl(
items = SEX_OPTIONS,
selection = SEX_OPTIONS.firstOrNull { it.tag == profile.sex } ?: SEX_OPTIONS[0],
- label = { it.label },
+ label = { uiString(it.labelRes) },
onSelect = { mutate { profile.sex = it.tag } },
)
}
@@ -991,7 +990,7 @@ fun SettingsScreen(
StepperField(
value = "%.0f".format(lb),
unit = "lb",
- accessibility = "Weight, ${lb.roundToInt()} pounds",
+ accessibility = uiString(R.string.l10n_settings_screen_weight_pounds_a1116333, lb.roundToInt()),
onMinus = { mutate { profile.weightKg = (lb - 1) / UnitFormatter.POUNDS_PER_KILOGRAM } },
onPlus = { mutate { profile.weightKg = (lb + 1) / UnitFormatter.POUNDS_PER_KILOGRAM } },
)
@@ -999,7 +998,7 @@ fun SettingsScreen(
StepperField(
value = "%.1f".format(profile.weightKg),
unit = "kg",
- accessibility = "Weight in kilograms",
+ accessibility = uiString(R.string.l10n_settings_screen_weight_in_kilograms_ea489a9f),
onMinus = { mutate { profile.weightKg -= 0.5 } },
onPlus = { mutate { profile.weightKg += 0.5 } },
)
@@ -1013,7 +1012,7 @@ fun SettingsScreen(
val totalInches = UnitFormatter.cmToInches(profile.heightCm).roundToInt()
StepperField(
value = "$ft′ $inch″",
- accessibility = "Height, $ft feet $inch inches",
+ accessibility = uiString(R.string.l10n_settings_screen_height_feet_inches_e7048143, ft, inch),
onMinus = { mutate { profile.heightCm = (totalInches - 1) * UnitFormatter.CENTIMETERS_PER_INCH } },
onPlus = { mutate { profile.heightCm = (totalInches + 1) * UnitFormatter.CENTIMETERS_PER_INCH } },
)
@@ -1021,7 +1020,7 @@ fun SettingsScreen(
StepperField(
value = "%.0f".format(profile.heightCm),
unit = "cm",
- accessibility = "Height in centimetres",
+ accessibility = uiString(R.string.l10n_settings_screen_height_in_centimetres_037a5d55),
onMinus = { mutate { profile.heightCm -= 1 } },
onPlus = { mutate { profile.heightCm += 1 } },
)
@@ -1042,14 +1041,14 @@ fun SettingsScreen(
if (unitSystem == UnitSystem.IMPERIAL) {
val totalInches = UnitFormatter.cmToInches(profile.waistCm).roundToInt()
StepperField(
- value = if (hasWaist) "%d″".format(totalInches) else "Add",
+ value = if (hasWaist) "%d″".format(totalInches) else uiString(R.string.l10n_add_device_wizard_add_61cc55aa),
accessibility = if (hasWaist) {
- "Waist, $totalInches inches"
+ uiString(R.string.l10n_settings_screen_waist_inches_cf936907, totalInches)
} else {
// #1391: a waist does NOT unlock VO₂max (the Uth HR-ratio fallback
// needs none) — it upgrades it. The visible footnote was corrected
// for this; this screen-reader copy had been left behind.
- "Waist, not set. Optional: your VO₂max is more accurate with it"
+ uiString(R.string.l10n_settings_screen_waist_not_set_optional_your_vo_f0c4578b)
},
valueColor = if (hasWaist) Palette.textPrimary else Palette.textTertiary,
onMinus = { mutate { profile.waistCm = waistInchesStep(profile.waistCm, up = false) } },
@@ -1057,15 +1056,15 @@ fun SettingsScreen(
)
} else {
StepperField(
- value = if (hasWaist) "%.0f".format(profile.waistCm) else "Add",
+ value = if (hasWaist) "%.0f".format(profile.waistCm) else uiString(R.string.l10n_add_device_wizard_add_61cc55aa),
unit = if (hasWaist) "cm" else null,
accessibility = if (hasWaist) {
- "Waist in centimetres"
+ uiString(R.string.l10n_settings_screen_waist_in_centimetres_ba68b075)
} else {
// #1391: a waist does NOT unlock VO₂max (the Uth HR-ratio fallback
// needs none) — it upgrades it. The visible footnote was corrected
// for this; this screen-reader copy had been left behind.
- "Waist, not set. Optional: your VO₂max is more accurate with it"
+ uiString(R.string.l10n_settings_screen_waist_not_set_optional_your_vo_f0c4578b)
},
valueColor = if (hasWaist) Palette.textPrimary else Palette.textTertiary,
onMinus = { mutate { profile.waistCm = waistCmStep(profile.waistCm, up = false) } },
@@ -1092,12 +1091,12 @@ fun SettingsScreen(
SettingsFormRow(label = uiString(R.string.l10n_settings_screen_max_heart_rate_3d4ed858)) {
Column(horizontalAlignment = Alignment.End) {
StepperField(
- value = if (profile.hrMaxOverride > 0) profile.hrMaxOverride.toString() else "Auto",
+ value = if (profile.hrMaxOverride > 0) profile.hrMaxOverride.toString() else uiString(R.string.l10n_settings_screen_auto_c614ba7c),
unit = "bpm",
accessibility = if (profile.hrMaxOverride == 0) {
- "Max heart rate override, automatic"
+ uiString(R.string.l10n_settings_screen_max_heart_rate_override_automatic_9e04bf2e)
} else {
- "Max heart rate override, ${profile.hrMaxOverride} bpm"
+ uiString(R.string.l10n_settings_screen_max_heart_rate_override_bpm_d9a57f8e, profile.hrMaxOverride)
},
valueColor = if (profile.hrMaxOverride > 0) Palette.textPrimary else Palette.textTertiary,
onMinus = { mutate { profile.hrMaxOverride -= 1 } },
@@ -1106,9 +1105,9 @@ fun SettingsScreen(
Spacer(Modifier.height(6.dp))
Text(
text = if (profile.hrMaxOverride > 0) {
- "Manual override"
+ uiString(R.string.l10n_settings_screen_manual_override_8661a63e)
} else {
- "Auto · ${profile.hrMaxAuto} bpm (Tanaka)"
+ uiString(R.string.l10n_settings_screen_auto_bpm_tanaka_e9e619ec, profile.hrMaxAuto)
},
style = NoopType.footnote,
color = if (profile.hrMaxOverride > 0) Palette.accent else Palette.textTertiary,
@@ -1144,7 +1143,7 @@ fun SettingsScreen(
StepperField(
value = value.toString(),
unit = "bpm",
- accessibility = "Zone ${index + 1} starts at $value bpm",
+ accessibility = uiString(R.string.l10n_settings_screen_zone_starts_at_bpm_b14f6156, index + 1, value),
onMinus = { mutate { profile.stepHrZoneThreshold(index, up = false) } },
onPlus = { mutate { profile.stepHrZoneThreshold(index, up = true) } },
)
@@ -1159,8 +1158,7 @@ fun SettingsScreen(
SettingsFormRow(label = uiString(R.string.l10n_settings_screen_step_calibration_351c09bf)) {
StepperField(
value = "%.1f".format(profile.stepTicksPerStep),
- accessibility = "Step calibration, %.1f counter ticks per step"
- .format(profile.stepTicksPerStep),
+ accessibility = uiString(R.string.l10n_settings_screen_step_calibration_counter_ticks_per_step_378808b8, profile.stepTicksPerStep),
onMinus = { mutate { profile.stepTicksPerStep = ProfileStore.steppedStepScale(profile.stepTicksPerStep, up = false) } },
onPlus = { mutate { profile.stepTicksPerStep = ProfileStore.steppedStepScale(profile.stepTicksPerStep, up = true) } },
)
@@ -1176,10 +1174,10 @@ fun SettingsScreen(
// motion and calibrates that to the phone. Opens the explainer + fit + comparison + manual
// override screen. Mirrors the macOS Profile "Steps estimate" row.
val stepsSummary = when {
- profile.stepsManualCoefficient > 0 -> "Manual"
+ profile.stepsManualCoefficient > 0 -> uiString(R.string.l10n_settings_screen_manual_4e836fdc)
profile.stepsCalibrationCoefficient > 0 ->
- "Auto · ${StepsCalibrationFormat.confidenceLabel(profile.stepsCalibrationConfidence)} confidence"
- else -> "Not calibrated"
+ uiString(R.string.l10n_settings_screen_auto_confidence_c7c3d8df, StepsCalibrationFormat.confidenceLabel(profile.stepsCalibrationConfidence))
+ else -> uiString(R.string.l10n_settings_screen_not_calibrated_2e269ed6)
}
val stepsRowInteraction = remember { MutableInteractionSource() }
Row(
@@ -1266,7 +1264,7 @@ fun SettingsScreen(
SegmentedPillControl(
items = listOf(UnitSystem.METRIC, UnitSystem.IMPERIAL),
selection = unitSystem,
- label = { if (it == UnitSystem.METRIC) "Metric" else "Imperial" },
+ label = { if (it == UnitSystem.METRIC) uiString(R.string.onboarding_metric) else uiString(R.string.onboarding_imperial) },
onSelect = {
unitSystem = it
NoopPrefs.setUnitSystem(context, it)
@@ -1583,19 +1581,19 @@ fun SettingsScreen(
modifier = Modifier.fillMaxWidth().heightIn(min = 44.dp).padding(vertical = 4.dp),
verticalArrangement = Arrangement.spacedBy(10.dp),
) {
- Text("Sleep chart", style = NoopType.body, color = Palette.textPrimary)
+ Text(uiString(R.string.l10n_settings_screen_sleep_chart_b6335ce1), style = NoopType.body, color = Palette.textPrimary)
SegmentedPillControl(
items = listOf(SleepChartStyle.CLASSIC, SleepChartStyle.FILLED,
SleepChartStyle.GARMIN_FILLED, SleepChartStyle.RIBBON),
selection = sleepChartStyle,
label = {
when (it) {
- SleepChartStyle.FILLED -> "Fill"
+ SleepChartStyle.FILLED -> uiString(R.string.l10n_settings_screen_fill_7adb6736)
// "Garmin" not "Garmin Fill": four equal-width segments ellipsis-truncate a long
// label on a normal-width phone (iOS keeps "Garmin Fill" — it's a menu, not a pill).
- SleepChartStyle.GARMIN_FILLED -> "Garmin"
- SleepChartStyle.RIBBON -> "Ribbon"
- else -> "Classic"
+ SleepChartStyle.GARMIN_FILLED -> uiString(R.string.today_source_garmin)
+ SleepChartStyle.RIBBON -> uiString(R.string.l10n_settings_screen_ribbon_ae48c34a)
+ else -> uiString(R.string.settings_chart_classic)
}
},
onSelect = { style ->
@@ -1719,9 +1717,9 @@ fun SettingsScreen(
horizontalArrangement = Arrangement.spacedBy(16.dp),
) {
Column(modifier = Modifier.weight(1f)) {
- Text("Transparent cards", style = NoopType.subhead, color = Palette.textPrimary)
+ Text(uiString(R.string.l10n_settings_screen_transparent_cards_24d17f6e), style = NoopType.subhead, color = Palette.textPrimary)
Text(
- "Let the background show through every card. Tune how much just below.",
+ uiString(R.string.l10n_settings_screen_let_the_background_show_through_every_4d2dd4f8),
style = NoopType.footnote,
color = Palette.textTertiary,
)
@@ -1913,16 +1911,15 @@ fun SettingsScreen(
// controls + the live backdrop update the instant an image is set, removed, or re-scaled.
SettingsCard(
icon = Icons.Outlined.Image,
- title = "Background image",
- blurb = "Optional. Use your own photo behind every tab, in place of the day-cycle sky. " +
- "Stored only on this phone. Pair it with Transparent cards above to let it show through.",
+ title = uiString(R.string.l10n_settings_screen_background_image_5eb0ff1a),
+ blurb = uiString(R.string.l10n_settings_screen_optional_use_your_own_photo_behind_4e354f6e),
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
NoopButton(
- text = if (BackgroundImageStore.hasImage) "Replace from Photos" else "Choose from Photos",
+ text = if (BackgroundImageStore.hasImage) uiString(R.string.l10n_settings_screen_replace_from_photos_dc6cc6ca) else uiString(R.string.l10n_settings_screen_choose_from_photos_935f1b61),
kind = NoopButtonKind.Secondary,
modifier = Modifier.weight(1f),
onClick = {
@@ -1932,7 +1929,7 @@ fun SettingsScreen(
},
)
NoopButton(
- text = "Browse files",
+ text = uiString(R.string.l10n_settings_screen_browse_files_524932e0),
kind = NoopButtonKind.Secondary,
modifier = Modifier.weight(1f),
onClick = { backgroundFileLauncher.launch(arrayOf("image/*")) },
@@ -1945,7 +1942,7 @@ fun SettingsScreen(
val recents = BackgroundImageStore.recents
if (recents.isNotEmpty()) {
Column(verticalArrangement = Arrangement.spacedBy(6.dp)) {
- Text("Recent", style = NoopType.footnote, color = Palette.textSecondary)
+ Text(uiString(R.string.l10n_settings_screen_recent_76eec760), style = NoopType.footnote, color = Palette.textSecondary)
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
recents.forEachIndexed { i, r ->
BackgroundRecentThumb(
@@ -1963,8 +1960,8 @@ fun SettingsScreen(
}
// Master gate + scaling only make sense once an image exists.
SettingsToggleRow(
- title = "Show custom background",
- detail = "Draw your photo behind every tab, replacing the day-cycle sky.",
+ title = uiString(R.string.l10n_settings_screen_show_custom_background_85a2c096),
+ detail = uiString(R.string.l10n_settings_screen_draw_your_photo_behind_every_tab_9cbd4de2),
checked = BackgroundImageStore.enabled,
onCheckedChange = { BackgroundImageStore.setEnabled(context, it) },
)
@@ -1973,16 +1970,16 @@ fun SettingsScreen(
// to ~0px, which wrapped "Scaling" one letter per line and blew the row up to a tall
// empty gap. A stacked label sidesteps that entirely.
Column(verticalArrangement = Arrangement.spacedBy(6.dp)) {
- Text("Scaling", style = NoopType.footnote, color = Palette.textSecondary)
+ Text(uiString(R.string.l10n_settings_screen_scaling_0b4193c5), style = NoopType.footnote, color = Palette.textSecondary)
SegmentedPillControl(
items = BackgroundFillMode.entries,
selection = BackgroundImageStore.fillMode,
label = { mode ->
when (mode) {
- BackgroundFillMode.FILL -> "Fill"
- BackgroundFillMode.FIT -> "Fit"
- BackgroundFillMode.STRETCH -> "Stretch"
- BackgroundFillMode.TILE -> "Tile"
+ BackgroundFillMode.FILL -> uiString(R.string.l10n_settings_screen_fill_7adb6736)
+ BackgroundFillMode.FIT -> uiString(R.string.l10n_settings_screen_fit_dab564d8)
+ BackgroundFillMode.STRETCH -> uiString(R.string.l10n_settings_screen_stretch_b148ed24)
+ BackgroundFillMode.TILE -> uiString(R.string.l10n_settings_screen_tile_2dd2c660)
}
},
onSelect = { BackgroundImageStore.setFillMode(context, it) },
@@ -1991,7 +1988,7 @@ fun SettingsScreen(
)
}
NoopButton(
- text = "Remove image",
+ text = uiString(R.string.l10n_settings_screen_remove_image_5f94b03c),
kind = NoopButtonKind.Tertiary,
modifier = Modifier.fillMaxWidth(),
onClick = {
@@ -2008,13 +2005,13 @@ fun SettingsScreen(
SettingsCard(
icon = Icons.Filled.Palette,
title = uiString(R.string.l10n_settings_screen_app_icon_abde7a74),
- blurb = "Choose how NOOP looks on your home screen. The launcher may take a moment to refresh the icon after you change it.",
+ blurb = uiString(R.string.l10n_settings_screen_choose_how_noop_looks_on_your_d680c8e0),
) {
SettingsFormRow(label = uiString(R.string.l10n_settings_screen_icon_716f63b9)) {
SegmentedPillControl(
items = listOf(false, true),
selection = appIconNavy,
- label = { if (it) "Blue Titanium" else "Titanium" },
+ label = { if (it) uiString(R.string.l10n_settings_screen_blue_titanium_4d16ffcd) else uiString(R.string.l10n_settings_screen_titanium_6d1def3d) },
onSelect = { navy ->
appIconNavy = navy
setAppIcon(context, navy)
@@ -2027,7 +2024,7 @@ fun SettingsScreen(
SettingsCard(
icon = Icons.Filled.Sensors,
title = uiString(R.string.l10n_settings_screen_strap_02b88eeb),
- blurb = "NOOP pairs directly with your WHOOP over Bluetooth: no WHOOP app, no cloud.",
+ blurb = uiString(R.string.l10n_settings_screen_noop_pairs_directly_with_your_whoop_0b5d57cd),
) {
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
Row(
@@ -2035,7 +2032,7 @@ fun SettingsScreen(
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
StatePill(
- title = strapStatusTitle(live.encryptedBond, live.bonded, live.connected),
+ title = uiString(strapStatusTitleRes(live.encryptedBond, live.bonded, live.connected)),
tone = strapTone(live.encryptedBond, live.bonded, live.connected),
pulsing = live.connected,
)
@@ -2052,13 +2049,13 @@ fun SettingsScreen(
}
}
Text(
- strapStatusDetail(live.encryptedBond, live.bonded, live.connected, live.scanning),
+ uiString(strapStatusDetailRes(live.encryptedBond, live.bonded, live.connected, live.scanning)),
style = NoopType.subhead,
color = Palette.textSecondary,
)
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
NoopButton(
- text = if (live.scanning) "Searching…" else "Re-scan",
+ text = if (live.scanning) uiString(R.string.l10n_add_device_wizard_searching_1a6a5ba8) else uiString(R.string.l10n_settings_screen_re_scan_8bd32cdf),
leadingIcon = Icons.Filled.Refresh,
kind = NoopButtonKind.Primary,
enabled = !live.scanning,
@@ -2502,7 +2499,7 @@ fun SettingsScreen(
selection = hrvWindow,
// #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" },
+ label = { if (it == HrvWindow.DEEP_SLEEP) uiString(R.string.l10n_settings_screen_deep_sleep_865e5887) else uiString(R.string.l10n_settings_screen_night_1097b553) },
onSelect = {
hrvWindow = it
UnitPrefs.setHrvWindow(context, it)
@@ -2519,7 +2516,10 @@ fun SettingsScreen(
vm.syncNow()
Toast.makeText(
context,
- "Re-scoring your recent nights over the ${if (it == HrvWindow.DEEP_SLEEP) "deep-sleep" else "whole-night"} window. Charge updates as soon as it's done.",
+ uiString(
+ if (it == HrvWindow.DEEP_SLEEP) R.string.l10n_settings_screen_re_scoring_your_recent_nights_over_25b34e97
+ else R.string.l10n_settings_screen_re_scoring_your_recent_nights_over_dc5bde82,
+ ),
Toast.LENGTH_LONG,
).show()
},
@@ -2603,7 +2603,7 @@ fun SettingsScreen(
// away. Mirrors the iOS SettingsView "Advanced" disclosure and the Test Centre Advanced group.
SettingsDisclosureGroup(
title = uiString(R.string.l10n_settings_screen_advanced_4d064726),
- subtitle = "Experimental probes, diagnostics, raw-sensor export, and the Trends report. Tucked away to keep the everyday screen tidy.",
+ subtitle = uiString(R.string.l10n_settings_screen_experimental_probes_diagnostics_raw_sensor_export_df4a89ef),
expanded = advancedOpen,
onToggle = { advancedOpen = !advancedOpen; SettingsDisclosurePrefs.write(NoopPrefs.of(context), advancedOpen) },
) {
@@ -3024,7 +3024,7 @@ fun SettingsScreen(
SettingsCard(
icon = Icons.Filled.Science,
title = uiString(R.string.l10n_settings_screen_diagnostics_3af2279f),
- blurb = "A read-only export of the decoded sensor streams NOOP already stores. Works on any strap. Nothing is written to your device, and nothing is uploaded.",
+ blurb = uiString(R.string.l10n_settings_screen_a_read_only_export_of_the_ad0afd99),
) {
Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
// --- Sleep staging (V2) — the DEFAULT engine after the 44-subject benchmark; toggle off to
@@ -3118,7 +3118,7 @@ fun SettingsScreen(
horizontalArrangement = Arrangement.spacedBy(16.dp),
) {
Text(
- "Blood Oxygen: strap estimate",
+ uiString(R.string.l10n_settings_screen_blood_oxygen_strap_estimate_873e7bd6),
style = NoopType.subhead,
color = Palette.textPrimary,
modifier = Modifier.weight(1f),
@@ -3139,14 +3139,7 @@ fun SettingsScreen(
)
}
Text(
- "Surfaces your strap's nightly SpO₂ estimate in the Blood Oxygen tile when no " +
- "calibrated percentage is available: a WHOOP 5.0/MG's @82 candidate byte, or an " +
- "Oura ring's own reading with each sample capped at 100% first (the ring's raw " +
- "reading runs high otherwise). This is an UNVERIFIED strap-computed value — the " +
- "WHOOP candidate matched a reference device closely on most nights but moved " +
- "opposite on some; the Oura one has only been checked against a few nights so " +
- "far. Shown as an 'estimate' and never fed into recovery or illness scoring. Off " +
- "by default.",
+ uiString(R.string.l10n_settings_screen_surfaces_your_strap_s_nightly_spo_d9b0f0f1),
style = NoopType.caption,
color = Palette.textTertiary,
)
@@ -3164,7 +3157,7 @@ fun SettingsScreen(
horizontalArrangement = Arrangement.spacedBy(16.dp),
) {
Text(
- "Stress: personal daytime baseline",
+ uiString(R.string.l10n_settings_screen_stress_personal_daytime_baseline_68a38abd),
style = NoopType.subhead,
color = Palette.textPrimary,
modifier = Modifier.weight(1f),
@@ -3186,10 +3179,7 @@ fun SettingsScreen(
}
Text(
- "Scores today's hour-by-hour stress timeline against YOUR own cross-day baseline " +
- "(how your days usually run, Oura-style) instead of the day's own calm hours. The " +
- "cutoff is tuned from a single-subject reference so far, so it's an alternative lens, " +
- "not the default. HR-only; never fed into recovery or illness scoring. Off by default.",
+ uiString(R.string.l10n_settings_screen_scores_today_s_hour_by_hour_a9f3f146),
style = NoopType.caption,
color = Palette.textTertiary,
)
@@ -3243,12 +3233,12 @@ fun SettingsScreen(
SettingsCard(
icon = Icons.Filled.Science,
title = uiString(R.string.l10n_settings_screen_health_wellness_93475778),
- blurb = "Optional, on-device wellness signals. Each is off by default, computed only on this phone from data you already have, and never a medical diagnosis.",
+ blurb = uiString(R.string.l10n_settings_screen_optional_on_device_wellness_signals_each_8e80e24a),
) {
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
SettingsToggleRow(
title = uiString(R.string.l10n_settings_screen_illness_heads_up_97e10035),
- detail = "Watches your resting heart rate, HRV and skin temperature for the pattern that often shows up before you feel unwell, and surfaces a gentle heads-up. An observation about your own numbers, not a diagnosis.",
+ detail = uiString(R.string.l10n_settings_screen_watches_your_resting_heart_rate_hrv_1ad88889),
checked = illnessWatch,
onCheckedChange = {
illnessWatch = it
@@ -3268,7 +3258,7 @@ fun SettingsScreen(
// Twin of the iOS Automations "Show cycle awareness" toggle.
SettingsToggleRow(
title = uiString(R.string.l10n_settings_screen_show_cycle_awareness_59709019),
- detail = "Shows the cycle-awareness card on Today and in Health. Turn off to hide it entirely — a private choice, never based on your age. You can turn it back on here any time.",
+ detail = uiString(R.string.l10n_settings_screen_shows_the_cycle_awareness_card_on_e19a7822),
checked = !cycleHidden,
onCheckedChange = { show ->
cycleHidden = !show
@@ -3280,7 +3270,7 @@ fun SettingsScreen(
if (!cycleHidden) {
SettingsToggleRow(
title = uiString(R.string.l10n_settings_screen_cycle_awareness_ffb94783),
- detail = "Reads a coarse menstrual-cycle phase from your nightly skin-temperature shift, on this device only. Awareness only: not contraception, not a fertility predictor, not a medical service.",
+ detail = uiString(R.string.l10n_settings_screen_reads_a_coarse_menstrual_cycle_phase_f176e436),
checked = cycleTracking,
onCheckedChange = {
cycleTracking = it
@@ -3292,7 +3282,7 @@ fun SettingsScreen(
}
SettingsToggleRow(
title = uiString(R.string.l10n_settings_screen_hydration_tracking_579a2b32),
- detail = "Adds a simple fluid log with a daily goal that adjusts to your effort. Tap to add a sip, cup or bottle and watch a progress ring fill. On this phone only. Nothing is synced.",
+ detail = uiString(R.string.l10n_settings_screen_adds_a_simple_fluid_log_with_007462a0),
checked = hydrationTracking,
onCheckedChange = {
hydrationTracking = it
@@ -3302,7 +3292,7 @@ fun SettingsScreen(
SettingsRowDivider()
SettingsToggleRow(
title = uiString(R.string.l10n_settings_screen_auto_detect_workouts_bed4cf2a),
- detail = "After a sync, NOOP looks over your recent heart rate for a sustained, raised stretch that looks like exercise and offers to save it. It only ever suggests. Nothing is saved until you tap Save, and you can dismiss any suggestion. Turning this off stops future suggestions; workouts already in your history remain. Deliberately conservative, so the odd workout may be missed. On this phone only.",
+ detail = uiString(R.string.l10n_settings_screen_after_a_sync_noop_looks_over_54156d92),
checked = autoDetectWorkouts,
onCheckedChange = {
autoDetectWorkouts = it
@@ -3322,7 +3312,7 @@ fun SettingsScreen(
SettingsRowDivider()
SettingsToggleRow(
title = uiString(R.string.l10n_settings_screen_keep_screen_on_during_a_workout_42d27284),
- detail = "Holds the screen awake while you're recording a workout, so your live heart rate stays visible without the phone dimming. Only applies during a recording. The screen sleeps normally the rest of the time. Leaving it on does use a bit more battery, and means your unlocked screen stays visible for the whole workout, so flip it off if that's a concern.",
+ detail = uiString(R.string.l10n_settings_screen_holds_the_screen_awake_while_you_77637345),
checked = workoutKeepScreenOn,
onCheckedChange = {
workoutKeepScreenOn = it
@@ -3334,7 +3324,7 @@ fun SettingsScreen(
// gates the Today entry so anyone can wave the beta away here with one flip.
SettingsToggleRow(
title = uiString(R.string.l10n_settings_screen_live_sessions_beta_2ca3a97f),
- detail = "Silence-first strap coaching during workouts.",
+ detail = uiString(R.string.l10n_settings_screen_silence_first_strap_coaching_during_workouts_e63b1007),
checked = liveSessionsBeta,
onCheckedChange = {
liveSessionsBeta = it
@@ -3344,7 +3334,7 @@ fun SettingsScreen(
SettingsRowDivider()
SettingsToggleRow(
title = uiString(R.string.l10n_settings_screen_stress_check_ins_haptic_bf2746ba),
- detail = "Lets NOOP notice a fresh HRV dip while you're still and offer a minute to breathe. \"Stress\" here is an autonomic proxy from your own baseline, never a diagnosis. The strap gives one light confirming buzz; no push notification.",
+ detail = uiString(R.string.l10n_settings_screen_lets_noop_notice_a_fresh_hrv_eb7eade4),
checked = stressCheckIn,
onCheckedChange = {
stressCheckIn = it
@@ -3356,7 +3346,7 @@ fun SettingsScreen(
if (stressCheckIn) {
SettingsToggleRow(
title = uiString(R.string.l10n_settings_screen_offer_a_breath_automatically_6c709dee),
- detail = "When a dip is detected, surface the check-in card on its own (rate-limited, quiet-hours aware). Off keeps it manual.",
+ detail = uiString(R.string.l10n_settings_screen_when_a_dip_is_detected_surface_4ccb8458),
checked = stressAutoNudge,
onCheckedChange = {
stressAutoNudge = it
@@ -3367,7 +3357,7 @@ fun SettingsScreen(
SettingsRowDivider()
SettingsToggleRow(
title = uiString(R.string.l10n_settings_screen_rhythm_experimental_12d357da),
- detail = "An experimental picture of your beat-to-beat timing: a Poincaré scatter and plain regularity stats from quiet resting windows. Not an ECG and not a diagnosis; you'll read a short disclaimer and accept before it turns on.",
+ detail = uiString(R.string.l10n_settings_screen_an_experimental_picture_of_your_beat_29a199d1),
checked = rhythmEnabled,
onCheckedChange = {
// Enabling here just un-gates the experimental item; the screen itself still shows
@@ -3384,7 +3374,7 @@ fun SettingsScreen(
SettingsRowDivider()
SettingsToggleRow(
title = uiString(R.string.l10n_settings_screen_share_on_device_signals_with_the_b3fd747e),
- detail = "When the opt-in Coach is set up with your own key, also include a short summary of your strongest on-device patterns and Lab Book markers in its context. Summary only; no raw data leaves your phone. Requires the Coach's own data consent first.",
+ detail = uiString(R.string.l10n_settings_screen_when_the_opt_in_coach_is_1e5112f4),
checked = coachSignals,
onCheckedChange = {
coachSignals = it
@@ -3401,7 +3391,7 @@ fun SettingsScreen(
SettingsCard(
icon = Icons.Filled.BugReport,
title = uiString(R.string.l10n_settings_screen_test_centre_37b36828),
- blurb = "Turn on a test for the thing that's wrong, wear the strap, then tap Report. Your strap log, recalibrate, scheduled export and experimental probes all live here too.",
+ blurb = uiString(R.string.l10n_settings_screen_turn_on_a_test_for_the_a88d29a4),
) {
NoopButton(
text = uiString(R.string.l10n_settings_screen_open_test_centre_a7fbe4e9),
@@ -3422,7 +3412,7 @@ fun SettingsScreen(
SettingsCard(
icon = Icons.Filled.Favorite,
title = uiString(R.string.l10n_settings_screen_charge_d4e1aee4),
- blurb = "Charge is NOOP's daily readiness score, learned from your own HRV, resting heart rate and more over time. Your history stays.",
+ blurb = uiString(R.string.l10n_settings_screen_charge_is_noop_s_daily_readiness_1f8911ea),
) {
Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
@@ -3469,7 +3459,7 @@ fun SettingsScreen(
when (again) {
is DataBackup.ImportResult.NeedsRestart -> Toast.makeText(
context,
- "Backup imported. Fully close and reopen NOOP for it to take effect.",
+ uiString(R.string.l10n_settings_screen_backup_imported_fully_close_and_reopen_8c17637d),
Toast.LENGTH_LONG,
).show()
// Same reason as the first attempt: these carry a next step, and a Toast
@@ -3571,7 +3561,7 @@ fun SettingsScreen(
vm.syncNow()
Toast.makeText(
context,
- "Charge baseline reset. NOOP will re-learn it from tonight. Your history stays, and it takes a few nights to settle.",
+ uiString(R.string.l10n_settings_screen_charge_baseline_reset_noop_will_re_bdbaf457),
Toast.LENGTH_LONG,
).show()
},
@@ -3588,7 +3578,7 @@ fun SettingsScreen(
SettingsCard(
icon = Icons.Filled.Storage,
title = uiString(R.string.l10n_settings_screen_backup_restore_a1616284),
- blurb = "Move all your NOOP data to another phone. Export saves everything (history, sleeps, workouts, settings) to a single file you can copy across; import replaces this phone's data with a backup.",
+ blurb = uiString(R.string.l10n_settings_screen_move_all_your_noop_data_to_83f17205),
) {
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
// Three equal-width buttons share the row (each takes a third via weight) — mirrors the
@@ -3674,7 +3664,7 @@ fun SettingsScreen(
SettingsCard(
icon = Icons.Filled.CloudSync,
title = uiString(R.string.l10n_settings_screen_automatic_backups_8a772f3c),
- blurb = "Have NOOP save a dated backup to a folder every day (around 1am) and keep the last several - so if data ever corrupts, restore the newest. Point the folder at Drive/Dropbox for off-device copies. Off until you switch it on.",
+ blurb = uiString(R.string.l10n_settings_screen_have_noop_save_a_dated_backup_755bb057),
) {
NoopButton(
text = uiString(R.string.l10n_settings_screen_set_up_automatic_backups_00b4780c),
@@ -3689,7 +3679,7 @@ fun SettingsScreen(
SettingsCard(
icon = Icons.Filled.Info,
title = uiString(R.string.l10n_settings_screen_about_6b21fb79),
- blurb = "NOOP: all your data, none of the cloud.",
+ blurb = uiString(R.string.l10n_settings_screen_noop_all_your_data_none_of_ba567df9),
) {
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
Row(
@@ -4022,9 +4012,9 @@ fun SettingsScreen(
SettingsRowDivider()
Column(verticalArrangement = Arrangement.spacedBy(6.dp)) {
- Overline("Built on")
- SettingsAttributionRow(repo = "my-whoop", note = "WHOOP 4.0 protocol")
- SettingsAttributionRow(repo = "goose", note = "WHOOP 5.0 protocol")
+ Overline(uiString(R.string.l10n_settings_screen_built_on_5342a274))
+ SettingsAttributionRow(repo = "my-whoop", note = uiString(R.string.l10n_settings_screen_whoop_4_0_protocol_87af84d3))
+ SettingsAttributionRow(repo = "goose", note = uiString(R.string.l10n_settings_screen_whoop_5_0_protocol_ca55847b))
}
Text(
uiString(R.string.l10n_settings_screen_open_source_ble_reverse_engineering_work_40062271),
@@ -4055,7 +4045,7 @@ fun SettingsScreen(
try {
context.startActivity(intent)
} catch (_: ActivityNotFoundException) {
- Toast.makeText(context, "Email us at $SUPPORT_EMAIL", Toast.LENGTH_LONG).show()
+ Toast.makeText(context, uiString(R.string.l10n_settings_screen_email_us_at_ee8307d4, SUPPORT_EMAIL), Toast.LENGTH_LONG).show()
}
}
.padding(horizontal = 14.dp, vertical = 12.dp)
@@ -4357,10 +4347,10 @@ private fun BackgroundRecentThumb(
}
Text(
text = when (mode) {
- BackgroundFillMode.FILL -> "Fill"
- BackgroundFillMode.FIT -> "Fit"
- BackgroundFillMode.STRETCH -> "Stretch"
- BackgroundFillMode.TILE -> "Tile"
+ BackgroundFillMode.FILL -> uiString(R.string.l10n_settings_screen_fill_7adb6736)
+ BackgroundFillMode.FIT -> uiString(R.string.l10n_settings_screen_fit_dab564d8)
+ BackgroundFillMode.STRETCH -> uiString(R.string.l10n_settings_screen_stretch_b148ed24)
+ BackgroundFillMode.TILE -> uiString(R.string.l10n_settings_screen_tile_2dd2c660)
},
style = NoopType.caption,
color = if (active) Palette.accent else Palette.textTertiary,
diff --git a/android/app/src/main/res/values-de/strings.xml b/android/app/src/main/res/values-de/strings.xml
index 842cbe7c8f..33e34b2430 100644
--- a/android/app/src/main/res/values-de/strings.xml
+++ b/android/app/src/main/res/values-de/strings.xml
@@ -2844,6 +2844,102 @@
Zahlen auf den Anzeigen
Fett
Weicher
+ Ein schreibgeschützter Export der decodierten Sensordatenströme, die NOOP bereits speichert. Funktioniert mit jedem Strap. Auf dein Gerät wird nichts geschrieben, und nichts wird hochgeladen.
+ Fügt ein einfaches Trinkprotokoll mit einem Tagesziel hinzu, das sich an deine Anstrengung anpasst. Tippe, um einen Schluck, eine Tasse oder eine Flasche hinzuzufügen, und sieh zu, wie sich ein Fortschrittsring füllt. Nur auf diesem Handy. Nichts wird synchronisiert.
+ Nach einem Sync prüft NOOP deine jüngste Herzfrequenz auf eine anhaltend erhöhte Phase, die nach Training aussieht, und bietet an, sie zu speichern. Es macht immer nur Vorschläge. Nichts wird gespeichert, bis du auf „Speichern“ tippst, und du kannst jeden Vorschlag verwerfen. Wenn du das ausschaltest, kommen keine neuen Vorschläge mehr; Workouts, die bereits in deinem Verlauf sind, bleiben erhalten. Bewusst zurückhaltend, daher kann gelegentlich ein Workout übersehen werden. Nur auf diesem Handy.
+ Alter, %1$s Jahre
+ Ein experimentelles Bild deines Herzschlag-Timings: ein Poincaré-Streudiagramm und einfache Regelmäßigkeitswerte aus ruhigen Ruhephasen. Kein ECG und keine Diagnose; du liest einen kurzen Hinweis und stimmst zu, bevor es aktiviert wird.
+ Auto · %1$s bpm (Tanaka)
+ Auto
+ Auto · Konfidenz %1$s
+ Hintergrundbild
+ Backup exportiert. Kopiere diese Datei auf dein neues Handy und nutze dort „Importieren“, um alles wiederherzustellen.
+ Backup exportiert. Das Backup-Archiv ist zu groß, um es sicher wiederherzustellen — beim Wiederherstellen wirst du um Bestätigung gebeten.
+ Backup importiert. Schließe NOOP vollständig und öffne es erneut, damit es wirksam wird.
+ Backup-Problem: %1$s
+ Blutsauerstoff: Strap-Schätzung
+ Blau-Titan
+ Dateien durchsuchen
+ Basiert auf
+ Foto ändern
+ Ladungs-Basislinie zurückgesetzt. NOOP lernt sie ab heute Nacht neu. Dein Verlauf bleibt erhalten, und es dauert ein paar Nächte, bis sie sich einpendelt.
+ Ladung ist der tägliche Bereitschaftswert von NOOP, mit der Zeit gelernt aus deiner eigenen HRV, deiner Ruheherzfrequenz und mehr. Dein Verlauf bleibt erhalten.
+ Aus Fotos wählen
+ Wähle, wie NOOP auf deinem Homescreen aussieht. Der Launcher braucht nach der Änderung eventuell einen Moment, um das Symbol zu aktualisieren.
+ Foto auswählen
+ Dieses Bild konnte nicht verwendet werden. Versuch ein anderes.
+ Dieses Foto konnte nicht verwendet werden. Versuch ein anderes.
+ Problem beim CSV-Export: %1$s
+ Tiefschlaf
+ Zeigt dein Foto hinter jedem Tab an, anstelle des Tageszyklus-Himmels.
+ Schreib uns an %1$s
+ Experimentelle Tests, Diagnose, Rohsensor-Export und der Trends-Report. Hier verstaut, damit der Alltagsbildschirm übersichtlich bleibt.
+ Füllen
+ Einpassen
+ Lass NOOP jeden Tag (gegen 1 Uhr) ein datiertes Backup in einem Ordner speichern und die letzten paar behalten - falls Daten jemals beschädigt werden, stellst du einfach das neueste wieder her. Richte den Ordner auf Drive/Dropbox, um Kopien außerhalb des Geräts zu haben. Aus, bis du es einschaltest.
+ Größe, %1$s Fuß %2$s Zoll
+ Größe in Zentimetern
+ Hält den Bildschirm an, während du ein Workout aufzeichnest, damit deine Live-Herzfrequenz sichtbar bleibt, ohne dass das Handy abdunkelt. Gilt nur während einer Aufzeichnung. Den Rest der Zeit geht der Bildschirm ganz normal in den Ruhezustand. Eingeschaltet verbraucht es etwas mehr Akku, und dein entsperrter Bildschirm bleibt während des gesamten Workouts sichtbar — schalte es also aus, wenn dich das stört.
+ Lass den Hintergrund durch jede Karte scheinen. Wie stark, stellst du direkt darunter ein.
+ Lässt NOOP einen frischen HRV-Abfall erkennen, während du stillhältst, und bietet dir eine Minute zum Durchatmen an. „Stress“ ist hier ein Näherungswert des autonomen Nervensystems auf Basis deines eigenen Basiswerts, nie eine Diagnose. Der Strap gibt eine leichte Bestätigungsvibration; keine Push-Benachrichtigung.
+ Manuell
+ Manuell festlegen
+ Manuelle maximale Herzfrequenz, automatisch
+ Manuelle maximale Herzfrequenz, %1$s bpm
+ Übertrage alle deine NOOP-Daten auf ein anderes Handy. Der Export speichert alles (Verlauf, Schlaf, Workouts, Einstellungen) in einer einzigen Datei, die du rüberkopieren kannst; der Import ersetzt die Daten dieses Handys durch ein Backup.
+ Nacht
+ NOOP: all deine Daten, nichts davon in der Cloud.
+ NOOP koppelt sich über Bluetooth direkt mit deinem WHOOP: keine WHOOP-App, keine Cloud.
+ Nicht kalibriert
+ Optional. Füge ein Foto für den Avatar oben links hinzu. Wird nur auf diesem Handy gespeichert. NOOP ist offline, daher wird es nie hochgeladen.
+ Optionale Wellness-Signale, direkt auf dem Gerät. Jedes ist standardmäßig aus, wird nur auf diesem Handy aus Daten berechnet, die du bereits hast, und ist nie eine medizinische Diagnose.
+ Optional. Verwende dein eigenes Foto hinter jedem Tab anstelle des Tageszyklus-Himmels. Wird nur auf diesem Handy gespeichert. Kombiniere es mit „Transparente Karten“ oben, damit es durchscheint.
+ %1$s Importiere es erneut über Datenquellen → WHOOP-Import, auf Android oder dem Mac.
+ Neu scannen
+ Deine letzten Nächte werden über das Tiefschlaf-Fenster neu bewertet. Die Ladung wird aktualisiert, sobald das erledigt ist.
+ Deine letzten Nächte werden über das Fenster der ganzen Nacht neu bewertet. Die Ladung wird aktualisiert, sobald das erledigt ist.
+ Leitet eine grobe Menstruationszyklusphase aus der nächtlichen Verschiebung deiner Hauttemperatur ab, nur auf diesem Gerät. Nur zur Orientierung: keine Verhütung, keine Fruchtbarkeitsvorhersage, kein medizinischer Dienst.
+ Zuletzt
+ Bild entfernen
+ Aus Fotos ersetzen
+ Streifen
+ Skalierung
+ Bewertet den heutigen stündlichen Stressverlauf anhand DEINES eigenen tagesübergreifenden Basiswerts (wie deine Tage normalerweise verlaufen, wie bei Oura) statt anhand der ruhigen Stunden des Tages selbst. Der Schwellenwert ist bisher nur an einer Referenzperson abgestimmt, daher ist dies eine alternative Sichtweise, nicht der Standard. Nur HF; fließt nie in die Erholungs- oder Krankheitsbewertung ein. Standardmäßig aus.
+ Eigenen Hintergrund anzeigen
+ Zeigt die Zyklusbewusstsein-Karte unter Heute und in Gesundheit. Schalte sie aus, um sie komplett auszublenden — eine private Entscheidung, nie von deinem Alter abhängig. Du kannst sie hier jederzeit wieder einschalten.
+ Zurückhaltendes Strap-Coaching während Workouts: Stille hat Vorrang.
+ Schlafdiagramm
+ Schrittkalibrierung, %1$.1f Zählerimpulse pro Schritt
+ Stress: persönlicher Tages-Basiswert
+ Strecken
+ Zeigt die nächtliche SpO₂-Schätzung deines Straps in der Blutsauerstoff-Kachel an, wenn kein kalibrierter Prozentwert verfügbar ist: das @82-Kandidatenbyte eines WHOOP 5.0/MG oder den eigenen Messwert eines Oura-Rings, wobei jeder Wert zuerst auf 100 % begrenzt wird (sonst liegt der Rohwert des Rings zu hoch). Dies ist ein UNBESTÄTIGTER, vom Strap berechneter Wert — der WHOOP-Kandidat stimmte in den meisten Nächten eng mit einem Referenzgerät überein, bewegte sich in manchen aber gegenläufig; der Oura-Wert wurde bisher nur in wenigen Nächten geprüft. Wird als „Schätzung“ angezeigt und fließt nie in die Erholungs- oder Krankheitsbewertung ein. Standardmäßig aus.
+ Diese Angaben bestimmen deine Herzfrequenzzonen, Kalorienschätzungen und Erholungs-Basiswerte. Achte darauf, dass sie stimmen.
+ Kacheln
+ Titan
+ Transparente Karten
+ Schalte einen Test für das Problem ein, trag den Strap und tippe dann auf „Bericht“. Dein Strap-Protokoll, Neu kalibrieren, der geplante Export und experimentelle Tests sind ebenfalls hier.
+ Taillenumfang in Zentimetern
+ Taillenumfang, %1$s Zoll
+ Taillenumfang, nicht festgelegt. Optional: Damit wird dein VO₂max genauer
+ Beobachtet deine Ruheherzfrequenz, HRV und Hauttemperatur auf das Muster, das sich oft zeigt, bevor du dich krank fühlst, und gibt dir einen sanften Hinweis. Eine Beobachtung deiner eigenen Werte, keine Diagnose.
+ Gewicht in Kilogramm
+ Gewicht, %1$s Pfund
+ Wenn ein Abfall erkannt wird, die Check-in-Karte von selbst anzeigen (begrenzte Häufigkeit, beachtet Ruhezeiten). Aus bedeutet: nur manuell.
+ Wenn der optionale Coach mit deinem eigenen Schlüssel eingerichtet ist, wird zusätzlich eine kurze Zusammenfassung deiner stärksten Muster auf dem Gerät und deiner Laborbuch-Marker in seinen Kontext aufgenommen. Nur eine Zusammenfassung; keine Rohdaten verlassen dein Handy. Erfordert zuerst die eigene Datenfreigabe des Coachs.
+ WHOOP 4.0-Protokoll
+ WHOOP 5.0-Protokoll
+ Deine Werte, dein Strap und wie NOOP funktioniert. Alles auf diesem Handy.
+ Zone %1$s beginnt bei %2$s bpm
+ Gekoppelt · inaktiv
+ Live-HF (nicht vollständig gekoppelt)
+ Getrennt
+ Suche nach deinem WHOOP… Achte darauf, dass es geladen ist, an deinem Handgelenk sitzt und die offizielle WHOOP-App nicht damit verbunden ist.
+ Dein Strap ist gekoppelt und sendet Daten. Öffne Live für deine Herzfrequenz in Echtzeit.
+ Die Live-Herzfrequenz wird übertragen, aber dein Strap ist nicht vollständig gekoppelt. Erst die verschlüsselte Kopplung überträgt Bewegung, Hauttemperatur, SpO₂ und Atemfrequenz — ohne sie wird der Schlaf nur anhand der Herzfrequenz in Phasen eingeteilt. Vibration, Wecker und Verlaufs-Sync benötigen sie ebenfalls.
+ Verbunden. Sicherer Kopplungs-Handshake wird abgeschlossen…
+ Bereits gekoppelt, aber derzeit nicht verbunden. Tippe auf „Neu scannen“, um die Verbindung wiederherzustellen.
+ Kein Strap verbunden. Leg dein WHOOP in die Nähe und tippe auf „Neu scannen“, um es zu koppeln.
+ Nicht-binär
Oura-Benachrichtigungsmaske ff (experimentell)
Sendet beim nächsten Verbinden die SetNotification-Maske der offiziellen App (1c 01 ff) statt NOOPs 3f. Der Ring packt für die offizielle App ~10 Pakete in eine Benachrichtigung, für NOOP nur eines (9× langsameres Auslesen); das ist der erste Kandidat für den Schalter. Standardmäßig aus; die erste Verbindung nach dem Ausschalten läuft wieder mit 3f. Im Strap-Protokoll auf „-> notify_all(ff)“ achten und die Benachrichtigungsgrößen in der Rohaufzeichnung vergleichen.
Koppelt sich direkt über Bluetooth mit deinem Strap: keine WHOOP-App, keine Cloud. Der Strap kann seine Herzfrequenz außerdem als Standard-Bluetooth-Sensor senden.
diff --git a/android/app/src/main/res/values-es/strings.xml b/android/app/src/main/res/values-es/strings.xml
index 60755b629a..975c3c83f6 100644
--- a/android/app/src/main/res/values-es/strings.xml
+++ b/android/app/src/main/res/values-es/strings.xml
@@ -2831,6 +2831,102 @@
Números de los medidores
Negrita
Más suave
+ Una exportación de solo lectura de los flujos de sensores decodificados que NOOP ya guarda. Funciona con cualquier pulsera. No se escribe nada en tu dispositivo y no se sube nada.
+ Añade un registro sencillo de líquidos con un objetivo diario que se adapta a tu esfuerzo. Toca para añadir un sorbo, una taza o una botella y mira cómo se llena el anillo de progreso. Solo en este teléfono. No se sincroniza nada.
+ Tras una sincronización, NOOP revisa tu frecuencia cardíaca reciente en busca de un tramo elevado y sostenido que parezca ejercicio, y te ofrece guardarlo. Solo sugiere: no se guarda nada hasta que tocas Guardar, y puedes descartar cualquier sugerencia. Al desactivarlo se detienen las sugerencias futuras; los entrenamientos que ya están en tu historial se conservan. Es deliberadamente prudente, así que puede pasar por alto algún entrenamiento. Solo en este teléfono.
+ Edad, %1$s años
+ Una imagen experimental de la sincronía latido a latido: un diagrama de Poincaré y estadísticas sencillas de regularidad a partir de ventanas de reposo tranquilo. No es un ECG ni un diagnóstico; leerás y aceptarás un breve aviso antes de activarlo.
+ Auto · %1$s bpm (Tanaka)
+ Auto
+ Auto · confianza %1$s
+ Imagen de fondo
+ Copia exportada. Copia este archivo a tu nuevo teléfono y usa Importar allí para restaurarlo todo.
+ Copia exportada. El archivo es demasiado grande para restaurarlo con seguridad: al restaurarlo se te pedirá confirmación.
+ Copia importada. Cierra NOOP por completo y vuelve a abrirlo para aplicarla.
+ Problema con la copia: %1$s
+ Oxígeno en sangre: estimación de la pulsera
+ Titanio azul
+ Explorar archivos
+ Basado en
+ Cambiar foto
+ Línea base de Carga restablecida. NOOP volverá a aprenderla desde esta noche. Tu historial se conserva y tarda unas noches en estabilizarse.
+ La Carga es la puntuación diaria de preparación de NOOP, aprendida con el tiempo a partir de tu HRV, tu frecuencia cardíaca en reposo y más. Tu historial se conserva.
+ Elegir de Fotos
+ Elige cómo se ve NOOP en tu pantalla de inicio. El launcher puede tardar un momento en actualizar el icono después de cambiarlo.
+ Elegir foto
+ No se pudo usar esa imagen. Prueba con otra.
+ No se pudo usar esa foto. Prueba con otra.
+ Problema al exportar CSV: %1$s
+ Sueño profundo
+ Muestra tu foto detrás de cada pestaña, en lugar del cielo según el ciclo del día.
+ Escríbenos a %1$s
+ Sondas experimentales, diagnósticos, exportación de datos brutos de sensores y el informe de Tendencias. Apartados para mantener ordenada la pantalla de todos los días.
+ Rellenar
+ Ajustar
+ Haz que NOOP guarde cada día (hacia la 1 de la madrugada) una copia con fecha en una carpeta y conserve las últimas; así, si los datos se dañan, restauras la más reciente. Apunta la carpeta a Drive/Dropbox para tener copias fuera del dispositivo. Desactivado hasta que lo actives.
+ Altura, %1$s pies %2$s pulgadas
+ Altura en centímetros
+ Mantiene la pantalla encendida mientras grabas un entrenamiento, para que tu frecuencia cardíaca en directo siga visible sin que el teléfono se atenúe. Solo se aplica durante una grabación; el resto del tiempo la pantalla se apaga con normalidad. Dejarlo activado gasta un poco más de batería y hace que tu pantalla desbloqueada siga visible durante todo el entrenamiento, así que desactívalo si eso te preocupa.
+ Deja que el fondo se vea a través de cada tarjeta. Ajusta cuánto justo debajo.
+ Permite que NOOP detecte una bajada reciente de la HRV mientras estás quieto y te ofrezca un minuto para respirar. Aquí \"estrés\" es un indicador autonómico a partir de tu propia línea base, nunca un diagnóstico. La pulsera da una vibración suave de confirmación; sin notificaciones push.
+ Manual
+ Ajuste manual
+ Frecuencia cardíaca máxima manual, automática
+ Frecuencia cardíaca máxima manual, %1$s bpm
+ Pasa todos tus datos de NOOP a otro teléfono. Exportar guarda todo (historial, sueño, entrenamientos, ajustes) en un único archivo que puedes copiar; Importar reemplaza los datos de este teléfono por una copia.
+ Noche
+ NOOP: todos tus datos, nada de nube.
+ NOOP se empareja directamente con tu WHOOP por Bluetooth: sin app de WHOOP, sin nube.
+ Sin calibrar
+ Opcional. Añade una foto para el avatar de arriba a la izquierda. Se guarda solo en este teléfono. NOOP funciona sin conexión, así que nunca se sube.
+ Señales de bienestar opcionales, en el dispositivo. Cada una está desactivada por defecto, se calcula solo en este teléfono a partir de datos que ya tienes y nunca es un diagnóstico médico.
+ Opcional. Usa tu propia foto detrás de cada pestaña, en lugar del cielo según el ciclo del día. Se guarda solo en este teléfono. Combínala con Tarjetas transparentes, arriba, para que se vea a través.
+ %1$s Vuelve a importarlo desde Fuentes de datos → Importación de WHOOP, en Android o Mac.
+ Volver a escanear
+ Recalculando tus noches recientes sobre la ventana de sueño profundo. La Carga se actualiza en cuanto termine.
+ Recalculando tus noches recientes sobre la ventana de toda la noche. La Carga se actualiza en cuanto termine.
+ Estima de forma aproximada la fase del ciclo menstrual a partir del cambio nocturno de la temperatura de la piel, solo en este dispositivo. Solo orientativo: no es un anticonceptivo, no predice la fertilidad y no es un servicio médico.
+ Recientes
+ Quitar imagen
+ Reemplazar desde Fotos
+ Cinta
+ Escala
+ Evalúa la curva de estrés hora a hora de hoy frente a TU propia línea base entre días (cómo suelen ser tus días, al estilo Oura) en lugar de frente a las horas tranquilas del propio día. El umbral se ha ajustado hasta ahora con una referencia de un solo sujeto, así que es una perspectiva alternativa, no la predeterminada. Solo FC; nunca se usa para la puntuación de recuperación ni de enfermedad. Desactivado por defecto.
+ Mostrar fondo personalizado
+ Muestra la tarjeta de Conciencia del ciclo en Hoy y en Salud. Desactívala para ocultarla por completo: una decisión privada, nunca basada en tu edad. Puedes volver a activarla aquí cuando quieras.
+ Guía discreta desde la pulsera durante los entrenamientos.
+ Gráfico de sueño
+ Calibración de pasos, %1$.1f pulsos del contador por paso
+ Estrés: línea base diurna personal
+ Estirar
+ Muestra la estimación nocturna de SpO₂ de tu pulsera en el recuadro Oxígeno en sangre cuando no hay un porcentaje calibrado: el byte candidato @82 de una WHOOP 5.0/MG, o la lectura propia de un anillo Oura con cada muestra limitada antes al 100% (si no, la lectura bruta del anillo sale alta). Es un valor calculado por la pulsera SIN VERIFICAR: el candidato de WHOOP coincidió de cerca con un dispositivo de referencia la mayoría de las noches, pero en algunas se movió en sentido contrario; el de Oura solo se ha comprobado en unas pocas noches hasta ahora. Se muestra como «estimación» y nunca se usa para la puntuación de recuperación ni de enfermedad. Desactivado por defecto.
+ Estos datos alimentan tus zonas de frecuencia cardíaca, las estimaciones de calorías y las líneas base de recuperación. Mantenlos al día.
+ Mosaico
+ Titanio
+ Tarjetas transparentes
+ Activa una prueba para lo que falla, ponte la pulsera y toca Informe. Aquí también están el registro de tu pulsera, la recalibración, la exportación programada y las sondas experimentales.
+ Cintura en centímetros
+ Cintura, %1$s pulgadas
+ Cintura, sin definir. Opcional: tu VO₂max es más preciso con ella
+ Vigila tu frecuencia cardíaca en reposo, la HRV y la temperatura de la piel en busca del patrón que a menudo aparece antes de que te encuentres mal, y te da un aviso suave. Una observación sobre tus propios números, no un diagnóstico.
+ Peso en kilogramos
+ Peso, %1$s libras
+ Cuando se detecta una bajada, muestra por sí sola la tarjeta de check-in (con límite de frecuencia y respetando las horas de silencio). Desactivado, queda en manual.
+ Cuando el Entrenador opcional esté configurado con tu propia clave, incluye también en su contexto un breve resumen de tus patrones más marcados calculados en el dispositivo y de los marcadores del Cuaderno de laboratorio. Solo un resumen; ningún dato bruto sale de tu teléfono. Requiere antes el consentimiento de datos del propio Entrenador.
+ Protocolo WHOOP 4.0
+ Protocolo WHOOP 5.0
+ Tus datos, tu pulsera y cómo funciona NOOP. Todo en este teléfono.
+ La zona %1$s empieza en %2$s bpm
+ Emparejada · inactiva
+ FC en vivo (emparejamiento incompleto)
+ Desconectada
+ Buscando tu WHOOP… asegúrate de que esté cargada, en tu muñeca y de que la app oficial de WHOOP no esté conectada a ella.
+ Tu pulsera está emparejada y enviando datos. Abre En vivo para ver la frecuencia cardíaca en tiempo real.
+ La frecuencia cardíaca en vivo se está transmitiendo, pero tu pulsera no está emparejada del todo. El emparejamiento cifrado es lo que transporta el movimiento, la temperatura de la piel, la SpO₂ y la frecuencia respiratoria; sin él, las fases del sueño se calculan solo con la frecuencia cardíaca. La vibración, las alarmas y la sincronización del historial también lo necesitan.
+ Conectada. Completando el protocolo de emparejamiento seguro…
+ Emparejada anteriormente, pero no conectada ahora. Vuelve a escanear para reconectar.
+ No hay ninguna pulsera conectada. Acerca tu WHOOP y toca Volver a escanear para emparejarla.
+ No binario
Máscara de notificación Oura ff (experimental)
Envía la máscara SetNotification de la aplicación oficial (1c 01 ff) en lugar del 3f de NOOP en la próxima conexión. El anillo agrupa ~10 paquetes por notificación para la aplicación oficial y uno para NOOP (descarga 9× más lenta); este es el primer interruptor candidato. Desactivado por defecto; la conexión siguiente a desactivarlo vuelve a 3f. Busca «-> notify_all(ff)» en el registro de la pulsera y compara los tamaños de notificación en la captura sin procesar.
Se empareja directamente con tu pulsera por Bluetooth: sin app de WHOOP, sin nube. La pulsera también puede anunciar su frecuencia cardíaca como un sensor Bluetooth estándar.
diff --git a/android/app/src/main/res/values-fr/strings.xml b/android/app/src/main/res/values-fr/strings.xml
index 6a25f6b4d2..14af1ac9c7 100644
--- a/android/app/src/main/res/values-fr/strings.xml
+++ b/android/app/src/main/res/values-fr/strings.xml
@@ -2830,6 +2830,102 @@
Chiffres des jauges
Gras
Plus douce
+ Un export en lecture seule des flux de capteurs décodés que NOOP stocke déjà. Fonctionne avec n\'importe quel bracelet. Rien n\'est écrit sur votre appareil, et rien n\'est envoyé.
+ Ajoute un journal d\'hydratation simple avec un objectif quotidien qui s\'adapte à votre effort. Touchez pour ajouter une gorgée, une tasse ou une bouteille et regardez un anneau de progression se remplir. Sur ce téléphone uniquement. Rien n\'est synchronisé.
+ Après une synchronisation, NOOP examine votre fréquence cardiaque récente à la recherche d\'une période élevée et soutenue qui ressemble à de l\'exercice, et propose de l\'enregistrer. Il ne fait que suggérer. Rien n\'est enregistré tant que vous n\'avez pas touché Enregistrer, et vous pouvez ignorer n\'importe quelle suggestion. Désactiver cette option arrête les suggestions futures ; les entraînements déjà présents dans votre historique sont conservés. Volontairement prudent : il peut donc manquer un entraînement de temps en temps. Sur ce téléphone uniquement.
+ Âge, %1$s ans
+ Une image expérimentale du rythme de vos battements, battement par battement : un nuage de points de Poincaré et de simples statistiques de régularité issues de périodes de repos calmes. Ce n\'est ni un ECG ni un diagnostic ; vous lirez un court avertissement et l\'accepterez avant l\'activation.
+ Auto · %1$s bpm (Tanaka)
+ Auto
+ Auto · confiance %1$s
+ Image de fond
+ Sauvegarde exportée. Copiez ce fichier sur votre nouveau téléphone et utilisez Importer pour tout restaurer.
+ Sauvegarde exportée. L\'archive de sauvegarde est trop volumineuse pour être restaurée en toute sécurité — la restauration vous demandera une confirmation.
+ Sauvegarde importée. Fermez complètement NOOP puis rouvrez-le pour qu\'elle prenne effet.
+ Problème de sauvegarde : %1$s
+ Oxygène sanguin : estimation du bracelet
+ Titane bleu
+ Parcourir les fichiers
+ Basé sur
+ Changer de photo
+ Ligne de base de la Charge réinitialisée. NOOP la réapprendra à partir de cette nuit. Votre historique est conservé, et il faut quelques nuits pour qu\'elle se stabilise.
+ La Charge est le score de préparation quotidien de NOOP, appris au fil du temps à partir de votre propre HRV, de votre fréquence cardiaque au repos et d\'autres données. Votre historique est conservé.
+ Choisir dans Photos
+ Choisissez l\'apparence de NOOP sur votre écran d\'accueil. Le lanceur peut mettre un moment à actualiser l\'icône après le changement.
+ Choisir une photo
+ Impossible d\'utiliser cette image. Essayez-en une autre.
+ Impossible d\'utiliser cette photo. Essayez-en une autre.
+ Problème d\'export CSV : %1$s
+ Sommeil profond
+ Affiche votre photo derrière chaque onglet, à la place du ciel du cycle journalier.
+ Écrivez-nous à %1$s
+ Sondes expérimentales, diagnostics, export des capteurs bruts et rapport Tendances. Rangés ici pour garder l\'écran du quotidien épuré.
+ Remplir
+ Ajuster
+ Laissez NOOP enregistrer chaque jour (vers 1 h) une sauvegarde datée dans un dossier en conservant les dernières - ainsi, si des données sont corrompues, restaurez la plus récente. Pointez le dossier vers Drive/Dropbox pour avoir des copies hors de l\'appareil. Désactivé tant que vous ne l\'activez pas.
+ Taille, %1$s pieds %2$s pouces
+ Taille en centimètres
+ Garde l\'écran allumé pendant que vous enregistrez un entraînement, pour que votre fréquence cardiaque en direct reste visible sans que le téléphone s\'assombrisse. S\'applique uniquement pendant un enregistrement. Le reste du temps, l\'écran se met en veille normalement. Laisser cette option activée consomme un peu plus de batterie, et votre écran déverrouillé reste visible pendant tout l\'entraînement : désactivez-la si cela vous gêne.
+ Laissez le fond transparaître à travers chaque carte. Réglez l\'intensité juste en dessous.
+ Permet à NOOP de repérer une baisse récente de la HRV pendant que vous êtes immobile et de vous proposer une minute pour respirer. Le « stress » est ici un indicateur du système nerveux autonome, dérivé de votre propre référence, jamais un diagnostic. Le bracelet émet une légère vibration de confirmation ; aucune notification push.
+ Manuel
+ Réglage manuel
+ Fréquence cardiaque max. manuelle, automatique
+ Fréquence cardiaque max. manuelle, %1$s bpm
+ Transférez toutes vos données NOOP vers un autre téléphone. L\'export enregistre tout (historique, nuits, entraînements, réglages) dans un seul fichier que vous pouvez copier ; l\'import remplace les données de ce téléphone par une sauvegarde.
+ Nuit
+ NOOP : toutes vos données, sans le cloud.
+ NOOP s\'associe directement à votre WHOOP via Bluetooth : pas d\'app WHOOP, pas de cloud.
+ Non calibré
+ Facultatif. Ajoutez une photo pour l\'avatar en haut à gauche. Stockée uniquement sur ce téléphone. NOOP fonctionne hors ligne : elle n\'est donc jamais envoyée.
+ Signaux de bien-être facultatifs, calculés sur l\'appareil. Chacun est désactivé par défaut, calculé uniquement sur ce téléphone à partir de données dont vous disposez déjà, et ne constitue jamais un diagnostic médical.
+ Facultatif. Utilisez votre propre photo derrière chaque onglet, à la place du ciel du cycle journalier. Stockée uniquement sur ce téléphone. Associez-la à « Cartes transparentes » ci-dessus pour qu\'elle apparaisse en transparence.
+ %1$s Réimportez ces données via Sources de données → Import WHOOP, sur Android ou Mac.
+ Nouveau scan
+ Nouveau calcul du score de vos dernières nuits sur la fenêtre de sommeil profond. La Charge se met à jour dès que c\'est terminé.
+ Nouveau calcul du score de vos dernières nuits sur la fenêtre de la nuit entière. La Charge se met à jour dès que c\'est terminé.
+ Déduit une phase approximative du cycle menstruel à partir de la variation nocturne de votre température cutanée, uniquement sur cet appareil. À titre indicatif seulement : ni contraception, ni prédiction de fertilité, ni service médical.
+ Récents
+ Supprimer l\'image
+ Remplacer depuis Photos
+ Ruban
+ Mise à l\'échelle
+ Évalue la chronologie heure par heure du stress d\'aujourd\'hui par rapport à VOTRE propre référence sur plusieurs jours (le déroulement habituel de vos journées, façon Oura) plutôt que par rapport aux heures calmes de la journée elle-même. Le seuil n\'a été réglé jusqu\'ici que sur une référence d\'un seul sujet ; c\'est donc un angle alternatif, pas le mode par défaut. FC uniquement ; jamais pris en compte dans le score de récupération ou de maladie. Désactivé par défaut.
+ Afficher le fond personnalisé
+ Affiche la carte Conscience du cycle dans Aujourd\'hui et dans Santé. Désactivez-la pour la masquer complètement — un choix privé, jamais basé sur votre âge. Vous pouvez la réactiver ici à tout moment.
+ Coaching discret par le bracelet pendant les entraînements : le silence d\'abord.
+ Graphique du sommeil
+ Calibration des pas, %1$.1f impulsions du compteur par pas
+ Stress : référence diurne personnelle
+ Étirer
+ Affiche l\'estimation nocturne de SpO₂ de votre bracelet dans la tuile Oxygène sanguin lorsqu\'aucun pourcentage calibré n\'est disponible : l\'octet candidat @82 d\'un WHOOP 5.0/MG, ou la mesure propre d\'une bague Oura, chaque échantillon étant d\'abord plafonné à 100 % (sinon la mesure brute de la bague est trop élevée). Il s\'agit d\'une valeur NON VÉRIFIÉE calculée par le bracelet — le candidat WHOOP a suivi de près un appareil de référence la plupart des nuits, mais a évolué en sens inverse certaines nuits ; la valeur Oura n\'a été vérifiée que sur quelques nuits jusqu\'ici. Affichée comme « estimation » et jamais prise en compte dans le score de récupération ou de maladie. Désactivé par défaut.
+ Ces données alimentent vos zones de fréquence cardiaque, vos estimations de calories et vos références de récupération. Veillez à ce qu\'elles soient exactes.
+ Mosaïque
+ Titane
+ Cartes transparentes
+ Activez un test pour ce qui ne va pas, portez le bracelet, puis touchez Signaler. Le journal du bracelet, la recalibration, l\'export programmé et les sondes expérimentales se trouvent aussi ici.
+ Tour de taille en centimètres
+ Tour de taille, %1$s pouces
+ Tour de taille, non renseigné. Facultatif : votre VO₂max est plus précis avec cette mesure
+ Surveille votre fréquence cardiaque au repos, votre HRV et votre température cutanée pour repérer le schéma qui apparaît souvent avant que vous ne vous sentiez malade, et vous prévient en douceur. Une observation de vos propres chiffres, pas un diagnostic.
+ Poids en kilogrammes
+ Poids, %1$s livres
+ Lorsqu\'une baisse est détectée, afficher d\'elle-même la carte de bilan (fréquence limitée, respecte les heures calmes). Désactivé, le bilan reste manuel.
+ Lorsque le Coach facultatif est configuré avec votre propre clé, inclure aussi dans son contexte un bref résumé de vos schémas les plus marqués, calculés sur l\'appareil, et de vos marqueurs du Carnet de laboratoire. Résumé uniquement ; aucune donnée brute ne quitte votre téléphone. Nécessite d\'abord le consentement aux données propre au Coach.
+ Protocole WHOOP 4.0
+ Protocole WHOOP 5.0
+ Vos chiffres, votre bracelet et le fonctionnement de NOOP. Tout reste sur ce téléphone.
+ La zone %1$s commence à %2$s bpm
+ Associé · inactif
+ FC en direct (association incomplète)
+ Déconnecté
+ Recherche de votre WHOOP… Assurez-vous qu\'il est chargé, porté au poignet, et que l\'app WHOOP officielle n\'y est pas connectée.
+ Votre bracelet est associé et envoie des données. Ouvrez En direct pour voir votre fréquence cardiaque en temps réel.
+ La fréquence cardiaque en direct est transmise, mais votre bracelet n\'est pas entièrement associé. C\'est l\'appairage chiffré qui transmet le mouvement, la température cutanée, la SpO₂ et la fréquence respiratoire — sans lui, les phases de sommeil sont déterminées à partir de la seule fréquence cardiaque. Les vibrations, les alarmes et la synchronisation de l\'historique en ont aussi besoin.
+ Connecté. Finalisation de l\'appairage sécurisé…
+ Déjà associé, mais pas connecté actuellement. Touchez Nouveau scan pour vous reconnecter.
+ Aucun bracelet connecté. Placez votre WHOOP à proximité et touchez Nouveau scan pour l\'associer.
+ Non binaire
Masque de notification Oura ff (expérimental)
Envoie le masque SetNotification de l’application officielle (1c 01 ff) au lieu du 3f de NOOP à la prochaine connexion. La bague regroupe ~10 paquets par notification pour l’application officielle et un seul pour NOOP (vidage 9× plus lent) ; c’est le premier commutateur candidat. Désactivé par défaut ; la connexion suivant la désactivation repasse en 3f. Surveillez « -> notify_all(ff) » dans le journal du bracelet et comparez la taille des notifications dans la capture brute.
S\'associe directement à votre bracelet par Bluetooth : pas d\'app WHOOP, pas de cloud. Le bracelet peut aussi annoncer sa fréquence cardiaque comme capteur Bluetooth standard.
diff --git a/android/app/src/main/res/values-it/strings.xml b/android/app/src/main/res/values-it/strings.xml
index 1d9aa4b617..9ef710065d 100644
--- a/android/app/src/main/res/values-it/strings.xml
+++ b/android/app/src/main/res/values-it/strings.xml
@@ -2799,6 +2799,102 @@
Numeri degli indicatori
Grassetto
Più tenue
+ Un\'esportazione in sola lettura dei flussi di sensori decodificati che NOOP già memorizza. Funziona con qualsiasi fascia. Nulla viene scritto sul dispositivo e nulla viene caricato.
+ Aggiunge un semplice registro dei liquidi con un obiettivo giornaliero che si adatta al tuo sforzo. Tocca per aggiungere un sorso, una tazza o una bottiglia e guarda riempirsi l\'anello di avanzamento. Solo su questo telefono. Nulla viene sincronizzato.
+ Dopo una sincronizzazione, NOOP esamina la tua frequenza cardiaca recente alla ricerca di un tratto prolungato ed elevato che sembri un allenamento, e ti propone di salvarlo. Si limita a suggerire: nulla viene salvato finché non tocchi Salva, e puoi ignorare qualsiasi suggerimento. Disattivandolo interrompi i suggerimenti futuri; gli allenamenti già nella cronologia restano. Volutamente prudente, quindi qualche allenamento può sfuggire. Solo su questo telefono.
+ Età, %1$s anni
+ Un quadro sperimentale della tua temporizzazione battito per battito: un grafico di Poincaré e semplici statistiche di regolarità da finestre di riposo tranquillo. Non è un ECG né una diagnosi; prima dell\'attivazione leggerai e accetterai una breve avvertenza.
+ Auto · %1$s bpm (Tanaka)
+ Auto
+ Auto · affidabilità %1$s
+ Immagine di sfondo
+ Backup esportato. Copia questo file sul nuovo telefono e usa Importa lì per ripristinare tutto.
+ Backup esportato. L\'archivio è troppo grande per un ripristino sicuro: ripristinarlo richiederà una conferma.
+ Backup importato. Chiudi completamente e riapri NOOP per applicarlo.
+ Problema con il backup: %1$s
+ Ossigeno nel sangue: stima della fascia
+ Titanio blu
+ Sfoglia file
+ Basato su
+ Cambia foto
+ Linea di base della Carica reimpostata. NOOP la riapprenderà da stanotte. La cronologia resta e servono alcune notti perché si stabilizzi.
+ La Carica è il punteggio di prontezza giornaliero di NOOP, appreso nel tempo dalla tua HRV, dalla frequenza cardiaca a riposo e da altro. La tua cronologia resta.
+ Scegli da Foto
+ Scegli come appare NOOP nella schermata Home. Il launcher potrebbe impiegare qualche istante ad aggiornare l\'icona dopo la modifica.
+ Scegli foto
+ Impossibile usare quell\'immagine. Provane un\'altra.
+ Impossibile usare quella foto. Provane un\'altra.
+ Problema con l\'esportazione CSV: %1$s
+ Sonno profondo
+ Mostra la tua foto dietro ogni scheda, al posto del cielo del ciclo giornaliero.
+ Scrivici a %1$s
+ Sonde sperimentali, diagnostica, esportazione dei dati grezzi dei sensori e il report Andamenti. Messi da parte per mantenere ordinata la schermata di tutti i giorni.
+ Riempi
+ Adatta
+ Fai salvare a NOOP ogni giorno (verso l\'1 di notte) un backup datato in una cartella, conservando gli ultimi: così, se i dati si danneggiano, ripristini il più recente. Punta la cartella su Drive/Dropbox per avere copie fuori dal dispositivo. Disattivato finché non lo attivi.
+ Altezza, %1$s piedi %2$s pollici
+ Altezza in centimetri
+ Mantiene lo schermo acceso mentre registri un allenamento, così la frequenza cardiaca in diretta resta visibile senza che il telefono si oscuri. Vale solo durante una registrazione: per il resto del tempo lo schermo si spegne normalmente. Lasciarlo attivo consuma un po\' più di batteria e significa che lo schermo sbloccato resta visibile per tutto l\'allenamento, quindi disattivalo se ti preoccupa.
+ Lascia trasparire lo sfondo da ogni scheda. Regola quanto qui sotto.
+ Permette a NOOP di notare un calo recente dell\'HRV mentre sei fermo e di proporti un minuto per respirare. Qui \"stress\" è un indicatore autonomico ricavato dalla tua linea di base, mai una diagnosi. La fascia dà una leggera vibrazione di conferma; nessuna notifica push.
+ Manuale
+ Impostazione manuale
+ Frequenza cardiaca massima manuale, automatica
+ Frequenza cardiaca massima manuale, %1$s bpm
+ Sposta tutti i tuoi dati NOOP su un altro telefono. Esporta salva tutto (cronologia, sonno, allenamenti, impostazioni) in un unico file da copiare; Importa sostituisce i dati di questo telefono con un backup.
+ Notte
+ NOOP: tutti i tuoi dati, niente cloud.
+ NOOP si abbina direttamente alla tua WHOOP via Bluetooth: niente app WHOOP, niente cloud.
+ Non calibrato
+ Facoltativo. Aggiungi una foto per l\'avatar in alto a sinistra. Salvata solo su questo telefono. NOOP è offline, quindi non viene mai caricata.
+ Segnali di benessere facoltativi, calcolati sul dispositivo. Ognuno è disattivato per impostazione predefinita, calcolato solo su questo telefono a partire dai dati che hai già e mai una diagnosi medica.
+ Facoltativo. Usa una tua foto dietro ogni scheda, al posto del cielo del ciclo giornaliero. Salvata solo su questo telefono. Abbinala alle Schede trasparenti qui sopra per lasciarla trasparire.
+ %1$s Reimportalo da Sorgenti dati → Importazione WHOOP, su Android o Mac.
+ Riscansiona
+ Ricalcolo delle notti recenti sulla finestra del sonno profondo. La Carica si aggiorna appena finito.
+ Ricalcolo delle notti recenti sulla finestra dell\'intera notte. La Carica si aggiorna appena finito.
+ Stima in modo approssimativo la fase del ciclo mestruale dalla variazione notturna della temperatura della pelle, solo su questo dispositivo. Solo consapevolezza: non è un contraccettivo, non prevede la fertilità, non è un servizio medico.
+ Recenti
+ Rimuovi immagine
+ Sostituisci da Foto
+ Nastro
+ Adattamento
+ Valuta l\'andamento ora per ora dello stress di oggi rispetto alla TUA linea di base tra più giorni (come vanno di solito le tue giornate, in stile Oura) invece che rispetto alle ore tranquille della giornata stessa. La soglia è tarata finora su un riferimento di un solo soggetto, quindi è una prospettiva alternativa, non quella predefinita. Solo FC; mai usato per il punteggio di recupero o di malattia. Disattivato per impostazione predefinita.
+ Mostra sfondo personalizzato
+ Mostra la scheda Consapevolezza del ciclo in Oggi e in Salute. Disattivala per nasconderla del tutto: una scelta privata, mai basata sulla tua età. Puoi riattivarla qui in qualsiasi momento.
+ Coaching discreto dalla fascia durante gli allenamenti.
+ Grafico del sonno
+ Calibrazione dei passi, %1$.1f impulsi del contatore per passo
+ Stress: linea di base diurna personale
+ Allunga
+ Mostra la stima notturna di SpO₂ della fascia nel riquadro Ossigeno nel sangue quando non è disponibile una percentuale calibrata: il byte candidato @82 di una WHOOP 5.0/MG, oppure la lettura di un anello Oura con ogni campione limitato prima al 100% (altrimenti la lettura grezza dell\'anello risulta alta). È un valore calcolato dalla fascia NON VERIFICATO: il candidato WHOOP ha seguito da vicino un dispositivo di riferimento nella maggior parte delle notti, ma in alcune si è mosso in senso opposto; quello Oura è stato verificato finora solo su poche notti. Mostrato come «stima» e mai usato per il punteggio di recupero o di malattia. Disattivato per impostazione predefinita.
+ Questi dati alimentano le zone di frequenza cardiaca, le stime delle calorie e le linee di base del recupero. Tienili aggiornati.
+ Affianca
+ Titanio
+ Schede trasparenti
+ Attiva un test per ciò che non funziona, indossa la fascia, poi tocca Segnala. Qui trovi anche il log della fascia, la ricalibrazione, l\'export pianificato e le sonde sperimentali.
+ Vita in centimetri
+ Vita, %1$s pollici
+ Vita, non impostata. Facoltativo: il tuo VO₂max è più preciso se la indichi
+ Tiene d\'occhio frequenza cardiaca a riposo, HRV e temperatura della pelle per individuare lo schema che spesso compare prima che tu ti senta male, e ti dà un avviso discreto. Un\'osservazione sui tuoi numeri, non una diagnosi.
+ Peso in chilogrammi
+ Peso, %1$s libbre
+ Quando viene rilevato un calo, mostra da sola la scheda di check-in (con limite di frequenza e rispettando le ore di silenzio). Se disattivato resta manuale.
+ Quando il Coach facoltativo è configurato con la tua chiave, includi nel suo contesto anche un breve riepilogo dei tuoi schemi più marcati calcolati sul dispositivo e dei marcatori del Quaderno di laboratorio. Solo un riepilogo: nessun dato grezzo lascia il telefono. Richiede prima il consenso ai dati del Coach.
+ Protocollo WHOOP 4.0
+ Protocollo WHOOP 5.0
+ I tuoi dati, la tua fascia e come funziona NOOP. Tutto su questo telefono.
+ La zona %1$s inizia a %2$s bpm
+ Abbinata · inattiva
+ FC in diretta (abbinamento incompleto)
+ Disconnessa
+ Ricerca della tua WHOOP… assicurati che sia carica, al polso e che l\'app ufficiale WHOOP non sia connessa.
+ La fascia è abbinata e sta inviando dati. Apri In diretta per la frequenza cardiaca in tempo reale.
+ La frequenza cardiaca in diretta arriva, ma la fascia non è completamente abbinata. È l\'abbinamento cifrato a trasportare movimento, temperatura della pelle, SpO₂ e frequenza respiratoria: senza di esso, il sonno viene suddiviso in fasi solo in base alla frequenza cardiaca. Ne hanno bisogno anche vibrazione, sveglie e sincronizzazione della cronologia.
+ Connessa. Completamento dell\'handshake di abbinamento sicuro…
+ Abbinata in precedenza ma al momento non connessa. Riscansiona per riconnetterla.
+ Nessuna fascia connessa. Avvicina la tua WHOOP e tocca Riscansiona per abbinarla.
+ Non binario
Maschera di notifica Oura ff (sperimentale)
Alla prossima connessione invia la maschera SetNotification dell’app ufficiale (1c 01 ff) invece del 3f di NOOP. L’anello impacchetta ~10 pacchetti per notifica per l’app ufficiale e uno solo per NOOP (scarico 9× più lento); questo è il primo interruttore candidato. Disattivato per impostazione predefinita; la connessione successiva alla disattivazione torna a 3f. Cerca “-> notify_all(ff)” nel registro della fascia e confronta le dimensioni delle notifiche nella cattura grezza.
Si abbina direttamente alla tua fascia tramite Bluetooth: niente app WHOOP, niente cloud. La fascia può anche trasmettere la frequenza cardiaca come un normale sensore Bluetooth.
diff --git a/android/app/src/main/res/values-pl/strings.xml b/android/app/src/main/res/values-pl/strings.xml
index 496c3dd829..47a427463e 100644
--- a/android/app/src/main/res/values-pl/strings.xml
+++ b/android/app/src/main/res/values-pl/strings.xml
@@ -2847,6 +2847,102 @@
Liczby na wskaźnikach
Pogrubione
Łagodniejsze
+ Eksport tylko do odczytu zdekodowanych strumieni z czujników, które NOOP już przechowuje. Działa z każdym paskiem. Nic nie jest zapisywane na Twoim urządzeniu ani nigdzie wysyłane.
+ Dodaje prosty dziennik płynów z dziennym celem dostosowanym do Twojego wysiłku. Stuknij, aby dodać łyk, kubek lub butelkę, i patrz, jak wypełnia się pierścień postępu. Tylko na tym telefonie. Nic nie jest synchronizowane.
+ Po synchronizacji NOOP przegląda Twoje ostatnie tętno w poszukiwaniu dłuższego, podwyższonego odcinka, który wygląda na trening, i proponuje jego zapisanie. To zawsze tylko sugestia. Nic nie zostanie zapisane, dopóki nie stukniesz Zapisz, a każdą sugestię możesz odrzucić. Wyłączenie tej opcji zatrzymuje przyszłe sugestie; treningi zapisane już w historii pozostają. Celowo ostrożne, więc pojedynczy trening może zostać pominięty. Tylko na tym telefonie.
+ Wiek w latach: %1$s
+ Eksperymentalny obraz Twojego rytmu uderzenie po uderzeniu: wykres Poincaré i proste statystyki regularności z okresów spokojnego odpoczynku. To nie ECG ani diagnoza; przed włączeniem przeczytasz i zaakceptujesz krótkie zastrzeżenie.
+ Auto · %1$s bpm (Tanaka)
+ Auto
+ Auto · pewność %1$s
+ Obraz tła
+ Kopia zapasowa wyeksportowana. Skopiuj ten plik na nowy telefon i użyj tam opcji Import, aby wszystko przywrócić.
+ Kopia zapasowa wyeksportowana. Archiwum jest zbyt duże, by przywrócić je bezpiecznie — przy przywracaniu zostaniesz poproszony o potwierdzenie.
+ Kopia zapasowa zaimportowana. Całkowicie zamknij i ponownie otwórz NOOP, aby zmiany zadziałały.
+ Problem z kopią zapasową: %1$s
+ Tlen we krwi: szacunek z paska
+ Niebieski tytan
+ Przeglądaj pliki
+ Zbudowane na
+ Zmień zdjęcie
+ Linia bazowa Energii zresetowana. NOOP nauczy się jej od nowa od dzisiejszej nocy. Twoja historia zostaje zachowana, a ustabilizowanie zajmie kilka nocy.
+ Energia to codzienny wskaźnik gotowości NOOP, uczący się z czasem na podstawie Twojego HRV, tętna spoczynkowego i innych danych. Twoja historia zostaje zachowana.
+ Wybierz ze Zdjęć
+ Wybierz, jak NOOP wygląda na ekranie głównym. Po zmianie launcher może potrzebować chwili na odświeżenie ikony.
+ Wybierz zdjęcie
+ Nie udało się użyć tego obrazu. Wybierz inny.
+ Nie udało się użyć tego zdjęcia. Wybierz inne.
+ Problem z eksportem CSV: %1$s
+ Sen głęboki
+ Wyświetla Twoje zdjęcie za każdą kartą zamiast nieba cyklu dnia.
+ Napisz do nas: %1$s
+ Eksperymentalne sondy, diagnostyka, eksport surowych danych z czujników i raport Trendy. Schowane tutaj, by codzienny ekran był przejrzysty.
+ Wypełnij
+ Dopasuj
+ NOOP codziennie (około 1:00) zapisuje datowaną kopię zapasową w folderze i przechowuje kilka ostatnich - więc jeśli dane kiedyś ulegną uszkodzeniu, przywróć najnowszą. Wskaż folder na Drive/Dropbox, aby mieć kopie poza urządzeniem. Wyłączone, dopóki tego nie włączysz.
+ Wzrost w stopach i calach: %1$s ft %2$s in
+ Wzrost w centymetrach
+ Utrzymuje ekran włączony podczas nagrywania treningu, aby tętno na żywo było widoczne bez przygaszania telefonu. Działa tylko w trakcie nagrywania. Przez resztę czasu ekran wygasa normalnie. Pozostawienie tej opcji włączonej zużywa nieco więcej baterii i oznacza, że odblokowany ekran jest widoczny przez cały trening, więc wyłącz ją, jeśli Ci to przeszkadza.
+ Tło prześwituje przez każdą kartę. Stopień przezroczystości ustawisz tuż poniżej.
+ Pozwala NOOP zauważyć świeży spadek HRV, gdy jesteś w bezruchu, i zaproponować minutę oddechu. „Stres” oznacza tu wskaźnik autonomiczny względem Twojej własnej linii bazowej, nigdy diagnozę. Pasek daje jedną lekką wibrację potwierdzającą; bez powiadomień push.
+ Ręcznie
+ Ustawienie ręczne
+ Ręczne tętno maksymalne: automatyczne
+ Ręczne tętno maksymalne: %1$s bpm
+ Przenieś wszystkie dane NOOP na inny telefon. Eksport zapisuje wszystko (historię, sen, treningi, ustawienia) w jednym pliku, który możesz skopiować; import zastępuje dane tego telefonu kopią zapasową.
+ Noc
+ NOOP: wszystkie Twoje dane, zero chmury.
+ NOOP łączy się z Twoim WHOOP bezpośrednio przez Bluetooth: bez aplikacji WHOOP, bez chmury.
+ Nieskalibrowany
+ Opcjonalne. Dodaj zdjęcie do awatara w lewym górnym rogu. Przechowywane tylko na tym telefonie. NOOP działa offline, więc nigdy nie jest wysyłane.
+ Opcjonalne sygnały samopoczucia obliczane na urządzeniu. Każdy jest domyślnie wyłączony, liczony wyłącznie na tym telefonie z danych, które już masz, i nigdy nie stanowi diagnozy medycznej.
+ Opcjonalne. Użyj własnego zdjęcia za każdą kartą zamiast nieba cyklu dnia. Przechowywane tylko na tym telefonie. Połącz je z opcją Przezroczyste karty powyżej, aby było widoczne przez karty.
+ %1$s Zaimportuj je ponownie przez Źródła danych → Import z WHOOP, na Androidzie lub Macu.
+ Skanuj ponownie
+ Ponowne przeliczanie ostatnich nocy według okna snu głębokiego. Energia zaktualizuje się, gdy tylko się zakończy.
+ Ponowne przeliczanie ostatnich nocy według okna całej nocy. Energia zaktualizuje się, gdy tylko się zakończy.
+ Określa przybliżoną fazę cyklu menstruacyjnego na podstawie nocnych zmian temperatury skóry, wyłącznie na tym urządzeniu. Tylko do obserwacji: to nie antykoncepcja, nie prognoza płodności i nie usługa medyczna.
+ Ostatnie
+ Usuń obraz
+ Zastąp ze Zdjęć
+ Wstęga
+ Skalowanie
+ Ocenia dzisiejszą godzinową oś stresu względem TWOJEJ własnej linii bazowej z wielu dni (jak zwykle przebiegają Twoje dni, w stylu Oura) zamiast względem spokojnych godzin danego dnia. Próg dostrojono dotąd na danych jednej osoby referencyjnej, więc to alternatywne spojrzenie, a nie ustawienie domyślne. Tylko na podstawie tętna; nigdy nie trafia do oceny regeneracji ani choroby. Domyślnie wyłączone.
+ Pokaż własne tło
+ Pokazuje kartę świadomości cyklu na ekranach Dzisiaj i Zdrowie. Wyłącz, aby całkowicie ją ukryć — to Twój prywatny wybór, nigdy nie zależy od Twojego wieku. Możesz ją tu ponownie włączyć w dowolnej chwili.
+ Dyskretne wskazówki z paska podczas treningów, z ciszą na pierwszym miejscu.
+ Wykres snu
+ Kalibracja kroków, impulsy licznika na krok: %1$.1f
+ Stres: osobista dzienna linia bazowa
+ Rozciągnij
+ Pokazuje nocny szacunek SpO₂ z Twojego paska w kafelku Tlen we krwi, gdy nie ma skalibrowanej wartości procentowej: bajt kandydujący @82 z WHOOP 5.0/MG albo własny odczyt pierścienia Oura, w którym każda próbka jest najpierw ograniczana do 100% (inaczej surowy odczyt pierścienia jest zawyżony). To NIEZWERYFIKOWANA wartość obliczana przez pasek — kandydat WHOOP w większość nocy ściśle zgadzał się z urządzeniem referencyjnym, ale w niektóre zmieniał się w przeciwnym kierunku; wartość z Oura sprawdzono dotąd tylko na kilku nocach. Wyświetlana jako „szacunek” i nigdy nie trafia do oceny regeneracji ani choroby. Domyślnie wyłączone.
+ Na tej podstawie wyliczane są Twoje strefy tętna, szacunki kalorii i linie bazowe regeneracji. Dbaj o ich dokładność.
+ Kafelki
+ Tytan
+ Przezroczyste karty
+ Włącz test dla tego, co nie działa, załóż pasek, a następnie stuknij Raport. Znajdziesz tu też dziennik paska, ponowną kalibrację, zaplanowany eksport i eksperymentalne sondy.
+ Obwód talii w centymetrach
+ Obwód talii w calach: %1$s
+ Obwód talii nieustawiony. Opcjonalnie: z nim Twój VO₂max jest dokładniejszy
+ Obserwuje Twoje tętno spoczynkowe, HRV i temperaturę skóry pod kątem wzorca, który często pojawia się, zanim poczujesz się źle, i daje delikatny sygnał. To obserwacja Twoich własnych danych, a nie diagnoza.
+ Waga w kilogramach
+ Waga w funtach: %1$s
+ Gdy wykryty zostanie spadek, samodzielnie wyświetl kartę check-in (z limitem częstotliwości i z uwzględnieniem godzin ciszy). Wyłączone pozostawia to ręcznie.
+ Gdy opcjonalny Trener jest skonfigurowany z Twoim własnym kluczem, dołącz do jego kontekstu także krótkie podsumowanie Twoich najsilniejszych wzorców z urządzenia i znaczników z Książki Laboratorium. Tylko podsumowanie; żadne surowe dane nie opuszczają telefonu. Najpierw wymagana jest osobna zgoda Trenera na dane.
+ Protokół WHOOP 4.0
+ Protokół WHOOP 5.0
+ Twoje dane, Twój pasek i sposób działania NOOP. Wszystko na tym telefonie.
+ Strefa %1$s zaczyna się od %2$s bpm
+ Sparowany · bezczynny
+ HR na żywo (nie w pełni sparowany)
+ Rozłączony
+ Szukam Twojego WHOOP… upewnij się, że jest naładowany, na nadgarstku i że oficjalna aplikacja WHOOP nie jest z nim połączona.
+ Twój pasek jest sparowany i przesyła dane. Otwórz Na żywo, aby zobaczyć tętno w czasie rzeczywistym.
+ Tętno na żywo jest przesyłane, ale Twój pasek nie jest w pełni sparowany. To szyfrowane parowanie przenosi ruch, temperaturę skóry, SpO₂ i częstość oddechów — bez niego fazy snu są wyznaczane tylko z tętna. Wibracje, alarmy i synchronizacja historii również go wymagają.
+ Połączono. Kończenie bezpiecznego parowania…
+ Wcześniej sparowany, ale obecnie niepołączony. Stuknij Skanuj ponownie, aby połączyć.
+ Brak połączonego paska. Umieść WHOOP w pobliżu i stuknij Skanuj ponownie, aby sparować.
+ Osoba niebinarna
Maska powiadomień Oura ff (eksperymentalne)
Przy następnym połączeniu wysyła maskę SetNotification oficjalnej aplikacji (1c 01 ff) zamiast 3f używanego przez NOOP. Pierścień pakuje ~10 pakietów w jedno powiadomienie dla oficjalnej aplikacji, a dla NOOP tylko jeden (9× wolniejsze zrzuty); to pierwszy kandydat na przełącznik. Domyślnie wyłączone; pierwsze połączenie po wyłączeniu wraca do 3f. Szukaj „-> notify_all(ff)” w dzienniku opaski i porównaj rozmiary powiadomień w surowym przechwyceniu.
Łączy się bezpośrednio z paskiem przez Bluetooth: bez aplikacji WHOOP i bez chmury. Pasek może też nadawać tętno jako standardowy czujnik Bluetooth.
diff --git a/android/app/src/main/res/values-pt-rPT/strings.xml b/android/app/src/main/res/values-pt-rPT/strings.xml
index 093bf2e7df..9e2df0b1fa 100644
--- a/android/app/src/main/res/values-pt-rPT/strings.xml
+++ b/android/app/src/main/res/values-pt-rPT/strings.xml
@@ -2823,6 +2823,102 @@
Números dos indicadores
Negrito
Mais suave
+ Uma exportação só de leitura dos fluxos de sensores descodificados que o NOOP já guarda. Funciona com qualquer bracelete. Nada é escrito no teu dispositivo e nada é enviado.
+ Adiciona um registo simples de líquidos com um objetivo diário que se ajusta ao teu esforço. Toca para adicionar um gole, um copo ou uma garrafa e vê um anel de progresso a encher. Apenas neste telemóvel. Nada é sincronizado.
+ Depois de uma sincronização, o NOOP analisa a tua frequência cardíaca recente à procura de um período elevado e prolongado que pareça exercício e propõe guardá-lo. É sempre apenas uma sugestão. Nada é guardado até tocares em Guardar, e podes dispensar qualquer sugestão. Desativar isto impede sugestões futuras; os treinos que já estão no teu histórico mantêm-se. Propositadamente conservador, por isso algum treino pode escapar. Apenas neste telemóvel.
+ Idade, %1$s anos
+ Uma imagem experimental do teu ritmo batimento a batimento: um gráfico de dispersão de Poincaré e estatísticas simples de regularidade a partir de períodos de repouso tranquilo. Não é um ECG nem um diagnóstico; vais ler e aceitar um breve aviso antes de ser ativado.
+ Auto · %1$s bpm (Tanaka)
+ Auto
+ Auto · confiança %1$s
+ Imagem de fundo
+ Cópia de segurança exportada. Copia este ficheiro para o teu novo telemóvel e usa Importar lá para restaurar tudo.
+ Cópia de segurança exportada. O arquivo é demasiado grande para ser restaurado em segurança — ao restaurá-lo, ser-te-á pedida confirmação.
+ Cópia de segurança importada. Fecha completamente e volta a abrir o NOOP para que tenha efeito.
+ Problema na cópia de segurança: %1$s
+ Oxigénio no sangue: estimativa da bracelete
+ Titânio azul
+ Procurar ficheiros
+ Criado com base em
+ Alterar fotografia
+ Linha de base da Carga reposta. O NOOP vai voltar a aprendê-la a partir desta noite. O teu histórico mantém-se e são precisas algumas noites para estabilizar.
+ A Carga é a pontuação diária de prontidão do NOOP, aprendida ao longo do tempo a partir da tua HRV, frequência cardíaca em repouso e mais. O teu histórico mantém-se.
+ Escolher de Fotos
+ Escolhe o aspeto do NOOP no teu ecrã principal. O launcher pode demorar um pouco a atualizar o ícone depois de o alterares.
+ Escolher fotografia
+ Não foi possível usar essa imagem. Experimenta outra.
+ Não foi possível usar essa fotografia. Experimenta outra.
+ Problema na exportação CSV: %1$s
+ Sono profundo
+ Mostra a tua fotografia por trás de cada separador, em vez do céu do ciclo diário.
+ Envia-nos um email para %1$s
+ Sondas experimentais, diagnósticos, exportação de dados em bruto dos sensores e o relatório de Tendências. Arrumados aqui para manter o ecrã do dia a dia simples.
+ Preencher
+ Ajustar
+ O NOOP guarda todos os dias (por volta da 1h) uma cópia de segurança datada numa pasta e mantém as últimas - assim, se os dados alguma vez se corromperem, restauras a mais recente. Aponta a pasta para o Drive/Dropbox para ter cópias fora do dispositivo. Desativado até o ativares.
+ Altura, %1$s pés e %2$s polegadas
+ Altura em centímetros
+ Mantém o ecrã ligado enquanto gravas um treino, para que a tua frequência cardíaca em direto continue visível sem o telemóvel escurecer. Só se aplica durante uma gravação. No resto do tempo o ecrã desliga-se normalmente. Deixar isto ativo gasta um pouco mais de bateria e significa que o teu ecrã desbloqueado fica visível durante todo o treino, por isso desativa-o se isso te preocupar.
+ Deixa o fundo ver-se através de todos os cartões. Ajusta a intensidade logo abaixo.
+ Permite que o NOOP detete uma queda recente de HRV enquanto estás parado e te ofereça um minuto para respirar. «Stress» é aqui um indicador autonómico baseado na tua própria linha de base, nunca um diagnóstico. A bracelete dá uma vibração leve de confirmação; sem notificação push.
+ Manual
+ Definição manual
+ Frequência cardíaca máxima manual, automática
+ Frequência cardíaca máxima manual, %1$s bpm
+ Passa todos os teus dados do NOOP para outro telemóvel. Exportar guarda tudo (histórico, sonos, treinos, definições) num único ficheiro que podes copiar; importar substitui os dados deste telemóvel por uma cópia de segurança.
+ Noite
+ NOOP: todos os teus dados, nada de nuvem.
+ O NOOP emparelha diretamente com a tua WHOOP por Bluetooth: sem app WHOOP, sem nuvem.
+ Não calibrado
+ Opcional. Adiciona uma fotografia para o avatar no canto superior esquerdo. Guardada apenas neste telemóvel. O NOOP funciona offline, por isso nunca é enviada.
+ Sinais de bem-estar opcionais, calculados no dispositivo. Todos estão desativados por predefinição, são calculados apenas neste telemóvel a partir de dados que já tens e nunca são um diagnóstico médico.
+ Opcional. Usa a tua própria fotografia por trás de cada separador, em vez do céu do ciclo diário. Guardada apenas neste telemóvel. Combina-a com Cartões transparentes acima para que fique visível.
+ %1$s Volta a importá-lo em Fontes de dados → Importação WHOOP, no Android ou no Mac.
+ Procurar de novo
+ A recalcular as tuas noites recentes com a janela de sono profundo. A Carga é atualizada assim que terminar.
+ A recalcular as tuas noites recentes com a janela da noite inteira. A Carga é atualizada assim que terminar.
+ Identifica uma fase aproximada do ciclo menstrual a partir da variação noturna da temperatura da pele, apenas neste dispositivo. Só para consciência: não é contraceção, não prevê a fertilidade e não é um serviço médico.
+ Recentes
+ Remover imagem
+ Substituir a partir de Fotos
+ Faixa
+ Dimensionamento
+ Avalia a linha temporal de stress de hoje, hora a hora, face à TUA própria linha de base entre dias (como os teus dias costumam decorrer, ao estilo Oura) em vez das horas calmas do próprio dia. O limiar foi afinado até agora com base num único sujeito de referência, por isso é uma perspetiva alternativa e não a predefinição. Apenas FC; nunca usado na pontuação de recuperação ou doença. Desativado por predefinição.
+ Mostrar fundo personalizado
+ Mostra o cartão de consciência do ciclo em Hoje e em Saúde. Desativa para o ocultar por completo — uma escolha privada, nunca baseada na tua idade. Podes voltar a ativá-lo aqui a qualquer momento.
+ Orientação discreta pela bracelete durante os treinos, com o silêncio em primeiro lugar.
+ Gráfico do sono
+ Calibração de passos, %1$.1f impulsos do contador por passo
+ Stress: linha de base diurna pessoal
+ Esticar
+ Mostra a estimativa noturna de SpO₂ da tua bracelete no mosaico Oxigénio no sangue quando não há uma percentagem calibrada disponível: o byte candidato @82 de uma WHOOP 5.0/MG, ou a leitura própria de um anel Oura com cada amostra limitada primeiro a 100% (caso contrário, a leitura em bruto do anel fica demasiado alta). É um valor NÃO VERIFICADO calculado pela bracelete — o candidato WHOOP coincidiu de perto com um dispositivo de referência na maioria das noites, mas moveu-se em sentido oposto em algumas; o da Oura só foi comparado com poucas noites até agora. Apresentado como «estimativa» e nunca usado na pontuação de recuperação ou doença. Desativado por predefinição.
+ Estes dados alimentam as tuas zonas de frequência cardíaca, estimativas de calorias e linhas de base de recuperação. Mantém-nos exatos.
+ Mosaico
+ Titânio
+ Cartões transparentes
+ Ativa um teste para aquilo que está a falhar, usa a bracelete e depois toca em Relatório. O registo da bracelete, a recalibração, a exportação agendada e as sondas experimentais também estão aqui.
+ Cintura em centímetros
+ Cintura, %1$s polegadas
+ Cintura não definida. Opcional: com ela, o teu VO₂max fica mais exato
+ Acompanha a tua frequência cardíaca em repouso, HRV e temperatura da pele à procura do padrão que costuma surgir antes de te sentires mal, e dá-te um aviso discreto. Uma observação sobre os teus próprios números, não um diagnóstico.
+ Peso em quilogramas
+ Peso, %1$s libras
+ Quando for detetada uma queda, mostra o cartão de check-in automaticamente (com limite de frequência e respeitando as horas de silêncio). Desativado, fica manual.
+ Quando o Treinador opcional estiver configurado com a tua própria chave, inclui também no seu contexto um breve resumo dos teus padrões mais fortes no dispositivo e dos marcadores do Caderno de laboratório. Apenas o resumo; nenhum dado em bruto sai do teu telemóvel. Requer primeiro o consentimento de dados do próprio Treinador.
+ Protocolo WHOOP 4.0
+ Protocolo WHOOP 5.0
+ Os teus números, a tua bracelete e como o NOOP funciona. Tudo neste telemóvel.
+ A zona %1$s começa em %2$s bpm
+ Emparelhada · inativa
+ FC em direto (emparelhamento incompleto)
+ Desligada
+ À procura da tua WHOOP… confirma que está carregada, no teu pulso e que a app oficial WHOOP não está ligada a ela.
+ A tua bracelete está emparelhada e a enviar dados. Abre Em direto para ver a frequência cardíaca em tempo real.
+ A frequência cardíaca em direto está a ser transmitida, mas a tua bracelete não está totalmente emparelhada. É o emparelhamento encriptado que transporta o movimento, a temperatura da pele, a SpO₂ e a frequência respiratória — sem ele, as fases do sono são calculadas apenas a partir da frequência cardíaca. A vibração, os alarmes e a sincronização do histórico também precisam dele.
+ Ligada. A concluir o emparelhamento seguro…
+ Emparelhada anteriormente, mas não ligada neste momento. Toca em Procurar de novo para voltar a ligar.
+ Nenhuma bracelete ligada. Coloca a tua WHOOP por perto e toca em Procurar de novo para emparelhar.
+ Não binário
Máscara de notificação Oura ff (experimental)
Envia a máscara SetNotification da aplicação oficial (1c 01 ff) em vez do 3f do NOOP na próxima ligação. O anel agrupa ~10 pacotes por notificação para a aplicação oficial e um para o NOOP (descarga 9× mais lenta); este é o primeiro candidato a interruptor. Desligado por predefinição; a ligação seguinte após desligar volta a 3f. Procure «-> notify_all(ff)» no registo da pulseira e compare os tamanhos das notificações na captura em bruto.
Emparelha diretamente com a tua bracelete via Bluetooth: sem aplicação WHOOP, sem cloud. A bracelete também pode anunciar a frequência cardíaca como um sensor Bluetooth padrão.
diff --git a/android/app/src/main/res/values-ru/strings.xml b/android/app/src/main/res/values-ru/strings.xml
index 3bfb53d968..d24b823ff9 100644
--- a/android/app/src/main/res/values-ru/strings.xml
+++ b/android/app/src/main/res/values-ru/strings.xml
@@ -2726,6 +2726,102 @@
Цифры на шкалах
Жирные
Мягче
+ Экспорт (только чтение) декодированных потоков датчиков, которые NOOP уже хранит. Работает с любым браслетом. На устройство ничего не записывается и ничего не загружается в сеть.
+ Добавляет простой журнал выпитой жидкости с дневной целью, которая подстраивается под ваше Усилие. Нажмите, чтобы добавить глоток, чашку или бутылку, и следите, как заполняется кольцо прогресса. Только на этом телефоне. Ничего не синхронизируется.
+ После синхронизации NOOP просматривает ваш недавний пульс в поисках продолжительного повышения, похожего на тренировку, и предлагает её сохранить. Это только предложение: ничего не сохраняется, пока вы не нажмёте «Сохранить», и любое предложение можно отклонить. Если выключить функцию, новые предложения перестанут появляться; тренировки, уже сохранённые в истории, останутся. Алгоритм намеренно осторожный, поэтому отдельные тренировки могут быть пропущены. Только на этом телефоне.
+ Возраст (лет): %1$s
+ Экспериментальная картина интервалов между ударами сердца: диаграмма Poincaré и простая статистика регулярности по спокойным периодам в покое. Это не ЭКГ и не диагноз; перед включением вы прочитаете короткое предупреждение и примете его.
+ Авто · %1$s уд/мин (Tanaka)
+ Авто
+ Авто · достоверность: %1$s
+ Фоновое изображение
+ Резервная копия экспортирована. Скопируйте этот файл на новый телефон и восстановите всё через «Импорт».
+ Резервная копия экспортирована. Архив слишком велик для безопасного восстановления — при восстановлении потребуется подтверждение.
+ Резервная копия импортирована. Полностью закройте и снова откройте NOOP, чтобы изменения вступили в силу.
+ Ошибка резервного копирования: %1$s
+ Кислород в крови: оценка браслета
+ Синий титан
+ Обзор файлов
+ Основано на
+ Сменить фото
+ Норма Заряда сброшена. NOOP заново определит её начиная с сегодняшней ночи. История сохраняется, а на стабилизацию уйдёт несколько ночей.
+ Заряд — ежедневный показатель готовности в NOOP, который со временем обучается на вашей ВСР, пульсе в покое и других данных. Ваша история сохраняется.
+ Выбрать из галереи
+ Выберите, как NOOP выглядит на главном экране. После смены лаунчеру может понадобиться немного времени, чтобы обновить значок.
+ Выбрать фото
+ Не удалось использовать это изображение. Выберите другое.
+ Не удалось использовать это фото. Выберите другое.
+ Ошибка экспорта CSV: %1$s
+ Глубокий сон
+ Показывать ваше фото фоном всех вкладок вместо неба суточного цикла.
+ Напишите нам: %1$s
+ Экспериментальные функции, диагностика, экспорт необработанных данных датчиков и отчёт по Трендам. Убраны сюда, чтобы не загромождать основной экран.
+ Заливка
+ Вписать
+ NOOP будет ежедневно (около 1:00) сохранять резервную копию с датой в папку и хранить несколько последних — если данные когда-нибудь повредятся, восстановите самую свежую. Укажите папку в Drive/Dropbox, чтобы копии хранились вне устройства. Выключено, пока вы не включите.
+ Рост — футы: %1$s, дюймы: %2$s
+ Рост в сантиметрах
+ Не даёт экрану погаснуть во время записи тренировки, чтобы пульс в реальном времени оставался виден. Действует только во время записи, в остальное время экран отключается как обычно. Включённая функция немного больше расходует батарею, а разблокированный экран остаётся открытым всю тренировку — выключите её, если это вас беспокоит.
+ Фон просвечивает сквозь все карточки. Степень настраивается чуть ниже.
+ Позволяет NOOP замечать свежее снижение ВСР, пока вы неподвижны, и предлагать минуту на дыхание. «Стресс» здесь — косвенный показатель вегетативной нервной системы относительно вашей собственной нормы, а не диагноз. Браслет подаёт одну лёгкую подтверждающую вибрацию; push-уведомлений нет.
+ Вручную
+ Задать вручную
+ Максимальный пульс: автоматически
+ Максимальный пульс вручную: %1$s уд/мин
+ Перенесите все данные NOOP на другой телефон. Экспорт сохраняет всё (историю, сон, тренировки, настройки) в один файл, который можно скопировать; импорт заменяет данные на этом телефоне данными из резервной копии.
+ Вся ночь
+ NOOP: все ваши данные, никакого облака.
+ NOOP напрямую сопрягается с вашим WHOOP по Bluetooth: без приложения WHOOP и без облака.
+ Не откалибровано
+ Необязательно. Добавьте фото для аватара в левом верхнем углу. Хранится только на этом телефоне. NOOP работает офлайн, поэтому фото никуда не загружается.
+ Необязательные сигналы самочувствия, рассчитываемые на устройстве. Каждый по умолчанию выключен, вычисляется только на этом телефоне из уже имеющихся данных и никогда не является медицинским диагнозом.
+ Необязательно. Поставьте своё фото фоном для всех вкладок вместо неба суточного цикла. Хранится только на этом телефоне. Включите «Прозрачные карточки» выше, чтобы фото просвечивало.
+ %1$s Импортируйте его заново через «Источники данных» → «Импорт WHOOP» на Android или Mac.
+ Повторный поиск
+ Пересчитываем ваши недавние ночи по окну глубокого сна. Заряд обновится сразу по завершении.
+ Пересчитываем ваши недавние ночи по окну всей ночи. Заряд обновится сразу по завершении.
+ Приблизительно определяет фазу менструального цикла по ночным изменениям температуры кожи, только на этом устройстве. Исключительно для осведомлённости: не контрацепция, не прогноз фертильности и не медицинская услуга.
+ Недавние
+ Удалить изображение
+ Заменить из галереи
+ Лента
+ Масштаб
+ Оценивает сегодняшний почасовой график стресса относительно ВАШЕЙ собственной нормы за несколько дней (как обычно проходят ваши дни, в стиле Oura), а не по спокойным часам текущего дня. Порог пока настроен по данным одного человека, поэтому это альтернативный взгляд, а не вариант по умолчанию. Только по пульсу; никогда не используется для расчёта восстановления или признаков болезни. По умолчанию выключено.
+ Показывать свой фон
+ Показывает карточку осведомлённости о цикле в разделах «Сегодня» и «Здоровье». Выключите, чтобы полностью её скрыть — это личный выбор, который никогда не зависит от вашего возраста. Включить снова можно здесь в любое время.
+ Ненавязчивые подсказки браслета во время тренировок.
+ График сна
+ Калибровка шагов: %1$.1f импульса счётчика на шаг
+ Стресс: личная дневная норма
+ Растянуть
+ Показывает ночную оценку SpO₂ от браслета на плитке «Кислород в крови», когда откалиброванный процент недоступен: байт-кандидат @82 для WHOOP 5.0/MG или собственное значение кольца Oura, где каждый замер предварительно ограничен 100% (иначе исходные данные кольца завышены). Это НЕПРОВЕРЕННОЕ значение, вычисленное браслетом: кандидат WHOOP в большинство ночей близко совпадал с эталонным устройством, но в некоторые менялся в противоположную сторону; значение Oura пока сверено лишь за несколько ночей. Отображается как «оценка» и никогда не используется для расчёта восстановления или признаков болезни. По умолчанию выключено.
+ На основе этих данных рассчитываются зоны пульса, расход калорий и нормы восстановления. Держите их актуальными.
+ Плитка
+ Титан
+ Прозрачные карточки
+ Включите тест для неполадки, наденьте браслет, затем нажмите «Отчёт». Здесь же журнал браслета, перекалибровка, экспорт по расписанию и экспериментальные функции.
+ Талия в сантиметрах
+ Талия (дюймы): %1$s
+ Талия не указана. Необязательно: с ней VO₂max точнее
+ Следит за пульсом в покое, ВСР и температурой кожи, выявляя картину, которая часто появляется ещё до того, как вы почувствуете недомогание, и мягко предупреждает. Это наблюдение за вашими собственными показателями, а не диагноз.
+ Вес в килограммах
+ Вес (фунты): %1$s
+ При обнаружении снижения показывать карточку отметки автоматически (с ограничением частоты и с учётом тихих часов). Если выключено — только вручную.
+ Если ИИ-тренер настроен с вашим собственным ключом, добавлять в его контекст краткую сводку самых выраженных закономерностей на устройстве и отметок из Лабораторного журнала. Только сводка; необработанные данные не покидают телефон. Сначала требуется отдельное согласие ИИ-тренера на обработку данных.
+ Протокол WHOOP 4.0
+ Протокол WHOOP 5.0
+ Ваши показатели, ваш браслет и то, как работает NOOP. Всё на этом телефоне.
+ Зона %1$s начинается с %2$s уд/мин
+ Сопряжено · ожидание
+ Пульс в реальном времени (сопряжение неполное)
+ Отключено
+ Ищем ваш WHOOP… Убедитесь, что он заряжен, надет на запястье и не подключён к официальному приложению WHOOP.
+ Браслет сопряжён и передаёт данные. Откройте «В реальном времени», чтобы видеть пульс сейчас.
+ Пульс в реальном времени передаётся, но браслет сопряжён не полностью. Именно зашифрованное сопряжение передаёт движение, температуру кожи, SpO₂ и частоту дыхания — без него стадии сна определяются только по пульсу. Оно также нужно для вибрации, будильников и синхронизации истории.
+ Подключено. Завершаем защищённое сопряжение…
+ Ранее сопряжён, но сейчас не подключён. Нажмите «Повторный поиск», чтобы переподключиться.
+ Браслет не подключён. Положите WHOOP рядом и нажмите «Повторный поиск» для сопряжения.
+ Небинарный
Маска уведомлений Oura ff (экспериментально)
При следующем подключении отправляет маску SetNotification официального приложения (1c 01 ff) вместо 3f, которую использует NOOP. Для официального приложения кольцо упаковывает ~10 пакетов в одно уведомление, для NOOP — только один (выгрузка в 9× медленнее); это первый кандидат на переключатель. По умолчанию выключено; первое подключение после выключения снова использует 3f. Ищите «-> notify_all(ff)» в журнале браслета и сравните размеры уведомлений в сырой записи.
Подключается к браслету напрямую по Bluetooth: без приложения WHOOP и без облака. Браслет также может передавать пульс как стандартный Bluetooth-датчик.
diff --git a/android/app/src/main/res/values-zh/strings.xml b/android/app/src/main/res/values-zh/strings.xml
index 34f2acd0e3..9243319dc6 100644
--- a/android/app/src/main/res/values-zh/strings.xml
+++ b/android/app/src/main/res/values-zh/strings.xml
@@ -2801,6 +2801,102 @@
仪表数字
粗体
更柔和
+ 以只读方式导出 NOOP 已存储的解码传感器数据流。适用于任何手环。不会向您的设备写入任何内容,也不会上传任何数据。
+ 添加一个简单的饮水记录,每日目标会根据您的负荷自动调整。轻点即可添加一小口、一杯或一瓶,看着进度环逐渐填满。仅保存在本机,不会同步。
+ 每次同步后,NOOP 会查看您最近的心率,寻找类似运动的持续升高时段,并建议您保存。它只会给出建议:在您点按“保存”之前不会保存任何内容,您也可以忽略任何建议。关闭此功能将不再产生新的建议;已在历史记录中的运动会保留。识别策略刻意保守,因此偶尔可能漏掉某次运动。仅在本机进行。
+ 年龄,%1$s 岁
+ 以实验方式呈现您的逐搏心跳间隔:基于安静静息时段的 Poincaré 散点图和简单的规律性统计。它不是 ECG,也不是诊断;开启前您需要阅读并接受一段简短的免责声明。
+ 自动 · %1$s bpm(Tanaka)
+ 自动
+ 自动 · 置信度 %1$s
+ 背景图片
+ 备份已导出。请将此文件复制到新手机,并在新手机上使用“导入”恢复全部数据。
+ 备份已导出。该备份文件过大,无法安全恢复——恢复时会请您确认。
+ 备份已导入。请完全关闭并重新打开 NOOP 以使其生效。
+ 备份出错:%1$s
+ 血氧饱和度:手环估算
+ 蓝色钛金属
+ 浏览文件
+ 构建基础
+ 更换照片
+ 充能基线已重置。NOOP 将从今晚开始重新学习。您的历史记录会保留,需要几个晚上才能趋于稳定。
+ 充能是 NOOP 的每日准备度评分,会随着时间从您自己的 HRV、静息心率等数据中学习。您的历史记录会保留。
+ 从相册选择
+ 选择 NOOP 在主屏幕上的外观。更改后,启动器可能需要片刻才能刷新图标。
+ 选择照片
+ 无法使用这张图片,请换一张。
+ 无法使用这张照片,请换一张。
+ CSV 导出出错:%1$s
+ 深睡
+ 在每个标签页背后显示您的照片,替代日夜交替的天空。
+ 发送邮件至 %1$s
+ 实验性探针、诊断信息、传感器原始数据导出以及趋势报告。收纳在这里,让日常界面保持整洁。
+ 填充
+ 适应
+ 让 NOOP 每天(凌晨 1 点左右)将带日期的备份保存到一个文件夹,并保留最近的若干份——万一数据损坏,可恢复最新的一份。将文件夹指向 Drive/Dropbox 即可在设备外保留副本。在您开启之前保持关闭。
+ 身高,%1$s 英尺 %2$s 英寸
+ 身高(厘米)
+ 在您记录运动期间保持屏幕常亮,让实时心率始终可见,不会因手机变暗而看不到。仅在记录期间生效,其余时间屏幕照常休眠。开启后会稍微多耗一点电,而且整个运动过程中解锁的屏幕都会保持可见;如有顾虑,请将其关闭。
+ 让背景透过每张卡片显示出来。透明程度可在下方调节。
+ 让 NOOP 在您静止时察觉到 HRV 的新近下降,并建议您花一分钟调整呼吸。这里的“压力”是基于您自身基线的自主神经代理指标,绝非诊断。手环会轻震一下作为确认;不会发送推送通知。
+ 手动
+ 手动设定
+ 最大心率设定,自动
+ 手动设定最大心率,%1$s bpm
+ 将您的全部 NOOP 数据迁移到另一部手机。导出会把所有内容(历史记录、睡眠、运动、设置)保存为一个可复制的文件;导入则会用备份替换本机的数据。
+ 整晚
+ NOOP:数据全归您,云端全不沾。
+ NOOP 通过 Bluetooth 直接与您的 WHOOP 配对:无需 WHOOP App,无需云端。
+ 未校准
+ 可选。为左上角的头像添加一张照片。仅保存在本机。NOOP 完全离线,照片绝不会被上传。
+ 可选的设备端身心状态信号。每项默认关闭,仅在本机根据您已有的数据计算,且绝非医学诊断。
+ 可选。用您自己的照片作为每个标签页的背景,替代日夜交替的天空。仅保存在本机。配合上方的“透明卡片”使用,照片才能透出来。
+ %1$s 请在 Android 或 Mac 上通过“数据源”→“WHOOP 导入”重新导入。
+ 重新扫描
+ 正在按深睡时段重新计算您最近几晚的数据。完成后充能会立即更新。
+ 正在按整晚时段重新计算您最近几晚的数据。完成后充能会立即更新。
+ 根据您夜间皮肤温度的变化,粗略判断月经周期所处阶段,仅在本设备上进行。仅供了解参考:不可用于避孕,不是生育力预测工具,也不是医疗服务。
+ 最近
+ 移除图片
+ 从相册替换
+ 条带
+ 缩放方式
+ 以您自己的跨日基线(即您平常的日子如何度过,类似 Oura 的方式)来评估今天的逐小时压力曲线,而不是以当天自身的平静时段为基准。目前的阈值仅基于单一受试者的参考数据调校,因此它只是另一种观察视角,而非默认方式。仅使用心率;绝不会用于恢复或患病评分。默认关闭。
+ 显示自定义背景
+ 在“今日”和“健康档案”中显示生理周期感知卡片。关闭即可完全隐藏——这是您的私人选择,绝不会根据您的年龄决定。您可以随时在这里重新开启。
+ 运动期间以安静为先的手环指导。
+ 睡眠图表
+ 步数校准,每步 %1$.1f 个计数
+ 压力:个人日间基线
+ 拉伸
+ 当没有经过校准的百分比数值时,在“血氧饱和度”卡片中显示手环的夜间 SpO₂ 估算值:WHOOP 5.0/MG 的 @82 候选字节,或 Oura 戒指自身的读数(每个样本会先被限制在 100% 以内,否则戒指的原始读数会偏高)。这是一个未经验证的手环计算值——WHOOP 候选值在大多数夜晚与参考设备非常接近,但在少数夜晚走势相反;Oura 的数值目前仅核对过几个夜晚。它会标注为“估算”,且绝不会用于恢复或患病评分。默认关闭。
+ 这些信息用于计算您的心率区间、卡路里估算和恢复基线。请保持准确。
+ 平铺
+ 钛金属
+ 透明卡片
+ 针对出问题的功能开启一项测试,佩戴手环,然后点按“报告”。手环日志、重新校准、定时导出和实验性探针也都在这里。
+ 腰围(厘米)
+ 腰围,%1$s 英寸
+ 腰围,未设置。可选:填写后 VO₂max 会更准确
+ 监测您的静息心率、HRV 和皮肤温度,留意那种常在您感到不适之前出现的变化规律,并给出温和的提醒。这只是对您自身数据的观察,而非诊断。
+ 体重(千克)
+ 体重,%1$s 磅
+ 检测到下降时,自动显示签到卡片(有频率限制,并遵守免打扰时段)。关闭则仅手动触发。
+ 当您已使用自己的密钥设置了可选的 AI 教练时,同时在其上下文中加入您最显著的设备端规律和实验室记录标记的简短摘要。仅限摘要;原始数据不会离开您的手机。需要先同意 AI 教练自身的数据授权。
+ WHOOP 4.0 协议
+ WHOOP 5.0 协议
+ 您的数据、您的手环,以及 NOOP 的工作方式。一切都在这部手机上。
+ 区间 %1$s 起点为 %2$s bpm
+ 已配对 · 空闲
+ 实时心率(尚未完全配对)
+ 已断开连接
+ 正在搜索您的 WHOOP… 请确保它已充电、戴在手腕上,并且没有连接到官方 WHOOP App。
+ 您的手环已配对并正在发送数据。打开“实时心率”查看实时心率。
+ 实时心率正在传输,但您的手环尚未完全配对。动作、皮肤温度、SpO₂ 和呼吸频率都依赖加密配对传输——没有它,睡眠分期只能仅凭心率判断。震动、闹钟和历史数据同步也都需要它。
+ 已连接。正在完成安全配对握手…
+ 之前已配对,但当前未连接。点按“重新扫描”以重新连接。
+ 未连接手环。请将 WHOOP 放在附近,然后点按“重新扫描”进行配对。
+ 非二元性别
Oura 通知掩码 ff(实验性)
下次连接时发送官方应用的 SetNotification 掩码(1c 01 ff),而不是 NOOP 的 3f。戒指为官方应用把约 10 个数据包打包进一条通知,为 NOOP 只发一个(读取慢 9 倍);这是第一个候选开关。默认关闭;关闭后的下一次连接恢复为 3f。请在腕带日志中查看“-> notify_all(ff)”,并在原始捕获中比较通知大小。
通过 Bluetooth 直接连接手环:无需 WHOOP 应用,也无需云端。手环还可以将心率作为标准 Bluetooth 传感器进行广播。
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index 0499f9d517..163c56d14a 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -2860,6 +2860,102 @@
Gauge numbers
Bold
Softer
+ A read-only export of the decoded sensor streams NOOP already stores. Works on any strap. Nothing is written to your device, and nothing is uploaded.
+ Adds a simple fluid log with a daily goal that adjusts to your effort. Tap to add a sip, cup or bottle and watch a progress ring fill. On this phone only. Nothing is synced.
+ After a sync, NOOP looks over your recent heart rate for a sustained, raised stretch that looks like exercise and offers to save it. It only ever suggests. Nothing is saved until you tap Save, and you can dismiss any suggestion. Turning this off stops future suggestions; workouts already in your history remain. Deliberately conservative, so the odd workout may be missed. On this phone only.
+ Age, %1$s years
+ An experimental picture of your beat-to-beat timing: a Poincaré scatter and plain regularity stats from quiet resting windows. Not an ECG and not a diagnosis; you\'ll read a short disclaimer and accept before it turns on.
+ Auto · %1$s bpm (Tanaka)
+ Auto
+ Auto · %1$s confidence
+ Background image
+ Backup exported. Copy this file to your new phone and use Import there to restore everything.
+ Backup exported. The backup archive is too large to restore safely — restoring it will ask you to confirm.
+ Backup imported. Fully close and reopen NOOP for it to take effect.
+ Backup problem: %1$s
+ Blood Oxygen: strap estimate
+ Blue Titanium
+ Browse files
+ Built on
+ Change photo
+ Charge baseline reset. NOOP will re-learn it from tonight. Your history stays, and it takes a few nights to settle.
+ Charge is NOOP\'s daily readiness score, learned from your own HRV, resting heart rate and more over time. Your history stays.
+ Choose from Photos
+ Choose how NOOP looks on your home screen. The launcher may take a moment to refresh the icon after you change it.
+ Choose photo
+ Couldn\'t use that image. Try another.
+ Couldn\'t use that photo. Try another.
+ CSV export problem: %1$s
+ Deep sleep
+ Draw your photo behind every tab, replacing the day-cycle sky.
+ Email us at %1$s
+ Experimental probes, diagnostics, raw-sensor export, and the Trends report. Tucked away to keep the everyday screen tidy.
+ Fill
+ Fit
+ Have NOOP save a dated backup to a folder every day (around 1am) and keep the last several - so if data ever corrupts, restore the newest. Point the folder at Drive/Dropbox for off-device copies. Off until you switch it on.
+ Height, %1$s feet %2$s inches
+ Height in centimetres
+ Holds the screen awake while you\'re recording a workout, so your live heart rate stays visible without the phone dimming. Only applies during a recording. The screen sleeps normally the rest of the time. Leaving it on does use a bit more battery, and means your unlocked screen stays visible for the whole workout, so flip it off if that\'s a concern.
+ Let the background show through every card. Tune how much just below.
+ Lets NOOP notice a fresh HRV dip while you\'re still and offer a minute to breathe. \"Stress\" here is an autonomic proxy from your own baseline, never a diagnosis. The strap gives one light confirming buzz; no push notification.
+ Manual
+ Manual override
+ Max heart rate override, automatic
+ Max heart rate override, %1$s bpm
+ Move all your NOOP data to another phone. Export saves everything (history, sleeps, workouts, settings) to a single file you can copy across; import replaces this phone\'s data with a backup.
+ Night
+ NOOP: all your data, none of the cloud.
+ NOOP pairs directly with your WHOOP over Bluetooth: no WHOOP app, no cloud.
+ Not calibrated
+ Optional. Add a photo for the avatar in the top-left. Stored only on this phone. NOOP is offline, so it\'s never uploaded.
+ Optional, on-device wellness signals. Each is off by default, computed only on this phone from data you already have, and never a medical diagnosis.
+ Optional. Use your own photo behind every tab, in place of the day-cycle sky. Stored only on this phone. Pair it with Transparent cards above to let it show through.
+ %1$s Re-import it via Data sources → WHOOP import, on Android or Mac.
+ Re-scan
+ Re-scoring your recent nights over the deep-sleep window. Charge updates as soon as it\'s done.
+ Re-scoring your recent nights over the whole-night window. Charge updates as soon as it\'s done.
+ Reads a coarse menstrual-cycle phase from your nightly skin-temperature shift, on this device only. Awareness only: not contraception, not a fertility predictor, not a medical service.
+ Recent
+ Remove image
+ Replace from Photos
+ Ribbon
+ Scaling
+ Scores today\'s hour-by-hour stress timeline against YOUR own cross-day baseline (how your days usually run, Oura-style) instead of the day\'s own calm hours. The cutoff is tuned from a single-subject reference so far, so it\'s an alternative lens, not the default. HR-only; never fed into recovery or illness scoring. Off by default.
+ Show custom background
+ Shows the cycle-awareness card on Today and in Health. Turn off to hide it entirely — a private choice, never based on your age. You can turn it back on here any time.
+ Silence-first strap coaching during workouts.
+ Sleep chart
+ Step calibration, %1$.1f counter ticks per step
+ Stress: personal daytime baseline
+ Stretch
+ Surfaces your strap\'s nightly SpO₂ estimate in the Blood Oxygen tile when no calibrated percentage is available: a WHOOP 5.0/MG\'s @82 candidate byte, or an Oura ring\'s own reading with each sample capped at 100% first (the ring\'s raw reading runs high otherwise). This is an UNVERIFIED strap-computed value — the WHOOP candidate matched a reference device closely on most nights but moved opposite on some; the Oura one has only been checked against a few nights so far. Shown as an \'estimate\' and never fed into recovery or illness scoring. Off by default.
+ These power your heart-rate zones, calorie estimates and recovery baselines. Keep them accurate.
+ Tile
+ Titanium
+ Transparent cards
+ Turn on a test for the thing that\'s wrong, wear the strap, then tap Report. Your strap log, recalibrate, scheduled export and experimental probes all live here too.
+ Waist in centimetres
+ Waist, %1$s inches
+ Waist, not set. Optional: your VO₂max is more accurate with it
+ Watches your resting heart rate, HRV and skin temperature for the pattern that often shows up before you feel unwell, and surfaces a gentle heads-up. An observation about your own numbers, not a diagnosis.
+ Weight in kilograms
+ Weight, %1$s pounds
+ When a dip is detected, surface the check-in card on its own (rate-limited, quiet-hours aware). Off keeps it manual.
+ When the opt-in Coach is set up with your own key, also include a short summary of your strongest on-device patterns and Lab Book markers in its context. Summary only; no raw data leaves your phone. Requires the Coach\'s own data consent first.
+ WHOOP 4.0 protocol
+ WHOOP 5.0 protocol
+ Your numbers, your strap, and how NOOP works. All on this phone.
+ Zone %1$s starts at %2$s bpm
+ Bonded · idle
+ Live HR (not fully paired)
+ Disconnected
+ Searching for your WHOOP… make sure it\'s charged, on your wrist, and the official WHOOP app isn\'t connected to it.
+ Your strap is paired and sending data. Open Live for a real-time heart rate.
+ Live heart rate is streaming, but your strap is not fully paired. The encrypted pairing is what carries motion, skin temperature, SpO₂ and respiratory rate — without it, sleep is staged from heart rate alone. Buzz, alarms and history sync need it too.
+ Connected. Finishing the secure pairing handshake…
+ Previously paired but not currently connected. Re-scan to reconnect.
+ No strap connected. Put your WHOOP nearby and tap Re-scan to pair.
+ Non-binary
Oura notification mask ff (experimental)
Sends the official app’s SetNotification mask (1c 01 ff) instead of NOOP’s 3f at the next connect. The ring packs ~10 packets per notification for the official app and one for NOOP (9× slower drains); this is the first candidate switch. Off by default; the next connect after turning it off is back on 3f. Watch the strap log for “-> notify_all(ff)” and compare notification sizes in the raw capture.
Pairs directly with your strap over Bluetooth: no WHOOP app, no cloud. The strap can also advertise its heart rate as a standard Bluetooth sensor.
diff --git a/android/app/src/test/java/com/noop/ui/StrapStatusDetailTest.kt b/android/app/src/test/java/com/noop/ui/StrapStatusDetailTest.kt
index 077b3d7c52..33848431e2 100644
--- a/android/app/src/test/java/com/noop/ui/StrapStatusDetailTest.kt
+++ b/android/app/src/test/java/com/noop/ui/StrapStatusDetailTest.kt
@@ -1,27 +1,78 @@
package com.noop.ui
+import com.noop.R
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Test
+import org.xmlpull.v1.XmlPullParser
+import java.io.File
/**
* Guards the Settings → Strap status detail copy, in particular that an in-flight scan takes
* precedence over bonded/connected so the user gets "Searching…" feedback the moment Re-scan is
* tapped (issue #1). The button's `enabled = !live.scanning` relies on the same scanning flag, so
* a regression here is the visible half of "Re-scan does nothing".
+ *
+ * The helpers return string resources (so the screen can be translated), and [uiString] cannot resolve
+ * them on the JVM. The wording checks therefore read the English source of each resource straight out of
+ * `values/strings.xml`: the copy under test is the same text a user on an English phone sees.
*/
class StrapStatusDetailTest {
+ private val english: Map by lazy {
+ val userDir = File(System.getProperty("user.dir") ?: ".")
+ // Gradle runs unit tests with the module dir (android/app) or the repo root as user.dir.
+ val file = listOf(
+ File(userDir, "src/main/res/values/strings.xml"),
+ File(userDir, "android/app/src/main/res/values/strings.xml"),
+ File(userDir, "app/src/main/res/values/strings.xml"),
+ ).firstOrNull { it.exists() }
+ assertNotNull(
+ "values/strings.xml not found from user.dir=$userDir; a skip here would read as a pass",
+ file,
+ )
+ val out = HashMap()
+ // kXML2 directly: android.jar's XmlPullParserFactory is a stub that throws on the JVM.
+ val parser = Class.forName("org.kxml2.io.KXmlParser")
+ .getDeclaredConstructor().newInstance() as XmlPullParser
+ file!!.inputStream().use { input ->
+ parser.setInput(input, "UTF-8")
+ var event = parser.eventType
+ while (event != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG && parser.name == "string") {
+ val name = parser.getAttributeValue(null, "name")
+ val value = parser.nextText().replace("\\'", "'")
+ if (name != null) out[name] = value
+ }
+ event = parser.next()
+ }
+ }
+ out
+ }
+
+ /** The English text behind a resource id: its name via the generated R class, then its value. */
+ private fun text(id: Int): String {
+ val name = R.string::class.java.fields.first { it.getInt(null) == id }.name
+ return checkNotNull(english[name]) { "no English value for $name" }
+ }
+
+ private fun detail(encryptedBond: Boolean, bonded: Boolean, connected: Boolean, scanning: Boolean) =
+ text(strapStatusDetailRes(encryptedBond, bonded, connected, scanning))
+
+ private fun title(encryptedBond: Boolean, bonded: Boolean, connected: Boolean) =
+ text(strapStatusTitleRes(encryptedBond, bonded, connected))
+
@Test
fun scanning_takesPrecedence_overEveryOtherState() {
// Even when already bonded + connected, an active scan must say "Searching…".
assertTrue(
- strapStatusDetail(encryptedBond = true, bonded = true, connected = true, scanning = true)
+ detail(encryptedBond = true, bonded = true, connected = true, scanning = true)
.startsWith("Searching for your WHOOP"),
)
assertTrue(
- strapStatusDetail(encryptedBond = false, bonded = false, connected = false, scanning = true)
+ detail(encryptedBond = false, bonded = false, connected = false, scanning = true)
.startsWith("Searching for your WHOOP"),
)
}
@@ -30,19 +81,19 @@ class StrapStatusDetailTest {
fun nonScanning_branches_areUnchanged() {
assertEquals(
"Your strap is paired and sending data. Open Live for a real-time heart rate.",
- strapStatusDetail(encryptedBond = true, bonded = true, connected = true, scanning = false),
+ detail(encryptedBond = true, bonded = true, connected = true, scanning = false),
)
assertEquals(
"Connected. Finishing the secure pairing handshake…",
- strapStatusDetail(encryptedBond = false, bonded = false, connected = true, scanning = false),
+ detail(encryptedBond = false, bonded = false, connected = true, scanning = false),
)
assertEquals(
"Previously paired but not currently connected. Re-scan to reconnect.",
- strapStatusDetail(encryptedBond = true, bonded = true, connected = false, scanning = false),
+ detail(encryptedBond = true, bonded = true, connected = false, scanning = false),
)
assertEquals(
"No strap connected. Put your WHOOP nearby and tap Re-scan to pair.",
- strapStatusDetail(encryptedBond = false, bonded = false, connected = false, scanning = false),
+ detail(encryptedBond = false, bonded = false, connected = false, scanning = false),
)
}
@@ -51,7 +102,7 @@ class StrapStatusDetailTest {
// #1635/#69: the 5/MG live-HR shortcut sets bonded without any encrypted pairing, and hello
// suppression makes that the permanent state. Telling the user their strap "is paired" there
// contradicts the Devices screen and the buzz/alarm rows on this same screen.
- val detail = strapStatusDetail(
+ val detail = detail(
encryptedBond = false, bonded = true, connected = true, scanning = false,
)
assertFalse(detail.contains("is paired"))
@@ -72,9 +123,9 @@ class StrapStatusDetailTest {
assertTrue(detail.contains("history sync"))
assertEquals("Live HR (not fully paired)",
- strapStatusTitle(encryptedBond = false, bonded = true, connected = true))
+ title(encryptedBond = false, bonded = true, connected = true))
assertEquals("Bonded · streaming",
- strapStatusTitle(encryptedBond = true, bonded = true, connected = true))
+ title(encryptedBond = true, bonded = true, connected = true))
}
@Test
From 38d9ffdf37cedb269332eaa8749263d9f3c6c3db Mon Sep 17 00:00:00 2001
From: paradix86 <2883806+paradix86@users.noreply.github.com>
Date: Sat, 26 Sep 2026 11:33:10 +0200
Subject: [PATCH 2/2] i18n(android): translate the max-HR auto caption instead
of echoing English
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The Tanaka caption was left as 'Auto · %1$s bpm (Tanaka)' in de, es, fr, it,
pl and pt-PT, which the i18n echo ratchet counts as untranslated. Spell the
word out in each locale, agreeing with the heart-rate noun it qualifies.
---
android/app/src/main/res/values-de/strings.xml | 2 +-
android/app/src/main/res/values-es/strings.xml | 2 +-
android/app/src/main/res/values-fr/strings.xml | 2 +-
android/app/src/main/res/values-it/strings.xml | 2 +-
android/app/src/main/res/values-pl/strings.xml | 2 +-
android/app/src/main/res/values-pt-rPT/strings.xml | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/android/app/src/main/res/values-de/strings.xml b/android/app/src/main/res/values-de/strings.xml
index 33e34b2430..7b73116b0e 100644
--- a/android/app/src/main/res/values-de/strings.xml
+++ b/android/app/src/main/res/values-de/strings.xml
@@ -2849,7 +2849,7 @@
Nach einem Sync prüft NOOP deine jüngste Herzfrequenz auf eine anhaltend erhöhte Phase, die nach Training aussieht, und bietet an, sie zu speichern. Es macht immer nur Vorschläge. Nichts wird gespeichert, bis du auf „Speichern“ tippst, und du kannst jeden Vorschlag verwerfen. Wenn du das ausschaltest, kommen keine neuen Vorschläge mehr; Workouts, die bereits in deinem Verlauf sind, bleiben erhalten. Bewusst zurückhaltend, daher kann gelegentlich ein Workout übersehen werden. Nur auf diesem Handy.
Alter, %1$s Jahre
Ein experimentelles Bild deines Herzschlag-Timings: ein Poincaré-Streudiagramm und einfache Regelmäßigkeitswerte aus ruhigen Ruhephasen. Kein ECG und keine Diagnose; du liest einen kurzen Hinweis und stimmst zu, bevor es aktiviert wird.
- Auto · %1$s bpm (Tanaka)
+ Automatisch · %1$s bpm (Tanaka)
Auto
Auto · Konfidenz %1$s
Hintergrundbild
diff --git a/android/app/src/main/res/values-es/strings.xml b/android/app/src/main/res/values-es/strings.xml
index 975c3c83f6..98dfe145e2 100644
--- a/android/app/src/main/res/values-es/strings.xml
+++ b/android/app/src/main/res/values-es/strings.xml
@@ -2836,7 +2836,7 @@
Tras una sincronización, NOOP revisa tu frecuencia cardíaca reciente en busca de un tramo elevado y sostenido que parezca ejercicio, y te ofrece guardarlo. Solo sugiere: no se guarda nada hasta que tocas Guardar, y puedes descartar cualquier sugerencia. Al desactivarlo se detienen las sugerencias futuras; los entrenamientos que ya están en tu historial se conservan. Es deliberadamente prudente, así que puede pasar por alto algún entrenamiento. Solo en este teléfono.
Edad, %1$s años
Una imagen experimental de la sincronía latido a latido: un diagrama de Poincaré y estadísticas sencillas de regularidad a partir de ventanas de reposo tranquilo. No es un ECG ni un diagnóstico; leerás y aceptarás un breve aviso antes de activarlo.
- Auto · %1$s bpm (Tanaka)
+ Automática · %1$s bpm (Tanaka)
Auto
Auto · confianza %1$s
Imagen de fondo
diff --git a/android/app/src/main/res/values-fr/strings.xml b/android/app/src/main/res/values-fr/strings.xml
index 14af1ac9c7..48d829883a 100644
--- a/android/app/src/main/res/values-fr/strings.xml
+++ b/android/app/src/main/res/values-fr/strings.xml
@@ -2835,7 +2835,7 @@
Après une synchronisation, NOOP examine votre fréquence cardiaque récente à la recherche d\'une période élevée et soutenue qui ressemble à de l\'exercice, et propose de l\'enregistrer. Il ne fait que suggérer. Rien n\'est enregistré tant que vous n\'avez pas touché Enregistrer, et vous pouvez ignorer n\'importe quelle suggestion. Désactiver cette option arrête les suggestions futures ; les entraînements déjà présents dans votre historique sont conservés. Volontairement prudent : il peut donc manquer un entraînement de temps en temps. Sur ce téléphone uniquement.
Âge, %1$s ans
Une image expérimentale du rythme de vos battements, battement par battement : un nuage de points de Poincaré et de simples statistiques de régularité issues de périodes de repos calmes. Ce n\'est ni un ECG ni un diagnostic ; vous lirez un court avertissement et l\'accepterez avant l\'activation.
- Auto · %1$s bpm (Tanaka)
+ Automatique · %1$s bpm (Tanaka)
Auto
Auto · confiance %1$s
Image de fond
diff --git a/android/app/src/main/res/values-it/strings.xml b/android/app/src/main/res/values-it/strings.xml
index 9ef710065d..4504e5dbf1 100644
--- a/android/app/src/main/res/values-it/strings.xml
+++ b/android/app/src/main/res/values-it/strings.xml
@@ -2804,7 +2804,7 @@
Dopo una sincronizzazione, NOOP esamina la tua frequenza cardiaca recente alla ricerca di un tratto prolungato ed elevato che sembri un allenamento, e ti propone di salvarlo. Si limita a suggerire: nulla viene salvato finché non tocchi Salva, e puoi ignorare qualsiasi suggerimento. Disattivandolo interrompi i suggerimenti futuri; gli allenamenti già nella cronologia restano. Volutamente prudente, quindi qualche allenamento può sfuggire. Solo su questo telefono.
Età, %1$s anni
Un quadro sperimentale della tua temporizzazione battito per battito: un grafico di Poincaré e semplici statistiche di regolarità da finestre di riposo tranquillo. Non è un ECG né una diagnosi; prima dell\'attivazione leggerai e accetterai una breve avvertenza.
- Auto · %1$s bpm (Tanaka)
+ Automatica · %1$s bpm (Tanaka)
Auto
Auto · affidabilità %1$s
Immagine di sfondo
diff --git a/android/app/src/main/res/values-pl/strings.xml b/android/app/src/main/res/values-pl/strings.xml
index 47a427463e..2edf91b3df 100644
--- a/android/app/src/main/res/values-pl/strings.xml
+++ b/android/app/src/main/res/values-pl/strings.xml
@@ -2852,7 +2852,7 @@
Po synchronizacji NOOP przegląda Twoje ostatnie tętno w poszukiwaniu dłuższego, podwyższonego odcinka, który wygląda na trening, i proponuje jego zapisanie. To zawsze tylko sugestia. Nic nie zostanie zapisane, dopóki nie stukniesz Zapisz, a każdą sugestię możesz odrzucić. Wyłączenie tej opcji zatrzymuje przyszłe sugestie; treningi zapisane już w historii pozostają. Celowo ostrożne, więc pojedynczy trening może zostać pominięty. Tylko na tym telefonie.
Wiek w latach: %1$s
Eksperymentalny obraz Twojego rytmu uderzenie po uderzeniu: wykres Poincaré i proste statystyki regularności z okresów spokojnego odpoczynku. To nie ECG ani diagnoza; przed włączeniem przeczytasz i zaakceptujesz krótkie zastrzeżenie.
- Auto · %1$s bpm (Tanaka)
+ Automatycznie · %1$s bpm (Tanaka)
Auto
Auto · pewność %1$s
Obraz tła
diff --git a/android/app/src/main/res/values-pt-rPT/strings.xml b/android/app/src/main/res/values-pt-rPT/strings.xml
index 9e2df0b1fa..64ab3de05d 100644
--- a/android/app/src/main/res/values-pt-rPT/strings.xml
+++ b/android/app/src/main/res/values-pt-rPT/strings.xml
@@ -2828,7 +2828,7 @@
Depois de uma sincronização, o NOOP analisa a tua frequência cardíaca recente à procura de um período elevado e prolongado que pareça exercício e propõe guardá-lo. É sempre apenas uma sugestão. Nada é guardado até tocares em Guardar, e podes dispensar qualquer sugestão. Desativar isto impede sugestões futuras; os treinos que já estão no teu histórico mantêm-se. Propositadamente conservador, por isso algum treino pode escapar. Apenas neste telemóvel.
Idade, %1$s anos
Uma imagem experimental do teu ritmo batimento a batimento: um gráfico de dispersão de Poincaré e estatísticas simples de regularidade a partir de períodos de repouso tranquilo. Não é um ECG nem um diagnóstico; vais ler e aceitar um breve aviso antes de ser ativado.
- Auto · %1$s bpm (Tanaka)
+ Automática · %1$s bpm (Tanaka)
Auto
Auto · confiança %1$s
Imagem de fundo