From 26f2a6d94ca912a131be9afe6ca3a4f9da2e2828 Mon Sep 17 00:00:00 2001 From: Marc G Fournier Date: Sat, 17 Feb 2024 02:05:54 -0800 Subject: [PATCH 01/44] Yet another attempt to sync default with Models --- .../defaults/freeaps/freeaps_settings.json | 22 +++++++++++-------- .../Resources/json/defaults/preferences.json | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/FreeAPS/Resources/json/defaults/freeaps/freeaps_settings.json b/FreeAPS/Resources/json/defaults/freeaps/freeaps_settings.json index fde30ed99b..44e42950f9 100644 --- a/FreeAPS/Resources/json/defaults/freeaps/freeaps_settings.json +++ b/FreeAPS/Resources/json/defaults/freeaps/freeaps_settings.json @@ -3,7 +3,6 @@ "closedLoop" : false, "allowAnnouncements" : false, "useAutotune" : false, - "onlyAutotuneBasals" : false, "isUploadEnabled" : false, "useLocalGlucoseSource" : false, "localGlucosePort" : 8080, @@ -25,7 +24,6 @@ "carbsRequiredThreshold" : 10, "animatedBackground" : false, "useFPUconversion" : true, - "tins": false, "individualAdjustmentFactor" : 0.5, "timeCap" : 8, "minuteInterval" : 30, @@ -42,11 +40,17 @@ "yGridLines" : true, "oneDimensionalGraph" : false, "rulerMarks" : false, - "maxCarbs": 1000, - "displayFatAndProteinOnWatch": false, - "confirmBolusFaster": false, - "overrideFactor": 0.8, - "useCalc": false, - "fattyMeals": false, - "fattyMealFactor": 0.7 + "maxCarbs" : 1000, + "displayFatAndProteinOnWatch" : false, + "confirmBolusFaster" : false, + "onlyAutotuneBasals" : false, + "overrideFactor" : 0.8, + "useCalc" : false, + "fattyMeals" : false, + "fattyMealFactor" : 0.7, + "displayPredictions" : true, + "useLiveActivity" : false, + "useTargetButton" : false, + "alwaysUseColors" : true, + "timeSettings" : true } diff --git a/FreeAPS/Resources/json/defaults/preferences.json b/FreeAPS/Resources/json/defaults/preferences.json index 6edb81100d..2eb4c5844c 100644 --- a/FreeAPS/Resources/json/defaults/preferences.json +++ b/FreeAPS/Resources/json/defaults/preferences.json @@ -19,8 +19,8 @@ "unsuspend_if_no_temp" : false, "min_5m_carbimpact" : 8, "autotune_isf_adjustmentFraction" : 1, - "remainingCarbsFraction" : 1, "remainingCarbsCap" : 90, + "remainingCarbsFraction" : 1, "enableUAM" : false, "A52_risk_enable" : false, "enableSMB_with_COB" : false, From 1a8330f7d5070687ffd2240d8f975750f254f4a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Thu, 22 Feb 2024 13:31:35 +0100 Subject: [PATCH 02/44] Profile Overrides in NS and on Watch app 1. Illustrates active and old overrides in Nightscout, using the Exercise eventType. Saves old overrides not uploaded (due to connectivity or other reason) for up to 48 hours, to upload these later when possible with next treatment push. 2. Watch Overrides. Activate and Cancel overrides from Watch app. 3. Adds back some old localized strings. 4. Deletes some unused CoreData entities. --- Config.xcconfig | 2 +- .../Core_Data.xcdatamodel/contents | 19 +- .../fi.lproj/Localizable.strings | 2 +- .../fr.lproj/Localizable.strings | 14 +- .../sk.lproj/Localizable.strings | 20 +- .../tr.lproj/Localizable.strings | 2 +- .../ar.lproj/Localizable.strings | 8 +- .../da.lproj/Localizable.strings | 5 +- .../en.lproj/Localizable.strings | 8 +- .../es.lproj/Localizable.strings | 8 +- .../fi.lproj/Localizable.strings | 8 +- .../fr.lproj/Localizable.strings | 8 +- .../he.lproj/Localizable.strings | 8 +- .../pl.lproj/Localizable.strings | 8 +- .../pt-BR.lproj/Localizable.strings | 8 +- .../pt-PT.lproj/Localizable.strings | 8 +- .../uk.lproj/Localizable.strings | 2 +- FreeAPS.xcodeproj/project.pbxproj | 10 +- .../Colors/Violet.colorset/Contents.json | 38 +++ .../Storage => Resources}/CarbsStorage.swift | 0 .../nightscout/not-uploaded-overrides.json | 1 + FreeAPS/Sources/APS/APSManager.swift | 40 ++- FreeAPS/Sources/APS/OpenAPS/Constants.swift | 1 + .../APS/Storage/AnnouncementsStorage.swift | 2 +- .../Sources/APS/Storage/CoreDataStorage.swift | 85 +---- .../Sources/APS/Storage/OverrideStorage.swift | 300 ++++++++++++++++-- .../Sources/Helpers/Color+Extensions.swift | 1 + .../Main/en.lproj/Localizable.strings | 3 + .../Main/sv.lproj/Localizable.strings | 2 +- FreeAPS/Sources/Models/FreeAPSSettings.swift | 5 + .../Sources/Models/NIghtscoutExercise.swift | 33 ++ FreeAPS/Sources/Models/PumpHistoryEvent.swift | 1 + .../View/AddTempTargetRootView.swift | 2 +- .../Sources/Modules/Home/HomeProvider.swift | 6 +- .../Sources/Modules/Home/HomeStateModel.swift | 32 +- .../Home/View/Chart/MainChartView.swift | 4 +- .../OverrideProfilesStateModel.swift | 43 ++- .../View/OverrideProfilesRootView.swift | 24 +- .../Modules/Settings/SettingsStateModel.swift | 8 + .../Settings/View/SettingsRootView.swift | 18 ++ .../View/WatchConfigRootView.swift | 4 + .../WatchConfig/WatchConfigStateModel.swift | 2 + .../Services/Network/NightscoutAPI.swift | 102 +++++- .../Services/Network/NightscoutManager.swift | 182 ++++++++++- .../Services/WatchManager/WatchManager.swift | 103 +++++- .../DataFlow.swift | 9 + .../Views/MainView.swift | 61 +++- .../Views/OverridesView.swift | 59 ++++ .../WatchStateModel.swift | 17 + 49 files changed, 1058 insertions(+), 278 deletions(-) create mode 100644 FreeAPS/Resources/Assets.xcassets/Colors/Violet.colorset/Contents.json rename FreeAPS/{Sources/APS/Storage => Resources}/CarbsStorage.swift (100%) create mode 100644 FreeAPS/Resources/json/defaults/nightscout/not-uploaded-overrides.json create mode 100644 FreeAPS/Sources/Models/NIghtscoutExercise.swift create mode 100644 FreeAPSWatch WatchKit Extension/Views/OverridesView.swift diff --git a/Config.xcconfig b/Config.xcconfig index 70f525f78b..22941888ed 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 3.0.2 +APP_VERSION = 3.1.3 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## diff --git a/Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents b/Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents index 716aaf395a..aadd8f0a83 100644 --- a/Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents +++ b/Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents @@ -1,16 +1,5 @@ - - - - - - - - - - - @@ -51,7 +40,6 @@ - @@ -76,9 +64,9 @@ - - - + + + @@ -151,7 +139,6 @@ - diff --git a/Dependencies/G7SensorKit/G7SensorKitUI/fi.lproj/Localizable.strings b/Dependencies/G7SensorKit/G7SensorKitUI/fi.lproj/Localizable.strings index 4c90a42664..7cd4649dfd 100644 --- a/Dependencies/G7SensorKit/G7SensorKitUI/fi.lproj/Localizable.strings +++ b/Dependencies/G7SensorKit/G7SensorKitUI/fi.lproj/Localizable.strings @@ -33,7 +33,7 @@ "Dexcom G7" = "Dexcom G7"; /* No comment provided by engineer. */ -"Done" = "Done"; +"Done" = "Valmis"; /* Field label */ "Glucose" = "Glucose"; diff --git a/Dependencies/G7SensorKit/G7SensorKitUI/fr.lproj/Localizable.strings b/Dependencies/G7SensorKit/G7SensorKitUI/fr.lproj/Localizable.strings index e02d131d69..40d1c0cccd 100644 --- a/Dependencies/G7SensorKit/G7SensorKitUI/fr.lproj/Localizable.strings +++ b/Dependencies/G7SensorKit/G7SensorKitUI/fr.lproj/Localizable.strings @@ -5,7 +5,7 @@ "%@/min" = "%@min"; /* No comment provided by engineer. */ -"Are you sure you want to delete this CGM?" = "Are you sure you want to delete this CGM?"; +"Are you sure you want to delete this CGM?" = "Voulez-vous vraiment supprimer ce CGM?"; /* No comment provided by engineer. */ "Bluetooth" = "Bluetooth"; @@ -45,19 +45,19 @@ "Grace period remaining" = "Période de grâce restante"; /* String displayed instead of a glucose value above the CGM range */ -"HIGH" = "HIGH"; +"HIGH" = "HAUT"; /* title for g7 settings row showing sensor last connect time */ "Last Connect" = "Dernière Connexion"; /* No comment provided by engineer. */ -"Last Reading" = "Last Reading"; +"Last Reading" = "Dernière lecture"; /* Descriptive text on G7StartupView */ "iAPS can read G7 CGM data, but you must still use the Dexcom G7 App for pairing, calibration, and other sensor management." = "iAPS peut lire les données G7 de la CGM mais vous devez toujours utiliser l'application Dexcom G7 pour associer, calibrer et gérer les capteurs."; /* String displayed instead of a glucose value below the CGM range */ -"LOW" = "LOW"; +"LOW" = "BAS"; /* title for g7 settings row showing BLE Name */ "Name" = "Nom"; @@ -90,7 +90,7 @@ "Sensor Expiration" = "Capteur expiré"; /* G7 Progress bar label when sensor expired */ -"Sensor expired" = "Sensor expired"; +"Sensor expired" = "Capteur expiré"; /* G7 Progress bar label when sensor lifetime progress showing */ "Sensor expires" = "Capteur expiré"; @@ -108,10 +108,10 @@ "Time" = "Heure"; /* Field label */ -"Trend" = "Trend"; +"Trend" = "Tendance"; /* title for g7 config settings to upload readings */ -"Upload Readings" = "Upload Readings"; +"Upload Readings" = "Envoyer les données"; /* G7 Progress bar label when sensor in warmup */ "Warmup completes" = "L'échauffement est terminé"; diff --git a/Dependencies/G7SensorKit/G7SensorKitUI/sk.lproj/Localizable.strings b/Dependencies/G7SensorKit/G7SensorKitUI/sk.lproj/Localizable.strings index fb10596224..4db4359d8e 100644 --- a/Dependencies/G7SensorKit/G7SensorKitUI/sk.lproj/Localizable.strings +++ b/Dependencies/G7SensorKit/G7SensorKitUI/sk.lproj/Localizable.strings @@ -11,7 +11,7 @@ "Bluetooth" = "Bluetooth"; /* Button text to cancel G7 setup */ -"Cancel" = "Cancel"; +"Cancel" = "Zrušiť"; /* No comment provided by engineer. */ "Configuration" = "Nastavenie"; @@ -33,10 +33,10 @@ "Dexcom G7" = "Dexcom G7"; /* No comment provided by engineer. */ -"Done" = "Done"; +"Done" = "Hotovo"; /* Field label */ -"Glucose" = "Glucose"; +"Glucose" = "Glykémia"; /* title for g7 settings row showing sensor grace period end time */ "Grace Period End" = "Dodatočná doba na výmenu senzoru končí"; @@ -48,7 +48,7 @@ "HIGH" = "VYSOKÉ"; /* title for g7 settings row showing sensor last connect time */ -"Last Connect" = "Last Connect"; +"Last Connect" = "Posledné spojenie"; /* No comment provided by engineer. */ "Last Reading" = "Posledná hodnota"; @@ -60,13 +60,7 @@ "LOW" = "NÍZKE"; /* title for g7 settings row showing BLE Name */ -"Name" = "Name"; - -/* No comment provided by engineer. */ -"Scan for new sensor" = "Načítať nový senzor"; - -/* No comment provided by engineer. */ -"Scan for new sensor" = "Načítať nový senzor"; +"Name" = "Názov"; /* No comment provided by engineer. */ "Scan for new sensor" = "Načítať nový senzor"; @@ -102,7 +96,7 @@ "Sensor expires" = "Senzor exspiruje"; /* G7 Progress bar label when sensor failed */ -"Sensor failed" = "Sensor failed"; +"Sensor failed" = "Senzor zlyhal"; /* title for g7 settings row showing sensor start time */ "Sensor Start" = "Senzor štartu"; @@ -111,7 +105,7 @@ "Signal\nLoss" = "Strata\nsignálu"; /* Field label */ -"Time" = "Time"; +"Time" = "Čas"; /* Field label */ "Trend" = "Vývoj"; diff --git a/Dependencies/G7SensorKit/G7SensorKitUI/tr.lproj/Localizable.strings b/Dependencies/G7SensorKit/G7SensorKitUI/tr.lproj/Localizable.strings index d25f3f78fa..74e2d7d3ab 100644 --- a/Dependencies/G7SensorKit/G7SensorKitUI/tr.lproj/Localizable.strings +++ b/Dependencies/G7SensorKit/G7SensorKitUI/tr.lproj/Localizable.strings @@ -5,7 +5,7 @@ "%@/min" = "%@/dak"; /* No comment provided by engineer. */ -"Are you sure you want to delete this CGM?" = "Are you sure you want to delete this CGM?"; +"Are you sure you want to delete this CGM?" = "Bu CGM'i silmek istediğinizden emin misiniz?"; /* No comment provided by engineer. */ "Bluetooth" = "Bluetooth"; diff --git a/Dependencies/OmniBLE/Localizations/ar.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/ar.lproj/Localizable.strings index 6b55134c44..0f30a43591 100644 --- a/Dependencies/OmniBLE/Localizations/ar.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/ar.lproj/Localizable.strings @@ -439,13 +439,7 @@ "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains." = "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains."; /* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; +"Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)." = "Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)."; /* Label text for step 1 of pair pod instructions */ "Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; diff --git a/Dependencies/OmniBLE/Localizations/da.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/da.lproj/Localizable.strings index 5317dc4e5f..3952235a6a 100644 --- a/Dependencies/OmniBLE/Localizations/da.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/da.lproj/Localizable.strings @@ -439,10 +439,7 @@ "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains." = "Skift Pod nu. Insulintilførsel stopper 8 timer efter, at Pod'en er udløbet, eller når der ikke er mere insulin tilbage."; /* Label text for step 1 of pair pod instructions */ -"Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)." = "Fyld et nyt bælg med U-100 Insulin (efterlad den blå nålehætte på)."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; +"Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)." = "Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)."; /* Label text for step 1 of pair pod instructions */ "Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; diff --git a/Dependencies/OmniBLE/Localizations/en.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/en.lproj/Localizable.strings index 22ff16086c..ecc6fc321d 100644 --- a/Dependencies/OmniBLE/Localizations/en.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/en.lproj/Localizable.strings @@ -441,13 +441,7 @@ "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains." = "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains."; /* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; +"Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)." = "Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)."; /* Label text for step 1 of pair pod instructions */ "Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; diff --git a/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings index bc71c1adfe..84ef29f74b 100644 --- a/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings @@ -439,13 +439,7 @@ "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains." = "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains."; /* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; +"Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)." = "Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)."; /* Label text for step 1 of pair pod instructions */ "Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; diff --git a/Dependencies/OmniBLE/Localizations/fi.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/fi.lproj/Localizable.strings index d01c77d760..dd72854034 100644 --- a/Dependencies/OmniBLE/Localizations/fi.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/fi.lproj/Localizable.strings @@ -439,13 +439,7 @@ "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains." = "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains."; /* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; +"Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)." = "Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)."; /* Label text for step 1 of pair pod instructions */ "Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; diff --git a/Dependencies/OmniBLE/Localizations/fr.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/fr.lproj/Localizable.strings index 88db58ba2b..25bd63b4fe 100644 --- a/Dependencies/OmniBLE/Localizations/fr.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/fr.lproj/Localizable.strings @@ -439,13 +439,7 @@ "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains." = "Changez de Pod maintenant. La fourniture d'insuline s'arrêtera 8 heures après l'expiration du Pod ou quand il n'y aura plus d'insuline."; /* Label text for step 1 of pair pod instructions */ -"Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)." = "Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; +"Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)." = "Remplissez une nouvelle cartouche avec de l'insuline U-100 (laissez le capuchon bleu sur le pod)."; /* Label text for step 1 of pair pod instructions */ "Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; diff --git a/Dependencies/OmniBLE/Localizations/he.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/he.lproj/Localizable.strings index 6b55134c44..0f30a43591 100644 --- a/Dependencies/OmniBLE/Localizations/he.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/he.lproj/Localizable.strings @@ -439,13 +439,7 @@ "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains." = "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains."; /* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; +"Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)." = "Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)."; /* Label text for step 1 of pair pod instructions */ "Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; diff --git a/Dependencies/OmniBLE/Localizations/pl.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/pl.lproj/Localizable.strings index 8d1ec77339..5e75acc908 100644 --- a/Dependencies/OmniBLE/Localizations/pl.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/pl.lproj/Localizable.strings @@ -439,13 +439,7 @@ "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains." = "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains."; /* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; +"Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)." = "Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)."; /* Label text for step 1 of pair pod instructions */ "Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; diff --git a/Dependencies/OmniBLE/Localizations/pt-BR.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/pt-BR.lproj/Localizable.strings index 9cf6f4bf97..56dea73cba 100644 --- a/Dependencies/OmniBLE/Localizations/pt-BR.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/pt-BR.lproj/Localizable.strings @@ -439,13 +439,7 @@ "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains." = "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains."; /* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; +"Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)." = "Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)."; /* Label text for step 1 of pair pod instructions */ "Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; diff --git a/Dependencies/OmniBLE/Localizations/pt-PT.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/pt-PT.lproj/Localizable.strings index ccc1346a92..9e8f1a98a3 100644 --- a/Dependencies/OmniBLE/Localizations/pt-PT.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/pt-PT.lproj/Localizable.strings @@ -439,13 +439,7 @@ "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains." = "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains."; /* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; - -/* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; +"Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)." = "Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)."; /* Label text for step 1 of pair pod instructions */ "Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; diff --git a/Dependencies/OmniBLE/Localizations/uk.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/uk.lproj/Localizable.strings index 59e5763079..a2cf90837b 100644 --- a/Dependencies/OmniBLE/Localizations/uk.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/uk.lproj/Localizable.strings @@ -582,7 +582,7 @@ /* Description text for critical alerts */ "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "Нагадування вище не звучатимуть, якщо ваш пристрій перебуває в беззвучному режимі або режимі «Не турбувати».\n\nІснують інші важливі сповіщення та будильники Podʼу, які лунатимуть, навіть якщо на пристрої встановлено режим «Без звуку» або «Не турбувати»."; /* navigation title for notification settings */ -"Notification Settings" = "Параметри сповіщень"; +"Notification Settings" = "Параметри Сповіщень"; /* Label for scheduled reminder value row */ "Time" = "Час"; diff --git a/FreeAPS.xcodeproj/project.pbxproj b/FreeAPS.xcodeproj/project.pbxproj index 4804340a1d..c46dd2246e 100644 --- a/FreeAPS.xcodeproj/project.pbxproj +++ b/FreeAPS.xcodeproj/project.pbxproj @@ -20,9 +20,11 @@ 190EBCCB29FF13CB00BA767D /* StatConfigRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 190EBCCA29FF13CB00BA767D /* StatConfigRootView.swift */; }; 191F62682AD6B05A004D7911 /* NightscoutSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191F62672AD6B05A004D7911 /* NightscoutSettings.swift */; }; 19229B962AFBB84800CD91CA /* Predictions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19229B952AFBB84800CD91CA /* Predictions.swift */; }; + 192424CB2B7A64E70063CBF0 /* NIghtscoutExercise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 192424CA2B7A64E70063CBF0 /* NIghtscoutExercise.swift */; }; 1927C8E62744606D00347C69 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1927C8E82744606D00347C69 /* InfoPlist.strings */; }; 1935364028496F7D001E0B16 /* Oref2_variables.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1935363F28496F7D001E0B16 /* Oref2_variables.swift */; }; 193F6CDD2A512C8F001240FD /* Loops.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193F6CDC2A512C8F001240FD /* Loops.swift */; }; + 194297512B815938006B8A0B /* OverridesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194297502B815938006B8A0B /* OverridesView.swift */; }; 1956FB212AFF79E200C7B4FF /* CoreDataStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1956FB202AFF79E200C7B4FF /* CoreDataStorage.swift */; }; 195D80B42AF6973A00D25097 /* DynamicRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B32AF6973A00D25097 /* DynamicRootView.swift */; }; 195D80B72AF697B800D25097 /* DynamicDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B62AF697B800D25097 /* DynamicDataFlow.swift */; }; @@ -543,6 +545,7 @@ 1918333A26ADA46800F45722 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = ""; }; 191F62672AD6B05A004D7911 /* NightscoutSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutSettings.swift; sourceTree = ""; }; 19229B952AFBB84800CD91CA /* Predictions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Predictions.swift; sourceTree = ""; }; + 192424CA2B7A64E70063CBF0 /* NIghtscoutExercise.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NIghtscoutExercise.swift; sourceTree = ""; }; 1927C8E92744611700347C69 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/InfoPlist.strings; sourceTree = ""; }; 1927C8EA2744611800347C69 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/InfoPlist.strings; sourceTree = ""; }; 1927C8EB2744611900347C69 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = ""; }; @@ -569,6 +572,7 @@ 193F1E3B2B44C14800525770 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/InfoPlist.strings; sourceTree = ""; }; 193F1E3C2B44C14800525770 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = ""; }; 193F6CDC2A512C8F001240FD /* Loops.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Loops.swift; sourceTree = ""; }; + 194297502B815938006B8A0B /* OverridesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverridesView.swift; sourceTree = ""; }; 1956FB202AFF79E200C7B4FF /* CoreDataStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataStorage.swift; sourceTree = ""; }; 195D80B32AF6973A00D25097 /* DynamicRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRootView.swift; sourceTree = ""; }; 195D80B62AF697B800D25097 /* DynamicDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicDataFlow.swift; sourceTree = ""; }; @@ -1477,6 +1481,7 @@ 3811DED425C9E1E300A708ED /* Resources */ = { isa = PBXGroup; children = ( + 38AEE75625F0F18E0013F05B /* CarbsStorage.swift */, 388E597125AD9CF10019842D /* json */, 388E596E25AD96040019842D /* javascript */, 3811DEC725C9DA7300A708ED /* FreeAPS.entitlements */, @@ -1732,6 +1737,7 @@ 193F6CDC2A512C8F001240FD /* Loops.swift */, CC6C406D2ACDD69E009B8058 /* RawFetchedProfile.swift */, 19B60B772B5E7E97002F4F74 /* Threshold.swift */, + 192424CA2B7A64E70063CBF0 /* NIghtscoutExercise.swift */, ); path = Models; sourceTree = ""; @@ -1772,7 +1778,6 @@ isa = PBXGroup; children = ( 385CEAC325F2F154002D6D5B /* AnnouncementsStorage.swift */, - 38AEE75625F0F18E0013F05B /* CarbsStorage.swift */, 38A0363A25ECF07E00FCBB52 /* GlucoseStorage.swift */, 38FCF3FC25E997A80078B0D1 /* PumpHistoryStorage.swift */, 38F3B2EE25ED8E2A005C48AA /* TempTargetsStorage.swift */, @@ -1904,6 +1909,7 @@ 38E8757A2757B1C300975559 /* TempTargetsView.swift */, 38E8757C2757C45D00975559 /* BolusView.swift */, 38E8757F27595DC500975559 /* BolusConfirmationView.swift */, + 194297502B815938006B8A0B /* OverridesView.swift */, ); path = Views; sourceTree = ""; @@ -2912,6 +2918,7 @@ E06B911A275B5EEA003C04B6 /* Array+Extension.swift in Sources */, 38EA0600262091870064E39B /* BolusProgressViewStyle.swift in Sources */, 19DC678329CA677D00FD9EC4 /* OverrideProfilesStateModel.swift in Sources */, + 192424CB2B7A64E70063CBF0 /* NIghtscoutExercise.swift in Sources */, 389ECDFE2601061500D86C4F /* View+Snapshot.swift in Sources */, 38FEF3FE2738083E00574A46 /* CGMProvider.swift in Sources */, 38E98A3725F5509500C0CED0 /* String+Extensions.swift in Sources */, @@ -3053,6 +3060,7 @@ files = ( 38E8757927579D9200975559 /* Publisher.swift in Sources */, 38E8755B27568A6800975559 /* ConfirmationView.swift in Sources */, + 194297512B815938006B8A0B /* OverridesView.swift in Sources */, 38E8757D2757C45D00975559 /* BolusView.swift in Sources */, 38E8752E27554D5700975559 /* NotificationController.swift in Sources */, 38E8754C2755548F00975559 /* WatchStateModel.swift in Sources */, diff --git a/FreeAPS/Resources/Assets.xcassets/Colors/Violet.colorset/Contents.json b/FreeAPS/Resources/Assets.xcassets/Colors/Violet.colorset/Contents.json new file mode 100644 index 0000000000..3d1aa91f0d --- /dev/null +++ b/FreeAPS/Resources/Assets.xcassets/Colors/Violet.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "extended-srgb", + "components" : { + "alpha" : "1.000", + "blue" : "86", + "green" : "55", + "red" : "95" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "extended-srgb", + "components" : { + "alpha" : "1.000", + "blue" : "86", + "green" : "55", + "red" : "95" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FreeAPS/Sources/APS/Storage/CarbsStorage.swift b/FreeAPS/Resources/CarbsStorage.swift similarity index 100% rename from FreeAPS/Sources/APS/Storage/CarbsStorage.swift rename to FreeAPS/Resources/CarbsStorage.swift diff --git a/FreeAPS/Resources/json/defaults/nightscout/not-uploaded-overrides.json b/FreeAPS/Resources/json/defaults/nightscout/not-uploaded-overrides.json new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/FreeAPS/Resources/json/defaults/nightscout/not-uploaded-overrides.json @@ -0,0 +1 @@ +[] diff --git a/FreeAPS/Sources/APS/APSManager.swift b/FreeAPS/Sources/APS/APSManager.swift index e863660b48..5a0e280d77 100644 --- a/FreeAPS/Sources/APS/APSManager.swift +++ b/FreeAPS/Sources/APS/APSManager.swift @@ -653,20 +653,40 @@ final class BaseAPSManager: APSManager, Injectable { ) case let .override(name): guard !name.isEmpty else { return } - if name.lowercased() == "cancel" { - OverrideStorage().cancelProfile() - announcementsStorage.storeAnnouncements([announcement], enacted: true) - debug(.apsManager, "Override Canceled by Announcement succeeded.") + let storage = OverrideStorage() + let lastActiveOveride = storage.fetchLatestOverride().first + let isActive = lastActiveOveride?.enabled ?? false + + // Command to Cancel Active Override + if name.lowercased() == "cancel", isActive { + if let activeOveride = lastActiveOveride { + let presetName = storage.isPresetName() + let nsString = presetName != nil ? presetName : activeOveride.percentage.formatted() + + if let duration = storage.cancelProfile() { + nightscout.editOverride(nsString!, duration, activeOveride.date ?? Date.now) + } + announcementsStorage.storeAnnouncements([announcement], enacted: true) + debug(.apsManager, "Override Canceled by Announcement succeeded.") + } return } - guard let override = CoreDataStorage().fetchProfile(name) else { return } - - // Cancel current active first (for the UI to update) - if CoreDataStorage().isActive() { - OverrideStorage().cancelProfile() + // Cancel eventual current active override first + if isActive { + if let duration = OverrideStorage().cancelProfile(), let last = lastActiveOveride { + let presetName = storage.isPresetName() + let nsString = presetName != nil ? presetName : last.percentage.formatted() + nightscout.editOverride(nsString!, duration, last.date ?? Date()) + } } - CoreDataStorage().activateOverride(override) + + // Activate the new override and uplad the new ovderride to NS. Some duplicate code now. Needs refactoring. + let preset = storage.fetchPreset(name) + guard let id = preset.id, let preset_ = preset.preset else { return } + storage.overrideFromPreset(preset_, id) + let currentActiveOveride = storage.fetchLatestOverride().first + nightscout.uploadOverride(name, Double(preset.preset?.duration ?? 0), currentActiveOveride?.date ?? Date.now) announcementsStorage.storeAnnouncements([announcement], enacted: true) debug(.apsManager, "Remote Override by Announcement succeeded.") } diff --git a/FreeAPS/Sources/APS/OpenAPS/Constants.swift b/FreeAPS/Sources/APS/OpenAPS/Constants.swift index 9aa815715b..b4df9ab0fe 100644 --- a/FreeAPS/Sources/APS/OpenAPS/Constants.swift +++ b/FreeAPS/Sources/APS/OpenAPS/Constants.swift @@ -88,6 +88,7 @@ extension OpenAPS { static let uploadedPreferences = "upload/uploaded-preferences.json" static let uploadedSettings = "upload/uploaded-settings.json" static let uploadedManualGlucose = "upload/uploaded-manual-readings.json" + static let notUploadedOverrides = "upload/not-uploaded-overrides.json" } enum FreeAPS { diff --git a/FreeAPS/Sources/APS/Storage/AnnouncementsStorage.swift b/FreeAPS/Sources/APS/Storage/AnnouncementsStorage.swift index 9db55b6f13..3cb982cf69 100644 --- a/FreeAPS/Sources/APS/Storage/AnnouncementsStorage.swift +++ b/FreeAPS/Sources/APS/Storage/AnnouncementsStorage.swift @@ -28,8 +28,8 @@ final class BaseAnnouncementsStorage: AnnouncementsStorage, Injectable { self.storage.transaction { storage in storage.append(announcements, to: file, uniqBy: \.createdAt) let uniqEvents = storage.retrieve(file, as: [Announcement].self)? - .filter { $0.createdAt.addingTimeInterval(1.days.timeInterval) > Date() } .sorted { $0.createdAt > $1.createdAt } ?? [] + .filter { $0.createdAt.addingTimeInterval(1.days.timeInterval) > Date() } storage.save(Array(uniqEvents), as: file) } } diff --git a/FreeAPS/Sources/APS/Storage/CoreDataStorage.swift b/FreeAPS/Sources/APS/Storage/CoreDataStorage.swift index 8a92cc41a2..8225eb856a 100644 --- a/FreeAPS/Sources/APS/Storage/CoreDataStorage.swift +++ b/FreeAPS/Sources/APS/Storage/CoreDataStorage.swift @@ -4,7 +4,7 @@ import SwiftDate import Swinject final class CoreDataStorage { - let coredataContext = CoreDataStack.shared.persistentContainer.viewContext // newBackgroundContext() + let coredataContext = CoreDataStack.shared.persistentContainer.viewContext func fetchGlucose(interval: NSDate) -> [Readings] { var fetchGlucose = [Readings]() @@ -19,87 +19,4 @@ final class CoreDataStorage { } return fetchGlucose } - - func fetchLatestOverride() -> [Override] { - var overrideArray = [Override]() - coredataContext.performAndWait { - let requestOverrides = Override.fetchRequest() as NSFetchRequest - let sortOverride = NSSortDescriptor(key: "date", ascending: false) - requestOverrides.sortDescriptors = [sortOverride] - requestOverrides.fetchLimit = 1 - try? overrideArray = self.coredataContext.fetch(requestOverrides) - } - return overrideArray - } - - func fetchProfile(_ name: String) -> Override? { - var presetsArray = [OverridePresets]() - var overrideArray = [Override]() - var override: Override? - coredataContext.performAndWait { - let requestPresets = OverridePresets.fetchRequest() as NSFetchRequest - requestPresets.predicate = NSPredicate( - format: "name == %@", name - ) - try? presetsArray = self.coredataContext.fetch(requestPresets) - - guard let preset = presetsArray.first else { - return - } - guard let id = preset.id else { - return - } - let requestOverrides = Override.fetchRequest() as NSFetchRequest - requestOverrides.predicate = NSPredicate( - format: "id == %@", id - ) - try? overrideArray = self.coredataContext.fetch(requestOverrides) - - guard let override_ = overrideArray.first else { - return - } - override = override_ - } - return override - } - - func activateOverride(_ override: Override) { - var overrideArray = [Override]() - coredataContext.performAndWait { - let save = Override(context: coredataContext) - save.date = Date.now - save.id = override.id - save.end = override.end - save.start = override.start - save.advancedSettings = override.advancedSettings - save.cr = override.cr - save.duration = override.duration - save.enabled = override.enabled - save.indefinite = override.indefinite - save.isPreset = override.isPreset - save.isf = override.isf - save.isfAndCr = override.isfAndCr - save.percentage = override.percentage - save.smbIsAlwaysOff = override.smbIsAlwaysOff - save.smbMinutes = override.smbMinutes - save.uamMinutes = override.uamMinutes - save.target = override.target - try? coredataContext.save() - } - } - - func isActive() -> Bool { - var overrideArray = [Override]() - coredataContext.performAndWait { - let requestOverrides = Override.fetchRequest() as NSFetchRequest - let sortOverride = NSSortDescriptor(key: "date", ascending: false) - requestOverrides.sortDescriptors = [sortOverride] - requestOverrides.fetchLimit = 1 - try? overrideArray = self.coredataContext.fetch(requestOverrides) - } - guard let lastOverride = overrideArray.first else { - return false - } - return lastOverride.enabled - } } diff --git a/FreeAPS/Sources/APS/Storage/OverrideStorage.swift b/FreeAPS/Sources/APS/Storage/OverrideStorage.swift index 672578e49e..9b2490a668 100644 --- a/FreeAPS/Sources/APS/Storage/OverrideStorage.swift +++ b/FreeAPS/Sources/APS/Storage/OverrideStorage.swift @@ -1,46 +1,32 @@ +import Combine import CoreData import Foundation import SwiftDate -import Swinject - -/* - protocol OverrideStorage { - func fetchOverrides(interval: NSDate) -> [Override] - func fetchLatestOverride() -> [Override] - } - */ -protocol OverrideObserver { - func overrideHistoryDidUpdate(_: [OverrideHistory]) -} final class OverrideStorage { - private let processQueue = DispatchQueue(label: "BaseOverrideStorage.processQueue") - - @Injected() private var broadcaster: Broadcaster! + let coredataContext = CoreDataStack.shared.persistentContainer.viewContext - let coredataContext = CoreDataStack.shared.persistentContainer.viewContext // newBackgroundContext() - - func fetchLatestOverride() -> [Override] { + func fetchOverrides(interval: NSDate) -> [Override] { var overrideArray = [Override]() coredataContext.performAndWait { let requestOverrides = Override.fetchRequest() as NSFetchRequest let sortOverride = NSSortDescriptor(key: "date", ascending: false) requestOverrides.sortDescriptors = [sortOverride] - requestOverrides.fetchLimit = 1 + requestOverrides.predicate = NSPredicate( + format: "date > %@", interval + ) try? overrideArray = self.coredataContext.fetch(requestOverrides) } return overrideArray } - func fetchOverrides(interval: NSDate) -> [Override] { + func fetchLatestOverride() -> [Override] { var overrideArray = [Override]() coredataContext.performAndWait { let requestOverrides = Override.fetchRequest() as NSFetchRequest let sortOverride = NSSortDescriptor(key: "date", ascending: false) requestOverrides.sortDescriptors = [sortOverride] - requestOverrides.predicate = NSPredicate( - format: "date > %@", interval - ) + requestOverrides.fetchLimit = 1 try? overrideArray = self.coredataContext.fetch(requestOverrides) } return overrideArray @@ -60,9 +46,10 @@ final class OverrideStorage { return overrideArray } - func cancelProfile() { + func cancelProfile() -> Double? { let scheduled = fetchLatestOverride().first - coredataContext.perform { [self] in + var duration: Double? + coredataContext.performAndWait { [self] in let profiles = Override(context: self.coredataContext) let history = OverrideHistory(context: self.coredataContext) if let latest = scheduled { @@ -70,10 +57,275 @@ final class OverrideStorage { print("History duration: \(history.duration) min") history.date = latest.date ?? Date() history.target = Double(latest.target ?? 100) + duration = history.duration } profiles.enabled = false profiles.date = Date() try? self.coredataContext.save() } + return duration + } + + func overrideFromPreset(_ preset: OverridePresets) { + coredataContext.performAndWait { + let save = Override(context: coredataContext) + save.date = Date.now + save.id = preset.id + save.end = preset.end + save.start = preset.start + save.advancedSettings = preset.advancedSettings + save.cr = preset.cr + save.duration = preset.duration + save.enabled = true + save.indefinite = preset.indefinite + save.isPreset = true + save.isf = preset.isf + save.isfAndCr = preset.isfAndCr + save.percentage = preset.percentage + save.smbIsAlwaysOff = preset.smbIsAlwaysOff + save.smbMinutes = preset.smbMinutes + save.uamMinutes = preset.uamMinutes + save.target = preset.target + try? coredataContext.save() + } + } + + func fetchProfile(_ name: String) -> Override? { + var presetsArray = [OverridePresets]() + var overrideArray = [Override]() + var override: Override? + coredataContext.performAndWait { + let requestPresets = OverridePresets.fetchRequest() as NSFetchRequest + requestPresets.predicate = NSPredicate( + format: "name == %@", name + ) + try? presetsArray = self.coredataContext.fetch(requestPresets) + + guard let preset = presetsArray.first else { + return + } + guard let id = preset.id else { + return + } + let requestOverrides = Override.fetchRequest() as NSFetchRequest + requestOverrides.predicate = NSPredicate( + format: "id == %@", id + ) + try? overrideArray = self.coredataContext.fetch(requestOverrides) + + guard let override_ = overrideArray.first else { + return + } + override = override_ + } + return override + } + + func fetchProfiles() -> OverridePresets? { + var presetsArray = [OverridePresets]() + coredataContext.performAndWait { + let requestPresets = OverridePresets.fetchRequest() as NSFetchRequest + requestPresets.predicate = NSPredicate( + format: "name != %@", "" as String + ) + try? presetsArray = self.coredataContext.fetch(requestPresets) + } + + guard let last = presetsArray.first else { + return nil + } + + guard (last.date ?? Date.now).addingTimeInterval(Int(last.duration ?? 0).minutes.timeInterval) > Date(), + (last.date ?? Date.now) <= Date.now, + last.duration != 0 + else { + return nil + } + return last + } + + func fetchProfiles() -> [OverridePresets] { + var presetsArray = [OverridePresets]() + coredataContext.performAndWait { + let requestPresets = OverridePresets.fetchRequest() as NSFetchRequest + requestPresets.predicate = NSPredicate( + format: "name != %@", "" as String + ) + try? presetsArray = self.coredataContext.fetch(requestPresets) + } + return presetsArray + } + + func activateOverride(_ override: Override) { + var overrideArray = [Override]() + coredataContext.performAndWait { + let save = Override(context: coredataContext) + save.date = Date.now + save.id = override.id + save.end = override.end + save.start = override.start + save.advancedSettings = override.advancedSettings + save.cr = override.cr + save.duration = override.duration + save.enabled = override.enabled + save.indefinite = override.indefinite + save.isPreset = override.isPreset + save.isf = override.isf + save.isfAndCr = override.isfAndCr + save.percentage = override.percentage + save.smbIsAlwaysOff = override.smbIsAlwaysOff + save.smbMinutes = override.smbMinutes + save.uamMinutes = override.uamMinutes + save.target = override.target + try? coredataContext.save() + } + } + + func isActive() -> Bool { + var overrideArray = [Override]() + coredataContext.performAndWait { + let requestOverrides = Override.fetchRequest() as NSFetchRequest + let sortOverride = NSSortDescriptor(key: "date", ascending: false) + requestOverrides.sortDescriptors = [sortOverride] + requestOverrides.fetchLimit = 1 + try? overrideArray = self.coredataContext.fetch(requestOverrides) + } + guard let lastOverride = overrideArray.first else { + return false + } + return lastOverride.enabled + } + + func isPresetName() -> String? { + var presetsArray = [OverridePresets]() + var overrideArray = [Override]() + var name: String? + coredataContext.performAndWait { + let requestOverrides = Override.fetchRequest() as NSFetchRequest + let sortOverride = NSSortDescriptor(key: "date", ascending: false) + requestOverrides.sortDescriptors = [sortOverride] + requestOverrides.fetchLimit = 1 + try? overrideArray = self.coredataContext.fetch(requestOverrides) + + if let or = overrideArray.first, let id = or.id { + let requestPresets = OverridePresets.fetchRequest() as NSFetchRequest + requestPresets.predicate = NSPredicate( + format: "id == %@", id + ) + try? presetsArray = self.coredataContext.fetch(requestPresets) + + guard let presets = presetsArray.first, let presetName = presets.name else { + return + } + name = presetName + } + } + return name + } + + func fetchPreset(_ name: String) -> (id: String?, preset: OverridePresets?) { + var presetsArray = [OverridePresets]() + var id: String? + var overridePreset: OverridePresets? + coredataContext.performAndWait { + let requestPresets = OverridePresets.fetchRequest() as NSFetchRequest + requestPresets.predicate = NSPredicate( + format: "name == %@", name + ) + try? presetsArray = self.coredataContext.fetch(requestPresets) + + guard let preset = presetsArray.first else { + return + } + guard let id_ = preset.id else { + return + } + id = id_ + overridePreset = preset + } + return (id, overridePreset) + } + + func overrideFromPreset(_ preset: OverridePresets, _ id: String) { + coredataContext.performAndWait { + coredataContext.performAndWait { + let save = Override(context: coredataContext) + save.date = Date.now + save.id = id + save.end = preset.end + save.start = preset.start + save.advancedSettings = preset.advancedSettings + save.cr = preset.cr + save.duration = preset.duration + save.enabled = true + save.indefinite = preset.indefinite + save.isPreset = true + save.isf = preset.isf + save.isfAndCr = preset.isfAndCr + save.percentage = preset.percentage + save.smbIsAlwaysOff = preset.smbIsAlwaysOff + save.smbMinutes = preset.smbMinutes + save.uamMinutes = preset.uamMinutes + save.target = preset.target + try? coredataContext.save() + } + } + } + + func addToNotUploaded(_ add: Int16) { + var currentCount = [NotUploaded]() + coredataContext.performAndWait { + let requestCount = NotUploaded.fetchRequest() as NSFetchRequest + let sortOverride = NSSortDescriptor(key: "date", ascending: false) + requestCount.sortDescriptors = [sortOverride] + requestCount.fetchLimit = 1 + try? currentCount = self.coredataContext.fetch(requestCount) + + var log: Int16 = currentCount.first?.number ?? 0 + + let save = NotUploaded(context: coredataContext) + if currentCount.first != nil, log != 0 { + save.number += add + save.date = Date.now + try? coredataContext.save() + log = save.number + } else if add > 0 { + save.number = add + save.date = Date.now + try? coredataContext.save() + log = save.number + } else if add < 0 { + if (currentCount.first?.number ?? 0) + add >= 0 { + save.number = add + save.date = Date.now + try? coredataContext.save() + log = save.number + } else { + save.number = 0 + save.date = Date.now + try? coredataContext.save() + log = save.number + } + } + debug(.service, "CoreData. addToNotUploaded Overides incremented. Current amount: \(log)") + } + } + + func countNotUploaded() -> Int? { + var currentCount = [NotUploaded]() + coredataContext.performAndWait { + let requestCount = NotUploaded.fetchRequest() as NSFetchRequest + let sortOverride = NSSortDescriptor(key: "date", ascending: false) + requestCount.predicate = NSPredicate( + format: "date > %@", Date().addingTimeInterval(-2.days.timeInterval) as NSDate + ) + requestCount.sortDescriptors = [sortOverride] + requestCount.fetchLimit = 1 + try? currentCount = self.coredataContext.fetch(requestCount) + } + if let latest = currentCount.first, latest.number > 0 { + return Int(latest.number) + } + return nil } } diff --git a/FreeAPS/Sources/Helpers/Color+Extensions.swift b/FreeAPS/Sources/Helpers/Color+Extensions.swift index 7b10fdda47..6bde81daa7 100644 --- a/FreeAPS/Sources/Helpers/Color+Extensions.swift +++ b/FreeAPS/Sources/Helpers/Color+Extensions.swift @@ -72,4 +72,5 @@ extension Color { static let homeBackground = Color("HomeBackground") static let popUpGray = Color("PopUpGray") static let darkChartBackground = Color("DarkChartBackground") + static let violet = Color("Violet") } diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index 5cb6d99ef8..0708de5254 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -314,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Enact"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manual Temp Basal"; diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index 9c87047a28..868e47317b 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -2163,7 +2163,7 @@ Enact a temp Basal or a temp target */ "Horizontal Scroll View Visible hours" = "Antal synliga timmar i hemfönstret"; /* UI/UX option */ -"Display Time Interval Setting Button" = "Visa knapp för tillfälligt målvärde"; +"Display Time Interval Setting Button" = "Visa knapp för tidsintervell"; /* Setting title */ "Bolus Calculator" = "Boluskalkylator"; diff --git a/FreeAPS/Sources/Models/FreeAPSSettings.swift b/FreeAPS/Sources/Models/FreeAPSSettings.swift index 5a2d3f9cc7..72cda22c0c 100644 --- a/FreeAPS/Sources/Models/FreeAPSSettings.swift +++ b/FreeAPS/Sources/Models/FreeAPSSettings.swift @@ -55,6 +55,7 @@ struct FreeAPSSettings: JSON, Equatable { var useTargetButton: Bool = false var alwaysUseColors: Bool = true var timeSettings: Bool = true + var profilesOrTempTargets: Bool = false } extension FreeAPSSettings: Decodable { @@ -284,6 +285,10 @@ extension FreeAPSSettings: Decodable { settings.timeSettings = timeSettings } + if let profilesOrTempTargets = try? container.decode(Bool.self, forKey: .profilesOrTempTargets) { + settings.profilesOrTempTargets = profilesOrTempTargets + } + self = settings } } diff --git a/FreeAPS/Sources/Models/NIghtscoutExercise.swift b/FreeAPS/Sources/Models/NIghtscoutExercise.swift new file mode 100644 index 0000000000..d4ecd21d08 --- /dev/null +++ b/FreeAPS/Sources/Models/NIghtscoutExercise.swift @@ -0,0 +1,33 @@ +import Foundation + +struct NigtscoutExercise: JSON, Hashable, Equatable { + var duration: Int? + var eventType: EventType + var createdAt: Date + var enteredBy: String? + var notes: String? + // var mills: Int + + static let local = "iAPS" + + static let empty = NigtscoutExercise(from: "{}")! + + static func == (lhs: NigtscoutExercise, rhs: NigtscoutExercise) -> Bool { + (lhs.createdAt) == rhs.createdAt + } + + func hash(into hasher: inout Hasher) { + hasher.combine(createdAt) + } +} + +extension NigtscoutExercise { + private enum CodingKeys: String, CodingKey { + case duration + case eventType + case createdAt = "created_at" + case enteredBy + case notes + // case mills + } +} diff --git a/FreeAPS/Sources/Models/PumpHistoryEvent.swift b/FreeAPS/Sources/Models/PumpHistoryEvent.swift index 320f6de833..f9c4cc6a4a 100644 --- a/FreeAPS/Sources/Models/PumpHistoryEvent.swift +++ b/FreeAPS/Sources/Models/PumpHistoryEvent.swift @@ -70,6 +70,7 @@ enum EventType: String, JSON { case nsAnnouncement = "Announcement" case nsSensorChange = "Sensor Start" case capillaryGlucose = "BG Check" + case nsExercise = "Exercise" } enum TempType: String, JSON { diff --git a/FreeAPS/Sources/Modules/AddTempTarget/View/AddTempTargetRootView.swift b/FreeAPS/Sources/Modules/AddTempTarget/View/AddTempTargetRootView.swift index fd7323bf26..89e0660c5e 100644 --- a/FreeAPS/Sources/Modules/AddTempTarget/View/AddTempTargetRootView.swift +++ b/FreeAPS/Sources/Modules/AddTempTarget/View/AddTempTargetRootView.swift @@ -116,7 +116,7 @@ extension AddTempTarget { Section { Button { state.enact() } - label: { Text("Enact") } + label: { Text("Start") } Button { state.cancel() } label: { Text("Cancel Temp Target") } } diff --git a/FreeAPS/Sources/Modules/Home/HomeProvider.swift b/FreeAPS/Sources/Modules/Home/HomeProvider.swift index 8ab9f613d2..56a158d9b0 100644 --- a/FreeAPS/Sources/Modules/Home/HomeProvider.swift +++ b/FreeAPS/Sources/Modules/Home/HomeProvider.swift @@ -15,12 +15,14 @@ extension Home { storage.retrieve(OpenAPS.Enact.suggested, as: Suggestion.self) } + let overrideStorage = OverrideStorage() + func overrides() -> [Override] { - OverrideStorage().fetchOverrides(interval: DateFilter().day) + overrideStorage.fetchOverrides(interval: DateFilter().day) } func overrideHistory() -> [OverrideHistory] { - OverrideStorage().fetchOverrideHistory(interval: DateFilter().day) + overrideStorage.fetchOverrideHistory(interval: DateFilter().day) } var enactedSuggestion: Suggestion? { diff --git a/FreeAPS/Sources/Modules/Home/HomeStateModel.swift b/FreeAPS/Sources/Modules/Home/HomeStateModel.swift index 4c9ec62064..bde45c94ba 100644 --- a/FreeAPS/Sources/Modules/Home/HomeStateModel.swift +++ b/FreeAPS/Sources/Modules/Home/HomeStateModel.swift @@ -70,6 +70,7 @@ extension Home { @Published var preview: Bool = true @Published var useTargetButton: Bool = false @Published var overrideHistory: [OverrideHistory] = [] + @Published var overrides: [Override] = [] @Published var alwaysUseColors: Bool = true @Published var timeSettings: Bool = true @@ -127,7 +128,6 @@ extension Home { broadcaster.register(EnactedSuggestionObserver.self, observer: self) broadcaster.register(PumpBatteryObserver.self, observer: self) broadcaster.register(PumpReservoirObserver.self, observer: self) - broadcaster.register(OverrideObserver.self, observer: self) animatedBackground = settingsManager.settings.animatedBackground subscribeSetting(\.hours, on: $hours, initial: { @@ -238,7 +238,16 @@ extension Home { } func cancelProfile() { - OverrideStorage().cancelProfile() + let os = OverrideStorage() + + if let activeOveride = os.fetchLatestOverride().first { + let presetName = os.isPresetName() + let nsString = presetName != nil ? presetName : activeOveride.percentage.formatted() + + if let duration = os.cancelProfile() { + nightscoutManager.editOverride(nsString!, duration, activeOveride.date ?? Date.now) + } + } setupOverrideHistory() } @@ -359,6 +368,13 @@ extension Home { } } + private func setupOverrides() { + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + self.overrides = self.provider.overrides() + } + } + private func setupAnnouncements() { DispatchQueue.main.async { [weak self] in guard let self = self else { return } @@ -451,9 +467,13 @@ extension Home.StateModel: EnactedSuggestionObserver, PumpBatteryObserver, PumpReservoirObserver, - PumpTimeZoneObserver, - OverrideObserver + PumpTimeZoneObserver { + /* + func overridesDidUpdate(_: [Override]) { + setupOverrides() + }*/ + func glucoseDidUpdate(_: [BloodGlucose]) { setupGlucose() } @@ -465,10 +485,6 @@ extension Home.StateModel: setupOverrideHistory() } - func overrideHistoryDidUpdate(_: [OverrideHistory]) { - setupOverrideHistory() - } - func settingsDidChange(_ settings: FreeAPSSettings) { allowManualTemp = !settings.closedLoop uploadStats = settingsManager.settings.uploadStats diff --git a/FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift b/FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift index 09c3959c26..c3f3e90aa1 100644 --- a/FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift +++ b/FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift @@ -639,9 +639,9 @@ struct MainChartView: View { private func overridesView(fullSize: CGSize) -> some View { ZStack { overridesPath - .fill(Color.purple.opacity(colorScheme == .light ? 0.1 : 0.3)) + .fill(Color.violet.opacity(colorScheme == .light ? 0.3 : 0.6)) overridesPath - .stroke(Color.purple.opacity(0.7), lineWidth: 1) + .stroke(Color.violet.opacity(0.7), lineWidth: 1) } .onChange(of: glucose) { _ in calculateOverridesRects(fullSize: fullSize) diff --git a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift index ccc8bf0f0c..85ceaf0c52 100644 --- a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift +++ b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift @@ -29,6 +29,8 @@ extension OverrideProfilesConfig { @Published var emoji: String = "" @Injected() var broadcaster: Broadcaster! + @Injected() var ns: NightscoutManager! + var units: GlucoseUnits = .mmolL override func subscribe() { @@ -41,6 +43,9 @@ extension OverrideProfilesConfig { let coredataContext = CoreDataStack.shared.persistentContainer.viewContext func saveSettings() { + // Is other override already active? + let last = OverrideStorage().fetchLatestOverride().last + coredataContext.perform { [self] in let saveOverride = Override(context: self.coredataContext) saveOverride.duration = self.duration as NSDecimalNumber @@ -76,12 +81,19 @@ extension OverrideProfilesConfig { saveOverride.smbMinutes = smbMinutes as NSDecimalNumber saveOverride.uamMinutes = uamMinutes as NSDecimalNumber } - try? self.coredataContext.save() - } - DispatchQueue.main.async { - self.broadcaster.notify(OverrideObserver.self, on: .main) { - $0.overrideHistoryDidUpdate(OverrideStorage().fetchOverrideHistory(interval: DateFilter().today)) + + if let active = last, active.enabled { + if let preset = OverrideStorage().isPresetName(), let duration = OverrideStorage().cancelProfile() { + ns.editOverride(preset, duration, last?.date ?? Date.now) + } else if let duration = OverrideStorage().cancelProfile() { + ns.editOverride("Custom", duration, last?.date ?? Date.now) + } + } else { + let duration = (self.duration as NSDecimalNumber) == 0 ? 2880 : Int(self.duration as NSDecimalNumber) + ns.uploadOverride(self.percentage.formatted(), Double(duration), saveOverride.date ?? Date.now) } + + try? self.coredataContext.save() } } @@ -128,6 +140,10 @@ extension OverrideProfilesConfig { func selectProfile(id_: String) { guard id_ != "" else { return } + + // Is other already active? + let last = OverrideStorage().fetchLatestOverride().last + coredataContext.performAndWait { var profileArray = [OverridePresets]() let requestProfiles = OverridePresets.fetchRequest() as NSFetchRequest @@ -167,6 +183,13 @@ extension OverrideProfilesConfig { saveOverride.smbMinutes = (profile.smbMinutes ?? 0) as NSDecimalNumber saveOverride.uamMinutes = (profile.uamMinutes ?? 0) as NSDecimalNumber } + + if let alreadyActive = last, alreadyActive.enabled, let duration = OverrideStorage().cancelProfile() { + ns.editOverride(profile.name ?? "Custom", duration, alreadyActive.date ?? Date.now) + } else { + ns.uploadOverride(profile.name ?? "", Double(saveOverride.duration ?? 0), saveOverride.date ?? Date()) + } + try? self.coredataContext.save() } } @@ -248,7 +271,15 @@ extension OverrideProfilesConfig { advancedSettings = false smbMinutes = defaultSmbMinutes uamMinutes = defaultUamMinutes - OverrideStorage().cancelProfile() + + let storage = OverrideStorage() + + let duration_ = storage.cancelProfile() + let last_ = storage.fetchLatestOverride().last + let name = storage.isPresetName() + if let last = last_, let duration = duration_ { + ns.editOverride(name ?? "", duration, last.date ?? Date.now) + } } } } diff --git a/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift b/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift index e28d29e12b..50d6e74514 100644 --- a/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift +++ b/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift @@ -185,7 +185,7 @@ extension OverrideProfilesConfig { } HStack { - Button("Start new Profile") { + Button("Start") { showAlert.toggle() alertSring = "\(state.percentage.formatted(.number)) %, " + ( @@ -261,16 +261,18 @@ extension OverrideProfilesConfig { "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." ) } - Section { - Button("Return to Normal") { - state.cancelProfile() - dismiss() - } - .frame(maxWidth: .infinity, alignment: .center) - .buttonStyle(BorderlessButtonStyle()) - .disabled(!state.isEnabled) - .tint(.red) - } footer: { Text("").padding(.bottom, 150) } + if state.isEnabled { + Section { + Button("Cancel Profile Override") { + state.cancelProfile() + dismiss() + } + .frame(maxWidth: .infinity, alignment: .center) + .buttonStyle(BorderlessButtonStyle()) + .disabled(!state.isEnabled) + .tint(.red) + } footer: { Text("").padding(.bottom, 150) } + } } .dynamicTypeSize(...DynamicTypeSize.xxLarge) .onAppear(perform: configureView) diff --git a/FreeAPS/Sources/Modules/Settings/SettingsStateModel.swift b/FreeAPS/Sources/Modules/Settings/SettingsStateModel.swift index cb53017e66..ca67d402c5 100644 --- a/FreeAPS/Sources/Modules/Settings/SettingsStateModel.swift +++ b/FreeAPS/Sources/Modules/Settings/SettingsStateModel.swift @@ -73,6 +73,14 @@ extension Settings { func hideSettingsModal() { hideModal() } + + func deleteOverrides() { + nightscoutManager.deleteAllNSoverrrides() // For testing + } + + /* func deleteOverride() { + nightscoutManager.deleteOverride() // For testing + } */ } } diff --git a/FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift b/FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift index f2170dad72..b391d93a6b 100644 --- a/FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift +++ b/FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift @@ -71,6 +71,22 @@ extension Settings { .frame(maxWidth: .infinity, alignment: .trailing) .buttonStyle(.borderedProminent) } + + HStack { + Text("Delete All NS Overrides") + Button("Delete") { state.deleteOverrides() } + .frame(maxWidth: .infinity, alignment: .trailing) + .buttonStyle(.borderedProminent) + .tint(.red) + } /* + + HStack { + Text("Delete latest NS Override") + Button("Delete") { state.deleteOverride() } + .frame(maxWidth: .infinity, alignment: .trailing) + .buttonStyle(.borderedProminent) + .tint(.red) + } */ } Group { Text("Preferences") @@ -104,6 +120,8 @@ extension Settings { .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.announcements), from: self) Text("Enacted announcements") .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.announcementsEnacted), from: self) + Text("Overrides Not Uploaded") + .navigationLink(to: .configEditor(file: OpenAPS.Nightscout.notUploadedOverrides), from: self) Text("Autotune") .navigationLink(to: .configEditor(file: OpenAPS.Settings.autotune), from: self) Text("Glucose") diff --git a/FreeAPS/Sources/Modules/WatchConfig/View/WatchConfigRootView.swift b/FreeAPS/Sources/Modules/WatchConfig/View/WatchConfigRootView.swift index eaaf5c90a2..f1146a2a08 100644 --- a/FreeAPS/Sources/Modules/WatchConfig/View/WatchConfigRootView.swift +++ b/FreeAPS/Sources/Modules/WatchConfig/View/WatchConfigRootView.swift @@ -23,6 +23,10 @@ extension WatchConfig { Toggle("Confirm Bolus Faster", isOn: $state.confirmBolusFaster) + Section { + Toggle("Profile Overrides Button / Temp Targets Button", isOn: $state.profilesOrTempTargets) + } header: { Text("Display either Overides or Temp Targets") } + Section(header: Text("Garmin Watch")) { List { ForEach(state.devices, id: \.uuid) { device in diff --git a/FreeAPS/Sources/Modules/WatchConfig/WatchConfigStateModel.swift b/FreeAPS/Sources/Modules/WatchConfig/WatchConfigStateModel.swift index a4f52b0a69..f14b6c8a19 100644 --- a/FreeAPS/Sources/Modules/WatchConfig/WatchConfigStateModel.swift +++ b/FreeAPS/Sources/Modules/WatchConfig/WatchConfigStateModel.swift @@ -32,6 +32,7 @@ extension WatchConfig { @Published var selectedAwConfig: AwConfig = .HR @Published var displayFatAndProteinOnWatch = false @Published var confirmBolusFaster = false + @Published var profilesOrTempTargets = false private(set) var preferences = Preferences() @@ -40,6 +41,7 @@ extension WatchConfig { subscribeSetting(\.displayFatAndProteinOnWatch, on: $displayFatAndProteinOnWatch) { displayFatAndProteinOnWatch = $0 } subscribeSetting(\.confirmBolusFaster, on: $confirmBolusFaster) { confirmBolusFaster = $0 } + subscribeSetting(\.profilesOrTempTargets, on: $profilesOrTempTargets) { profilesOrTempTargets = $0 } subscribeSetting(\.displayOnWatch, on: $selectedAwConfig) { selectedAwConfig = $0 } didSet: { [weak self] value in // for compatibility with old displayHR diff --git a/FreeAPS/Sources/Services/Network/NightscoutAPI.swift b/FreeAPS/Sources/Services/Network/NightscoutAPI.swift index 326fc9e58b..dfe2f0306e 100644 --- a/FreeAPS/Sources/Services/Network/NightscoutAPI.swift +++ b/FreeAPS/Sources/Services/Network/NightscoutAPI.swift @@ -16,7 +16,7 @@ class NightscoutAPI { static let treatmentsPath = "/api/v1/treatments.json" static let statusPath = "/api/v1/devicestatus.json" static let profilePath = "/api/v1/profile.json" - static let retryCount = 1 + static let retryCount = 2 static let timeout: TimeInterval = 60 } @@ -341,6 +341,82 @@ extension NightscoutAPI { .eraseToAnyPublisher() } + func deleteNSoverride() -> AnyPublisher { + var components = URLComponents() + components.scheme = url.scheme + components.host = url.host + components.port = url.port + components.path = Config.treatmentsPath + components.queryItems = [ + URLQueryItem(name: "find[eventType]", value: "Exercise"), + URLQueryItem(name: "count", value: "\(1)"), // Delete latest + URLQueryItem(name: "find[enteredBy]", value: "iAPS") // Don't delete entries created in NS + ] + var request = URLRequest(url: components.url!) + request.allowsConstrainedNetworkAccess = false + request.timeoutInterval = Config.timeout + request.httpMethod = "DELETE" + + if let secret = secret { + request.addValue(secret.sha1(), forHTTPHeaderField: "api-secret") + } + return service.run(request) + .retry(Config.retryCount) + .map { _ in () } + .eraseToAnyPublisher() + } + + func deleteOverride(at date: Date) -> AnyPublisher { + var components = URLComponents() + components.scheme = url.scheme + components.host = url.host + components.port = url.port + components.path = Config.treatmentsPath + components.queryItems = [ + URLQueryItem(name: "find[Exercise][$exists]", value: "true"), + URLQueryItem( + name: "find[created_at][$eq]", + value: Formatter.iso8601withFractionalSeconds.string(from: date) + ) + ] + var request = URLRequest(url: components.url!) + request.allowsConstrainedNetworkAccess = false + request.timeoutInterval = Config.timeout + request.httpMethod = "DELETE" + + if let secret = secret { + request.addValue(secret.sha1(), forHTTPHeaderField: "api-secret") + } + return service.run(request) + .retry(Config.retryCount) + .map { _ in () } + .eraseToAnyPublisher() + } + + // Dev work. Delete all exercise events + func deleteAllNSoverrrides() -> AnyPublisher { + var components = URLComponents() + components.scheme = url.scheme + components.host = url.host + components.port = url.port + components.path = Config.treatmentsPath + components.queryItems = [ + URLQueryItem(name: "find[eventType]", value: "Exercise") + ] + var request = URLRequest(url: components.url!) + request.allowsConstrainedNetworkAccess = false + request.timeoutInterval = Config.timeout + request.httpMethod = "DELETE" + + if let secret = secret { + request.addValue(secret.sha1(), forHTTPHeaderField: "api-secret") + } + return service.run(request) + .retry(Config.retryCount) + .map { _ in () } + .eraseToAnyPublisher() + } + func uploadTreatments(_ treatments: [NigtscoutTreatment]) -> AnyPublisher { var components = URLComponents() components.scheme = url.scheme @@ -365,6 +441,30 @@ extension NightscoutAPI { .eraseToAnyPublisher() } + func uploadEcercises(_ override: [NigtscoutExercise]) -> AnyPublisher { + var components = URLComponents() + components.scheme = url.scheme + components.host = url.host + components.port = url.port + components.path = Config.treatmentsPath + + var request = URLRequest(url: components.url!) + request.allowsConstrainedNetworkAccess = false + request.timeoutInterval = Config.timeout + request.addValue("application/json", forHTTPHeaderField: "Content-Type") + + if let secret = secret { + request.addValue(secret.sha1(), forHTTPHeaderField: "api-secret") + } + request.httpBody = try? JSONCoding.encoder.encode(override) + request.httpMethod = "POST" + + return service.run(request) + .retry(Config.retryCount) + .map { _ in () } + .eraseToAnyPublisher() + } + func uploadGlucose(_ glucose: [BloodGlucose]) -> AnyPublisher { var components = URLComponents() components.scheme = url.scheme diff --git a/FreeAPS/Sources/Services/Network/NightscoutManager.swift b/FreeAPS/Sources/Services/Network/NightscoutManager.swift index 3800e1440a..75c4271681 100644 --- a/FreeAPS/Sources/Services/Network/NightscoutManager.swift +++ b/FreeAPS/Sources/Services/Network/NightscoutManager.swift @@ -20,7 +20,11 @@ protocol NightscoutManager: GlucoseSource { func uploadStatistics(dailystat: Statistics) func uploadPreferences(_ preferences: Preferences) func uploadProfileAndSettings(_: Bool) + func uploadOverride(_ profile: String, _ duration: Double, _ date: Date) func deleteAnnouncements() + func deleteAllNSoverrrides() + func deleteOverride() + func editOverride(_ profile: String, _ duration_: Double, _ date: Date) var cgmURL: URL? { get } } @@ -37,6 +41,8 @@ final class BaseNightscoutManager: NightscoutManager, Injectable { @Injected() private var reachabilityManager: ReachabilityManager! @Injected() var healthkitManager: HealthKitManager! + let overrideStorage = OverrideStorage() + private let processQueue = DispatchQueue(label: "BaseNetworkManager.processQueue") private var ping: TimeInterval? @@ -726,6 +732,136 @@ final class BaseNightscoutManager: NightscoutManager, Injectable { ) } + func editOverride(_ profile: String, _ duration_: Double, _ date: Date) { + let duration = Int(duration_ == 0 ? 2880 : duration_) + let exercise = + [NigtscoutExercise( + duration: duration, + eventType: EventType.nsExercise, + createdAt: date, + enteredBy: NigtscoutTreatment.local, + notes: profile + )] + + guard let nightscout = nightscoutAPI, isUploadEnabled else { + return + } + + processQueue.async { + nightscout.deleteOverride(at: date) + .sink { completion in + switch completion { + case .finished: + debug(.nightscout, "Old Override deleted in NS, date: \(date)") + nightscout.uploadEcercises(exercise) + .sink { completion in + switch completion { + case .finished: + debug(.nightscout, "Override Uploaded to NS, date: \(date)") + case let .failure(error): + self.overrideStorage.addToNotUploaded(1) + self.notUploaded(overrides: exercise) + debug(.nightscout, "Upload of Override failed: " + error.localizedDescription) + } + } receiveValue: {} + .store(in: &self.lifetime) + case let .failure(error): + debug(.nightscout, "Deletion of Old Override failed: " + error.localizedDescription) + self.overrideStorage.addToNotUploaded(1) + self.notUploaded(overrides: exercise) + } + } receiveValue: {} + .store(in: &self.lifetime) + } + } + + func uploadOverride(_ profile: String, _ duration_: Double, _ date: Date) { + guard let nightscout = nightscoutAPI, isUploadEnabled else { + return + } + let duration = Int(duration_ == 0 ? 2880 : duration_) + + let exercise = + [NigtscoutExercise( + duration: duration, + eventType: EventType.nsExercise, + createdAt: date, + enteredBy: NigtscoutTreatment.local, + notes: profile + )] + + print("Override uploaded: \(exercise)") + + processQueue.async { + nightscout.uploadEcercises(exercise) + // nightscout.uploadTreatments(override) + .sink { completion in + switch completion { + case .finished: + debug(.nightscout, "Override Uploaded to NS, date: \(date)") + case let .failure(error): + debug(.nightscout, "Upload of Override failed: " + error.localizedDescription) + } + } receiveValue: {} + .store(in: &self.lifetime) + } + } + + func deleteOverride() { + guard let nightscout = nightscoutAPI, isUploadEnabled else { + return + } + nightscout.deleteNSoverride() + .sink { completion in + switch completion { + case .finished: + debug(.nightscout, "Override deleted in NS") + case let .failure(error): + debug(.nightscout, "Override deletion in NS failed: " + error.localizedDescription) + } + } receiveValue: {} + .store(in: &lifetime) + } + + func deleteAllNSoverrrides() { + guard let nightscout = nightscoutAPI, isUploadEnabled else { + return + } + nightscout.deleteAllNSoverrrides() + .sink { completion in + switch completion { + case .finished: + debug(.nightscout, "All Overrides deleted in NS") + case let .failure(error): + debug(.nightscout, "Deletion of all overrides in NS failed: " + error.localizedDescription) + } + } receiveValue: {} + .store(in: &lifetime) + } + + private func notUploaded(overrides: [NigtscoutExercise]) { + let file = OpenAPS.Nightscout.notUploadedOverrides + var uniqEvents: [NigtscoutExercise] = [] + + storage.transaction { storage in + storage.append(overrides, to: file, uniqBy: \.createdAt) + uniqEvents = storage.retrieve(file, as: [NigtscoutExercise].self)? + .filter { $0.createdAt.addingTimeInterval(2.days.timeInterval) > Date() } + .sorted { $0.createdAt > $1.createdAt } ?? [] + storage.save(Array(uniqEvents), as: file) + debug(.nightscout, "\(uniqEvents.count) Overide added to list ot not uploaded Overrides.") + } + } + + private func removeFromNotUploaded() { + let file = OpenAPS.Nightscout.notUploadedOverrides + storage.transaction { storage in + let newFile: [NigtscoutExercise] = [] + storage.save(newFile, as: file) + debug(.nightscout, "Override(s) deleted from list of not uploaded Overrides.") + } + } + private func uploadPumpHistory() { uploadTreatments(pumpHistoryStorage.nightscoutTretmentsNotUploaded(), fileToSave: OpenAPS.Nightscout.uploadedPumphistory) } @@ -763,6 +899,9 @@ final class BaseNightscoutManager: NightscoutManager, Injectable { case .finished: self.storage.save(glucose, as: fileToSave) debug(.nightscout, "Glucose uploaded") + + // self.checkForNoneUploadedOverides() // To do : Move somewhere else + case let .failure(error): debug(.nightscout, "Upload of glucose failed: " + error.localizedDescription) } @@ -771,10 +910,47 @@ final class BaseNightscoutManager: NightscoutManager, Injectable { } } + private func checkForNoneUploadedOverides() { + guard let nightscout = nightscoutAPI, isUploadEnabled else { return } + guard let count = overrideStorage.countNotUploaded() else { return } + + let file = storage.retrieve(OpenAPS.Nightscout.notUploadedOverrides, as: [NigtscoutExercise].self) ?? [] + guard file.isNotEmpty else { return } + + let deleteLast = file[0] // To do: Not always needed, but try everytime for now... + nightscout.deleteOverride(at: deleteLast.createdAt) + .sink { completion in + switch completion { + case .finished: + self.removeFromNotUploaded() + self.overrideStorage.addToNotUploaded(0) + debug(.nightscout, "Last Override deleted from NS") + case let .failure(error): + debug(.nightscout, "Last Override deleteion from NS failed! " + error.localizedDescription) + } + } receiveValue: {} + .store(in: &lifetime) + + nightscout.uploadEcercises(file) + .sink { completion in + switch completion { + case .finished: + self.removeFromNotUploaded() + self.overrideStorage.addToNotUploaded(0) + debug(.nightscout, "\(count) Override(s) from list of not uploaded now uploaded!") + case let .failure(error): + debug(.nightscout, "Upload of Override from list of not uploaded failed: " + error.localizedDescription) + } + } receiveValue: {} + .store(in: &lifetime) + } + private func uploadTreatments(_ treatments: [NigtscoutTreatment], fileToSave: String) { - guard !treatments.isEmpty, let nightscout = nightscoutAPI, isUploadEnabled else { - return - } + guard let nightscout = nightscoutAPI, isUploadEnabled else { return } + + checkForNoneUploadedOverides() // To do : Move somewhere else + + guard !treatments.isEmpty else { return } processQueue.async { treatments.chunks(ofCount: 100) diff --git a/FreeAPS/Sources/Services/WatchManager/WatchManager.swift b/FreeAPS/Sources/Services/WatchManager/WatchManager.swift index 74e3f4b3b4..629ed615fd 100644 --- a/FreeAPS/Sources/Services/WatchManager/WatchManager.swift +++ b/FreeAPS/Sources/Services/WatchManager/WatchManager.swift @@ -1,4 +1,5 @@ import Foundation +import SwiftDate import Swinject import WatchConnectivity @@ -16,6 +17,7 @@ final class BaseWatchManager: NSObject, WatchManager, Injectable { @Injected() private var carbsStorage: CarbsStorage! @Injected() private var tempTargetsStorage: TempTargetsStorage! @Injected() private var garmin: GarminManager! + @Injected() private var nightscout: NightscoutManager! let coreDataStorage = CoreDataStorage() @@ -55,6 +57,7 @@ final class BaseWatchManager: NSObject, WatchManager, Injectable { private func configureState() { processQueue.async { + let overrideStorage = OverrideStorage() let readings = self.coreDataStorage.fetchGlucose(interval: DateFilter().twoHours) let glucoseValues = self.glucoseText(readings) self.state.glucose = glucoseValues.glucose @@ -115,10 +118,43 @@ final class BaseWatchManager: NSObject, WatchManager, Injectable { until: untilDate ) } + + self.state.overrides = overrideStorage.fetchProfiles() + .map { preset -> OverridePresets_ in + let untilDate = overrideStorage.fetchLatestOverride().first.flatMap { currentOverride -> Date? in + guard currentOverride.id == preset.id, currentOverride.enabled else { return nil } + + let duration = Double(currentOverride.duration ?? 0) + let overrideDate: Date = currentOverride.date ?? Date.now + + let date = duration == 0 ? Date.distantFuture : overrideDate.addingTimeInterval(duration * 60) + return date > Date.now ? date : nil + } + + return OverridePresets_( + name: preset.name ?? "", + id: preset.id ?? "", + until: untilDate, + description: self.description(preset) + ) + } + // Is there an active override but no preset? + let currentButNoOverrideNotPreset = self.state.overrides.filter({ $0.until != nil }).first + if let last = overrideStorage.fetchLatestOverride().first, last.enabled, currentButNoOverrideNotPreset == nil { + let duration = Double(last.duration ?? 0) + let overrideDate: Date = last.date ?? Date.now + let date_ = duration == 0 ? Date.distantFuture : overrideDate.addingTimeInterval(duration * 60) + let date = date_ > Date.now ? date_ : nil + + self.state.overrides + .append(OverridePresets_(name: "custom", id: last.id ?? "", until: date, description: self.description(last))) + } + self.state.bolusAfterCarbs = !self.settingsManager.settings.skipBolusScreenAfterCarbs self.state.displayOnWatch = self.settingsManager.settings.displayOnWatch self.state.displayFatAndProteinOnWatch = self.settingsManager.settings.displayFatAndProteinOnWatch self.state.confirmBolusFaster = self.settingsManager.settings.confirmBolusFaster + self.state.profilesOrTempTargets = self.settingsManager.settings.profilesOrTempTargets let eBG = self.eventualBGString() self.state.eventualBG = eBG.map { "⇢ " + $0 } @@ -126,12 +162,11 @@ final class BaseWatchManager: NSObject, WatchManager, Injectable { self.state.isf = self.suggestion?.isf - let overrideArray = self.coreDataStorage.fetchLatestOverride() + let overrideArray = overrideStorage.fetchLatestOverride() if overrideArray.first?.enabled ?? false { let percentString = "\((overrideArray.first?.percentage ?? 100).formatted(.number)) %" self.state.override = percentString - } else { self.state.override = "100 %" } @@ -288,6 +323,30 @@ final class BaseWatchManager: NSObject, WatchManager, Injectable { return insulinCalculated } + private func description(_ preset: OverridePresets) -> String { + let rawtarget = (preset.target ?? 0) as Decimal + + let targetValue = settingsManager.settings.units == .mmolL ? rawtarget.asMmolL : rawtarget + let target: String = rawtarget > 6 ? glucoseFormatter.string(from: targetValue as NSNumber) ?? "" : "" + + let percentage = preset.percentage != 100 ? preset.percentage.formatted() + "%" : "" + let string = (preset.target ?? 0) as Decimal > 6 && !percentage.isEmpty ? target + " " + settingsManager.settings.units + .rawValue + ", " + percentage : target + percentage + return string + } + + private func description(_ override: Override) -> String { + let rawtarget = (override.target ?? 0) as Decimal + + let targetValue = settingsManager.settings.units == .mmolL ? rawtarget.asMmolL : rawtarget + let target: String = rawtarget > 6 ? glucoseFormatter.string(from: targetValue as NSNumber) ?? "" : "" + + let percentage = override.percentage != 100 ? override.percentage.formatted() + "%" : "" + let string = (override.target ?? 0) as Decimal > 6 && !percentage.isEmpty ? target + " " + settingsManager.settings.units + .rawValue + ", " + percentage : target + percentage + return string + } + private var glucoseFormatter: NumberFormatter { let formatter = NumberFormatter() formatter.numberStyle = .decimal @@ -407,6 +466,46 @@ extension BaseWatchManager: WCSessionDelegate { } } + if let overrideID = message["override"] as? String { + let storage = OverrideStorage() + if let preset = storage.fetchProfiles().first(where: { $0.id == overrideID }) { + preset.date = Date.now + + // Cancel eventual current active override first + if let activeOveride = storage.fetchLatestOverride().first, activeOveride.enabled { + let name = storage.isPresetName() + + if let duration = storage.cancelProfile() { + let presetName = preset.name + let nsString = name != nil ? name! : activeOveride.percentage.formatted() + nightscout.editOverride(nsString, duration, activeOveride.date ?? Date()) + } + } + // Activate the new override and uplad the new ovderride to NS. Some duplicate code now. + storage.overrideFromPreset(preset) + nightscout.uploadOverride( + preset.name ?? "", + Double(preset.duration ?? 0), + storage.fetchLatestOverride().first?.date ?? Date.now + ) + replyHandler(["confirmation": true]) + configureState() + return + } else if overrideID == "cancel" { + if let activeOveride = storage.fetchLatestOverride().first, activeOveride.enabled { + let presetName = storage.isPresetName() + let nsString = presetName != nil ? presetName : activeOveride.percentage.formatted() + + if let duration = storage.cancelProfile() { + nightscout.editOverride(nsString!, duration, activeOveride.date ?? Date.now) + replyHandler(["confirmation": true]) + configureState() + } + } + return + } + } + if let bolus = message["bolus"] as? Double, bolus > 0 { apsManager.enactBolus(amount: bolus, isSMB: false) replyHandler(["confirmation": true]) diff --git a/FreeAPSWatch WatchKit Extension/DataFlow.swift b/FreeAPSWatch WatchKit Extension/DataFlow.swift index 0b02b0ef4a..c48b798b9b 100644 --- a/FreeAPSWatch WatchKit Extension/DataFlow.swift +++ b/FreeAPSWatch WatchKit Extension/DataFlow.swift @@ -17,12 +17,14 @@ struct WatchState: Codable { var iob: Decimal? var cob: Decimal? var tempTargets: [TempTargetWatchPreset] = [] + var overrides: [OverridePresets_] = [] var bolusAfterCarbs: Bool? var eventualBG: String? var eventualBGRaw: String? var displayOnWatch: AwConfig? var displayFatAndProteinOnWatch: Bool? var confirmBolusFaster: Bool? + var profilesOrTempTargets: Bool? var useNewCalc: Bool? var isf: Decimal? var override: String? @@ -34,3 +36,10 @@ struct TempTargetWatchPreset: Codable, Identifiable { let description: String let until: Date? } + +struct OverridePresets_: Codable, Identifiable { + let name: String + let id: String + let until: Date? + let description: String +} diff --git a/FreeAPSWatch WatchKit Extension/Views/MainView.swift b/FreeAPSWatch WatchKit Extension/Views/MainView.swift index 456bbb8f1a..b85dcdf557 100644 --- a/FreeAPSWatch WatchKit Extension/Views/MainView.swift +++ b/FreeAPSWatch WatchKit Extension/Views/MainView.swift @@ -11,6 +11,7 @@ struct MainView: View { @State var isCarbsActive = false @State var isTargetsActive = false + @State var isOverrideActive = false @State var isBolusActive = false @State private var pulse = 0 @State private var steps = 0 @@ -272,20 +273,52 @@ struct MainView: View { .foregroundColor(.loopYellow) } - NavigationLink(isActive: $state.isTempTargetViewActive) { - TempTargetsView() - .environmentObject(state) - } label: { - VStack { - Image("target", bundle: nil) - .renderingMode(.template) - .resizable() - .frame(width: 24, height: 24) - .foregroundColor(.loopGreen) - if let until = state.tempTargets.compactMap(\.until).first, until > Date() { - Text(until, style: .timer) - .scaledToFill() - .font(.system(size: 8)) + if state.profilesOrTempTargets { + NavigationLink(isActive: $state.isTempTargetViewActive) { + TempTargetsView() + .environmentObject(state) + } label: { + VStack { + Image("target", bundle: nil) + .renderingMode(.template) + .resizable() + .frame(width: 24, height: 24) + .foregroundColor(.loopGreen) + if let until = state.tempTargets.compactMap(\.until).first, until > Date() { + Text(until, style: .timer) + .scaledToFill() + .font(.system(size: 8)) + } + } + } + } else { + NavigationLink(isActive: $state.isOverridesViewActive) { + OverridesView() + .environmentObject(state) + } label: { + VStack { + if let until = state.overrides.compactMap(\.until).first, until > Date.now { + Image(systemName: "person.fill") + .renderingMode(.template) + .resizable() + .frame(width: 24, height: 24) + .foregroundColor(.purple) + + if until > Date.now.addingTimeInterval(48.hours.timeInterval) { + Text("> 48h") + .scaledToFill() + .font(.system(size: 7)) + } else { + Text(until, style: .timer) + .font(.system(size: 8)) + } + } else { + Image(systemName: "person") + .renderingMode(.template) + .resizable() + .frame(width: 24, height: 24) + .foregroundColor(.purple) + } } } } diff --git a/FreeAPSWatch WatchKit Extension/Views/OverridesView.swift b/FreeAPSWatch WatchKit Extension/Views/OverridesView.swift new file mode 100644 index 0000000000..04293cb220 --- /dev/null +++ b/FreeAPSWatch WatchKit Extension/Views/OverridesView.swift @@ -0,0 +1,59 @@ +import SwiftUI + +struct OverridesView: View { + @EnvironmentObject var state: WatchStateModel + + var body: some View { + List { + if state.overrides.isEmpty { + Text("Set override presets on iPhone first").padding() + } else { + ForEach(state.overrides) { override in + Button { + WKInterfaceDevice.current().play(.click) + state.enactOverride(id: override.id) + } label: { + VStack(alignment: .leading) { + HStack { + Text(override.name) + if let until = override.until, until > Date.now { + Spacer() + if until > Date.now.addingTimeInterval(48.hours.timeInterval) { + Text("> 48h").foregroundStyle(.purple) + } else { + Text(until, style: .timer).foregroundStyle(.purple) + } + } + } + Text(override.description).font(.caption2).foregroundColor(.secondary) + } + } + } + } + + Button { + WKInterfaceDevice.current().play(.click) + state.enactOverride(id: "cancel") + } label: { + Text("Cancel Override") + } + } + .navigationTitle("Overrides") + } +} + +struct OverridesView_Previews: PreviewProvider { + static var previews: some View { + let model = WatchStateModel() + model.overrides = [ + OverridePresets_( + name: "Custom", + id: UUID().uuidString, + until: Date().addingTimeInterval(60 * 60), description: "110 %" + ), + OverridePresets_(name: "Override 1", id: UUID().uuidString, until: nil, description: "120 %"), + OverridePresets_(name: "Override 2", id: UUID().uuidString, until: nil, description: "6,5 mmol/l, 90 %") + ] + return OverridesView().environmentObject(model) + } +} diff --git a/FreeAPSWatch WatchKit Extension/WatchStateModel.swift b/FreeAPSWatch WatchKit Extension/WatchStateModel.swift index dbbdac667f..d70c780cba 100644 --- a/FreeAPSWatch WatchKit Extension/WatchStateModel.swift +++ b/FreeAPSWatch WatchKit Extension/WatchStateModel.swift @@ -28,8 +28,10 @@ class WatchStateModel: NSObject, ObservableObject { @Published var iob: Decimal? @Published var cob: Decimal? @Published var tempTargets: [TempTargetWatchPreset] = [] + @Published var overrides: [OverridePresets_] = [] @Published var bolusAfterCarbs = true @Published var isCarbsViewActive = false + @Published var isOverridesViewActive = false @Published var isTempTargetViewActive = false @Published var isBolusViewActive = false @Published var displayOnWatch: AwConfig = .BGTarget @@ -37,6 +39,7 @@ class WatchStateModel: NSObject, ObservableObject { @Published var confirmBolusFaster = false @Published var useNewCalc = false @Published var eventualBG = "" + @Published var profilesOrTempTargets = true @Published var isConfirmationViewActive = false { didSet { confirmationTimeout = nil @@ -102,6 +105,18 @@ class WatchStateModel: NSObject, ObservableObject { } } + func enactOverride(id: String) { + confirmationSuccess = nil + isConfirmationViewActive = true + isOverridesViewActive = false + session.sendMessage(["override": id], replyHandler: completionHandler) { error in + print(error.localizedDescription) + DispatchQueue.main.async { + self.confirmation(false) + } + } + } + func addBolus(amount: Double) { isBolusViewActive = false pendingBolus = amount @@ -171,12 +186,14 @@ class WatchStateModel: NSObject, ObservableObject { iob = state.iob cob = state.cob tempTargets = state.tempTargets + overrides = state.overrides bolusAfterCarbs = state.bolusAfterCarbs ?? true lastUpdate = Date() eventualBG = state.eventualBG ?? "" displayOnWatch = state.displayOnWatch ?? .BGTarget displayFatAndProteinOnWatch = state.displayFatAndProteinOnWatch ?? false confirmBolusFaster = state.confirmBolusFaster ?? false + profilesOrTempTargets = state.profilesOrTempTargets ?? true useNewCalc = state.useNewCalc ?? false isf = state.isf override = state.override From 156f2838a2a833d57717121a33bb71691bac0e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Thu, 22 Feb 2024 13:42:58 +0100 Subject: [PATCH 03/44] Always display header. By request. --- FreeAPS/Sources/Modules/Home/View/HomeRootView.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift index 706eae63a8..16144fb271 100644 --- a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift +++ b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift @@ -539,7 +539,7 @@ extension Home { @ViewBuilder private func headerView(_ geo: GeometryProxy) -> some View { addHeaderBackground() .frame( - minHeight: fontSize < .extraExtraLarge ? 125 + geo.safeAreaInsets.top : 135 + geo.safeAreaInsets.top + maxHeight: fontSize < .extraExtraLarge ? 125 + geo.safeAreaInsets.top : 135 + geo.safeAreaInsets.top ) .overlay { VStack { @@ -583,9 +583,9 @@ extension Home { var body: some View { GeometryReader { geo in VStack { + headerView(geo) ScrollView { VStack(spacing: 0) { - headerView(geo) RaisedRectangle() chart preview.padding(.top, 15) From 8a8e5d10c64e3310d9287099729a91816afffded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Thu, 22 Feb 2024 13:44:57 +0100 Subject: [PATCH 04/44] Bump version --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index 22941888ed..b7be5bd145 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 3.1.3 +APP_VERSION = 3.1.4 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## From 07a8b03db9f4baa0be5a23f85bb7ae25aaa63311 Mon Sep 17 00:00:00 2001 From: Pete Wilkins Date: Thu, 22 Feb 2024 13:30:09 +0000 Subject: [PATCH 05/44] Typo in Adjustment Factor popup (#526) --- FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings | 2 +- FreeAPS/Sources/Modules/Dynamic/View/DynamicRootView.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index 0708de5254..4edbf8f15f 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -2081,7 +2081,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Modules/Dynamic/View/DynamicRootView.swift b/FreeAPS/Sources/Modules/Dynamic/View/DynamicRootView.swift index 8e05f9b5f5..2475645f4f 100644 --- a/FreeAPS/Sources/Modules/Dynamic/View/DynamicRootView.swift +++ b/FreeAPS/Sources/Modules/Dynamic/View/DynamicRootView.swift @@ -95,7 +95,7 @@ extension Dynamic { .onTapGesture { info( header: "Adjustment Factor", - body: "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment.", + body: "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment.", useGraphics: nil ) } From 3d9346ca4ea0a9072b091322225fe7e43660f4e2 Mon Sep 17 00:00:00 2001 From: Joe Moran Date: Fri, 23 Feb 2024 10:51:54 -0800 Subject: [PATCH 06/44] Backport of missing changes from LoopKit OmniBLE #110 and OmniKit #24 (#542) --- .../OmniBLE/OmniBLE/OmnipodCommon/Pod.swift | 10 +- .../PumpManager/OmniBLEPumpManager.swift | 172 +++++++++--------- .../OmniBLE/PumpManager/PodCommsSession.swift | 50 +++-- .../OmniBLE/PumpManager/PodState.swift | 31 ++-- .../OmniKit/OmniKit/OmnipodCommon/Pod.swift | 10 +- .../PumpManager/OmnipodPumpManager.swift | 31 ++-- .../OmniKit/PumpManager/PodCommsSession.swift | 50 +++-- .../OmniKit/PumpManager/PodState.swift | 28 ++- .../OmniKitTests/PodCommsSessionTests.swift | 10 +- 9 files changed, 219 insertions(+), 173 deletions(-) diff --git a/Dependencies/OmniBLE/OmniBLE/OmnipodCommon/Pod.swift b/Dependencies/OmniBLE/OmniBLE/OmnipodCommon/Pod.swift index 8839feea59..5bd1d6b5fd 100644 --- a/Dependencies/OmniBLE/OmniBLE/OmnipodCommon/Pod.swift +++ b/Dependencies/OmniBLE/OmniBLE/OmnipodCommon/Pod.swift @@ -106,16 +106,20 @@ public enum DeliveryStatus: UInt8, CustomStringConvertible { case bolusAndTempBasal = 6 case extendedBolusRunning = 9 case extendedBolusAndTempBasal = 10 - + + public var suspended: Bool { + return self == .suspended + } + public var bolusing: Bool { return self == .bolusInProgress || self == .bolusAndTempBasal || self == .extendedBolusRunning || self == .extendedBolusAndTempBasal } - + public var tempBasalRunning: Bool { return self == .tempBasalRunning || self == .bolusAndTempBasal || self == .extendedBolusAndTempBasal } - public var extendedBolusRunninng: Bool { + public var extendedBolusRunning: Bool { return self == .extendedBolusRunning || self == .extendedBolusAndTempBasal } diff --git a/Dependencies/OmniBLE/OmniBLE/PumpManager/OmniBLEPumpManager.swift b/Dependencies/OmniBLE/OmniBLE/PumpManager/OmniBLEPumpManager.swift index 4fb4d9df05..6c7641f8d3 100644 --- a/Dependencies/OmniBLE/OmniBLE/PumpManager/OmniBLEPumpManager.swift +++ b/Dependencies/OmniBLE/OmniBLE/PumpManager/OmniBLEPumpManager.swift @@ -32,7 +32,6 @@ public enum OmniBLEPumpManagerError: Error { case insulinTypeNotConfigured case notReadyForCannulaInsertion case invalidSetting - case setupNotComplete case communication(Error) case state(Error) } @@ -45,13 +44,11 @@ extension OmniBLEPumpManagerError: LocalizedError { case .podAlreadyPaired: return LocalizedString("Pod already paired", comment: "Error message shown when user cannot pair because pod is already paired") case .insulinTypeNotConfigured: - return LocalizedString("Insulin type not configured", comment: "Error description for OmniBLEPumpManagerError.insulinTypeNotConfigured") + return LocalizedString("Insulin type not configured", comment: "Error description for insulin type not configured") case .notReadyForCannulaInsertion: return LocalizedString("Pod is not in a state ready for cannula insertion.", comment: "Error message when cannula insertion fails because the pod is in an unexpected state") case .invalidSetting: return LocalizedString("Invalid Setting", comment: "Error description for invalid setting") - case .setupNotComplete: - return LocalizedString("Pod setup is not complete", comment: "Error description when pod setup is not complete") case .communication(let error): if let error = error as? LocalizedError { return error.errorDescription @@ -1087,7 +1084,7 @@ extension OmniBLEPumpManager { guard state.podState?.setupProgress == .completed else { // A cancel delivery command before pod setup is complete will fault the pod - completion(.state(OmniBLEPumpManagerError.setupNotComplete)) + completion(.state(PodCommsError.setupNotComplete)) return } @@ -1127,7 +1124,7 @@ extension OmniBLEPumpManager { guard state.podState?.setupProgress == .completed else { // A cancel delivery command before pod setup is complete will fault the pod - return .failure(PumpManagerError.deviceState(OmniBLEPumpManagerError.setupNotComplete)) + return .failure(PumpManagerError.deviceState(PodCommsError.setupNotComplete)) } guard state.podState?.unfinalizedBolus?.isFinished() != false else { @@ -1822,7 +1819,7 @@ extension OmniBLEPumpManager: PumpManager { guard state.podState?.setupProgress == .completed else { // A cancel delivery command before pod setup is complete will fault the pod - completion(.failure(PumpManagerError.deviceState(OmniBLEPumpManagerError.setupNotComplete))) + completion(.failure(PumpManagerError.deviceState(PodCommsError.setupNotComplete))) return } @@ -1883,8 +1880,15 @@ extension OmniBLEPumpManager: PumpManager { } public func runTemporaryBasalProgram(unitsPerHour: Double, for duration: TimeInterval, automatic: Bool, completion: @escaping (PumpManagerError?) -> Void) { - guard self.hasActivePod else { - completion(.deviceState(OmniBLEPumpManagerError.noPodPaired)) + + guard self.hasActivePod, let podState = self.state.podState else { + completion(.configuration(OmniBLEPumpManagerError.noPodPaired)) + return + } + + guard state.podState?.setupProgress == .completed else { + // A cancel delivery command before pod setup is complete will fault the pod + completion(.deviceState(PodCommsError.setupNotComplete)) return } @@ -1917,95 +1921,97 @@ extension OmniBLEPumpManager: PumpManager { return } - do { - if case .some(.suspended) = self.state.podState?.suspendState { - self.log.info("Not enacting temp basal because podState indicates pod is suspended.") - throw PodCommsError.podSuspended - } - - // A resume scheduled basal delivery request is denoted by a 0 duration that cancels any existing temp basal. - let resumingScheduledBasal = duration < .ulpOfOne + if case (.suspended) = podState.suspendState { + self.log.info("Not enacting temp basal because podState indicates pod is suspended.") + completion(.deviceState(PodCommsError.podSuspended)) + return + } - // If a bolus is not finished, fail if not resuming the scheduled basal - guard self.state.podState?.unfinalizedBolus?.isFinished() != false || resumingScheduledBasal else { - self.log.info("Not enacting temp basal because podState indicates unfinalized bolus in progress.") - throw PodCommsError.unfinalizedBolus - } + // A resume scheduled basal delivery request is denoted by a 0 duration that cancels any existing temp basal. + let resumingScheduledBasal = duration < .ulpOfOne - // Did the last message have comms issues or is the last delivery status not verified correctly? - let uncertainDeliveryStatus = self.state.podState?.lastCommsOK == false || self.state.podState?.deliveryStatusVerified == false + // If a bolus is not finished, fail if not resuming the scheduled basal + guard podState.unfinalizedBolus?.isFinished() != false || resumingScheduledBasal else { + self.log.info("Not enacting temp basal because podState indicates unfinalized bolus in progress.") + completion(.deviceState(PodCommsError.unfinalizedBolus)) + return + } - // Do the cancel temp basal command if currently running a temp basal OR - // if resuming scheduled basal delivery OR if the delivery status is uncertain. - if self.state.podState?.unfinalizedTempBasal != nil || resumingScheduledBasal || uncertainDeliveryStatus { - let status: StatusResponse + // Do the safe cancel TB command when resuming scheduled basal delivery OR if unfinalizedTempBasal indicates a + // running a temp basal OR if we don't have the last pod delivery status confirming that no temp basal is running. + if resumingScheduledBasal || podState.unfinalizedTempBasal != nil || + podState.lastDeliveryStatusReceived == nil || podState.lastDeliveryStatusReceived!.tempBasalRunning + { + let status: StatusResponse - // if resuming scheduled basal delivery & an acknowledgement beep is needed, use the cancel TB beep - let beepType: BeepType = resumingScheduledBasal && acknowledgementBeep ? .beep : .noBeepCancel - let result = session.cancelDelivery(deliveryType: .tempBasal, beepType: beepType) - switch result { - case .certainFailure(let error): - throw error - case .unacknowledged(let error): - throw error - case .success(let cancelTempStatus, _): - status = cancelTempStatus - } + // if resuming scheduled basal delivery & an acknowledgement beep is needed, use the cancel TB beep + let beepType: BeepType = resumingScheduledBasal && acknowledgementBeep ? .beep : .noBeepCancel + let result = session.cancelDelivery(deliveryType: .tempBasal, beepType: beepType) + switch result { + case .certainFailure(let error): + completion(.communication(error)) + return + case .unacknowledged(let error): + completion(.communication(error)) + return + case .success(let cancelTempStatus, _): + status = cancelTempStatus + } - // If pod is bolusing, fail if not resuming the scheduled basal - guard !status.deliveryStatus.bolusing || resumingScheduledBasal else { - throw PodCommsError.unfinalizedBolus - } + // If pod is bolusing, fail if not resuming the scheduled basal + guard !status.deliveryStatus.bolusing || resumingScheduledBasal else { + self.log.info("Canceling temp basal because status return indicates bolus in progress.") + completion(.communication(PodCommsError.unfinalizedBolus)) + return + } - guard status.deliveryStatus != .suspended else { - self.log.info("Canceling temp basal because status return indicates pod is suspended.") - throw PodCommsError.podSuspended - } - } else { - self.log.info("Skipped Cancel TB command before enacting temp basal") + guard status.deliveryStatus != .suspended else { + self.log.info("Canceling temp basal because status return indicates pod is suspended!") + completion(.communication(PodCommsError.podSuspended)) + return } + } else { + self.log.info("Skipped Cancel TB command before enacting temp basal") + } - defer { - self.setState({ (state) in - state.tempBasalEngageState = .stable - }) + defer { + self.setState({ (state) in + state.tempBasalEngageState = .stable + }) + } + + if resumingScheduledBasal { + self.setState({ (state) in + state.tempBasalEngageState = .disengaging + }) + session.dosesForStorage() { (doses) -> Bool in + return self.store(doses: doses, in: session) } + completion(nil) + } else { + self.setState({ (state) in + state.tempBasalEngageState = .engaging + }) - if resumingScheduledBasal { - self.setState({ (state) in - state.tempBasalEngageState = .disengaging - }) + var calendar = Calendar(identifier: .gregorian) + calendar.timeZone = self.state.timeZone + let scheduledRate = self.state.basalSchedule.currentRate(using: calendar, at: self.dateGenerator()) + let isHighTemp = rate > scheduledRate + + let result = session.setTempBasal(rate: rate, duration: duration, isHighTemp: isHighTemp, automatic: automatic, acknowledgementBeep: acknowledgementBeep, completionBeep: completionBeep) + switch result { + case .success: session.dosesForStorage() { (doses) -> Bool in return self.store(doses: doses, in: session) } completion(nil) - } else { - self.setState({ (state) in - state.tempBasalEngageState = .engaging - }) - - var calendar = Calendar(identifier: .gregorian) - calendar.timeZone = self.state.timeZone - let scheduledRate = self.state.basalSchedule.currentRate(using: calendar, at: self.dateGenerator()) - let isHighTemp = rate > scheduledRate - - let result = session.setTempBasal(rate: rate, duration: duration, isHighTemp: isHighTemp, automatic: automatic, acknowledgementBeep: acknowledgementBeep, completionBeep: completionBeep) - - switch result { - case .success: - session.dosesForStorage() { (doses) -> Bool in - return self.store(doses: doses, in: session) - } - completion(nil) - case .unacknowledged(let error): - throw error - case .certainFailure(let error): - throw error - } + case .unacknowledged(let error): + self.log.error("Temp basal uncertain error: %@", String(describing: error)) + completion(nil) + case .certainFailure(let error): + self.log.error("setTempBasal failed: %{public}@", String(describing: error)) + completion(.communication(error)) } - } catch let error { - self.log.error("Error during temp basal: %{public}@", String(describing: error)) - completion(.communication(error as? LocalizedError)) } } } diff --git a/Dependencies/OmniBLE/OmniBLE/PumpManager/PodCommsSession.swift b/Dependencies/OmniBLE/OmniBLE/PumpManager/PodCommsSession.swift index 24392b65cf..739a9a5104 100644 --- a/Dependencies/OmniBLE/OmniBLE/PumpManager/PodCommsSession.swift +++ b/Dependencies/OmniBLE/OmniBLE/PumpManager/PodCommsSession.swift @@ -38,6 +38,7 @@ public enum PodCommsError: Error { case podIncompatible(str: String) case noPodsFound case tooManyPodsFound + case setupNotComplete } extension PodCommsError: LocalizedError { @@ -96,7 +97,8 @@ extension PodCommsError: LocalizedError { return LocalizedString("No pods found", comment: "Error message for PodCommsError.noPodsFound") case .tooManyPodsFound: return LocalizedString("Too many pods found", comment: "Error message for PodCommsError.tooManyPodsFound") - + case .setupNotComplete: + return LocalizedString("Pod setup is not complete", comment: "Error description when pod setup is not complete") } } @@ -158,6 +160,8 @@ extension PodCommsError: LocalizedError { return LocalizedString("Make sure your pod is filled and nearby.", comment: "Recovery suggestion for PodCommsError.noPodsFound") case .tooManyPodsFound: return LocalizedString("Move to a new area away from any other pods and try again.", comment: "Recovery suggestion for PodCommsError.tooManyPodsFound") + case .setupNotComplete: + return nil } } @@ -274,7 +278,9 @@ public class PodCommsSession { let message = Message(address: podState.address, messageBlocks: blocksToSend, sequenceNum: messageNumber, expectFollowOnMessage: expectFollowOnMessage) - self.podState.lastCommsOK = false // mark last comms as not OK until we get the expected response + // Clear the lastDeliveryStatusReceived variable which is used to guard against possible 0x31 pod faults + podState.lastDeliveryStatusReceived = nil + let response = try transport.sendMessage(message) // Simulate fault @@ -283,7 +289,6 @@ public class PodCommsSession { if let responseMessageBlock = response.messageBlocks[0] as? T { log.info("POD Response: %{public}@", String(describing: responseMessageBlock)) - self.podState.lastCommsOK = true // message successfully sent and expected response received return responseMessageBlock } @@ -508,16 +513,18 @@ public class PodCommsSession { let timeBetweenPulses = TimeInterval(seconds: Pod.secondsPerBolusPulse) let bolusScheduleCommand = SetInsulinScheduleCommand(nonce: podState.currentNonce, units: units, timeBetweenPulses: timeBetweenPulses, extendedUnits: extendedUnits, extendedDuration: extendedDuration) - // Do a getstatus to verify that there isn't an on-going bolus in progress if the last bolus command is still - // finalized, if the last delivery status wasn't successfully verified or the last comms attempt wasn't OK - if podState.unfinalizedBolus != nil || !podState.deliveryStatusVerified || !podState.lastCommsOK { - var ongoingBolus = true + // Do a get status here to verify that there isn't an on-going bolus in progress if the last bolus command + // is still not finalized OR we don't have the last pod delivery status confirming that no bolus is active. + if podState.unfinalizedBolus != nil || podState.lastDeliveryStatusReceived == nil || podState.lastDeliveryStatusReceived!.bolusing { if let statusResponse: StatusResponse = try? send([GetStatusCommand()]) { podState.updateFromStatusResponse(statusResponse, at: currentDate) - ongoingBolus = podState.unfinalizedBolus != nil - } - guard !ongoingBolus else { - return DeliveryCommandResult.certainFailure(error: .unfinalizedBolus) + guard podState.unfinalizedBolus == nil else { + log.default("bolus: pod is still bolusing") + return DeliveryCommandResult.certainFailure(error: .unfinalizedBolus) + } + } else { + log.default("bolus: failed to read pod status to verify there is no bolus running") + return DeliveryCommandResult.certainFailure(error: .noResponse) } } @@ -619,6 +626,11 @@ public class PodCommsSession { return .certainFailure(error: .unacknowledgedCommandPending) } + guard podState.setupProgress == .completed else { + // A cancel delivery command before pod setup is complete will fault the pod + return .certainFailure(error: PodCommsError.setupNotComplete) + } + do { var alertConfigurations: [AlertConfiguration] = [] var podSuspendedReminderAlert: PodAlert? = nil @@ -699,6 +711,11 @@ public class PodCommsSession { return .certainFailure(error: .unacknowledgedCommandPending) } + guard podState.setupProgress == .completed else { + // A cancel delivery command before pod setup is complete will fault the pod + return .certainFailure(error: PodCommsError.setupNotComplete) + } + do { podState.unacknowledgedCommand = PendingCommand.stopProgram(deliveryType, transport.messageNumber, currentDate) let cancelDeliveryCommand = CancelDeliveryCommand(nonce: podState.currentNonce, deliveryType: deliveryType, beepType: beepType) @@ -747,10 +764,13 @@ public class PodCommsSession { let basalExtraCommand = BasalScheduleExtraCommand.init(schedule: schedule, scheduleOffset: scheduleOffset, acknowledgementBeep: acknowledgementBeep, programReminderInterval: programReminderInterval) do { - if podState.setupProgress == .completed && !(podState.lastCommsOK && podState.deliveryStatusVerified) { - // The pod setup is complete and the current delivery state can't be trusted so - // do a cancel all to be sure that setting the basal program won't fault the pod. - let _: StatusResponse = try send([CancelDeliveryCommand(nonce: podState.currentNonce, deliveryType: .all, beepType: .noBeepCancel)]) + if !podState.isSuspended || podState.lastDeliveryStatusReceived == nil || !podState.lastDeliveryStatusReceived!.suspended { + // The podState or the last pod delivery status return indicates that the pod is not currently suspended. + // So execute a cancel all command here before setting the basal to prevent a possible 0x31 pod fault, + // but only when the pod startup is complete as a cancel command during pod setup also fault the pod! + if podState.setupProgress == .completed { + let _: StatusResponse = try send([CancelDeliveryCommand(nonce: podState.currentNonce, deliveryType: .all, beepType: .noBeepCancel)]) + } } var status: StatusResponse = try send([basalScheduleCommand, basalExtraCommand]) let now = currentDate diff --git a/Dependencies/OmniBLE/OmniBLE/PumpManager/PodState.swift b/Dependencies/OmniBLE/OmniBLE/PumpManager/PodState.swift index 31fc77a9f7..7c55d73890 100644 --- a/Dependencies/OmniBLE/OmniBLE/PumpManager/PodState.swift +++ b/Dependencies/OmniBLE/OmniBLE/PumpManager/PodState.swift @@ -111,11 +111,12 @@ public struct PodState: RawRepresentable, Equatable, CustomDebugStringConvertibl return false } - // the following two vars are not persistent across app restarts - public var deliveryStatusVerified: Bool - public var lastCommsOK: Bool + var lastDeliveryStatusReceived: DeliveryStatus? // this variable is not persistent across app restarts - public init(address: UInt32, ltk: Data, firmwareVersion: String, bleFirmwareVersion: String, lotNo: UInt32, lotSeq: UInt32, productId: UInt8, messageTransportState: MessageTransportState? = nil, bleIdentifier: String, insulinType: InsulinType) { + + public init(address: UInt32, ltk: Data, firmwareVersion: String, bleFirmwareVersion: String, lotNo: UInt32, lotSeq: UInt32, productId: UInt8, + messageTransportState: MessageTransportState? = nil, bleIdentifier: String, insulinType: InsulinType, initialDeliveryStatus: DeliveryStatus? = nil) + { self.address = address self.ltk = ltk self.firmwareVersion = firmwareVersion @@ -134,9 +135,8 @@ public struct PodState: RawRepresentable, Equatable, CustomDebugStringConvertibl self.configuredAlerts = [.slot7Expired: .waitingForPairingReminder] self.bleIdentifier = bleIdentifier self.insulinType = insulinType - self.deliveryStatusVerified = false - self.lastCommsOK = false self.podTime = 0 + self.lastDeliveryStatusReceived = initialDeliveryStatus // can be non-nil when testing } public var unfinishedSetup: Bool { @@ -293,24 +293,22 @@ public struct PodState: RawRepresentable, Equatable, CustomDebugStringConvertibl self.unacknowledgedCommand = nil } - private mutating func updateDeliveryStatus(deliveryStatus: DeliveryStatus, podProgressStatus: PodProgressStatus, bolusNotDelivered: Double, at date: Date) { - deliveryStatusVerified = true - // See if the pod deliveryStatus indicates an active bolus or temp basal that the PodState isn't tracking (possible Loop restart) - if deliveryStatus.bolusing && unfinalizedBolus == nil { // active bolus that Loop doesn't know about? + // save the current pod delivery state for verification before any insulin delivery command + self.lastDeliveryStatusReceived = deliveryStatus + + // See if the pod's deliveryStatus indicates some insulin delivery that podState isn't tracking + if deliveryStatus.bolusing && unfinalizedBolus == nil { // active bolus that we aren't tracking if podProgressStatus.readyForDelivery { - deliveryStatusVerified = false // remember that we had inconsistent (bolus) delivery status // Create an unfinalizedBolus with the remaining bolus amount to capture what we can. unfinalizedBolus = UnfinalizedDose(bolusAmount: bolusNotDelivered, startTime: date, scheduledCertainty: .certain, insulinType: insulinType, automatic: false) } } - if deliveryStatus.tempBasalRunning && unfinalizedTempBasal == nil { // active temp basal that app isn't tracking - deliveryStatusVerified = false // remember that we had inconsistent (temp basal) delivery status + if deliveryStatus.tempBasalRunning && unfinalizedTempBasal == nil { // active temp basal that we aren't tracking // unfinalizedTempBasal = UnfinalizedDose(tempBasalRate: 0, startTime: Date(), duration: .minutes(30), isHighTemp: false, scheduledCertainty: .certain, insulinType: insulinType) } - if deliveryStatus != .suspended && isSuspended { // active basal that app isn't tracking - deliveryStatusVerified = false // remember that we had inconsistent (basal) delivery status + if deliveryStatus != .suspended && isSuspended { // active basal that we aren't tracking let resumeStartTime = Date() suspendState = .resumed(resumeStartTime) unfinalizedResume = UnfinalizedDose(resumeStartTime: resumeStartTime, scheduledCertainty: .certain, insulinType: insulinType) @@ -511,8 +509,7 @@ public struct PodState: RawRepresentable, Equatable, CustomDebugStringConvertibl self.insulinType = .novolog } - self.deliveryStatusVerified = false - self.lastCommsOK = false + self.lastDeliveryStatusReceived = nil } public var rawValue: RawValue { diff --git a/Dependencies/OmniKit/OmniKit/OmnipodCommon/Pod.swift b/Dependencies/OmniKit/OmniKit/OmnipodCommon/Pod.swift index d98621a732..4e6308c145 100644 --- a/Dependencies/OmniKit/OmniKit/OmnipodCommon/Pod.swift +++ b/Dependencies/OmniKit/OmniKit/OmnipodCommon/Pod.swift @@ -108,16 +108,20 @@ public enum DeliveryStatus: UInt8, CustomStringConvertible { case bolusAndTempBasal = 6 case extendedBolusRunning = 9 case extendedBolusAndTempBasal = 10 - + + public var suspended: Bool { + return self == .suspended + } + public var bolusing: Bool { return self == .bolusInProgress || self == .bolusAndTempBasal || self == .extendedBolusRunning || self == .extendedBolusAndTempBasal } - + public var tempBasalRunning: Bool { return self == .tempBasalRunning || self == .bolusAndTempBasal || self == .extendedBolusAndTempBasal } - public var extendedBolusRunninng: Bool { + public var extendedBolusRunning: Bool { return self == .extendedBolusRunning || self == .extendedBolusAndTempBasal } diff --git a/Dependencies/OmniKit/OmniKit/PumpManager/OmnipodPumpManager.swift b/Dependencies/OmniKit/OmniKit/PumpManager/OmnipodPumpManager.swift index 777d324250..d0b578fbcb 100644 --- a/Dependencies/OmniKit/OmniKit/PumpManager/OmnipodPumpManager.swift +++ b/Dependencies/OmniKit/OmniKit/PumpManager/OmnipodPumpManager.swift @@ -44,7 +44,6 @@ public enum OmnipodPumpManagerError: Error { case insulinTypeNotConfigured case notReadyForCannulaInsertion case invalidSetting - case setupNotComplete case communication(Error) case state(Error) } @@ -57,13 +56,11 @@ extension OmnipodPumpManagerError: LocalizedError { case .podAlreadyPaired: return LocalizedString("Pod already paired", comment: "Error message shown when user cannot pair because pod is already paired") case .insulinTypeNotConfigured: - return LocalizedString("Insulin type not configured", comment: "Error description for OmniBLEPumpManagerError.insulinTypeNotConfigured") + return LocalizedString("Insulin type not configured", comment: "Error description for insulin type not configured") case .notReadyForCannulaInsertion: return LocalizedString("Pod is not in a state ready for cannula insertion.", comment: "Error message when cannula insertion fails because the pod is in an unexpected state") case .invalidSetting: return LocalizedString("Invalid Setting", comment: "Error description for invalid setting") - case .setupNotComplete: - return LocalizedString("Pod setup is not complete", comment: "Error description when pod setup is not complete") case .communication(let error): if let error = error as? LocalizedError { return error.errorDescription @@ -1026,7 +1023,7 @@ extension OmnipodPumpManager { guard state.podState?.setupProgress == .completed else { // A cancel delivery command before pod setup is complete will fault the pod - completion(.state(OmnipodPumpManagerError.setupNotComplete)) + completion(.state(PodCommsError.setupNotComplete)) return } @@ -1066,7 +1063,7 @@ extension OmnipodPumpManager { guard state.podState?.setupProgress == .completed else { // A cancel delivery command before pod setup is complete will fault the pod - return .failure(PumpManagerError.deviceState(OmnipodPumpManagerError.setupNotComplete)) + return .failure(PumpManagerError.deviceState(PodCommsError.setupNotComplete)) } guard state.podState?.unfinalizedBolus?.isFinished() != false else { @@ -1815,7 +1812,7 @@ extension OmnipodPumpManager: PumpManager { guard state.podState?.setupProgress == .completed else { // A cancel delivery command before pod setup is complete will fault the pod - completion(.failure(PumpManagerError.deviceState(OmnipodPumpManagerError.setupNotComplete))) + completion(.failure(PumpManagerError.deviceState(PodCommsError.setupNotComplete))) return } @@ -1879,14 +1876,14 @@ extension OmnipodPumpManager: PumpManager { public func runTemporaryBasalProgram(unitsPerHour: Double, for duration: TimeInterval, automatic: Bool, completion: @escaping (PumpManagerError?) -> Void) { - guard self.hasActivePod else { + guard self.hasActivePod, let podState = self.state.podState else { completion(.configuration(OmnipodPumpManagerError.noPodPaired)) return } guard state.podState?.setupProgress == .completed else { // A cancel delivery command before pod setup is complete will fault the pod - completion(.deviceState(OmnipodPumpManagerError.setupNotComplete)) + completion(.deviceState(PodCommsError.setupNotComplete)) return } @@ -1920,7 +1917,7 @@ extension OmnipodPumpManager: PumpManager { return } - if case .some(.suspended) = self.state.podState?.suspendState { + if case (.suspended) = podState.suspendState { self.log.info("Not enacting temp basal because podState indicates pod is suspended.") completion(.deviceState(PodCommsError.podSuspended)) return @@ -1930,18 +1927,17 @@ extension OmnipodPumpManager: PumpManager { let resumingScheduledBasal = duration < .ulpOfOne // If a bolus is not finished, fail if not resuming the scheduled basal - guard self.state.podState?.unfinalizedBolus?.isFinished() != false || resumingScheduledBasal else { + guard podState.unfinalizedBolus?.isFinished() != false || resumingScheduledBasal else { self.log.info("Not enacting temp basal because podState indicates unfinalized bolus in progress.") completion(.deviceState(PodCommsError.unfinalizedBolus)) return } - // Did the last message have comms issues or is the last delivery status not verified correctly? - let uncertainDeliveryStatus = self.state.podState?.lastCommsOK == false || self.state.podState?.deliveryStatusVerified == false - - // Do the cancel temp basal command if currently running a temp basal OR - // if resuming scheduled basal delivery OR if the delivery status is uncertain. - if self.state.podState?.unfinalizedTempBasal != nil || resumingScheduledBasal || uncertainDeliveryStatus { + // Do the safe cancel TB command when resuming scheduled basal delivery OR if unfinalizedTempBasal indicates a + // running a temp basal OR if we don't have the last pod delivery status confirming that no temp basal is running. + if resumingScheduledBasal || podState.unfinalizedTempBasal != nil || + podState.lastDeliveryStatusReceived == nil || podState.lastDeliveryStatusReceived!.tempBasalRunning + { let status: StatusResponse // if resuming scheduled basal delivery & an acknowledgement beep is needed, use the cancel TB beep @@ -1952,7 +1948,6 @@ extension OmnipodPumpManager: PumpManager { completion(.communication(error)) return case .unacknowledged(let error): - // TODO: Return PumpManagerError.uncertainDelivery and implement recovery completion(.communication(error)) return case .success(let cancelTempStatus, _): diff --git a/Dependencies/OmniKit/OmniKit/PumpManager/PodCommsSession.swift b/Dependencies/OmniKit/OmniKit/PumpManager/PodCommsSession.swift index cca005e176..e1f042e5c8 100644 --- a/Dependencies/OmniKit/OmniKit/PumpManager/PodCommsSession.swift +++ b/Dependencies/OmniKit/OmniKit/PumpManager/PodCommsSession.swift @@ -38,6 +38,7 @@ public enum PodCommsError: Error { case podIncompatible(str: String) case noPodsFound case tooManyPodsFound + case setupNotComplete } extension PodCommsError: LocalizedError { @@ -98,7 +99,8 @@ extension PodCommsError: LocalizedError { return LocalizedString("No pods found", comment: "Error message for PodCommsError.noPodsFound") case .tooManyPodsFound: return LocalizedString("Too many pods found", comment: "Error message for PodCommsError.tooManyPodsFound") - + case .setupNotComplete: + return LocalizedString("Pod setup is not complete", comment: "Error description when pod setup is not complete") } } @@ -162,6 +164,8 @@ extension PodCommsError: LocalizedError { return LocalizedString("Make sure your pod is filled and nearby.", comment: "Recovery suggestion for PodCommsError.noPodsFound") case .tooManyPodsFound: return LocalizedString("Move to a new area away from any other pods and try again.", comment: "Recovery suggestion for PodCommsError.tooManyPodsFound") + case .setupNotComplete: + return nil } } @@ -279,7 +283,9 @@ public class PodCommsSession { let message = Message(address: podState.address, messageBlocks: blocksToSend, sequenceNum: messageNumber, expectFollowOnMessage: expectFollowOnMessage) - self.podState.lastCommsOK = false // mark last comms as not OK until we get the expected response + // Clear the lastDeliveryStatusReceived variable which is used to guard against possible 0x31 pod faults + podState.lastDeliveryStatusReceived = nil + let response = try transport.sendMessage(message) // Simulate fault @@ -288,7 +294,6 @@ public class PodCommsSession { if let responseMessageBlock = response.messageBlocks[0] as? T { log.info("POD Response: %{public}@", String(describing: responseMessageBlock)) - self.podState.lastCommsOK = true // message successfully sent and expected response received return responseMessageBlock } @@ -513,16 +518,18 @@ public class PodCommsSession { let timeBetweenPulses = TimeInterval(seconds: Pod.secondsPerBolusPulse) let bolusScheduleCommand = SetInsulinScheduleCommand(nonce: podState.currentNonce, units: units, timeBetweenPulses: timeBetweenPulses, extendedUnits: extendedUnits, extendedDuration: extendedDuration) - // Do a getstatus to verify that there isn't an on-going bolus in progress if the last bolus command is still - // finalized, if the last delivery status wasn't successfully verified or the last comms attempt wasn't OK - if podState.unfinalizedBolus != nil || !podState.deliveryStatusVerified || !podState.lastCommsOK { - var ongoingBolus = true + // Do a get status here to verify that there isn't an on-going bolus in progress if the last bolus command + // is still not finalized OR we don't have the last pod delivery status confirming that no bolus is active. + if podState.unfinalizedBolus != nil || podState.lastDeliveryStatusReceived == nil || podState.lastDeliveryStatusReceived!.bolusing { if let statusResponse: StatusResponse = try? send([GetStatusCommand()]) { podState.updateFromStatusResponse(statusResponse, at: currentDate) - ongoingBolus = podState.unfinalizedBolus != nil - } - guard !ongoingBolus else { - return DeliveryCommandResult.certainFailure(error: .unfinalizedBolus) + guard podState.unfinalizedBolus == nil else { + log.default("bolus: pod is still bolusing") + return DeliveryCommandResult.certainFailure(error: .unfinalizedBolus) + } + } else { + log.default("bolus: failed to read pod status to verify there is no bolus running") + return DeliveryCommandResult.certainFailure(error: .noResponse) } } @@ -624,6 +631,11 @@ public class PodCommsSession { return .certainFailure(error: .unacknowledgedCommandPending) } + guard podState.setupProgress == .completed else { + // A cancel delivery command before pod setup is complete will fault the pod + return .certainFailure(error: PodCommsError.setupNotComplete) + } + do { var alertConfigurations: [AlertConfiguration] = [] var podSuspendedReminderAlert: PodAlert? = nil @@ -704,6 +716,11 @@ public class PodCommsSession { return .certainFailure(error: .unacknowledgedCommandPending) } + guard podState.setupProgress == .completed else { + // A cancel delivery command before pod setup is complete will fault the pod + return .certainFailure(error: PodCommsError.setupNotComplete) + } + do { podState.unacknowledgedCommand = PendingCommand.stopProgram(deliveryType, transport.messageNumber, currentDate) let cancelDeliveryCommand = CancelDeliveryCommand(nonce: podState.currentNonce, deliveryType: deliveryType, beepType: beepType) @@ -752,10 +769,13 @@ public class PodCommsSession { let basalExtraCommand = BasalScheduleExtraCommand.init(schedule: schedule, scheduleOffset: scheduleOffset, acknowledgementBeep: acknowledgementBeep, programReminderInterval: programReminderInterval) do { - if podState.setupProgress == .completed && !(podState.lastCommsOK && podState.deliveryStatusVerified) { - // The pod setup is complete and the current delivery state can't be trusted so - // do a cancel all to be sure that setting the basal program won't fault the pod. - let _: StatusResponse = try send([CancelDeliveryCommand(nonce: podState.currentNonce, deliveryType: .all, beepType: .noBeepCancel)]) + if !podState.isSuspended || podState.lastDeliveryStatusReceived == nil || !podState.lastDeliveryStatusReceived!.suspended { + // The podState or the last pod delivery status return indicates that the pod is not currently suspended. + // So execute a cancel all command here before setting the basal to prevent a possible 0x31 pod fault, + // but only when the pod startup is complete as a cancel command during pod setup also fault the pod! + if podState.setupProgress == .completed { + let _: StatusResponse = try send([CancelDeliveryCommand(nonce: podState.currentNonce, deliveryType: .all, beepType: .noBeepCancel)]) + } } var status: StatusResponse = try send([basalScheduleCommand, basalExtraCommand]) let now = currentDate diff --git a/Dependencies/OmniKit/OmniKit/PumpManager/PodState.swift b/Dependencies/OmniKit/OmniKit/PumpManager/PodState.swift index 48622a1fb7..354d1265cf 100644 --- a/Dependencies/OmniKit/OmniKit/PumpManager/PodState.swift +++ b/Dependencies/OmniKit/OmniKit/PumpManager/PodState.swift @@ -107,11 +107,10 @@ public struct PodState: RawRepresentable, Equatable, CustomDebugStringConvertibl return false } - // the following two vars are not persistent across app restarts - public var deliveryStatusVerified: Bool - public var lastCommsOK: Bool + var lastDeliveryStatusReceived: DeliveryStatus? // this variable is not persistent across app restarts - public init(address: UInt32, pmVersion: String, piVersion: String, lot: UInt32, tid: UInt32, packetNumber: Int = 0, messageNumber: Int = 0, insulinType: InsulinType) { + public init(address: UInt32, pmVersion: String, piVersion: String, lot: UInt32, tid: UInt32, packetNumber: Int = 0, messageNumber: Int = 0, insulinType: InsulinType, initialDeliveryStatus: DeliveryStatus? = nil) + { self.address = address self.nonceState = NonceState(lot: lot, tid: tid) self.pmVersion = pmVersion @@ -128,9 +127,8 @@ public struct PodState: RawRepresentable, Equatable, CustomDebugStringConvertibl self.setupProgress = .addressAssigned self.configuredAlerts = [.slot7Expired: .waitingForPairingReminder] self.insulinType = insulinType - self.deliveryStatusVerified = false - self.lastCommsOK = false self.podTime = 0 + self.lastDeliveryStatusReceived = initialDeliveryStatus // can be non-nil when testing } public var unfinishedSetup: Bool { @@ -285,21 +283,20 @@ public struct PodState: RawRepresentable, Equatable, CustomDebugStringConvertibl private mutating func updateDeliveryStatus(deliveryStatus: DeliveryStatus, podProgressStatus: PodProgressStatus, bolusNotDelivered: Double, at date: Date) { - deliveryStatusVerified = true - // See if the pod deliveryStatus indicates an active bolus or temp basal that the PodState isn't tracking (possible Loop restart) - if deliveryStatus.bolusing && unfinalizedBolus == nil { // active bolus that Loop doesn't know about? + // save the current pod delivery state for verification before any insulin delivery command + self.lastDeliveryStatusReceived = deliveryStatus + + // See if the pod's deliveryStatus indicates some insulin delivery that podState isn't tracking + if deliveryStatus.bolusing && unfinalizedBolus == nil { // active bolus that we aren't tracking if podProgressStatus.readyForDelivery { - deliveryStatusVerified = false // remember that we had inconsistent (bolus) delivery status // Create an unfinalizedBolus with the remaining bolus amount to capture what we can. unfinalizedBolus = UnfinalizedDose(bolusAmount: bolusNotDelivered, startTime: date, scheduledCertainty: .certain, insulinType: insulinType, automatic: false) } } - if deliveryStatus.tempBasalRunning && unfinalizedTempBasal == nil { // active temp basal that app isn't tracking - deliveryStatusVerified = false // remember that we had inconsistent (temp basal) delivery status + if deliveryStatus.tempBasalRunning && unfinalizedTempBasal == nil { // active temp basal that we aren't tracking // unfinalizedTempBasal = UnfinalizedDose(tempBasalRate: 0, startTime: Date(), duration: .minutes(30), isHighTemp: false, scheduledCertainty: .certain, insulinType: insulinType) } - if deliveryStatus != .suspended && isSuspended { // active basal that app isn't tracking - deliveryStatusVerified = false // remember that we had inconsistent (basal) delivery status + if deliveryStatus != .suspended && isSuspended { // active basal that we aren't tracking let resumeStartTime = Date() suspendState = .resumed(resumeStartTime) unfinalizedResume = UnfinalizedDose(resumeStartTime: resumeStartTime, scheduledCertainty: .certain, insulinType: insulinType) @@ -492,8 +489,7 @@ public struct PodState: RawRepresentable, Equatable, CustomDebugStringConvertibl self.insulinType = .novolog } - self.deliveryStatusVerified = false - self.lastCommsOK = false + self.lastDeliveryStatusReceived = nil } public var rawValue: RawValue { diff --git a/Dependencies/OmniKit/OmniKitTests/PodCommsSessionTests.swift b/Dependencies/OmniKit/OmniKitTests/PodCommsSessionTests.swift index 1a8ded160d..9d1302c330 100644 --- a/Dependencies/OmniKit/OmniKitTests/PodCommsSessionTests.swift +++ b/Dependencies/OmniKit/OmniKitTests/PodCommsSessionTests.swift @@ -20,7 +20,7 @@ class PodCommsSessionTests: XCTestCase { override func setUp() { - podState = PodState(address: address, pmVersion: "2.7.0", piVersion: "2.7.0", lot: 43620, tid: 560313, insulinType: .novolog) + podState = PodState(address: address, pmVersion: "2.7.0", piVersion: "2.7.0", lot: 43620, tid: 560313, insulinType: .novolog, initialDeliveryStatus: .scheduledBasal) mockTransport = MockMessageTransport(address: podState.address, messageNumber: 5) } @@ -34,6 +34,9 @@ class PodCommsSessionTests: XCTestCase { // 2018-05-26T09:11:08.580347 pod Message(1f16b11e seq:06 [OmniKitPacketParser.ErrorResponse(blockType: OmniKitPacketParser.MessageBlockType.errorResponse, errorReponseType: OmniKitPacketParser.ErrorResponse.ErrorReponseType.badNonce, nonceSearchKey: 43492, data: 5 bytes)]) mockTransport.addResponse(try ErrorResponse(encodedData: Data(hexadecimalString: "060314a9e403f5")!)) mockTransport.addResponse(try StatusResponse(encodedData: Data(hexadecimalString: "1d5800d1a8140012e3ff8018")!)) + // These responses are for session.bolus() which verifies that the pod is not bolusing before sending a bolus command + mockTransport.addResponse(try StatusResponse(encodedData: Data(hexadecimalString: "1d180160a800001cd3ff001e")!)) // not bolusing + mockTransport.addResponse(try StatusResponse(encodedData: Data(hexadecimalString: "1d580160e014001cd7ff81ce")!)) // bolus successfully started } catch (let error) { XCTFail("message decoding threw error: \(error)") return @@ -61,11 +64,12 @@ class PodCommsSessionTests: XCTestCase { XCTFail("message sending error: \(error)") } - // Try sending another bolus command: nonce should be 676940027 + // Try sending another bolus command: nonce should be 545302454 XCTAssertEqual(545302454, lastPodStateUpdate!.currentNonce) let _ = session.bolus(units: 2, automatic: false) - let bolusTry3 = mockTransport.sentMessages[2].messageBlocks[0] as! SetInsulinScheduleCommand + let lastSentMessageIndex = mockTransport.sentMessages.endIndex - 1 + let bolusTry3 = mockTransport.sentMessages[lastSentMessageIndex].messageBlocks[0] as! SetInsulinScheduleCommand XCTAssertEqual(545302454, bolusTry3.nonce) } From 58efd7c6a2fd18a73c137cc2220b51823b7bff06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Sat, 24 Feb 2024 11:01:37 +0100 Subject: [PATCH 07/44] New Crowdin updates (#521) --- .../es.lproj/Localizable.strings | 4 +- .../G7SensorKit/es.lproj/Localizable.strings | 2 +- .../es.lproj/Localizable.strings | 8 +- .../Main/ar.lproj/Localizable.strings | 20 +- .../Main/da.lproj/Localizable.strings | 20 +- .../Main/de.lproj/Localizable.strings | 20 +- .../Main/es.lproj/Localizable.strings | 492 +++++++++--------- .../Main/fi.lproj/Localizable.strings | 20 +- .../Main/fr.lproj/Localizable.strings | 30 +- .../Main/he.lproj/Localizable.strings | 20 +- .../Main/hu.lproj/Localizable.strings | 20 +- .../Main/it.lproj/Localizable.strings | 24 +- .../Main/nb.lproj/Localizable.strings | 20 +- .../Main/nl.lproj/Localizable.strings | 22 +- .../Main/pl.lproj/Localizable.strings | 20 +- .../Main/pt-BR.lproj/Localizable.strings | 20 +- .../Main/pt-PT.lproj/Localizable.strings | 20 +- .../Main/ru.lproj/Localizable.strings | 20 +- .../Main/sk.lproj/Localizable.strings | 20 +- .../Main/sv.lproj/Localizable.strings | 10 +- .../Main/tr.lproj/Localizable.strings | 20 +- .../Main/uk.lproj/Localizable.strings | 20 +- .../Main/vi.lproj/Localizable.strings | 30 +- .../Main/zh-Hans.lproj/Localizable.strings | 20 +- 24 files changed, 643 insertions(+), 279 deletions(-) diff --git a/Dependencies/G7SensorKit/G7SensorKitUI/es.lproj/Localizable.strings b/Dependencies/G7SensorKit/G7SensorKitUI/es.lproj/Localizable.strings index 4b41e6d168..5f2c696e3a 100644 --- a/Dependencies/G7SensorKit/G7SensorKitUI/es.lproj/Localizable.strings +++ b/Dependencies/G7SensorKit/G7SensorKitUI/es.lproj/Localizable.strings @@ -5,7 +5,7 @@ "%@/min" = "%@/min"; /* No comment provided by engineer. */ -"Are you sure you want to delete this CGM?" = "Are you sure you want to delete this CGM?"; +"Are you sure you want to delete this CGM?" = "¿Está usted seguro de querer eliminar este MCG?"; /* No comment provided by engineer. */ "Bluetooth" = "Bluetooth"; @@ -36,7 +36,7 @@ "Done" = "Hecho"; /* Field label */ -"Glucose" = "Glucose"; +"Glucose" = "Glucosa"; /* title for g7 settings row showing sensor grace period end time */ "Grace Period End" = "Grace Period End"; diff --git a/Dependencies/G7SensorKit/es.lproj/Localizable.strings b/Dependencies/G7SensorKit/es.lproj/Localizable.strings index 7851967612..2372e386d3 100644 --- a/Dependencies/G7SensorKit/es.lproj/Localizable.strings +++ b/Dependencies/G7SensorKit/es.lproj/Localizable.strings @@ -41,7 +41,7 @@ "Grace Period End" = "Grace Period End"; /* Field label */ -"Glucose" = "Glucose"; +"Glucose" = "Glucosa"; "Last Reading" = "Last Reading"; diff --git a/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings index 84ef29f74b..319f7028b2 100644 --- a/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings @@ -117,7 +117,7 @@ "day" = "day"; /* Unit for plural days in pod life remaining */ -"days" = "days"; +"days" = "días"; /* Unit for singular hour in pod life remaining */ "hour" = "hour"; @@ -285,13 +285,13 @@ "Set Confirmation Beeps Preference" = "Set Confirmation Beeps Preference"; /* */ -"Suspend" = "Suspend"; +"Suspend" = "Suspender"; /* */ "Failed to suspend: %{public}@" = "Failed to suspend: %{public}@"; /* */ -"Resume" = "Resume"; +"Resume" = "Reanudar"; /* */ "Bolus" = "Bolo"; @@ -508,7 +508,7 @@ "The window on the top of the Pod should be colored pink when the cannula is properly inserted into the skin." = "The window on the top of the Pod should be colored pink when the cannula is properly inserted into the skin."; /* Button label for user to answer cannula was properly inserted */ -"Yes" = "Yes"; +"Yes" = "Sí"; /* Button label for user to answer cannula was not properly inserted */ "No" = "No"; diff --git a/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings index c05b3c4ca1..a1f2376c0a 100644 --- a/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Enact"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manual Temp Basal"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Remote control"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings index 2f9326fb1d..a6deae607b 100644 --- a/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Udført"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Udfør"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manuel Temp Basal"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Fjernkontrol"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nKontroller nu alle dine nye indstillinger grundigt:\n\n* Basal Indstillinger\n * Kulhydratratios\n * Glukose Mål\n * Insulin Følsomhed\n * VIA\n\n i iAPS Indstillinger > Konfiguration.\n\nDårlige eller ugyldige profilindstillinger kan have katastrofale effekter."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings index 7170383034..ab59a27e46 100644 --- a/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "von"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Letzte Berechnung um"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Starten"; +/* Start a temp target or a profile override */ +"Start" = "Starten"; + /* */ "Manual Temp Basal" = "Manuelle Temporäre Basalrate"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Fernbedienung"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nBitte überprüfen Sie jetzt alle Ihre neuen Einstellungen gründlich:\n\n* Basaleinstellungen\n * Carb Ratios\n * Glukose-Ziele\n * Insulinempfindlichkeiten\n * DIA\n\n in iAPS-Einstellungen > Konfiguration.\n\nSchlechte oder ungültige Profileinstellungen können abscheuliche Effekte haben."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Dynamic ISF-Konstante anpassen"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individuelle Anpassung der berechneten dynamischen Verhältnisse. Die Voreinstellung ist 0,5. Je höher der Wert, desto größer ist die Korrektur Ihres ISF/CR für einen hohen oder niedrigen Blutzuckerwert. Die maximale/minimale Korrektur wird durch die Min/Max-Einstellungen von Autosens bestimmt.\n\nFür die Sigmoid-Funktion wird für den Anfang ein Anpassungsfaktor von 0,4 - 0,5 empfohlen.\n\nFür die logarithmische Formel gibt es weniger Konsens, aber ein Wert von 0,8 ist wahrscheinlich für die meisten erwachsenen Benutzer angemessen. Für jüngere Anwender wird empfohlen, bei der logaritmischen Formel noch niedriger anzusetzen, um eine zu aggressive Behandlung zu vermeiden."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Sigmoid-Funktion verwenden"; diff --git a/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings index f224da9747..3ad7d73d19 100644 --- a/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings @@ -17,7 +17,7 @@ "Continue without bolus" = "Continuar sin administrar bolo"; /* Alert when adding large amount without bolusing */ -"\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add "; +"\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "¡La cantidad es mayor que el ajuste del bolo máximo!\n ¿Está seguro de que desea añadir "; /* Header */ "Enact Bolus" = "Administrar Bolo"; @@ -47,49 +47,61 @@ "Agree and continue" = "Aceptar y continuar"; /* Bolus progress view */ -"of" = "of"; +"of" = "de"; + +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "Un Bolo Remoto "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "fue entregado"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " hace X minutos, activado de forma remota en Nightscout, por un cuidador o un padre. ¿Todavía quieres aplicar el bolo?\n\nSe prevé que la glucosa eventual, si no aplica un bolo, será: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "¡Un Bolo Remoto se acaba de entregar!"; /* Headline in enacted pop up (at: at what time) */ -"Enacted at" = "Enacted at"; +"Enacted at" = "Entregado a las"; /* Headline in suggested pop up (at: at what time) */ -"Suggested at" = "Suggested at"; +"Suggested at" = "Sugerido a las"; /* Headline in enacted pop up (at: at what time) */ -"Error at" = "Error at"; +"Error at" = "Error en"; /* Bolus View Meal Summary Header */ -"Meal Summary" = "Meal Summary"; +"Meal Summary" = "Resumen de la comida"; /* Bolus View Meal Edit Meal Button */ -"Edit Meal" = "Edit Meal"; +"Edit Meal" = "Editar comida"; /* Bolus View Meal Add Meal Button */ -"Add Meal" = "Add Meal"; +"Add Meal" = "Agregar Alimento"; /* Bolus View Bolus Summary Header */ -"Bolus Summary" = "Bolus Summary"; +"Bolus Summary" = "Resumen del Bolo"; /* For the Bolus View pop-up */ -"Calculations" = "Calculations"; +"Calculations" = "Cálculos"; /* For the Bolus View pop-up */ -"Fatty Meal" = "Fatty Meal"; +"Fatty Meal" = "Comida Grasienta"; /* For the Bolus View pop-up */ -"Full Bolus" = "Full Bolus"; +"Full Bolus" = "Bolo Completo"; /* For the Bolus View pop-up */ -"Fraction" = "Fraction"; +"Fraction" = "Fracción"; /* For the Bolus View pop-up */ -"Fatty Meal Factor" = "Fatty Meal Factor"; +"Fatty Meal Factor" = "Factor de comida grasienta"; /* For the Bolus View pop-up */ -"Result" = "Result"; +"Result" = "Resultado"; /* For the Bolus View pop-up */ -"Your entered amount was limited by your max Bolus setting of %d%@" = "Your entered amount was limited by your max Bolus setting of %d%@"; +"Your entered amount was limited by your max Bolus setting of %d%@" = "La cantidad ingresada ha sido limitada por la configuración máxima del bolo de %d%@"; /* Bolus View Continue Button */ "Continue" = "Continuar"; @@ -125,7 +137,7 @@ "Carbs required" = "Se requieren carbohidratos"; /* Saved Food Presets */ -"Saved Food" = "Saved Food"; +"Saved Food" = "Alimento guardado"; /* */ "Are you sure?" = "¿Estás seguro?"; @@ -158,19 +170,19 @@ "Enact Temp Target" = "Iniciar objetivo temporal"; /* */ -"Target" = "Target"; +"Target" = "Objetivo"; /* */ -"Basal Insulin and Sensitivity ratio" = "Basal Insulin and Sensitivity ratio"; +"Basal Insulin and Sensitivity ratio" = "Ratio de insulina basal y sensibilidad"; /* */ -"A lower 'Half Basal Target' setting will reduce the basal and raise the ISF earlier, at a lower target glucose." = "A lower 'Half Basal Target' setting will reduce the basal and raise the ISF earlier, at a lower target glucose."; +"A lower 'Half Basal Target' setting will reduce the basal and raise the ISF earlier, at a lower target glucose." = "Un ajuste inferior de 'Objetivo Basal Medio' reducirá la basal y elevará el factor de sensibilidad antes, en un objetivo glucémico más bajo."; /* */ -" Your setting: " = " Your setting: "; +" Your setting: " = " Tu configuración: "; /* */ -"mg/dl. Autosens.max limits the max endpoint" = "mg/dl. Autosens.max limits the max endpoint"; +"mg/dl. Autosens.max limits the max endpoint" = "mg/dl. Autosens.max limita el extremo máximo"; /* */ "Enter preset name" = "Introduzca nombre del predef"; @@ -188,19 +200,19 @@ "Save" = "Guardar"; /* */ -"Save as Preset" = "Save as Preset"; +"Save as Preset" = "Guardar como Ajuste Predefinido"; /* Delete Meal Preset */ -"Delete Preset" = "Delete Preset"; +"Delete Preset" = "Eliminar Ajuste Predefinido"; /* Confirm Deletion */ -"Delete preset '%@'?" = "Delete preset '%@'?"; +"Delete preset '%@'?" = "¿Eliminar ajuste predefinido \"%@'?"; /* Button */ "No" = "No"; /* Button */ -"Yes" = "Yes"; +"Yes" = "Sí"; /* + Button */ "[ +1 ]" = "[ +1 ]"; @@ -212,7 +224,7 @@ "Top target" = "Objetivo Superior"; /* Temp target set for ... minutes */ -"for" = "for"; +"for" = "para"; /* Temp target set for ... minutes */ "min" = "min"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Ejecutar"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Basal temporal manual"; @@ -339,7 +354,7 @@ Enact a temp Basal or a temp target */ "Use local glucose server" = "Usar servidor local de glucosa"; /* Enable Statistics */ -"This enables uploading of statistics.json to Nightscout, which can be used by the Community Statistics and Demographics Project.\n\nParticipation in Community Statistics is opt-in, and requires separate registration at:\n" = "This enables uploading of statistics.json to Nightscout, which can be used by the Community Statistics and Demographics Project.\n\nParticipation in Community Statistics is opt-in, and requires separate registration at:\n"; +"This enables uploading of statistics.json to Nightscout, which can be used by the Community Statistics and Demographics Project.\n\nParticipation in Community Statistics is opt-in, and requires separate registration at:\n" = "Esto permite subir estadísticas.json a Nightscout, que puede ser utilizado por el Proyecto de Estadísticas y Demografía de la Comunidad.\n\nLa participación en las estadísticas de la comunidad es opcional, y requiere registrarse por separado en:\n"; /* */ "Edit settings json" = "Editar configuración json"; @@ -359,38 +374,41 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Control a distancia"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Permitir Control Remoto de iAPS"; + /* Imported Profiles Alert */ -"\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; +"\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nAhora, por favor, verifique todos sus nuevos ajustes de forma exhaustiva:\n\n* Ajustes Basales\n * Relación de Carbs\n * Objetivos de Glucosa\n * Sensibilidades a la Insulina\n * DAI\n\n en Ajustes de iAPS > Configuración.\n\nConfiguración del perfil incorrecta o inválida podría tener efectos desatrosos."; /* Profile Import Alert */ -"This will replace some or all of your current pump settings. Are you sure you want to import profile settings from Nightscout?" = "This will replace some or all of your current pump settings. Are you sure you want to import profile settings from Nightscout?"; +"This will replace some or all of your current pump settings. Are you sure you want to import profile settings from Nightscout?" = "Esto reemplazará algunos o todos los ajustes actuales de la bomba. ¿Está seguro de que desea importar la configuración del perfil de Nightscout?"; /* Import Error */ -"\nInvalid Nightcsout Basal Settings. \n\nImport aborted. Please check your Nightscout Profile Basal Settings!" = "\nInvalid Nightcsout Basal Settings. \n\nImport aborted. Please check your Nightscout Profile Basal Settings!"; +"\nInvalid Nightcsout Basal Settings. \n\nImport aborted. Please check your Nightscout Profile Basal Settings!" = "\nConfiguración basal de Nightscout inválida. \n\nImportación cancelada. ¡Compruebe la configuración basal de su perfil de Nightscout!"; /* Import Error */ -"\nSettings were imported but the Basals couldn't be saved to pump (No pump). Check your basal settings and tap ´Save on Pump´ to sync the new basal settings" = "\nSettings were imported but the Basals couldn't be saved to pump (No pump). Check your basal settings and tap ´Save on Pump´ to sync the new basal settings"; +"\nSettings were imported but the Basals couldn't be saved to pump (No pump). Check your basal settings and tap ´Save on Pump´ to sync the new basal settings" = "\nConfiguración importada pero las Basales no se pudieron guardar en la bomba (Sin bomba). Revisa la configuración basal y pulsa \"Guardar en la bomba\" para sincronizar la nueva configuración basal"; /* Import Error Headline */ -"Import Error" = "Import Error"; +"Import Error" = "Error de Importación"; /* */ -"Yes, Import" = "Yes, Import"; +"Yes, Import" = "Sí, Importar"; /* */ -"Import settings from Nightscout" = "Import settings from Nightscout"; +"Import settings from Nightscout" = "Importar ajustes de Nightscout"; /* */ -"Import settings?" = "Import settings?"; +"Import settings?" = "¿Importar ajustes?"; /* */ -"Import from Nightscout" = "Import from Nightscout"; +"Import from Nightscout" = "Importar de Nightscout"; /* */ -"Settings imported" = "Settings imported"; +"Settings imported" = "Ajustes importados"; /* Import Error */ -"\nMismatching glucose units in Nightscout and Pump Settings. Import settings aborted." = "\nMismatching glucose units in Nightscout and Pump Settings. Import settings aborted."; +"\nMismatching glucose units in Nightscout and Pump Settings. Import settings aborted." = "Las unidades de glucosa de Nightscout y la bomba no coinciden. Ajustes de importación cancelados."; /* Import Error */ "Can't find the default Nightscout Profile." = "Can't find the default Nightscout Profile."; @@ -683,10 +701,10 @@ Enact a temp Basal or a temp target */ "Pairinginfo" = "Pairinginfo"; /* */ -"PatchInfo" = "PatchInfo"; +"PatchInfo" = "Info del parche"; /* */ -"Calibrationinfo" = "Calibrationinfo"; +"Calibrationinfo" = "Info de calibración"; /* */ "Unknown" = "Desconocido"; @@ -695,139 +713,139 @@ Enact a temp Basal or a temp target */ "Not paired yet" = "No emparejado aún"; /* */ -"Pair Sensor & connect" = "Pair Sensor & connect"; +"Pair Sensor & connect" = "Emparejar Sensor y conectar"; /* */ -"Phone NFC required!" = "Phone NFC required!"; +"Phone NFC required!" = "¡Es necesario un teléfono con NFC!"; /* */ -"Your phone or app is not enabled for NFC communications, which is needed to pair to libre2 sensors" = "Your phone or app is not enabled for NFC communications, which is needed to pair to libre2 sensors"; +"Your phone or app is not enabled for NFC communications, which is needed to pair to libre2 sensors" = "Tu teléfono o aplicación no está habilitada para el uso de NFC, lo que es necesario para emparejar con sensores Libre 2"; /* Bluetooth Power Off */ -"Bluetooth Power Off" = "Bluetooth Power Off"; +"Bluetooth Power Off" = "Apagar Bluetooth"; /* Please turn on Bluetooth */ -"Please turn on Bluetooth" = "Please turn on Bluetooth"; +"Please turn on Bluetooth" = "Por favor, active el Bluetooth"; /* No Libre Transmitter Selected */ -"No Libre Transmitter Selected" = "No Libre Transmitter Selected"; +"No Libre Transmitter Selected" = "Ningún Transmisor Libre seleccionado"; /* Delete Transmitter and start anew. */ -"Delete CGMManager and start anew. Your libreoopweb credentials will be preserved" = "Delete CGMManager and start anew. Your libreoopweb credentials will be preserved"; +"Delete CGMManager and start anew. Your libreoopweb credentials will be preserved" = "Eliminar el gestor de MCG e iniciar de nuevo. Sus credenciales libreoopweb se conservarán"; /* Invalid libre checksum */ -"Invalid libre checksum" = "Invalid libre checksum"; +"Invalid libre checksum" = "Suma de verificación del Libre no válida"; /* Libre sensor was incorrectly read, CRCs were not valid */ -"Libre sensor was incorrectly read, CRCs were not valid" = "Libre sensor was incorrectly read, CRCs were not valid"; +"Libre sensor was incorrectly read, CRCs were not valid" = "El sensor Libre fue leído incorrectamente, sus CRCs no son válidos"; /* Glucose */ -"Glucose" = "Glucose"; +"Glucose" = "Glucosa"; /* LOWALERT! */ -"LOWALERT!" = "LOWALERT!"; +"LOWALERT!" = "¡ALERTA BAJA!"; /* HIGHALERT! */ -"HIGHALERT!" = "HIGHALERT!"; +"HIGHALERT!" = "¡ALERTA ALTA!"; /* (Snoozed)*/ -"(Snoozed)" = "(Snoozed)"; +"(Snoozed)" = "(Pospuesto)"; /* Glucose: %@ */ -"Glucose: %@" = "Glucose: %@"; +"Glucose: %@" = "Glucosa: %@"; /* Transmitter: %@%% */ -"Transmitter: %@%%" = "Transmitter: %@%%"; +"Transmitter: %@%%" = "Transmisor %@"; /* No Sensor Detected */ -"No Sensor Detected" = "No Sensor Detected"; +"No Sensor Detected" = "Ningún sensor detectado"; /* This might be an intermittent problem, but please check that your transmitter is tightly secured over your sensor */ -"This might be an intermittent problem, but please check that your transmitter is tightly secured over your sensor" = "This might be an intermittent problem, but please check that your transmitter is tightly secured over your sensor"; +"This might be an intermittent problem, but please check that your transmitter is tightly secured over your sensor" = "Esto podría ser un problema intermitente, pero por favor compruebe que su transmisor está firmemente asegurado sobre su sensor"; /* New Sensor Detected */ -"New Sensor Detected" = "New Sensor Detected"; +"New Sensor Detected" = "Se ha detectado un sensor nuevo"; /* Please wait up to 30 minutes before glucose readings are available! */ -"Please wait up to 30 minutes before glucose readings are available!" = "Please wait up to 30 minutes before glucose readings are available!"; +"Please wait up to 30 minutes before glucose readings are available!" = "¡Por favor, espere hasta 30 minutos antes de que las lecturas de glucosa estén disponibles!"; /* Invalid Glucose sample detected, try again later */ -"Invalid Glucose sample detected, try again later" = "Invalid Glucose sample detected, try again later"; +"Invalid Glucose sample detected, try again later" = "Se detectó una muestra de glucosa no válida, inténtalo de nuevo más tarde"; /* ensor might have temporarily stopped, fallen off or is too cold or too warm */ -"Sensor might have temporarily stopped, fallen off or is too cold or too warm" = "Sensor might have temporarily stopped, fallen off or is too cold or too warm"; +"Sensor might have temporarily stopped, fallen off or is too cold or too warm" = "El sensor podría haberse detenido temporalmente, caído o estar demasiado frío o demasiado caliente"; /* Invalid Sensor Detected */ -"Invalid Sensor Detected" = "Invalid Sensor Detected"; +"Invalid Sensor Detected" = "Sensor no válido detectado"; /* Detected sensor seems not to be a libre 1 sensor! */ -"Detected sensor seems not to be a libre 1 sensor!" = "Detected sensor seems not to be a libre 1 sensor!"; +"Detected sensor seems not to be a libre 1 sensor!" = "¡El sensor detectado parece no ser un sensor Libre 1!"; /* Detected sensor is invalid: %@ */ -"Detected sensor is invalid: %@" = "Detected sensor is invalid: %@"; +"Detected sensor is invalid: %@" = "El sensor detectado no es válido: %@"; /* Low Battery */ -"Low battery" = "Low battery"; +"Low battery" = "Batería baja"; /* */ -"Invalid sensor" = "Invalid sensor"; +"Invalid sensor" = "Sensor inválido"; /* */ -"Sensor change" = "Sensor change"; +"Sensor change" = "Cambio de sensor"; /* */ -"Sensor expires soon" = "Sensor expires soon"; +"Sensor expires soon" = "El sensor expira pronto"; /* Battery is running low %@, consider charging your %@ device as soon as possible */ -"Battery is running low %@, consider charging your %@ device as soon as possible" = "Battery is running low %@, consider charging your %@ device as soon as possible"; +"Battery is running low %@, consider charging your %@ device as soon as possible" = "La batería es baja %@, considera cargar tu dispositivo %@ lo antes posible"; /* Extracting calibrationdata from sensor */ -"Extracting calibrationdata from sensor" = "Extracting calibrationdata from sensor"; +"Extracting calibrationdata from sensor" = "Extrayendo datos de calibración del sensor"; /* Sensor Ending Soon */ -"Sensor Ending Soon" = "Sensor Ending Soon"; +"Sensor Ending Soon" = "El sensor finaliza pronto"; /* Current Sensor is Ending soon! Sensor Life left in %@ */ -"Current Sensor is Ending soon! Sensor Life left in %@" = "Current Sensor is Ending soon! Sensor Life left in %@"; +"Current Sensor is Ending soon! Sensor Life left in %@" = "¡El sensor actual terminará pronto! Vida restante del sensor en %@"; /* */ "Libre Bluetooth" = "Bluetooth Libre"; /* */ -"Snooze Alerts" = "Snooze Alerts"; +"Snooze Alerts" = "Silenciar Alarmas"; /* */ "Last measurement" = "Última medición"; /* */ -"Sensor Footer checksum" = "Sensor Footer checksum"; +"Sensor Footer checksum" = "Suma de verificación del sensor"; /* */ -"Last Blood Sugar prediction" = "Last Blood Sugar prediction"; +"Last Blood Sugar prediction" = "Última predicción del nivel de glucosa"; /* */ -"CurrentBG" = "CurrentBG"; +"CurrentBG" = "Glucosa actual"; /* */ -"Sensor Info" = "Sensor Info"; +"Sensor Info" = "Info del sensor"; /* */ -"Sensor Age" = "Sensor Age"; +"Sensor Age" = "Tiempo del sensor"; /* */ -"Sensor Age Left" = "Sensor Age Left"; +"Sensor Age Left" = "Tiempo restante del sensor"; /* */ -"Sensor Endtime" = "Sensor Endtime"; +"Sensor Endtime" = "Caducidad del sensor"; /* */ -"Sensor State" = "Sensor State"; +"Sensor State" = "Estado del sensor"; /* */ -"Sensor Serial" = "Sensor Serial"; +"Sensor Serial" = "Serial del sensor"; /* */ -"Transmitter Info" = "Transmitter Info"; +"Transmitter Info" = "Información del transmisor"; /* */ "Hardware" = "Hardware"; @@ -839,13 +857,13 @@ Enact a temp Basal or a temp target */ "Connection State" = "Estado de Conexión"; /* */ -"Transmitter Type" = "Transmitter Type"; +"Transmitter Type" = "Tipo de transmisor"; /* */ -"Sensor Type" = "Sensor Type"; +"Sensor Type" = "Tipo de sensor"; /* */ -"Factory Calibration Parameters" = "Factory Calibration Parameters"; +"Factory Calibration Parameters" = "Parámetros de calibración de fábrica"; /* */ "Valid for footer" = "Valid for footer"; @@ -1001,157 +1019,157 @@ Enact a temp Basal or a temp target */ "Backfill options" = "Backfill options"; /* */ -"Backfilling from trend is currently not well supported by Loop" = "Backfilling from trend is currently not well supported by Loop"; +"Backfilling from trend is currently not well supported by Loop" = "El relleno de las tendencias no está bien soportado por Loop"; /* */ -"Backfill from history" = "Backfill from history"; +"Backfill from history" = "Rellenar valores desde historial"; /* */ -"Backfill from trend" = "Backfill from trend"; +"Backfill from trend" = "Rellenar valores desde tendencia"; /* */ -"Debug options" = "Debug options"; +"Debug options" = "Opciones de depuración"; /* */ -"Adds a lot of data to the Issue Report " = "Adds a lot of data to the Issue Report "; +"Adds a lot of data to the Issue Report " = "Añade muchos datos al Informe de Incidencias "; /* */ -"Persist sensordata" = "Persist sensordata"; +"Persist sensordata" = "Mantener datos del sensor"; /* */ -"Battery" = "Battery"; +"Battery" = "Batería"; /* */ -"Also add source info" = "Also add source info"; +"Also add source info" = "Añadir también información de origen"; /* */ -"Carbs Required Threshold" = "Carbs Required Threshold"; +"Carbs Required Threshold" = "Umbral de carbohidratos requeridos"; /* */ -"Carbs required: %d g" = "Carbs required: %d g"; +"Carbs required: %d g" = "Carbohidratos necesarios: %d g"; /* */ -"To prevent LOW required %d g of carbs" = "To prevent LOW required %d g of carbs"; +"To prevent LOW required %d g of carbs" = "Para prevenir BAJO se requieren %d g. de carbohidratos"; /* */ -"iAPS not active" = "iAPS not active"; +"iAPS not active" = "iAPS inactivo"; /* */ -"Last loop was more than %d min ago" = "Last loop was more than %d min ago"; +"Last loop was more than %d min ago" = "El último ciclo fue hace más de %d mins"; /* Glucose badge */ -"Show glucose on the app badge" = "Show glucose on the app badge"; +"Show glucose on the app badge" = "Mostrar glucosa en la insignia de la aplicación"; /* */ -"Backfill glucose" = "Backfill glucose"; +"Backfill glucose" = "Rellenar valores de glucosa"; /* About this source */ -"About this source" = "About this source"; +"About this source" = "Acerca de esta fuente"; /* */ -"Bolus failed" = "Bolus failed"; +"Bolus failed" = "Bolo fallido"; /* "Max Bolus Exceeded label" */ -"Max Bolus exceeded!" = "Max Bolus exceeded!"; +"Max Bolus exceeded!" = "¡Bolo máximo superado!"; /* */ -"Bolus failed or inaccurate. Check pump history before repeating." = "Bolus failed or inaccurate. Check pump history before repeating."; +"Bolus failed or inaccurate. Check pump history before repeating." = "Bolo fallido o inexacto. Revise el historial de la bomba antes de repetir la acción."; /* */ -"Carbs" = "Carbs"; +"Carbs" = "Carbohidratos"; /* Food Type / Meal Note */ -"Note" = "Note"; +"Note" = "Nota"; /* */ -"Temp Basal" = "Temp Basal"; +"Temp Basal" = "Insulina basal temporal"; /* */ -"Temp Target" = "Temp Target"; +"Temp Target" = "Objetivo temporal"; /* */ -"Resume" = "Resume"; +"Resume" = "Reanudar"; /* */ -"Suspend" = "Suspend"; +"Suspend" = "Suspender"; /* */ -"Animated Background" = "Animated Background"; +"Animated Background" = "Fondo animado"; /* Sensor day(s) */ -" day(s)" = " day(s)"; +" day(s)" = " día(s)"; /* Option to show HR in Watch app*/ -"Display HR on Watch" = "Display HR on Watch"; +"Display HR on Watch" = "Mostrar frecuencia cardíaca en el reloj"; /* Headers for settings ----------------------- */ -"OpenAPS main settings" = "OpenAPS main settings"; +"OpenAPS main settings" = "Ajustes principales de OpenAPS"; -"OpenAPS SMB settings" = "OpenAPS SMB settings"; +"OpenAPS SMB settings" = "Ajustes de SMB en OpenAPS"; -"OpenAPS targets settings" = "OpenAPS targets settings"; +"OpenAPS targets settings" = "Ajustes de objetivos de OpenAPS"; -"OpenAPS other settings" = "OpenAPS other settings"; +"OpenAPS other settings" = "Otros ajustes de OpenAPS"; /* Glucose Simulator CGM */ -"Glucose Simulator" = "Glucose Simulator"; +"Glucose Simulator" = "Simulador de glucosa"; /* Restored state message */ -"Bluetooth State restored (APS restarted?). Found %d peripherals, and connected to %@ with identifier %@" = "Bluetooth State restored (APS restarted?). Found %d peripherals, and connected to %@ with identifier %@"; +"Bluetooth State restored (APS restarted?). Found %d peripherals, and connected to %@ with identifier %@" = "Estado del Bluetooth restaurado (¿se ha reiniciado APS?). Se encontraron %d periféricos, y se conectó al %@ con el identificador %@"; /* Shared app group xDrip4iOS */ -"Using shared app group with external CGM app xDrip4iOS" = "Using shared app group with external CGM app xDrip4iOS"; +"Using shared app group with external CGM app xDrip4iOS" = "Utilizar el grupo de aplicaciones compartidas con la app de MCG externa xDrip4iOS"; /* Shared app group GlucoseDirect */ -"Using shared app group with external CGM app GlucoseDirect" = "Using shared app group with external CGM app GlucoseDirect"; +"Using shared app group with external CGM app GlucoseDirect" = "Utilizar el grupo de aplicaciones compartidas con la app de MCG externa GlucoseDirect"; /* Dexcom G6 app */ -"Dexcom G6 app" = "Dexcom G6 app"; +"Dexcom G6 app" = "Aplicación Dexcom G6"; /* Native G5 app */ -"Native G5 app" = "Native G5 app"; +"Native G5 app" = "Aplicación nativa de Dexcom G5"; /* Minilink transmitter */ -"Minilink transmitter" = "Minilink transmitter"; +"Minilink transmitter" = "Transmisor Minilink"; /* Simple simulator */ -"Simple simulator" = "Simple simulator"; +"Simple simulator" = "Simulador simple"; /* Direct connection with Libre 1 transmitters or Libre 2 */ -"Direct connection with Libre 1 transmitters or European Libre 2 sensors" = "Direct connection with Libre 1 transmitters or European Libre 2 sensors"; +"Direct connection with Libre 1 transmitters or European Libre 2 sensors" = "Conexión directa con transmisores Libre 1 o sensores europeos Libre 2"; /* Online or internal server */ -"Online or internal server" = "Online or internal server"; +"Online or internal server" = "Servidor en línea o interno"; /* -------------- Developer settings ---------------------- */ /* Debug options */ -"Developer" = "Developer"; +"Developer" = "Desarrollador"; /* Debug option view NS Upload Profile */ -"NS Upload Profile" = "NS Upload Profile"; +"NS Upload Profile" = "Subir perfil a NS"; /* Debug option view NS Uploaded Profile */ -"NS Uploaded Profile" = "NS Uploaded Profile"; +"NS Uploaded Profile" = "Perfil subido a NS"; /* Debug option view Autosense */ "Autosense" = "Autosense"; /* Insulin sensitivity config header */ -"Dynamic Sensitivity" = "Dynamic Sensitivity"; +"Dynamic Sensitivity" = "Sensibilidad Dinámica"; /* Autotune config */ -"Only Autotune Basal Insulin" = "Only Autotune Basal Insulin"; +"Only Autotune Basal Insulin" = "Sólo Insulina Basal de Autotune"; /* */ -"Save as your Normal Basal Rates" = "Save as your Normal Basal Rates"; +"Save as your Normal Basal Rates" = "Guardar como tus ratios basales normales"; /* */ "Save on Pump" = "Guardar en Bomba"; /* Debug option view Pump History */ -"Pump History" = "Pump History"; +"Pump History" = "Historial de la bomba"; /* Debug option view Target Ranges */ "Target ranges" = "Target ranges"; @@ -1313,28 +1331,28 @@ Enact a temp Basal or a temp target */ "More options" = "More options"; /* */ -"Schedule when SMBs are Off" = "Schedule when SMBs are Off"; +"Schedule when SMBs are Off" = "Programar cuándo los SMB están apagados"; /* */ -"Change ISF and CR" = "Change ISF and CR"; +"Change ISF and CR" = "Modificar el Factor de Sensibilidad a la Insulina (ISF) y Factor de Carbohidratos (CR)"; /* */ -"Change ISF" = "Change ISF"; +"Change ISF" = "Cambiar Factor de Sensibilidad a la Insulina (ISF)"; /* */ -"Change CR" = "Change CR"; +"Change CR" = "Cambiar Factor de Carbohidratos (CR)"; /* */ -"SMB Minutes" = "SMB Minutes"; +"SMB Minutes" = "Minutos de SMB"; /* */ -"UAM SMB Minutes" = "UAM SMB Minutes"; +"UAM SMB Minutes" = "Minutos de SMB en UAM"; /* */ -"Start new Profile" = "Start new Profile"; +"Start new Profile" = "Iniciar nuevo perfil"; /* */ -"Save as Profile" = "Save as Profile"; +"Save as Profile" = "Guardar como perfil"; /* Alert */ "Cancel Profile Override" = "Cancel Profile Override"; @@ -1343,135 +1361,135 @@ Enact a temp Basal or a temp target */ "Cancel Temp Target" = "Cancelar objetivo temporal"; /* Alert */ -"Return to Normal?" = "Return to Normal?"; +"Return to Normal?" = "¿Regresar a normal?"; /* */ -"This will change settings back to your normal profile." = "This will change settings back to your normal profile."; +"This will change settings back to your normal profile." = "Esto cambiará la configuración a tu perfil normal."; /* Start Profile Alert */ -"Start Profile" = "Start Profile"; +"Start Profile" = "Iniciar perfil"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Su dosis basal de insulina se ajustará con el porcentaje de ajuste temporal. En consecuencia, su factor de sensibilidad a la insulina (ISF) y su índice glucémico (CR) se ajustarán en sentido inverso al mismo porcentaje."; /* */ -"Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile."; +"Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Al iniciar esta anulación, se modificarán tus perfiles y/o tu glucosa objetivo utilizados para el lazo cerrado durante toda la duración seleccionada. Al tocar \"Iniciar perfil\", se iniciará tu nuevo perfil o se editará tu perfil activo actual."; /* Change Target glucose in profile settings */ -"Override Profile Target" = "Override Profile Target"; +"Override Profile Target" = "Sobreescribir el objetivo del perfil"; /* Alert string. Keep spaces. */ -" SMBs are disabled either by schedule or during the entire duration." = " SMBs are disabled either by schedule or during the entire duration."; +" SMBs are disabled either by schedule or during the entire duration." = " Los SMB están desactivados ya sea por horario o durante toda la duración."; /* Alert strings. Keep spaces */ -" infinite duration." = " infinite duration."; +" infinite duration." = " duración infinita."; /* Service Section */ -"App Icons" = "App Icons"; +"App Icons" = "Iconos de la aplicación"; /* */ -"iAPS Icon" = "iAPS Icon"; +"iAPS Icon" = "Icono de iAPS"; /* Service Section */ -"Statistics and Home View" = "Statistics and Home View"; +"Statistics and Home View" = "Estadísticas y Vista de Inicio"; /* Alert text */ -"Delete Carb Equivalents?" = "Delete Carb Equivalents?"; +"Delete Carb Equivalents?" = "¿Eliminar Equivalentes de Carbohidratos?"; /* */ -"All FPUs of the meal will be deleted." = "All FPUs of the meal will be deleted."; +"All FPUs of the meal will be deleted." = "Se eliminarán todas las unidades de grasa y proteína (FPU) de la comida."; /* */ -"Delete Glucose?" = "Delete Glucose?"; +"Delete Glucose?" = "¿Eliminar glucosa?"; /* */ -"Meal Presets" = "Meal Presets"; +"Meal Presets" = "Atajo de comida"; /* */ -"Empty" = "Empty"; +"Empty" = "Vacío"; /* */ -"Delete Selected Preset" = "Delete Selected Preset"; +"Delete Selected Preset" = "Eliminar preajuste seleccionado"; /* */ -"Enter Meal Preset Name" = "Enter Meal Preset Name"; +"Enter Meal Preset Name" = "Introduce nombre del atajo de comida"; /* */ -"Name Of Dish" = "Name Of Dish"; +"Name Of Dish" = "Nombre del plato"; /* Save Carbs and continue to bolus recommendation */ -"Save and continue" = "Save and continue"; +"Save and continue" = "Guardar y continuar"; /* */ -"Save as Preset" = "Save as Preset"; +"Save as Preset" = "Guardar como Ajuste Predefinido"; /* */ -"Predictions" = "Predictions"; +"Predictions" = "Predicciones"; /* Watch Config Option */ -"Display Protein & Fat" = "Display Protein & Fat"; +"Display Protein & Fat" = "Mostrar proteínas y grasas"; /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ -"Warning!" = "Warning!"; +"Warning!" = "¡Advertencia!"; /* Alert to confirm bolus amount to add */ -"\n\nTap 'Add' to continue with selected amount." = "\n\nTap 'Add' to continue with selected amount."; +"\n\nTap 'Add' to continue with selected amount." = "\n\nPulse 'Añadir' para continuar con la cantidad seleccionada."; /* */ -"Eventual Glucose" = "Eventual Glucose"; +"Eventual Glucose" = "Glucosa eventual"; /* */ -"Please wait" = "Please wait"; +"Please wait" = "Por favor, espere"; /* */ -"Glucose, " = "Glucose, "; +"Glucose, " = "Glucosa, "; /* */ -"Target Glucose" = "Target Glucose"; +"Target Glucose" = "Glucosa objetivo"; /* */ -"Percentage setting" = "Percentage setting"; +"Percentage setting" = "Ajuste del porcentaje"; /* */ -"Insulin Sensitivity" = "Insulin Sensitivity"; +"Insulin Sensitivity" = "Sensibilidad a la insulina"; /* Formula displayed in Bolus info pop-up. Make translation short! */ -"(Eventual Glucose - Target) / ISF" = "(Eventual Glucose - Target) / ISF"; +"(Eventual Glucose - Target) / ISF" = "(Glucosa eventual - objetivo) / ISF"; /* */ -"Formula:" = "Formula:"; +"Formula:" = "Fórmula:"; /* Bolus pop-up footer */ -"Carbs and previous insulin are included in the glucose prediction, but if the Eventual Glucose is lower than the Target Glucose, a bolus will not be recommended." = "Carbs and previous insulin are included in the glucose prediction, but if the Eventual Glucose is lower than the Target Glucose, a bolus will not be recommended."; +"Carbs and previous insulin are included in the glucose prediction, but if the Eventual Glucose is lower than the Target Glucose, a bolus will not be recommended." = "Los carbohidratos y la insulina anterior están incluidos en la predicción de la glucosa. Si la glucosa eventual es inferior a la glucosa ovjetivo, no se recomienda bolo."; /* Hide pop-up */ -"Hide" = "Hide"; +"Hide" = "Ocultar"; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose is predicted to drop down to " = "Eventual Glucose > Target Glucose, but glucose is predicted to first drop down to "; +"Eventual Glucose > Target Glucose, but glucose is predicted to drop down to " = "Glucosa eventual > glucosa objetivo, pero se prevé que la glucosa caiga primero a "; /* Bolus pop-up / Alert string. Make translations concise! */ -"which is below your Threshold (" = "which is below your Threshold ("; +"which is below your Threshold (" = "que está por debajo del umbral ("; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: " = "Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: "; +"Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: " = "Glucosa eventual > glucosa objetivo, pero el valor de glucosa está aumentando más lento de lo esperado. Se espera: "; //* Bolus pop-up / Alert string. Make translations concise! */ -". Climbing: " = ". Climbing: "; +". Climbing: " = ". Subiendo: "; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: " = "Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: "; +"Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: " = "Glucosa eventual > glucosa objetivo, pero el valor de glucosa está descendiendo más rápido de lo esperado. Se espera: "; /* Bolus pop-up / Alert string. Make translations concise! */ -". Falling: " = ". Falling: "; +". Falling: " = ". Descendiendo: "; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose is changing faster than expected. Expected: " = "Eventual Glucose > Target Glucose, but glucose is changing faster than expected. Expected: "; +"Eventual Glucose > Target Glucose, but glucose is changing faster than expected. Expected: " = "Glucosa eventual > glucosa objetivo, pero el valor de glucosa está cambiando más rápido de lo esperado. Se espera: "; /* Bolus pop-up / Alert string. Make translations concise! */ -". Changing: " = ". Changing: "; +". Changing: " = ". Cambiando: "; /* Add insulin without bolusing alert */ " without bolusing" = " without bolusing"; @@ -1652,61 +1670,61 @@ Enact a temp Basal or a temp target */ "Change HbA1c Unit" = "Change HbA1c Unit"; /* */ -"Display Chart X - Grid lines" = "Display Chart X - Grid lines"; +"Display Chart X - Grid lines" = "Mostrar eje X - líneas de la cuadrícula"; /* */ -"Display Chart Y - Grid lines" = "Display Chart Y - Grid lines"; +"Display Chart Y - Grid lines" = "Mostrar eje Y - líneas de la cuadrícula"; /* */ -"Display Chart Threshold lines for Low and High" = "Display Chart Threshold lines for Low and High"; +"Display Chart Threshold lines for Low and High" = "Mostrar umbrales en el gráfico para glucemia baja y alta"; /* */ -"Standing / Laying TIR Chart" = "Standing / Laying TIR Chart"; +"Standing / Laying TIR Chart" = "Gráfico de Tiempo en Rango (TIR) vertical / horizontal"; /* */ -"Hours X-Axis (6 default)" = "Hours X-Axis (6 default)"; +"Hours X-Axis (6 default)" = "Horas mostradas en el eje X (por defecto, 6)"; /* */ -"2 hours" = "2 hours"; +"2 hours" = "2 horas"; /* */ -"4 hours" = "4 hours"; +"4 hours" = "4 horas"; /* */ -"6 hours" = "6 hours"; +"6 hours" = "6 horas"; /* */ -"12 hours" = "12 hours"; +"12 hours" = "12 horas"; /* */ -"24 hours" = "24 hours"; +"24 hours" = "24 horas"; /* Average BG = */ -"Average" = "Average"; +"Average" = "Media"; /* Median BG */ -"Median" = "Median"; +"Median" = "Mediana"; /* CGM readings in statView */ -"Readings" = "Readings"; +"Readings" = "Lecturas"; /* CGM readings in statView */ -"Readings / 24h" = "Readings / 24h"; +"Readings / 24h" = "Lecturas / 24h"; /* Days of saved readings*/ -"Days" = "Days"; +"Days" = "Días"; /* Normal BG (within TIR) */ "Normal" = "Normal"; /* Title High BG in statPanel */ -"High (>" = "High (>"; +"High (>" = "Alto (>"; /* Title Low BG in statPanel */ -"Low (<" = "Low (<"; +"Low (<" = "Bajo (<"; /* SD */ -"SD" = "SD"; +"SD" = "DS"; /* CV */ "CV" = "CV"; @@ -1715,78 +1733,78 @@ Enact a temp Basal or a temp target */ "HbA1c" = "HbA1c"; /* Total number of days of data for HbA1c estimation, part 1/2*/ -"All" = "All"; +"All" = "Todos"; /* Total number of days of data for HbA1c estimation, part 2/2*/ -"days" = "days"; +"days" = "días"; /* Nr of Loops in statPanel */ -"Loops" = "Loops"; +"Loops" = "Ciclos"; /* Loop Errors in statPanel */ -"Errors" = "Errors"; +"Errors" = "Errores"; /* Average loop interval */ -"Interval" = "Interval"; +"Interval" = "Intervalo"; /* Median loop interval */ "Duration" = "Duración"; /* "Display SD */ -"Display SD instead of CV" = "Display SD instead of CV"; +"Display SD instead of CV" = "Mostrar DS en lugar de CV"; /* Description for display SD */ -"Display Standard Deviation (SD) instead of Coefficient of Variation (CV) in statPanel" = "Display Standard Deviation (SD) instead of Coefficient of Variation (CV) in statPanel"; +"Display Standard Deviation (SD) instead of Coefficient of Variation (CV) in statPanel" = "Mostrar Desviación Estándar (DS) en lugar del Coeficiente de Variación (CV) en el Panel de Estadísticas"; /* How often to update the statistics */ -"Update every number of minutes:" = "Update every number of minutes:"; +"Update every number of minutes:" = "Actualizar cada número de minutos:"; /* Description for update interval for statistics */ -"Default is 20 minutes. How often to update and save the statistics.json and to upload last array, when enabled, to Nightscout." = "Default is 20 minutes. How often to update and save the statistics.json and to upload last array, when enabled, to Nightscout."; +"Default is 20 minutes. How often to update and save the statistics.json and to upload last array, when enabled, to Nightscout." = "Con qué frecuencia actualizar, guardar las estadísticas.json y subir la última línea de la matriz, si está habilitado, a Nightscout. Por defecto, 20 minutos."; /* Duration displayed in statPanel */ -"Past 24 Hours " = "Past 24 Hours "; +"Past 24 Hours " = "Últimas 24 horas"; /* Duration displayed in statPanel */ -"Past Week " = "Past Week "; +"Past Week " = "Última semana"; /* Duration displayed in statPanel */ -"Past Month " = "Past Month "; +"Past Month " = "Último mes"; /* Duration displayed in statPanel */ -"Past 90 Days " = "Past 90 Days "; +"Past 90 Days " = "Últimos 90 días"; /* Duration displayed in statPanel */ -"All Past Days of Data " = "All Past Days of Data "; +"All Past Days of Data " = "Todos los días pasados de datos "; /* "Display Loop statistics in statPanel */ -"Display Loop Cycle statistics" = "Display Loop Cycle statistics"; +"Display Loop Cycle statistics" = "Mostrar estadísticas de ciclos del lazo cerrado"; /* Description for Display Loop statistics */ -"Displays Loop statistics in the statPanel in Home View" = "Displays Loop statistics in the statPanel in Home View"; +"Displays Loop statistics in the statPanel in Home View" = "Muestra las estadísticas del lazo cerrado en el panel de estado en la vista de inicio"; /* Description for Override HbA1c unit */ -"Change default HbA1c unit in statPanlel. The unit in statPanel will be updateded with next statistics.json update" = "Change default HbA1c unit in statPanlel. The unit in statPanel will be updateded with next statistics.json update"; +"Change default HbA1c unit in statPanlel. The unit in statPanel will be updateded with next statistics.json update" = "Cambiar las unidad por defecto de HbA1c en el panel de estadísticas. Las unidades serán actualizadas en dicho panel de estadísticas en la próxima actualización del fichero estadísticas.json"; /* HbA1c for all glucose storage days */ -"all" = "all"; +"all" = "todos"; /* -------------------------------------------------------- Dexcom G7 --------------------------------------*/ -"CGM Configuration" = "CGM Configuration"; +"CGM Configuration" = "Configuración de MCG"; -"Heartbeat" = "Heartbeat"; +"Heartbeat" = "Latido del corazón"; -"CGM address :" = "CGM address :"; +"CGM address :" = "Dirección del MCG :"; -"CGM is not used as heartbeat." = "CGM is not used as heartbeat."; +"CGM is not used as heartbeat." = "El MCG no se utiliza como latido de corazón."; -"Are you sure you want to delete this CGM?" = "Are you sure you want to delete this CGM?"; +"Are you sure you want to delete this CGM?" = "¿Está usted seguro de querer eliminar este MCG?"; /* New Experimental feature */ "Experimental" = "Experimental"; /* Smoothing of CGM readings */ -"Smooth Glucose Value" = "Smooth Glucose Value"; +"Smooth Glucose Value" = "Suavizar valores de glucosa"; /* ----------------------------------------------------------------------------------------------------------- @@ -1795,25 +1813,25 @@ Enact a temp Basal or a temp target */ */ /* Headline Rewind Resets Autosens */ -"Rewind Resets Autosens" = "Rewind Resets Autosens"; +"Rewind Resets Autosens" = "Rebobinar reinicia Autosens"; /* ”Rewind Resets Autosens” */ "This feature, enabled by default, resets the autosens ratio to neutral when you rewind your pump, on the assumption that this corresponds to a probable site change. Autosens will begin learning sensitivity anew from the time of the rewind, which may take up to 6 hours. If you usually rewind your pump independently of site changes, you may want to consider disabling this feature." = "Esta función, activada por defecto, restablece la proporción de autosens a neutral cuando rebobinas la bomba, suponiendo que esto corresponde a un probable cambio en el sitio. Autosens comenzará a aprender la sensibilidad desde el momento del evento, y puede tardar hasta 6 horas. Si normalmente rebobina su bomba independientemente de los cambios en el sitio, puede considerar desactivar esta función."; /* Headline "High Temptarget Raises Sensitivity" */ -"High Temptarget Raises Sensitivity" = "High Temptarget Raises Sensitivity"; +"High Temptarget Raises Sensitivity" = "Objetivo temporal elevado aumenta la sensibilidad"; /* ”High Temptarget Raises Sensitivity" */ "Defaults to false. When set to true, raises sensitivity (lower sensitivity ratio) for temp targets set to >= 111. Synonym for exercise_mode. The higher your temp target above 110 will result in more sensitive (lower) ratios, e.g., temp target of 120 results in sensitivity ratio of 0.75, while 140 results in 0.6 (with default halfBasalTarget of 160)." = "Por defecto 'Falso'. Cuando se cambia a 'Verdadero', aumenta la sensibilidad (menor proporción de sensibilidad) para objetivos temporales fijados en >= 111. Sinónimo de modo ejercicio. Cuanto mayor sea su objetivo temporal superior a 110, resultará en relaciones más sensibles (más bajas), p.ej., objetivo temporal de 120 resulta en una proporción de sensibilidad de 0.75, mientras que 140 resultaría en 0.6 (con un valor por defecto de objetivo basal de 160)."; /* Headline ”Low Temptarget Lowers Sensitivity" */ -"Low Temptarget Lowers Sensitivity" = "Low Temptarget Lowers Sensitivity"; +"Low Temptarget Lowers Sensitivity" = "Objetivo temporal bajo reduce la sensibilidad"; /* ”Low Temptarget Lowers Sensitivity" */ "Defaults to false. When set to true, can lower sensitivity (higher sensitivity ratio) for temptargets <= 99. The lower your temp target below 100 will result in less sensitive (higher) ratios, e.g., temp target of 95 results in sensitivity ratio of 1.09, while 85 results in 1.33 (with default halfBasalTarget of 160)." = "Por defecto 'Falso'. Cuando se establece 'Verdadero', puede disminuir la sensibilidad (mayor proporción de sensibilidad) para objetivos temporales <= 99. Cuanto menor sea su objetivo temporal por debajo de 100, resultará en proporciones menos sensibles (superiores), p. ej., el objetivo temporal de 95 resulta en la proporción de sensibilidad de 1.09, mientras que 85 resulta en 1.33 (con la mitad de objetivo predeterminada de 160)."; /* Headline ”Sensitivity Raises Target" */ -"Sensitivity Raises Target" = "Sensitivity Raises Target"; +"Sensitivity Raises Target" = "Sensibilidad aumenta el objetivo"; /* ”Sensitivity Raises Target" */ "When true, raises BG target when autosens detects sensitivity" = "Cuando es verdadero, aumenta el objetivo BG cuando los autosens detectan sensibilidad"; @@ -2064,16 +2082,16 @@ Un 1.0 de valor permite un ajuste completo con el nuevo factor de sensibilidad d "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ -"Use Sigmoid Function" = "Use Sigmoid Function"; +"Use Sigmoid Function" = "Usar función de Sigmoid"; /* Which dyn ISF function to use */ -"Formula" = "Formula"; +"Formula" = "Fórmula"; /* Extra Safety Features when using dyn ISF */ -"Safety" = "Safety"; +"Safety" = "Seguridad"; /* Use Sigmoid Function */ "Use a sigmoid function for ISF (and for CR, when enabled), instead of the default Logarithmic formula. Requires the Dynamic ISF setting to be enabled in settings\n\nThe Adjustment setting adjusts the slope of the curve (Y: Dynamic ratio, X: Blood Glucose). A lower value ==> less steep == less aggressive.\n\nThe autosens.min/max settings determines both the max/min limits for the dynamic ratio AND how much the dynamic ratio is adjusted. If AF is the slope of the curve, the autosens.min/max is the height of the graph, the Y-interval, where Y: dynamic ratio. The curve will always have a sigmoid shape, no matter which autosens.min/max settings are used, meaning these settings have big consequences for the outcome of the computed dynamic ISF. Please be careful setting a too high autosens.max value. With a proper profile ISF setting, you will probably never need it to be higher than 1.5\n\nAn Autosens.max limit > 1.5 is not advisable when using the sigmoid function." = "Use a sigmoid function for ISF (and for CR, when enabled), instead of the default Logarithmic formula. Requires the Dynamic ISF setting to be enabled in settings\n\nThe Adjustment setting adjusts the slope of the curve (Y: Dynamic ratio, X: Blood Glucose). A lower value ==> less steep == less aggressive.\n\nThe autosens.min/max settings determines both the max/min limits for the dynamic ratio AND how much the dynamic ratio is adjusted. If AF is the slope of the curve, the autosens.min/max is the height of the graph, the Y-interval, where Y: dynamic ratio. The curve will always have a sigmoid shape, no matter which autosens.min/max settings are used, meaning these settings have big consequences for the outcome of the computed dynamic ISF. Please be careful setting a too high autosens.max value. With a proper profile ISF setting, you will probably never need it to be higher than 1.5\n\nAn Autosens.max limit > 1.5 is not advisable when using the sigmoid function."; diff --git a/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings index 91bdc9e32c..aabe297b82 100644 --- a/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Aktivoi"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Väliaikainen basaali"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Remote control"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings index 5bdc403d2c..68681405d4 100644 --- a/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "de"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Dernier calcul à"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Injecter"; +/* Start a temp target or a profile override */ +"Start" = "Démarrer"; + /* */ "Manual Temp Basal" = "Basal temporaire manuel"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Contrôle à distance"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nVeuillez maintenant vérifier soigneusement tous vos nouveaux paramètres:\n\n* Paramètres basaux\n * Ratios glucidiques\n * Objectifs glycémiques\n * Sensibilité à l'insuline\n * DIA\n\n dans iAPS Paramètres > Configuration.\n\nDes paramètres de profil incorrects ou invalides peuvent avoir des effets désastreux."; @@ -1583,7 +1601,7 @@ Enact a temp Basal or a temp target */ "This PumpManager has not been configured with a maximum basal rate because it was added before manual temp basal was a feature. Please go to therapy settings -> delivery limits and set a new maximum basal rate." = "Le Gestionnaire de Pompes n'a pas été configuré avec un débit de base maximum car il a été ajouté avant que le Basal temporaire manuel soit une fonctionnalité. Veuillez aller dans les paramètres de thérapie -> limites de délivrance et définir un nouveau taux de basal maximum."; /* description label for active time pod details row */ -"Active Time" = "Durée d’activité"; +"Active Time" = "Heure d’activation"; /* description label for total delivery pod details row */ "Total Delivery" = " Total délivré"; @@ -2029,13 +2047,13 @@ Enact a temp Basal or a temp target */ // Dynamic ISF + CR Settings: /* Headline "Adjust Dynamic ISF constant" */ -"Adjust Dynamic ISF constant" = "Ajuster la constante ISF Dynamique"; +"Adjust Dynamic ISF constant" = "Ajuster la constante du FSI Dynamique"; /* Adjust Dynamic ISF constant */ -"Adjust Dynamic ISF constant" = "Ajuster la constante ISF Dynamique"; +"Adjust Dynamic ISF constant" = "Ajuster la constante du FSI Dynamique"; /* Enable Dynamic ISF, Headline */ -"Enable Dynamic ISF" = "Activer ISF dynamique"; +"Enable Dynamic ISF" = "Activer le facteur de sensibilité à l'insuline (FSI) dynamique"; /* Headline "Enable Dynamic ISF" */ "Enable Dynamic ISF" = "Activer le facteur de sensibilité à l'insuline (FSI) dynamique"; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Ajuster la constante du FSI Dynamique"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Utiliser la fonction Sigmoid"; @@ -2163,7 +2181,7 @@ Enact a temp Basal or a temp target */ "Live Activity" = "Live Activity"; /* Notification option */ -"Live activity displays blood glucose live on the lock screen and on the dynamic island (if available)" = "Live activity displays blood glucose live on the lock screen and on the dynamic island (if available)"; +"Live activity displays blood glucose live on the lock screen and on the dynamic island (if available)" = "L'activité en direct affiche la glycémie sur l'écran de verrouillage et sur l'île dynamique (si disponible)"; /* Notification option */ "Show Live activity" = "Afficher l'activité en direct"; diff --git a/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings index c05b3c4ca1..a1f2376c0a 100644 --- a/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Enact"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manual Temp Basal"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Remote control"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings index a08e3b81a1..0c8c55d624 100644 --- a/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Beadva"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Beadni"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Átmeneti Kézi Bázis"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Távirányítás"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nMost kérlek alaposan nézd át a beállításokat:\n\n* Bázis Ceállítások\n * Szénhidrát Arány\n * Cukorszint Célpont\n * Inzulin Érzékenység\n * DIA\n\n iAPS beállítások > Konfiguráció.\n\nHelytelen vagy rossz beállításoknak halálos következményei lehetnek."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings index 96f01f0559..d978889098 100644 --- a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "di"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "Un Bolo Remoto "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "è stato consegnato"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minuti fa, innescato a distanza da Nightscout, da un assistente o da un genitore. Vuoi ancora fare il bolo?\n\nL'eventuale glicemia prevista, se non fai bolo, è:"; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "Un Bolo Remoto è appena Consegnato!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Eseguito alle"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Attiva"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Basale temporanea manuale"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Controllo remoto"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Consenti il controllo remoto di iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nOra verifica attentamente tutte le nuove impostazioni:\n\n* Impostazioni basali\n * Rapporti carboidrati\n * Obiettivi glucosio\n * Sensibilità insulinica\n * DIA\n\n in Impostazioni iAPS > Configurazione.\n\nImpostazioni del profilo errate o non valide potrebbero avere effetti disastrosi."; @@ -1195,7 +1213,7 @@ Enact a temp Basal or a temp target */ "Apple Health" = "Apple Salute"; /* */ -"Connect to Apple Health" = "Connetti con Apple Salute"; +"Connect to Apple Health" = "Connetti ad Apple Salute"; /* Show when have not permissions for writing to Health */ "For write data to Apple Health you must give permissions in Settings > Health > Data Access" = "Per scrivere dati su Apple Health devi dare il permesso in Impostazioni > Salute > Accesso dati"; @@ -2059,9 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Regola i rapporti dinamici della costante ISF"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Regola i rapporti dinamici di una costante. Il valore predefinito è 0,5. Più alto è il valore, maggiore sarà la correzione del tuo ISF per una glicemia alta o bassa. La correzione massima è determinata dalle impostazioni Autosens min/max.\n\nPer la funzione sigmoidea si consiglia di iniziare con un fattore di correzione di 0,4 - 0,5.\n\n Per la formula logaritmica c'è meno consenso, ma iniziare con 0,5 - 0,8 è più appropriato per la maggior parte degli utenti adulti. -Per gli utenti più giovani si consiglia di iniziare con un dosaggio ancora più basso quando si utilizza la formula logaritmica, per evitare un trattamento eccessivamente aggressivo. -Regola la costante ISF dinamica."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Usa Funzione Sigmoid"; diff --git a/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings index c40c097cdf..0a649755a6 100644 --- a/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "av"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Utført kl."; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Start"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manuell basal"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Fjernstyring"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nGå nøye gjennom alle de nye innstillingene:\n\n* Basalprofil\n * Karbohydratforhold\n * Blodsukkermål\n * Insulinfølsomhet\n\n i iAPS Innstillinger > Oppsett.\n\nFeil eller ugyldige profilinnstillinger kan ha katastrofale følger."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Juster konstant for dynamisk ISF"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Justeringsfaktoren brukes til å bestemme hvor mye ISF/CR skal justeres når man benytter dynamisk ISF/CR. Standardverdi er 0.5. Jo høyere verdi, jo større blir korrigeringen av ISF/CR ved høyt eller lavt blodsukker. Maks/min korrigering avgjøres av dine Autosens maks/min-innstillinger.\n\nFor Sigmoid anbefales det en justeringsfaktor på 0.4 - 0.5 til å begynne med.\n\nNår Sigmoid ikke er i bruk anbefales det å starte på 0.8 for voksne brukere. For yngre brukere er det anbefalt å starte med en lavere justeringsfaktor for å unngå aggresiv behandling."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Bruk sigmoid-funksjon"; diff --git a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings index fe9e9923c5..e9fe7cc3d9 100644 --- a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "van"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "Een bolus op afstand "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "zojuist afgeleverd"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minuten geleden, op afstand gestart vanuit Nightscout, door een verzorger of een ouder. Wil je nog steeds een bolus?\n\nDe verwachte uiteindelijke glucose, als je niet bolust, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "De bolus op afstand is zojuist geleverd!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Toegediend op"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Uitvoeren"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Handmatige tijdelijke basaal"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Afstandsbediening"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Toestaan dat iAPS op afstand beheerd wordt"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nCheck nu al je nieuwe instellingen:\n\n* Basaal instellingen\n * Koolhydraat ratio's\n * Doel glucose waarde\n * Insuline sensitiviteit\n * DIA\n\n in iAPS instellingen > Configuratie.\n\nSlechte of ongeldige profielinstellingen kunnen desastreuze effecten hebben!"; @@ -2063,7 +2081,7 @@ Eenvoudig gezegd, de Dynamische Carb Ratio past de koolhydraatverhouding aan op "Adjust Dynamic ISF constant" = "Dynamische ISF-constante aanpassen"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individuele aanpassing van de berekende dynamische verhoudingen. De standaardwaarde is 0,5. Hoe hoger de waarde, hoe groter de correctie van je ISF/CR zal zijn voor een hoge of lage bloedglucosewaarde.\n\nDe maximale/minimale correctie wordt bepaald door de Autosens min/max instellingen.\\Voor de Sigmoid functie wordt een aanpassingsfactor van 0.4 - 0.5 aanbevolen om mee te beginnen.n\nVoor de logaritmische formule is er minder overeenstemming, maar beginnen rond de 0.8 is waarschijnlijk goed voor de meeste volwassen gebruikers. Voor jongere gebruikers is het aan te raden om nog lager te beginnen met de logaritmische formule, om een te agressieve behandeling te voorkomen."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Gebruik Sigmoid functie"; @@ -2155,7 +2173,7 @@ Eenvoudig gezegd, de Dynamische Carb Ratio past de koolhydraatverhouding aan op "Horizontal Scroll View Visible hours" = "Horizontale scrolweergave zichtbare uren"; /* UI/UX option */ -"Display Time Interval Setting Button" = "Display Time Interval Setting Button"; +"Display Time Interval Setting Button" = "Knop voor tijdinterval weergeven"; /* Setting title */ "Bolus Calculator" = "Bolus calculator"; diff --git a/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings index be5270d8b0..60cdaddbbd 100644 --- a/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Enact"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manual Temp Basal"; @@ -361,6 +376,9 @@ Połączono z Nightscout!"; /* Allow remote control from NS */ "Remote control" = "Remote control"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2061,7 +2079,7 @@ Połączono z Nightscout!"; "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings index 7d4331b80f..5262083892 100644 --- a/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Executar"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Basal Temporária Manual"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Controle remoto"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings index d4de4b553d..1da1a40fbf 100644 --- a/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Executar"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Basal Temporária Manual"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Controle remoto"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings index 1050bf1d57..3028ee4640 100644 --- a/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "из"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "Дистанционный Болюс "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "был введен"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " минут назад, запущенный удаленно из Nightscout лицом, осуществляющим уход, или родителем. Вы все еще хотите выполнить болюс?\n\nПрогнозируемый уровень глюкозы, если вы не подтверждаете болюс, составляет: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "Дистанционный Болюс был только что введен!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Принято в"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Запустить"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Ручная ВБС"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Удаленное управление"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Разрешить дистанционное управление iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nПожалуйста, проверьте все ваши новые настройки:\n\n* Настройки базала\n * Углеводные коэффициенты\n * Целевой диапазон\n * Чувствительность к инсулину\n\n в настройках iAPS Настройки > Конфигурация.\n\nНекорректные настройки профиля могут привести к катастрофическим последствиям."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Настроить константу динамического ISF"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Индивидуальная настройка рассчитанных динамических коэффициентов. Значение по умолчанию равно 0.5. Чем выше значение, тем больше будет коррекция вашего ISF/CR для высокого или низкого уровня глюкозы в крови. Максимальная/минимальная коррекция определяется настройками autosens min/max.\n\nДля сигмоидной функции рекомендуется для начала использовать коэффициент 0.4 - 0.5.\n\nДля логарифмической формулы существует меньшее единодушие, но для большинства взрослых пользователей, вероятно, подходит значение, начинающееся примерно с 0.8. Для более молодых пользователей рекомендуется начинать с еще меньшего значения при использовании логарифмической формулы, чтобы избежать чрезмерно агрессивного лечения."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Использовать Сигмоидную функцию"; diff --git a/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings index e7db241ce8..d48dcc1be8 100644 --- a/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "z"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Uskutočnené o"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Vykonať"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manuálny dočasný bazál"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Vzdialené ovládanie"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\\Teraz dôkladne skontrolujte všetky nové nastavenia:\n\n* Bazálne nastavenia\n * Pomery uhľohydrátov\n * Cieľové hodnoty glukózy\n * Citlivosť na inzulín\n * DIA\n\n v iAPS Nastavenia > Konfigurácia.\n\nZlé alebo neplatné nastavenia profilu by mohli mať škodlivé účinky."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Nastavenie konštanty Dynamic ISF"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individuálne nastavenie vypočítaných dynamických pomerov. Predvolená hodnota je 0,5. Čím vyššia je táto hodnota, tým väčšia bude korekcia vášho ISF/CR pre vysokú alebo nízku hladinu glukózy v krvi. Maximálna/minimálna korekcia je určená nastavením min/max v programe Autosens.\n\nPre sigmoidnú funkciu sa na začiatok odporúča korekčný faktor 0,4 - 0,5.\n\nPre logaritmický vzorec existuje menej konsenzu, ale začiatok okolo 0,8 je pravdepodobne vhodný pre väčšinu dospelých používateľov. U mladších používateľov sa pri používaní logaritmickej formuly odporúča začať ešte nižšie, aby sa zabránilo príliš agresívnej liečbe."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Použitie funkcie Sigmoid"; diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index 868e47317b..117e263219 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -56,7 +56,7 @@ "was delivered" = "gavs för"; /* Remote Bolus Alert, Part 3 */ -" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minuter sedan, aktiverad från Nightscout, av en assistent eller förälder. Vill du fortfarande ge en ny bolus?\n\nBeräknad blodsockerprognos, om du inte ger bolus, är: "; +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minuter sedan, aktiverad från Nightscout, av en assistent eller förälder. Vill du fortfarande ge en ny bolus?\n\nBeräknad blodsockerprognos, om du inte ger bolus, är: "; /* Remote Bolus Alert, Title */ "A Remote Bolus Was Just Delivered!" = "En fjärrstyrd bolus gavs precis!"; @@ -314,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Utför"; +/* Start a temp target or a profile override */ +"Start" = "Starta"; + /* */ "Manual Temp Basal" = "Manuell temporär basal"; @@ -371,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Fjärrstyrning"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Tillåt fjärrstyrning från Nightscout"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nKontrollera nu alla dina nya pumpinställningar noga:\n\n* Basalinställningar\n * Insulinkvoter\n * Målvärden\n * Insulinkänslighet\n\n i Inställningar > Konfiguration.\n\nDåliga eller ogiltiga pumpinställningar kan gå katastrofala följder."; @@ -2071,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Ändra AF-konstant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individuell justering av hur din insulinkänslighet och insulinkvot (om du använder dyamisk insulinkvot) räknas ut. Stnadarvärde är 0.5. Ett högre värde betyder mer aggressiv justering.\n\nFör S-formad dynamisk inställning rekommendaras att börja med 0.3-0-4. För logaritmisk inställning rekommenderas att börja med 0.5-0.8."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individuell justering av hur din insulinkänslighet och insulinkvot (om du använder dyamisk insulinkvot) räknas ut. Standardvärde är 0.5. Ett högre värde betyder mer aggressiv justering.\n\nFör S-formad dynamisk inställning rekommendaras att börja med 0.3-0-4. För logaritmisk inställning rekommenderas att börja med 0.5-0.8."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Använd S-formad dynamisk insulinkänslighet"; diff --git a/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings index cc89fbb7c1..d3a315b1b8 100644 --- a/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Başlat"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manuel Geçici Bazal"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Uzaktan kontrol"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Dinamik İDF sabitini ayarla"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Sigmoid Fonksiyonunu Kullan"; diff --git a/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings index 4b52afda99..a3242e732f 100644 --- a/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "із"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "Віддалений Болюс "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "було доставлено"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = "хвилин тому, активовано дистанційно з Nightscout опікуном або батьком. Ви все ще хочете вводити болюс?\n\nПрогнозований кінцевий рівень глюкози, якщо ви не вводите болюс, становить:"; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "Дистанційний болюс щойно був доставлений!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Виконано в"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Запустити"; +/* Start a temp target or a profile override */ +"Start" = "Почати"; + /* */ "Manual Temp Basal" = "Ручна Тимчасова Базальна Швидкість (ТБШ)"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Віддалене керування"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Дозволити дистанційне керування iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nТепер уважно перевірте всі ваші нові налаштування:\n\n* Базальні параметри\n * Вуглеводні співвідношення\n * Цільові показники глюкози\n * Чутливість до інсуліну\n\n у меню «Налаштування iAPS» > «Конфігурація».\n\nПоганий або недійсний профіль налаштування можуть мати згубні наслідки."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Налаштувати константу Динамічного ISF"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Індивідуальне налаштування розрахованих динамічних коефіцієнтів. За замовчуванням 0,5. Чим вище значення, тим більшою буде корекція вашого ISF/CR для високого або низького рівня глюкози в крові. Максимальна/мінімальна корекція визначається мінімальними/максимальними налаштуваннями Autosens.\n\nДля сигмоїдної функції спочатку рекомендується коригувальний коефіцієнт 0,4–0,5.\n\nДля логаритмічної формули три є менш узгодженими, але починаючи приблизно з 0,8 ймовірно підходить для більшості дорослих користувачів. Для молодших користувачів рекомендується починати ще нижче при використанні логарифмічної формули, щоб уникнути занадто агресивного лікування."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Індивідуальне налаштування розрахованих динамічних коефіцієнтів. За замовчуванням 0,5. Чим вище значення, тим більшою буде корекція вашого ISF/CR для високого або низького рівня глюкози в крові. Максимальна/мінімальна корекція визначається мінімальними/максимальними налаштуваннями Autosens.\n\nДля сигмоїдної функції спочатку рекомендується коригувальний коефіцієнт 0,4–0,5.\n\nДля логаритмічної формули три є менш узгодженими, але починаючи приблизно з 0,8 ймовірно підходить для більшості дорослих користувачів. Для молодших користувачів рекомендується починати ще нижче при використанні логарифмічної формули, щоб уникнути занадто агресивного лікування."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Використовувати Сігмоїдну Функцію"; diff --git a/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings index da92463af7..b52a42f746 100644 --- a/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "của"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "Một liều Bolus từ xa "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "vừa được hoàn thành"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " phút trước, được kích hoạt từ xa từ Nightscout, bởi người chăm sóc hoặc phụ huynh. Bạn vẫn muốn bolus?\n\nDự đoán lượng đường cuối cùng, nếu bạn không bolus, là: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "Một liều Bolus từ xa vừa được hoàn thành!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Thực hiện ở"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Chấp nhận"; +/* Start a temp target or a profile override */ +"Start" = "Khởi chạy"; + /* */ "Manual Temp Basal" = "Liều cơ bản thủ công"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Điều khiển từ xa"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Cho phép điều khiển iAPS từ xa"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\n Bây giờ xin hãy xác minh lại tất cả các cài đặt của bạn kỹ lưỡng:\n\n* Cài đặt liều nền\n * Tỷ lệ Carb\n * Mục tiêu đường huyết \n * Độ nhạy của Insulin\n * Thời gian hoạt động của insulin\n\n trong iAPS Cài đặt > Cấu hình.\n\n Cấu hình không hợp lệ hoặc tồi có thể có tác động thảm họa."; @@ -486,7 +504,7 @@ Enact a temp Basal or a temp target */ "Devices" = "Thiết bị"; /* */ -"Pump" = "Bơm"; +"Pump" = "Bơm Insulin"; /* */ "Watch" = "Đồng hồ"; @@ -609,7 +627,7 @@ Enact a temp Basal or a temp target */ "Create Events in Calendar" = "Tạo sự kiện trong Calendar"; /* */ -"Calendar" = "Calendar"; +"Calendar" = "Lập lịch"; /* Automatic delivered treatments */ "Automatic" = "Tự động"; @@ -852,10 +870,10 @@ Enact a temp Basal or a temp target */ "Valid for footer" = "Hợp lệ"; /* */ -"Edit calibrations" = "Thêm kết quả hiệu chuẩn"; +"Edit calibrations" = "Chỉnh sửa hiệu chuẩn"; /* */ -"edit calibration clicked" = "Nhấp vào để hiệu chuẩn"; +"edit calibration clicked" = "nhấp vào để chỉnh sửa hiệu chuẩn"; /* */ "Delete CGM" = "Xóa CGM"; @@ -894,7 +912,7 @@ Enact a temp Basal or a temp target */ "Saved to %@" = "Đã lưu vào %@"; /* */ -"No logs available" = "Không có nhật ký"; +"No logs available" = "Không có nhật ký nào"; /* */ "Glucose Notification visibility" = "Khả năng hiển thị thông báo Glucose"; @@ -2060,7 +2078,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Điều chỉnh hằng số ISF động"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Điều chỉnh riêng các tỷ lệ động được tính toán. Mặc định là 0,5. Giá trị càng cao thì mức điều chỉnh ISF/CR của bạn đối với mức đường huyết cao hay thấp càng lớn. Hiệu chỉnh tối đa/tối thiểu được xác định bởi cài đặt tối thiểu/tối đa của Autosens.\n\nĐối với hàm Sigmoid, hệ số điều chỉnh được khuyến nghị là 0,4 - 0,5 để bắt đầu.\n\nĐối với công thức logarit, có ít sự đồng thuận hơn, nhưng bắt đầu từ khoảng 0,8 là có lẽ phù hợp với hầu hết người dùng trưởng thành. Đối với người dùng trẻ tuổi, nên bắt đầu ở mức thấp hơn nữa khi sử dụng công thức logarit để tránh điều trị quá tích cực."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Điều chỉnh riêng các tỷ lệ động được tính toán. Mặc định là 0,5. Giá trị càng cao thì mức điều chỉnh ISF/CR của bạn đối với mức đường huyết cao hay thấp càng lớn. Hiệu chỉnh tối đa/tối thiểu được xác định bởi cài đặt tối thiểu/tối đa của Autosens.\n\nĐối với hàm Sigmoid, hệ số điều chỉnh được khuyến nghị là 0,4 - 0,5 để bắt đầu.\n\nĐối với công thức logarit, có ít sự đồng thuận hơn, nhưng bắt đầu từ khoảng 0,8 là có lẽ phù hợp với hầu hết người dùng trưởng thành. Đối với người dùng trẻ tuổi, nên bắt đầu ở mức thấp hơn nữa khi sử dụng công thức logarit để tránh điều trị quá tích cực."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Sử dụng hàm Sigmoid (SF)"; diff --git a/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings index 1e966eb0d0..e71a87abe2 100644 --- a/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "执行"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "手动设置临时基础"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "远程控制"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2061,7 +2079,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; From 9fceccb6198dd9b8fe1d6129628119c7d14291c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Sat, 24 Feb 2024 11:03:49 +0100 Subject: [PATCH 08/44] New Crowdin updates --- .../es.lproj/Localizable.strings | 4 +- .../G7SensorKit/es.lproj/Localizable.strings | 2 +- .../es.lproj/Localizable.strings | 8 +- .../Main/ar.lproj/Localizable.strings | 20 +- .../Main/da.lproj/Localizable.strings | 20 +- .../Main/de.lproj/Localizable.strings | 20 +- .../Main/es.lproj/Localizable.strings | 492 +++++++++--------- .../Main/fi.lproj/Localizable.strings | 20 +- .../Main/fr.lproj/Localizable.strings | 30 +- .../Main/he.lproj/Localizable.strings | 20 +- .../Main/hu.lproj/Localizable.strings | 20 +- .../Main/it.lproj/Localizable.strings | 24 +- .../Main/nb.lproj/Localizable.strings | 20 +- .../Main/nl.lproj/Localizable.strings | 22 +- .../Main/pl.lproj/Localizable.strings | 20 +- .../Main/pt-BR.lproj/Localizable.strings | 20 +- .../Main/pt-PT.lproj/Localizable.strings | 20 +- .../Main/ru.lproj/Localizable.strings | 20 +- .../Main/sk.lproj/Localizable.strings | 20 +- .../Main/sv.lproj/Localizable.strings | 10 +- .../Main/tr.lproj/Localizable.strings | 20 +- .../Main/uk.lproj/Localizable.strings | 20 +- .../Main/vi.lproj/Localizable.strings | 30 +- .../Main/zh-Hans.lproj/Localizable.strings | 20 +- 24 files changed, 643 insertions(+), 279 deletions(-) diff --git a/Dependencies/G7SensorKit/G7SensorKitUI/es.lproj/Localizable.strings b/Dependencies/G7SensorKit/G7SensorKitUI/es.lproj/Localizable.strings index 4b41e6d168..5f2c696e3a 100644 --- a/Dependencies/G7SensorKit/G7SensorKitUI/es.lproj/Localizable.strings +++ b/Dependencies/G7SensorKit/G7SensorKitUI/es.lproj/Localizable.strings @@ -5,7 +5,7 @@ "%@/min" = "%@/min"; /* No comment provided by engineer. */ -"Are you sure you want to delete this CGM?" = "Are you sure you want to delete this CGM?"; +"Are you sure you want to delete this CGM?" = "¿Está usted seguro de querer eliminar este MCG?"; /* No comment provided by engineer. */ "Bluetooth" = "Bluetooth"; @@ -36,7 +36,7 @@ "Done" = "Hecho"; /* Field label */ -"Glucose" = "Glucose"; +"Glucose" = "Glucosa"; /* title for g7 settings row showing sensor grace period end time */ "Grace Period End" = "Grace Period End"; diff --git a/Dependencies/G7SensorKit/es.lproj/Localizable.strings b/Dependencies/G7SensorKit/es.lproj/Localizable.strings index 7851967612..2372e386d3 100644 --- a/Dependencies/G7SensorKit/es.lproj/Localizable.strings +++ b/Dependencies/G7SensorKit/es.lproj/Localizable.strings @@ -41,7 +41,7 @@ "Grace Period End" = "Grace Period End"; /* Field label */ -"Glucose" = "Glucose"; +"Glucose" = "Glucosa"; "Last Reading" = "Last Reading"; diff --git a/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings index 84ef29f74b..319f7028b2 100644 --- a/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings @@ -117,7 +117,7 @@ "day" = "day"; /* Unit for plural days in pod life remaining */ -"days" = "days"; +"days" = "días"; /* Unit for singular hour in pod life remaining */ "hour" = "hour"; @@ -285,13 +285,13 @@ "Set Confirmation Beeps Preference" = "Set Confirmation Beeps Preference"; /* */ -"Suspend" = "Suspend"; +"Suspend" = "Suspender"; /* */ "Failed to suspend: %{public}@" = "Failed to suspend: %{public}@"; /* */ -"Resume" = "Resume"; +"Resume" = "Reanudar"; /* */ "Bolus" = "Bolo"; @@ -508,7 +508,7 @@ "The window on the top of the Pod should be colored pink when the cannula is properly inserted into the skin." = "The window on the top of the Pod should be colored pink when the cannula is properly inserted into the skin."; /* Button label for user to answer cannula was properly inserted */ -"Yes" = "Yes"; +"Yes" = "Sí"; /* Button label for user to answer cannula was not properly inserted */ "No" = "No"; diff --git a/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings index c05b3c4ca1..a1f2376c0a 100644 --- a/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Enact"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manual Temp Basal"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Remote control"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings index 2f9326fb1d..a6deae607b 100644 --- a/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Udført"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Udfør"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manuel Temp Basal"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Fjernkontrol"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nKontroller nu alle dine nye indstillinger grundigt:\n\n* Basal Indstillinger\n * Kulhydratratios\n * Glukose Mål\n * Insulin Følsomhed\n * VIA\n\n i iAPS Indstillinger > Konfiguration.\n\nDårlige eller ugyldige profilindstillinger kan have katastrofale effekter."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings index 7170383034..ab59a27e46 100644 --- a/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "von"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Letzte Berechnung um"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Starten"; +/* Start a temp target or a profile override */ +"Start" = "Starten"; + /* */ "Manual Temp Basal" = "Manuelle Temporäre Basalrate"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Fernbedienung"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nBitte überprüfen Sie jetzt alle Ihre neuen Einstellungen gründlich:\n\n* Basaleinstellungen\n * Carb Ratios\n * Glukose-Ziele\n * Insulinempfindlichkeiten\n * DIA\n\n in iAPS-Einstellungen > Konfiguration.\n\nSchlechte oder ungültige Profileinstellungen können abscheuliche Effekte haben."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Dynamic ISF-Konstante anpassen"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individuelle Anpassung der berechneten dynamischen Verhältnisse. Die Voreinstellung ist 0,5. Je höher der Wert, desto größer ist die Korrektur Ihres ISF/CR für einen hohen oder niedrigen Blutzuckerwert. Die maximale/minimale Korrektur wird durch die Min/Max-Einstellungen von Autosens bestimmt.\n\nFür die Sigmoid-Funktion wird für den Anfang ein Anpassungsfaktor von 0,4 - 0,5 empfohlen.\n\nFür die logarithmische Formel gibt es weniger Konsens, aber ein Wert von 0,8 ist wahrscheinlich für die meisten erwachsenen Benutzer angemessen. Für jüngere Anwender wird empfohlen, bei der logaritmischen Formel noch niedriger anzusetzen, um eine zu aggressive Behandlung zu vermeiden."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Sigmoid-Funktion verwenden"; diff --git a/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings index f224da9747..3ad7d73d19 100644 --- a/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings @@ -17,7 +17,7 @@ "Continue without bolus" = "Continuar sin administrar bolo"; /* Alert when adding large amount without bolusing */ -"\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add "; +"\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "¡La cantidad es mayor que el ajuste del bolo máximo!\n ¿Está seguro de que desea añadir "; /* Header */ "Enact Bolus" = "Administrar Bolo"; @@ -47,49 +47,61 @@ "Agree and continue" = "Aceptar y continuar"; /* Bolus progress view */ -"of" = "of"; +"of" = "de"; + +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "Un Bolo Remoto "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "fue entregado"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " hace X minutos, activado de forma remota en Nightscout, por un cuidador o un padre. ¿Todavía quieres aplicar el bolo?\n\nSe prevé que la glucosa eventual, si no aplica un bolo, será: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "¡Un Bolo Remoto se acaba de entregar!"; /* Headline in enacted pop up (at: at what time) */ -"Enacted at" = "Enacted at"; +"Enacted at" = "Entregado a las"; /* Headline in suggested pop up (at: at what time) */ -"Suggested at" = "Suggested at"; +"Suggested at" = "Sugerido a las"; /* Headline in enacted pop up (at: at what time) */ -"Error at" = "Error at"; +"Error at" = "Error en"; /* Bolus View Meal Summary Header */ -"Meal Summary" = "Meal Summary"; +"Meal Summary" = "Resumen de la comida"; /* Bolus View Meal Edit Meal Button */ -"Edit Meal" = "Edit Meal"; +"Edit Meal" = "Editar comida"; /* Bolus View Meal Add Meal Button */ -"Add Meal" = "Add Meal"; +"Add Meal" = "Agregar Alimento"; /* Bolus View Bolus Summary Header */ -"Bolus Summary" = "Bolus Summary"; +"Bolus Summary" = "Resumen del Bolo"; /* For the Bolus View pop-up */ -"Calculations" = "Calculations"; +"Calculations" = "Cálculos"; /* For the Bolus View pop-up */ -"Fatty Meal" = "Fatty Meal"; +"Fatty Meal" = "Comida Grasienta"; /* For the Bolus View pop-up */ -"Full Bolus" = "Full Bolus"; +"Full Bolus" = "Bolo Completo"; /* For the Bolus View pop-up */ -"Fraction" = "Fraction"; +"Fraction" = "Fracción"; /* For the Bolus View pop-up */ -"Fatty Meal Factor" = "Fatty Meal Factor"; +"Fatty Meal Factor" = "Factor de comida grasienta"; /* For the Bolus View pop-up */ -"Result" = "Result"; +"Result" = "Resultado"; /* For the Bolus View pop-up */ -"Your entered amount was limited by your max Bolus setting of %d%@" = "Your entered amount was limited by your max Bolus setting of %d%@"; +"Your entered amount was limited by your max Bolus setting of %d%@" = "La cantidad ingresada ha sido limitada por la configuración máxima del bolo de %d%@"; /* Bolus View Continue Button */ "Continue" = "Continuar"; @@ -125,7 +137,7 @@ "Carbs required" = "Se requieren carbohidratos"; /* Saved Food Presets */ -"Saved Food" = "Saved Food"; +"Saved Food" = "Alimento guardado"; /* */ "Are you sure?" = "¿Estás seguro?"; @@ -158,19 +170,19 @@ "Enact Temp Target" = "Iniciar objetivo temporal"; /* */ -"Target" = "Target"; +"Target" = "Objetivo"; /* */ -"Basal Insulin and Sensitivity ratio" = "Basal Insulin and Sensitivity ratio"; +"Basal Insulin and Sensitivity ratio" = "Ratio de insulina basal y sensibilidad"; /* */ -"A lower 'Half Basal Target' setting will reduce the basal and raise the ISF earlier, at a lower target glucose." = "A lower 'Half Basal Target' setting will reduce the basal and raise the ISF earlier, at a lower target glucose."; +"A lower 'Half Basal Target' setting will reduce the basal and raise the ISF earlier, at a lower target glucose." = "Un ajuste inferior de 'Objetivo Basal Medio' reducirá la basal y elevará el factor de sensibilidad antes, en un objetivo glucémico más bajo."; /* */ -" Your setting: " = " Your setting: "; +" Your setting: " = " Tu configuración: "; /* */ -"mg/dl. Autosens.max limits the max endpoint" = "mg/dl. Autosens.max limits the max endpoint"; +"mg/dl. Autosens.max limits the max endpoint" = "mg/dl. Autosens.max limita el extremo máximo"; /* */ "Enter preset name" = "Introduzca nombre del predef"; @@ -188,19 +200,19 @@ "Save" = "Guardar"; /* */ -"Save as Preset" = "Save as Preset"; +"Save as Preset" = "Guardar como Ajuste Predefinido"; /* Delete Meal Preset */ -"Delete Preset" = "Delete Preset"; +"Delete Preset" = "Eliminar Ajuste Predefinido"; /* Confirm Deletion */ -"Delete preset '%@'?" = "Delete preset '%@'?"; +"Delete preset '%@'?" = "¿Eliminar ajuste predefinido \"%@'?"; /* Button */ "No" = "No"; /* Button */ -"Yes" = "Yes"; +"Yes" = "Sí"; /* + Button */ "[ +1 ]" = "[ +1 ]"; @@ -212,7 +224,7 @@ "Top target" = "Objetivo Superior"; /* Temp target set for ... minutes */ -"for" = "for"; +"for" = "para"; /* Temp target set for ... minutes */ "min" = "min"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Ejecutar"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Basal temporal manual"; @@ -339,7 +354,7 @@ Enact a temp Basal or a temp target */ "Use local glucose server" = "Usar servidor local de glucosa"; /* Enable Statistics */ -"This enables uploading of statistics.json to Nightscout, which can be used by the Community Statistics and Demographics Project.\n\nParticipation in Community Statistics is opt-in, and requires separate registration at:\n" = "This enables uploading of statistics.json to Nightscout, which can be used by the Community Statistics and Demographics Project.\n\nParticipation in Community Statistics is opt-in, and requires separate registration at:\n"; +"This enables uploading of statistics.json to Nightscout, which can be used by the Community Statistics and Demographics Project.\n\nParticipation in Community Statistics is opt-in, and requires separate registration at:\n" = "Esto permite subir estadísticas.json a Nightscout, que puede ser utilizado por el Proyecto de Estadísticas y Demografía de la Comunidad.\n\nLa participación en las estadísticas de la comunidad es opcional, y requiere registrarse por separado en:\n"; /* */ "Edit settings json" = "Editar configuración json"; @@ -359,38 +374,41 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Control a distancia"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Permitir Control Remoto de iAPS"; + /* Imported Profiles Alert */ -"\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; +"\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nAhora, por favor, verifique todos sus nuevos ajustes de forma exhaustiva:\n\n* Ajustes Basales\n * Relación de Carbs\n * Objetivos de Glucosa\n * Sensibilidades a la Insulina\n * DAI\n\n en Ajustes de iAPS > Configuración.\n\nConfiguración del perfil incorrecta o inválida podría tener efectos desatrosos."; /* Profile Import Alert */ -"This will replace some or all of your current pump settings. Are you sure you want to import profile settings from Nightscout?" = "This will replace some or all of your current pump settings. Are you sure you want to import profile settings from Nightscout?"; +"This will replace some or all of your current pump settings. Are you sure you want to import profile settings from Nightscout?" = "Esto reemplazará algunos o todos los ajustes actuales de la bomba. ¿Está seguro de que desea importar la configuración del perfil de Nightscout?"; /* Import Error */ -"\nInvalid Nightcsout Basal Settings. \n\nImport aborted. Please check your Nightscout Profile Basal Settings!" = "\nInvalid Nightcsout Basal Settings. \n\nImport aborted. Please check your Nightscout Profile Basal Settings!"; +"\nInvalid Nightcsout Basal Settings. \n\nImport aborted. Please check your Nightscout Profile Basal Settings!" = "\nConfiguración basal de Nightscout inválida. \n\nImportación cancelada. ¡Compruebe la configuración basal de su perfil de Nightscout!"; /* Import Error */ -"\nSettings were imported but the Basals couldn't be saved to pump (No pump). Check your basal settings and tap ´Save on Pump´ to sync the new basal settings" = "\nSettings were imported but the Basals couldn't be saved to pump (No pump). Check your basal settings and tap ´Save on Pump´ to sync the new basal settings"; +"\nSettings were imported but the Basals couldn't be saved to pump (No pump). Check your basal settings and tap ´Save on Pump´ to sync the new basal settings" = "\nConfiguración importada pero las Basales no se pudieron guardar en la bomba (Sin bomba). Revisa la configuración basal y pulsa \"Guardar en la bomba\" para sincronizar la nueva configuración basal"; /* Import Error Headline */ -"Import Error" = "Import Error"; +"Import Error" = "Error de Importación"; /* */ -"Yes, Import" = "Yes, Import"; +"Yes, Import" = "Sí, Importar"; /* */ -"Import settings from Nightscout" = "Import settings from Nightscout"; +"Import settings from Nightscout" = "Importar ajustes de Nightscout"; /* */ -"Import settings?" = "Import settings?"; +"Import settings?" = "¿Importar ajustes?"; /* */ -"Import from Nightscout" = "Import from Nightscout"; +"Import from Nightscout" = "Importar de Nightscout"; /* */ -"Settings imported" = "Settings imported"; +"Settings imported" = "Ajustes importados"; /* Import Error */ -"\nMismatching glucose units in Nightscout and Pump Settings. Import settings aborted." = "\nMismatching glucose units in Nightscout and Pump Settings. Import settings aborted."; +"\nMismatching glucose units in Nightscout and Pump Settings. Import settings aborted." = "Las unidades de glucosa de Nightscout y la bomba no coinciden. Ajustes de importación cancelados."; /* Import Error */ "Can't find the default Nightscout Profile." = "Can't find the default Nightscout Profile."; @@ -683,10 +701,10 @@ Enact a temp Basal or a temp target */ "Pairinginfo" = "Pairinginfo"; /* */ -"PatchInfo" = "PatchInfo"; +"PatchInfo" = "Info del parche"; /* */ -"Calibrationinfo" = "Calibrationinfo"; +"Calibrationinfo" = "Info de calibración"; /* */ "Unknown" = "Desconocido"; @@ -695,139 +713,139 @@ Enact a temp Basal or a temp target */ "Not paired yet" = "No emparejado aún"; /* */ -"Pair Sensor & connect" = "Pair Sensor & connect"; +"Pair Sensor & connect" = "Emparejar Sensor y conectar"; /* */ -"Phone NFC required!" = "Phone NFC required!"; +"Phone NFC required!" = "¡Es necesario un teléfono con NFC!"; /* */ -"Your phone or app is not enabled for NFC communications, which is needed to pair to libre2 sensors" = "Your phone or app is not enabled for NFC communications, which is needed to pair to libre2 sensors"; +"Your phone or app is not enabled for NFC communications, which is needed to pair to libre2 sensors" = "Tu teléfono o aplicación no está habilitada para el uso de NFC, lo que es necesario para emparejar con sensores Libre 2"; /* Bluetooth Power Off */ -"Bluetooth Power Off" = "Bluetooth Power Off"; +"Bluetooth Power Off" = "Apagar Bluetooth"; /* Please turn on Bluetooth */ -"Please turn on Bluetooth" = "Please turn on Bluetooth"; +"Please turn on Bluetooth" = "Por favor, active el Bluetooth"; /* No Libre Transmitter Selected */ -"No Libre Transmitter Selected" = "No Libre Transmitter Selected"; +"No Libre Transmitter Selected" = "Ningún Transmisor Libre seleccionado"; /* Delete Transmitter and start anew. */ -"Delete CGMManager and start anew. Your libreoopweb credentials will be preserved" = "Delete CGMManager and start anew. Your libreoopweb credentials will be preserved"; +"Delete CGMManager and start anew. Your libreoopweb credentials will be preserved" = "Eliminar el gestor de MCG e iniciar de nuevo. Sus credenciales libreoopweb se conservarán"; /* Invalid libre checksum */ -"Invalid libre checksum" = "Invalid libre checksum"; +"Invalid libre checksum" = "Suma de verificación del Libre no válida"; /* Libre sensor was incorrectly read, CRCs were not valid */ -"Libre sensor was incorrectly read, CRCs were not valid" = "Libre sensor was incorrectly read, CRCs were not valid"; +"Libre sensor was incorrectly read, CRCs were not valid" = "El sensor Libre fue leído incorrectamente, sus CRCs no son válidos"; /* Glucose */ -"Glucose" = "Glucose"; +"Glucose" = "Glucosa"; /* LOWALERT! */ -"LOWALERT!" = "LOWALERT!"; +"LOWALERT!" = "¡ALERTA BAJA!"; /* HIGHALERT! */ -"HIGHALERT!" = "HIGHALERT!"; +"HIGHALERT!" = "¡ALERTA ALTA!"; /* (Snoozed)*/ -"(Snoozed)" = "(Snoozed)"; +"(Snoozed)" = "(Pospuesto)"; /* Glucose: %@ */ -"Glucose: %@" = "Glucose: %@"; +"Glucose: %@" = "Glucosa: %@"; /* Transmitter: %@%% */ -"Transmitter: %@%%" = "Transmitter: %@%%"; +"Transmitter: %@%%" = "Transmisor %@"; /* No Sensor Detected */ -"No Sensor Detected" = "No Sensor Detected"; +"No Sensor Detected" = "Ningún sensor detectado"; /* This might be an intermittent problem, but please check that your transmitter is tightly secured over your sensor */ -"This might be an intermittent problem, but please check that your transmitter is tightly secured over your sensor" = "This might be an intermittent problem, but please check that your transmitter is tightly secured over your sensor"; +"This might be an intermittent problem, but please check that your transmitter is tightly secured over your sensor" = "Esto podría ser un problema intermitente, pero por favor compruebe que su transmisor está firmemente asegurado sobre su sensor"; /* New Sensor Detected */ -"New Sensor Detected" = "New Sensor Detected"; +"New Sensor Detected" = "Se ha detectado un sensor nuevo"; /* Please wait up to 30 minutes before glucose readings are available! */ -"Please wait up to 30 minutes before glucose readings are available!" = "Please wait up to 30 minutes before glucose readings are available!"; +"Please wait up to 30 minutes before glucose readings are available!" = "¡Por favor, espere hasta 30 minutos antes de que las lecturas de glucosa estén disponibles!"; /* Invalid Glucose sample detected, try again later */ -"Invalid Glucose sample detected, try again later" = "Invalid Glucose sample detected, try again later"; +"Invalid Glucose sample detected, try again later" = "Se detectó una muestra de glucosa no válida, inténtalo de nuevo más tarde"; /* ensor might have temporarily stopped, fallen off or is too cold or too warm */ -"Sensor might have temporarily stopped, fallen off or is too cold or too warm" = "Sensor might have temporarily stopped, fallen off or is too cold or too warm"; +"Sensor might have temporarily stopped, fallen off or is too cold or too warm" = "El sensor podría haberse detenido temporalmente, caído o estar demasiado frío o demasiado caliente"; /* Invalid Sensor Detected */ -"Invalid Sensor Detected" = "Invalid Sensor Detected"; +"Invalid Sensor Detected" = "Sensor no válido detectado"; /* Detected sensor seems not to be a libre 1 sensor! */ -"Detected sensor seems not to be a libre 1 sensor!" = "Detected sensor seems not to be a libre 1 sensor!"; +"Detected sensor seems not to be a libre 1 sensor!" = "¡El sensor detectado parece no ser un sensor Libre 1!"; /* Detected sensor is invalid: %@ */ -"Detected sensor is invalid: %@" = "Detected sensor is invalid: %@"; +"Detected sensor is invalid: %@" = "El sensor detectado no es válido: %@"; /* Low Battery */ -"Low battery" = "Low battery"; +"Low battery" = "Batería baja"; /* */ -"Invalid sensor" = "Invalid sensor"; +"Invalid sensor" = "Sensor inválido"; /* */ -"Sensor change" = "Sensor change"; +"Sensor change" = "Cambio de sensor"; /* */ -"Sensor expires soon" = "Sensor expires soon"; +"Sensor expires soon" = "El sensor expira pronto"; /* Battery is running low %@, consider charging your %@ device as soon as possible */ -"Battery is running low %@, consider charging your %@ device as soon as possible" = "Battery is running low %@, consider charging your %@ device as soon as possible"; +"Battery is running low %@, consider charging your %@ device as soon as possible" = "La batería es baja %@, considera cargar tu dispositivo %@ lo antes posible"; /* Extracting calibrationdata from sensor */ -"Extracting calibrationdata from sensor" = "Extracting calibrationdata from sensor"; +"Extracting calibrationdata from sensor" = "Extrayendo datos de calibración del sensor"; /* Sensor Ending Soon */ -"Sensor Ending Soon" = "Sensor Ending Soon"; +"Sensor Ending Soon" = "El sensor finaliza pronto"; /* Current Sensor is Ending soon! Sensor Life left in %@ */ -"Current Sensor is Ending soon! Sensor Life left in %@" = "Current Sensor is Ending soon! Sensor Life left in %@"; +"Current Sensor is Ending soon! Sensor Life left in %@" = "¡El sensor actual terminará pronto! Vida restante del sensor en %@"; /* */ "Libre Bluetooth" = "Bluetooth Libre"; /* */ -"Snooze Alerts" = "Snooze Alerts"; +"Snooze Alerts" = "Silenciar Alarmas"; /* */ "Last measurement" = "Última medición"; /* */ -"Sensor Footer checksum" = "Sensor Footer checksum"; +"Sensor Footer checksum" = "Suma de verificación del sensor"; /* */ -"Last Blood Sugar prediction" = "Last Blood Sugar prediction"; +"Last Blood Sugar prediction" = "Última predicción del nivel de glucosa"; /* */ -"CurrentBG" = "CurrentBG"; +"CurrentBG" = "Glucosa actual"; /* */ -"Sensor Info" = "Sensor Info"; +"Sensor Info" = "Info del sensor"; /* */ -"Sensor Age" = "Sensor Age"; +"Sensor Age" = "Tiempo del sensor"; /* */ -"Sensor Age Left" = "Sensor Age Left"; +"Sensor Age Left" = "Tiempo restante del sensor"; /* */ -"Sensor Endtime" = "Sensor Endtime"; +"Sensor Endtime" = "Caducidad del sensor"; /* */ -"Sensor State" = "Sensor State"; +"Sensor State" = "Estado del sensor"; /* */ -"Sensor Serial" = "Sensor Serial"; +"Sensor Serial" = "Serial del sensor"; /* */ -"Transmitter Info" = "Transmitter Info"; +"Transmitter Info" = "Información del transmisor"; /* */ "Hardware" = "Hardware"; @@ -839,13 +857,13 @@ Enact a temp Basal or a temp target */ "Connection State" = "Estado de Conexión"; /* */ -"Transmitter Type" = "Transmitter Type"; +"Transmitter Type" = "Tipo de transmisor"; /* */ -"Sensor Type" = "Sensor Type"; +"Sensor Type" = "Tipo de sensor"; /* */ -"Factory Calibration Parameters" = "Factory Calibration Parameters"; +"Factory Calibration Parameters" = "Parámetros de calibración de fábrica"; /* */ "Valid for footer" = "Valid for footer"; @@ -1001,157 +1019,157 @@ Enact a temp Basal or a temp target */ "Backfill options" = "Backfill options"; /* */ -"Backfilling from trend is currently not well supported by Loop" = "Backfilling from trend is currently not well supported by Loop"; +"Backfilling from trend is currently not well supported by Loop" = "El relleno de las tendencias no está bien soportado por Loop"; /* */ -"Backfill from history" = "Backfill from history"; +"Backfill from history" = "Rellenar valores desde historial"; /* */ -"Backfill from trend" = "Backfill from trend"; +"Backfill from trend" = "Rellenar valores desde tendencia"; /* */ -"Debug options" = "Debug options"; +"Debug options" = "Opciones de depuración"; /* */ -"Adds a lot of data to the Issue Report " = "Adds a lot of data to the Issue Report "; +"Adds a lot of data to the Issue Report " = "Añade muchos datos al Informe de Incidencias "; /* */ -"Persist sensordata" = "Persist sensordata"; +"Persist sensordata" = "Mantener datos del sensor"; /* */ -"Battery" = "Battery"; +"Battery" = "Batería"; /* */ -"Also add source info" = "Also add source info"; +"Also add source info" = "Añadir también información de origen"; /* */ -"Carbs Required Threshold" = "Carbs Required Threshold"; +"Carbs Required Threshold" = "Umbral de carbohidratos requeridos"; /* */ -"Carbs required: %d g" = "Carbs required: %d g"; +"Carbs required: %d g" = "Carbohidratos necesarios: %d g"; /* */ -"To prevent LOW required %d g of carbs" = "To prevent LOW required %d g of carbs"; +"To prevent LOW required %d g of carbs" = "Para prevenir BAJO se requieren %d g. de carbohidratos"; /* */ -"iAPS not active" = "iAPS not active"; +"iAPS not active" = "iAPS inactivo"; /* */ -"Last loop was more than %d min ago" = "Last loop was more than %d min ago"; +"Last loop was more than %d min ago" = "El último ciclo fue hace más de %d mins"; /* Glucose badge */ -"Show glucose on the app badge" = "Show glucose on the app badge"; +"Show glucose on the app badge" = "Mostrar glucosa en la insignia de la aplicación"; /* */ -"Backfill glucose" = "Backfill glucose"; +"Backfill glucose" = "Rellenar valores de glucosa"; /* About this source */ -"About this source" = "About this source"; +"About this source" = "Acerca de esta fuente"; /* */ -"Bolus failed" = "Bolus failed"; +"Bolus failed" = "Bolo fallido"; /* "Max Bolus Exceeded label" */ -"Max Bolus exceeded!" = "Max Bolus exceeded!"; +"Max Bolus exceeded!" = "¡Bolo máximo superado!"; /* */ -"Bolus failed or inaccurate. Check pump history before repeating." = "Bolus failed or inaccurate. Check pump history before repeating."; +"Bolus failed or inaccurate. Check pump history before repeating." = "Bolo fallido o inexacto. Revise el historial de la bomba antes de repetir la acción."; /* */ -"Carbs" = "Carbs"; +"Carbs" = "Carbohidratos"; /* Food Type / Meal Note */ -"Note" = "Note"; +"Note" = "Nota"; /* */ -"Temp Basal" = "Temp Basal"; +"Temp Basal" = "Insulina basal temporal"; /* */ -"Temp Target" = "Temp Target"; +"Temp Target" = "Objetivo temporal"; /* */ -"Resume" = "Resume"; +"Resume" = "Reanudar"; /* */ -"Suspend" = "Suspend"; +"Suspend" = "Suspender"; /* */ -"Animated Background" = "Animated Background"; +"Animated Background" = "Fondo animado"; /* Sensor day(s) */ -" day(s)" = " day(s)"; +" day(s)" = " día(s)"; /* Option to show HR in Watch app*/ -"Display HR on Watch" = "Display HR on Watch"; +"Display HR on Watch" = "Mostrar frecuencia cardíaca en el reloj"; /* Headers for settings ----------------------- */ -"OpenAPS main settings" = "OpenAPS main settings"; +"OpenAPS main settings" = "Ajustes principales de OpenAPS"; -"OpenAPS SMB settings" = "OpenAPS SMB settings"; +"OpenAPS SMB settings" = "Ajustes de SMB en OpenAPS"; -"OpenAPS targets settings" = "OpenAPS targets settings"; +"OpenAPS targets settings" = "Ajustes de objetivos de OpenAPS"; -"OpenAPS other settings" = "OpenAPS other settings"; +"OpenAPS other settings" = "Otros ajustes de OpenAPS"; /* Glucose Simulator CGM */ -"Glucose Simulator" = "Glucose Simulator"; +"Glucose Simulator" = "Simulador de glucosa"; /* Restored state message */ -"Bluetooth State restored (APS restarted?). Found %d peripherals, and connected to %@ with identifier %@" = "Bluetooth State restored (APS restarted?). Found %d peripherals, and connected to %@ with identifier %@"; +"Bluetooth State restored (APS restarted?). Found %d peripherals, and connected to %@ with identifier %@" = "Estado del Bluetooth restaurado (¿se ha reiniciado APS?). Se encontraron %d periféricos, y se conectó al %@ con el identificador %@"; /* Shared app group xDrip4iOS */ -"Using shared app group with external CGM app xDrip4iOS" = "Using shared app group with external CGM app xDrip4iOS"; +"Using shared app group with external CGM app xDrip4iOS" = "Utilizar el grupo de aplicaciones compartidas con la app de MCG externa xDrip4iOS"; /* Shared app group GlucoseDirect */ -"Using shared app group with external CGM app GlucoseDirect" = "Using shared app group with external CGM app GlucoseDirect"; +"Using shared app group with external CGM app GlucoseDirect" = "Utilizar el grupo de aplicaciones compartidas con la app de MCG externa GlucoseDirect"; /* Dexcom G6 app */ -"Dexcom G6 app" = "Dexcom G6 app"; +"Dexcom G6 app" = "Aplicación Dexcom G6"; /* Native G5 app */ -"Native G5 app" = "Native G5 app"; +"Native G5 app" = "Aplicación nativa de Dexcom G5"; /* Minilink transmitter */ -"Minilink transmitter" = "Minilink transmitter"; +"Minilink transmitter" = "Transmisor Minilink"; /* Simple simulator */ -"Simple simulator" = "Simple simulator"; +"Simple simulator" = "Simulador simple"; /* Direct connection with Libre 1 transmitters or Libre 2 */ -"Direct connection with Libre 1 transmitters or European Libre 2 sensors" = "Direct connection with Libre 1 transmitters or European Libre 2 sensors"; +"Direct connection with Libre 1 transmitters or European Libre 2 sensors" = "Conexión directa con transmisores Libre 1 o sensores europeos Libre 2"; /* Online or internal server */ -"Online or internal server" = "Online or internal server"; +"Online or internal server" = "Servidor en línea o interno"; /* -------------- Developer settings ---------------------- */ /* Debug options */ -"Developer" = "Developer"; +"Developer" = "Desarrollador"; /* Debug option view NS Upload Profile */ -"NS Upload Profile" = "NS Upload Profile"; +"NS Upload Profile" = "Subir perfil a NS"; /* Debug option view NS Uploaded Profile */ -"NS Uploaded Profile" = "NS Uploaded Profile"; +"NS Uploaded Profile" = "Perfil subido a NS"; /* Debug option view Autosense */ "Autosense" = "Autosense"; /* Insulin sensitivity config header */ -"Dynamic Sensitivity" = "Dynamic Sensitivity"; +"Dynamic Sensitivity" = "Sensibilidad Dinámica"; /* Autotune config */ -"Only Autotune Basal Insulin" = "Only Autotune Basal Insulin"; +"Only Autotune Basal Insulin" = "Sólo Insulina Basal de Autotune"; /* */ -"Save as your Normal Basal Rates" = "Save as your Normal Basal Rates"; +"Save as your Normal Basal Rates" = "Guardar como tus ratios basales normales"; /* */ "Save on Pump" = "Guardar en Bomba"; /* Debug option view Pump History */ -"Pump History" = "Pump History"; +"Pump History" = "Historial de la bomba"; /* Debug option view Target Ranges */ "Target ranges" = "Target ranges"; @@ -1313,28 +1331,28 @@ Enact a temp Basal or a temp target */ "More options" = "More options"; /* */ -"Schedule when SMBs are Off" = "Schedule when SMBs are Off"; +"Schedule when SMBs are Off" = "Programar cuándo los SMB están apagados"; /* */ -"Change ISF and CR" = "Change ISF and CR"; +"Change ISF and CR" = "Modificar el Factor de Sensibilidad a la Insulina (ISF) y Factor de Carbohidratos (CR)"; /* */ -"Change ISF" = "Change ISF"; +"Change ISF" = "Cambiar Factor de Sensibilidad a la Insulina (ISF)"; /* */ -"Change CR" = "Change CR"; +"Change CR" = "Cambiar Factor de Carbohidratos (CR)"; /* */ -"SMB Minutes" = "SMB Minutes"; +"SMB Minutes" = "Minutos de SMB"; /* */ -"UAM SMB Minutes" = "UAM SMB Minutes"; +"UAM SMB Minutes" = "Minutos de SMB en UAM"; /* */ -"Start new Profile" = "Start new Profile"; +"Start new Profile" = "Iniciar nuevo perfil"; /* */ -"Save as Profile" = "Save as Profile"; +"Save as Profile" = "Guardar como perfil"; /* Alert */ "Cancel Profile Override" = "Cancel Profile Override"; @@ -1343,135 +1361,135 @@ Enact a temp Basal or a temp target */ "Cancel Temp Target" = "Cancelar objetivo temporal"; /* Alert */ -"Return to Normal?" = "Return to Normal?"; +"Return to Normal?" = "¿Regresar a normal?"; /* */ -"This will change settings back to your normal profile." = "This will change settings back to your normal profile."; +"This will change settings back to your normal profile." = "Esto cambiará la configuración a tu perfil normal."; /* Start Profile Alert */ -"Start Profile" = "Start Profile"; +"Start Profile" = "Iniciar perfil"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Su dosis basal de insulina se ajustará con el porcentaje de ajuste temporal. En consecuencia, su factor de sensibilidad a la insulina (ISF) y su índice glucémico (CR) se ajustarán en sentido inverso al mismo porcentaje."; /* */ -"Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile."; +"Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Al iniciar esta anulación, se modificarán tus perfiles y/o tu glucosa objetivo utilizados para el lazo cerrado durante toda la duración seleccionada. Al tocar \"Iniciar perfil\", se iniciará tu nuevo perfil o se editará tu perfil activo actual."; /* Change Target glucose in profile settings */ -"Override Profile Target" = "Override Profile Target"; +"Override Profile Target" = "Sobreescribir el objetivo del perfil"; /* Alert string. Keep spaces. */ -" SMBs are disabled either by schedule or during the entire duration." = " SMBs are disabled either by schedule or during the entire duration."; +" SMBs are disabled either by schedule or during the entire duration." = " Los SMB están desactivados ya sea por horario o durante toda la duración."; /* Alert strings. Keep spaces */ -" infinite duration." = " infinite duration."; +" infinite duration." = " duración infinita."; /* Service Section */ -"App Icons" = "App Icons"; +"App Icons" = "Iconos de la aplicación"; /* */ -"iAPS Icon" = "iAPS Icon"; +"iAPS Icon" = "Icono de iAPS"; /* Service Section */ -"Statistics and Home View" = "Statistics and Home View"; +"Statistics and Home View" = "Estadísticas y Vista de Inicio"; /* Alert text */ -"Delete Carb Equivalents?" = "Delete Carb Equivalents?"; +"Delete Carb Equivalents?" = "¿Eliminar Equivalentes de Carbohidratos?"; /* */ -"All FPUs of the meal will be deleted." = "All FPUs of the meal will be deleted."; +"All FPUs of the meal will be deleted." = "Se eliminarán todas las unidades de grasa y proteína (FPU) de la comida."; /* */ -"Delete Glucose?" = "Delete Glucose?"; +"Delete Glucose?" = "¿Eliminar glucosa?"; /* */ -"Meal Presets" = "Meal Presets"; +"Meal Presets" = "Atajo de comida"; /* */ -"Empty" = "Empty"; +"Empty" = "Vacío"; /* */ -"Delete Selected Preset" = "Delete Selected Preset"; +"Delete Selected Preset" = "Eliminar preajuste seleccionado"; /* */ -"Enter Meal Preset Name" = "Enter Meal Preset Name"; +"Enter Meal Preset Name" = "Introduce nombre del atajo de comida"; /* */ -"Name Of Dish" = "Name Of Dish"; +"Name Of Dish" = "Nombre del plato"; /* Save Carbs and continue to bolus recommendation */ -"Save and continue" = "Save and continue"; +"Save and continue" = "Guardar y continuar"; /* */ -"Save as Preset" = "Save as Preset"; +"Save as Preset" = "Guardar como Ajuste Predefinido"; /* */ -"Predictions" = "Predictions"; +"Predictions" = "Predicciones"; /* Watch Config Option */ -"Display Protein & Fat" = "Display Protein & Fat"; +"Display Protein & Fat" = "Mostrar proteínas y grasas"; /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ -"Warning!" = "Warning!"; +"Warning!" = "¡Advertencia!"; /* Alert to confirm bolus amount to add */ -"\n\nTap 'Add' to continue with selected amount." = "\n\nTap 'Add' to continue with selected amount."; +"\n\nTap 'Add' to continue with selected amount." = "\n\nPulse 'Añadir' para continuar con la cantidad seleccionada."; /* */ -"Eventual Glucose" = "Eventual Glucose"; +"Eventual Glucose" = "Glucosa eventual"; /* */ -"Please wait" = "Please wait"; +"Please wait" = "Por favor, espere"; /* */ -"Glucose, " = "Glucose, "; +"Glucose, " = "Glucosa, "; /* */ -"Target Glucose" = "Target Glucose"; +"Target Glucose" = "Glucosa objetivo"; /* */ -"Percentage setting" = "Percentage setting"; +"Percentage setting" = "Ajuste del porcentaje"; /* */ -"Insulin Sensitivity" = "Insulin Sensitivity"; +"Insulin Sensitivity" = "Sensibilidad a la insulina"; /* Formula displayed in Bolus info pop-up. Make translation short! */ -"(Eventual Glucose - Target) / ISF" = "(Eventual Glucose - Target) / ISF"; +"(Eventual Glucose - Target) / ISF" = "(Glucosa eventual - objetivo) / ISF"; /* */ -"Formula:" = "Formula:"; +"Formula:" = "Fórmula:"; /* Bolus pop-up footer */ -"Carbs and previous insulin are included in the glucose prediction, but if the Eventual Glucose is lower than the Target Glucose, a bolus will not be recommended." = "Carbs and previous insulin are included in the glucose prediction, but if the Eventual Glucose is lower than the Target Glucose, a bolus will not be recommended."; +"Carbs and previous insulin are included in the glucose prediction, but if the Eventual Glucose is lower than the Target Glucose, a bolus will not be recommended." = "Los carbohidratos y la insulina anterior están incluidos en la predicción de la glucosa. Si la glucosa eventual es inferior a la glucosa ovjetivo, no se recomienda bolo."; /* Hide pop-up */ -"Hide" = "Hide"; +"Hide" = "Ocultar"; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose is predicted to drop down to " = "Eventual Glucose > Target Glucose, but glucose is predicted to first drop down to "; +"Eventual Glucose > Target Glucose, but glucose is predicted to drop down to " = "Glucosa eventual > glucosa objetivo, pero se prevé que la glucosa caiga primero a "; /* Bolus pop-up / Alert string. Make translations concise! */ -"which is below your Threshold (" = "which is below your Threshold ("; +"which is below your Threshold (" = "que está por debajo del umbral ("; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: " = "Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: "; +"Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: " = "Glucosa eventual > glucosa objetivo, pero el valor de glucosa está aumentando más lento de lo esperado. Se espera: "; //* Bolus pop-up / Alert string. Make translations concise! */ -". Climbing: " = ". Climbing: "; +". Climbing: " = ". Subiendo: "; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: " = "Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: "; +"Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: " = "Glucosa eventual > glucosa objetivo, pero el valor de glucosa está descendiendo más rápido de lo esperado. Se espera: "; /* Bolus pop-up / Alert string. Make translations concise! */ -". Falling: " = ". Falling: "; +". Falling: " = ". Descendiendo: "; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose is changing faster than expected. Expected: " = "Eventual Glucose > Target Glucose, but glucose is changing faster than expected. Expected: "; +"Eventual Glucose > Target Glucose, but glucose is changing faster than expected. Expected: " = "Glucosa eventual > glucosa objetivo, pero el valor de glucosa está cambiando más rápido de lo esperado. Se espera: "; /* Bolus pop-up / Alert string. Make translations concise! */ -". Changing: " = ". Changing: "; +". Changing: " = ". Cambiando: "; /* Add insulin without bolusing alert */ " without bolusing" = " without bolusing"; @@ -1652,61 +1670,61 @@ Enact a temp Basal or a temp target */ "Change HbA1c Unit" = "Change HbA1c Unit"; /* */ -"Display Chart X - Grid lines" = "Display Chart X - Grid lines"; +"Display Chart X - Grid lines" = "Mostrar eje X - líneas de la cuadrícula"; /* */ -"Display Chart Y - Grid lines" = "Display Chart Y - Grid lines"; +"Display Chart Y - Grid lines" = "Mostrar eje Y - líneas de la cuadrícula"; /* */ -"Display Chart Threshold lines for Low and High" = "Display Chart Threshold lines for Low and High"; +"Display Chart Threshold lines for Low and High" = "Mostrar umbrales en el gráfico para glucemia baja y alta"; /* */ -"Standing / Laying TIR Chart" = "Standing / Laying TIR Chart"; +"Standing / Laying TIR Chart" = "Gráfico de Tiempo en Rango (TIR) vertical / horizontal"; /* */ -"Hours X-Axis (6 default)" = "Hours X-Axis (6 default)"; +"Hours X-Axis (6 default)" = "Horas mostradas en el eje X (por defecto, 6)"; /* */ -"2 hours" = "2 hours"; +"2 hours" = "2 horas"; /* */ -"4 hours" = "4 hours"; +"4 hours" = "4 horas"; /* */ -"6 hours" = "6 hours"; +"6 hours" = "6 horas"; /* */ -"12 hours" = "12 hours"; +"12 hours" = "12 horas"; /* */ -"24 hours" = "24 hours"; +"24 hours" = "24 horas"; /* Average BG = */ -"Average" = "Average"; +"Average" = "Media"; /* Median BG */ -"Median" = "Median"; +"Median" = "Mediana"; /* CGM readings in statView */ -"Readings" = "Readings"; +"Readings" = "Lecturas"; /* CGM readings in statView */ -"Readings / 24h" = "Readings / 24h"; +"Readings / 24h" = "Lecturas / 24h"; /* Days of saved readings*/ -"Days" = "Days"; +"Days" = "Días"; /* Normal BG (within TIR) */ "Normal" = "Normal"; /* Title High BG in statPanel */ -"High (>" = "High (>"; +"High (>" = "Alto (>"; /* Title Low BG in statPanel */ -"Low (<" = "Low (<"; +"Low (<" = "Bajo (<"; /* SD */ -"SD" = "SD"; +"SD" = "DS"; /* CV */ "CV" = "CV"; @@ -1715,78 +1733,78 @@ Enact a temp Basal or a temp target */ "HbA1c" = "HbA1c"; /* Total number of days of data for HbA1c estimation, part 1/2*/ -"All" = "All"; +"All" = "Todos"; /* Total number of days of data for HbA1c estimation, part 2/2*/ -"days" = "days"; +"days" = "días"; /* Nr of Loops in statPanel */ -"Loops" = "Loops"; +"Loops" = "Ciclos"; /* Loop Errors in statPanel */ -"Errors" = "Errors"; +"Errors" = "Errores"; /* Average loop interval */ -"Interval" = "Interval"; +"Interval" = "Intervalo"; /* Median loop interval */ "Duration" = "Duración"; /* "Display SD */ -"Display SD instead of CV" = "Display SD instead of CV"; +"Display SD instead of CV" = "Mostrar DS en lugar de CV"; /* Description for display SD */ -"Display Standard Deviation (SD) instead of Coefficient of Variation (CV) in statPanel" = "Display Standard Deviation (SD) instead of Coefficient of Variation (CV) in statPanel"; +"Display Standard Deviation (SD) instead of Coefficient of Variation (CV) in statPanel" = "Mostrar Desviación Estándar (DS) en lugar del Coeficiente de Variación (CV) en el Panel de Estadísticas"; /* How often to update the statistics */ -"Update every number of minutes:" = "Update every number of minutes:"; +"Update every number of minutes:" = "Actualizar cada número de minutos:"; /* Description for update interval for statistics */ -"Default is 20 minutes. How often to update and save the statistics.json and to upload last array, when enabled, to Nightscout." = "Default is 20 minutes. How often to update and save the statistics.json and to upload last array, when enabled, to Nightscout."; +"Default is 20 minutes. How often to update and save the statistics.json and to upload last array, when enabled, to Nightscout." = "Con qué frecuencia actualizar, guardar las estadísticas.json y subir la última línea de la matriz, si está habilitado, a Nightscout. Por defecto, 20 minutos."; /* Duration displayed in statPanel */ -"Past 24 Hours " = "Past 24 Hours "; +"Past 24 Hours " = "Últimas 24 horas"; /* Duration displayed in statPanel */ -"Past Week " = "Past Week "; +"Past Week " = "Última semana"; /* Duration displayed in statPanel */ -"Past Month " = "Past Month "; +"Past Month " = "Último mes"; /* Duration displayed in statPanel */ -"Past 90 Days " = "Past 90 Days "; +"Past 90 Days " = "Últimos 90 días"; /* Duration displayed in statPanel */ -"All Past Days of Data " = "All Past Days of Data "; +"All Past Days of Data " = "Todos los días pasados de datos "; /* "Display Loop statistics in statPanel */ -"Display Loop Cycle statistics" = "Display Loop Cycle statistics"; +"Display Loop Cycle statistics" = "Mostrar estadísticas de ciclos del lazo cerrado"; /* Description for Display Loop statistics */ -"Displays Loop statistics in the statPanel in Home View" = "Displays Loop statistics in the statPanel in Home View"; +"Displays Loop statistics in the statPanel in Home View" = "Muestra las estadísticas del lazo cerrado en el panel de estado en la vista de inicio"; /* Description for Override HbA1c unit */ -"Change default HbA1c unit in statPanlel. The unit in statPanel will be updateded with next statistics.json update" = "Change default HbA1c unit in statPanlel. The unit in statPanel will be updateded with next statistics.json update"; +"Change default HbA1c unit in statPanlel. The unit in statPanel will be updateded with next statistics.json update" = "Cambiar las unidad por defecto de HbA1c en el panel de estadísticas. Las unidades serán actualizadas en dicho panel de estadísticas en la próxima actualización del fichero estadísticas.json"; /* HbA1c for all glucose storage days */ -"all" = "all"; +"all" = "todos"; /* -------------------------------------------------------- Dexcom G7 --------------------------------------*/ -"CGM Configuration" = "CGM Configuration"; +"CGM Configuration" = "Configuración de MCG"; -"Heartbeat" = "Heartbeat"; +"Heartbeat" = "Latido del corazón"; -"CGM address :" = "CGM address :"; +"CGM address :" = "Dirección del MCG :"; -"CGM is not used as heartbeat." = "CGM is not used as heartbeat."; +"CGM is not used as heartbeat." = "El MCG no se utiliza como latido de corazón."; -"Are you sure you want to delete this CGM?" = "Are you sure you want to delete this CGM?"; +"Are you sure you want to delete this CGM?" = "¿Está usted seguro de querer eliminar este MCG?"; /* New Experimental feature */ "Experimental" = "Experimental"; /* Smoothing of CGM readings */ -"Smooth Glucose Value" = "Smooth Glucose Value"; +"Smooth Glucose Value" = "Suavizar valores de glucosa"; /* ----------------------------------------------------------------------------------------------------------- @@ -1795,25 +1813,25 @@ Enact a temp Basal or a temp target */ */ /* Headline Rewind Resets Autosens */ -"Rewind Resets Autosens" = "Rewind Resets Autosens"; +"Rewind Resets Autosens" = "Rebobinar reinicia Autosens"; /* ”Rewind Resets Autosens” */ "This feature, enabled by default, resets the autosens ratio to neutral when you rewind your pump, on the assumption that this corresponds to a probable site change. Autosens will begin learning sensitivity anew from the time of the rewind, which may take up to 6 hours. If you usually rewind your pump independently of site changes, you may want to consider disabling this feature." = "Esta función, activada por defecto, restablece la proporción de autosens a neutral cuando rebobinas la bomba, suponiendo que esto corresponde a un probable cambio en el sitio. Autosens comenzará a aprender la sensibilidad desde el momento del evento, y puede tardar hasta 6 horas. Si normalmente rebobina su bomba independientemente de los cambios en el sitio, puede considerar desactivar esta función."; /* Headline "High Temptarget Raises Sensitivity" */ -"High Temptarget Raises Sensitivity" = "High Temptarget Raises Sensitivity"; +"High Temptarget Raises Sensitivity" = "Objetivo temporal elevado aumenta la sensibilidad"; /* ”High Temptarget Raises Sensitivity" */ "Defaults to false. When set to true, raises sensitivity (lower sensitivity ratio) for temp targets set to >= 111. Synonym for exercise_mode. The higher your temp target above 110 will result in more sensitive (lower) ratios, e.g., temp target of 120 results in sensitivity ratio of 0.75, while 140 results in 0.6 (with default halfBasalTarget of 160)." = "Por defecto 'Falso'. Cuando se cambia a 'Verdadero', aumenta la sensibilidad (menor proporción de sensibilidad) para objetivos temporales fijados en >= 111. Sinónimo de modo ejercicio. Cuanto mayor sea su objetivo temporal superior a 110, resultará en relaciones más sensibles (más bajas), p.ej., objetivo temporal de 120 resulta en una proporción de sensibilidad de 0.75, mientras que 140 resultaría en 0.6 (con un valor por defecto de objetivo basal de 160)."; /* Headline ”Low Temptarget Lowers Sensitivity" */ -"Low Temptarget Lowers Sensitivity" = "Low Temptarget Lowers Sensitivity"; +"Low Temptarget Lowers Sensitivity" = "Objetivo temporal bajo reduce la sensibilidad"; /* ”Low Temptarget Lowers Sensitivity" */ "Defaults to false. When set to true, can lower sensitivity (higher sensitivity ratio) for temptargets <= 99. The lower your temp target below 100 will result in less sensitive (higher) ratios, e.g., temp target of 95 results in sensitivity ratio of 1.09, while 85 results in 1.33 (with default halfBasalTarget of 160)." = "Por defecto 'Falso'. Cuando se establece 'Verdadero', puede disminuir la sensibilidad (mayor proporción de sensibilidad) para objetivos temporales <= 99. Cuanto menor sea su objetivo temporal por debajo de 100, resultará en proporciones menos sensibles (superiores), p. ej., el objetivo temporal de 95 resulta en la proporción de sensibilidad de 1.09, mientras que 85 resulta en 1.33 (con la mitad de objetivo predeterminada de 160)."; /* Headline ”Sensitivity Raises Target" */ -"Sensitivity Raises Target" = "Sensitivity Raises Target"; +"Sensitivity Raises Target" = "Sensibilidad aumenta el objetivo"; /* ”Sensitivity Raises Target" */ "When true, raises BG target when autosens detects sensitivity" = "Cuando es verdadero, aumenta el objetivo BG cuando los autosens detectan sensibilidad"; @@ -2064,16 +2082,16 @@ Un 1.0 de valor permite un ajuste completo con el nuevo factor de sensibilidad d "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ -"Use Sigmoid Function" = "Use Sigmoid Function"; +"Use Sigmoid Function" = "Usar función de Sigmoid"; /* Which dyn ISF function to use */ -"Formula" = "Formula"; +"Formula" = "Fórmula"; /* Extra Safety Features when using dyn ISF */ -"Safety" = "Safety"; +"Safety" = "Seguridad"; /* Use Sigmoid Function */ "Use a sigmoid function for ISF (and for CR, when enabled), instead of the default Logarithmic formula. Requires the Dynamic ISF setting to be enabled in settings\n\nThe Adjustment setting adjusts the slope of the curve (Y: Dynamic ratio, X: Blood Glucose). A lower value ==> less steep == less aggressive.\n\nThe autosens.min/max settings determines both the max/min limits for the dynamic ratio AND how much the dynamic ratio is adjusted. If AF is the slope of the curve, the autosens.min/max is the height of the graph, the Y-interval, where Y: dynamic ratio. The curve will always have a sigmoid shape, no matter which autosens.min/max settings are used, meaning these settings have big consequences for the outcome of the computed dynamic ISF. Please be careful setting a too high autosens.max value. With a proper profile ISF setting, you will probably never need it to be higher than 1.5\n\nAn Autosens.max limit > 1.5 is not advisable when using the sigmoid function." = "Use a sigmoid function for ISF (and for CR, when enabled), instead of the default Logarithmic formula. Requires the Dynamic ISF setting to be enabled in settings\n\nThe Adjustment setting adjusts the slope of the curve (Y: Dynamic ratio, X: Blood Glucose). A lower value ==> less steep == less aggressive.\n\nThe autosens.min/max settings determines both the max/min limits for the dynamic ratio AND how much the dynamic ratio is adjusted. If AF is the slope of the curve, the autosens.min/max is the height of the graph, the Y-interval, where Y: dynamic ratio. The curve will always have a sigmoid shape, no matter which autosens.min/max settings are used, meaning these settings have big consequences for the outcome of the computed dynamic ISF. Please be careful setting a too high autosens.max value. With a proper profile ISF setting, you will probably never need it to be higher than 1.5\n\nAn Autosens.max limit > 1.5 is not advisable when using the sigmoid function."; diff --git a/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings index 91bdc9e32c..aabe297b82 100644 --- a/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Aktivoi"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Väliaikainen basaali"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Remote control"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings index 5bdc403d2c..68681405d4 100644 --- a/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "de"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Dernier calcul à"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Injecter"; +/* Start a temp target or a profile override */ +"Start" = "Démarrer"; + /* */ "Manual Temp Basal" = "Basal temporaire manuel"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Contrôle à distance"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nVeuillez maintenant vérifier soigneusement tous vos nouveaux paramètres:\n\n* Paramètres basaux\n * Ratios glucidiques\n * Objectifs glycémiques\n * Sensibilité à l'insuline\n * DIA\n\n dans iAPS Paramètres > Configuration.\n\nDes paramètres de profil incorrects ou invalides peuvent avoir des effets désastreux."; @@ -1583,7 +1601,7 @@ Enact a temp Basal or a temp target */ "This PumpManager has not been configured with a maximum basal rate because it was added before manual temp basal was a feature. Please go to therapy settings -> delivery limits and set a new maximum basal rate." = "Le Gestionnaire de Pompes n'a pas été configuré avec un débit de base maximum car il a été ajouté avant que le Basal temporaire manuel soit une fonctionnalité. Veuillez aller dans les paramètres de thérapie -> limites de délivrance et définir un nouveau taux de basal maximum."; /* description label for active time pod details row */ -"Active Time" = "Durée d’activité"; +"Active Time" = "Heure d’activation"; /* description label for total delivery pod details row */ "Total Delivery" = " Total délivré"; @@ -2029,13 +2047,13 @@ Enact a temp Basal or a temp target */ // Dynamic ISF + CR Settings: /* Headline "Adjust Dynamic ISF constant" */ -"Adjust Dynamic ISF constant" = "Ajuster la constante ISF Dynamique"; +"Adjust Dynamic ISF constant" = "Ajuster la constante du FSI Dynamique"; /* Adjust Dynamic ISF constant */ -"Adjust Dynamic ISF constant" = "Ajuster la constante ISF Dynamique"; +"Adjust Dynamic ISF constant" = "Ajuster la constante du FSI Dynamique"; /* Enable Dynamic ISF, Headline */ -"Enable Dynamic ISF" = "Activer ISF dynamique"; +"Enable Dynamic ISF" = "Activer le facteur de sensibilité à l'insuline (FSI) dynamique"; /* Headline "Enable Dynamic ISF" */ "Enable Dynamic ISF" = "Activer le facteur de sensibilité à l'insuline (FSI) dynamique"; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Ajuster la constante du FSI Dynamique"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Utiliser la fonction Sigmoid"; @@ -2163,7 +2181,7 @@ Enact a temp Basal or a temp target */ "Live Activity" = "Live Activity"; /* Notification option */ -"Live activity displays blood glucose live on the lock screen and on the dynamic island (if available)" = "Live activity displays blood glucose live on the lock screen and on the dynamic island (if available)"; +"Live activity displays blood glucose live on the lock screen and on the dynamic island (if available)" = "L'activité en direct affiche la glycémie sur l'écran de verrouillage et sur l'île dynamique (si disponible)"; /* Notification option */ "Show Live activity" = "Afficher l'activité en direct"; diff --git a/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings index c05b3c4ca1..a1f2376c0a 100644 --- a/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Enact"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manual Temp Basal"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Remote control"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings index a08e3b81a1..0c8c55d624 100644 --- a/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Beadva"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Beadni"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Átmeneti Kézi Bázis"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Távirányítás"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nMost kérlek alaposan nézd át a beállításokat:\n\n* Bázis Ceállítások\n * Szénhidrát Arány\n * Cukorszint Célpont\n * Inzulin Érzékenység\n * DIA\n\n iAPS beállítások > Konfiguráció.\n\nHelytelen vagy rossz beállításoknak halálos következményei lehetnek."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings index 96f01f0559..d978889098 100644 --- a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "di"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "Un Bolo Remoto "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "è stato consegnato"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minuti fa, innescato a distanza da Nightscout, da un assistente o da un genitore. Vuoi ancora fare il bolo?\n\nL'eventuale glicemia prevista, se non fai bolo, è:"; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "Un Bolo Remoto è appena Consegnato!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Eseguito alle"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Attiva"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Basale temporanea manuale"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Controllo remoto"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Consenti il controllo remoto di iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nOra verifica attentamente tutte le nuove impostazioni:\n\n* Impostazioni basali\n * Rapporti carboidrati\n * Obiettivi glucosio\n * Sensibilità insulinica\n * DIA\n\n in Impostazioni iAPS > Configurazione.\n\nImpostazioni del profilo errate o non valide potrebbero avere effetti disastrosi."; @@ -1195,7 +1213,7 @@ Enact a temp Basal or a temp target */ "Apple Health" = "Apple Salute"; /* */ -"Connect to Apple Health" = "Connetti con Apple Salute"; +"Connect to Apple Health" = "Connetti ad Apple Salute"; /* Show when have not permissions for writing to Health */ "For write data to Apple Health you must give permissions in Settings > Health > Data Access" = "Per scrivere dati su Apple Health devi dare il permesso in Impostazioni > Salute > Accesso dati"; @@ -2059,9 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Regola i rapporti dinamici della costante ISF"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Regola i rapporti dinamici di una costante. Il valore predefinito è 0,5. Più alto è il valore, maggiore sarà la correzione del tuo ISF per una glicemia alta o bassa. La correzione massima è determinata dalle impostazioni Autosens min/max.\n\nPer la funzione sigmoidea si consiglia di iniziare con un fattore di correzione di 0,4 - 0,5.\n\n Per la formula logaritmica c'è meno consenso, ma iniziare con 0,5 - 0,8 è più appropriato per la maggior parte degli utenti adulti. -Per gli utenti più giovani si consiglia di iniziare con un dosaggio ancora più basso quando si utilizza la formula logaritmica, per evitare un trattamento eccessivamente aggressivo. -Regola la costante ISF dinamica."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Usa Funzione Sigmoid"; diff --git a/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings index c40c097cdf..0a649755a6 100644 --- a/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "av"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Utført kl."; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Start"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manuell basal"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Fjernstyring"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nGå nøye gjennom alle de nye innstillingene:\n\n* Basalprofil\n * Karbohydratforhold\n * Blodsukkermål\n * Insulinfølsomhet\n\n i iAPS Innstillinger > Oppsett.\n\nFeil eller ugyldige profilinnstillinger kan ha katastrofale følger."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Juster konstant for dynamisk ISF"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Justeringsfaktoren brukes til å bestemme hvor mye ISF/CR skal justeres når man benytter dynamisk ISF/CR. Standardverdi er 0.5. Jo høyere verdi, jo større blir korrigeringen av ISF/CR ved høyt eller lavt blodsukker. Maks/min korrigering avgjøres av dine Autosens maks/min-innstillinger.\n\nFor Sigmoid anbefales det en justeringsfaktor på 0.4 - 0.5 til å begynne med.\n\nNår Sigmoid ikke er i bruk anbefales det å starte på 0.8 for voksne brukere. For yngre brukere er det anbefalt å starte med en lavere justeringsfaktor for å unngå aggresiv behandling."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Bruk sigmoid-funksjon"; diff --git a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings index fe9e9923c5..e9fe7cc3d9 100644 --- a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "van"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "Een bolus op afstand "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "zojuist afgeleverd"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minuten geleden, op afstand gestart vanuit Nightscout, door een verzorger of een ouder. Wil je nog steeds een bolus?\n\nDe verwachte uiteindelijke glucose, als je niet bolust, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "De bolus op afstand is zojuist geleverd!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Toegediend op"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Uitvoeren"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Handmatige tijdelijke basaal"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Afstandsbediening"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Toestaan dat iAPS op afstand beheerd wordt"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nCheck nu al je nieuwe instellingen:\n\n* Basaal instellingen\n * Koolhydraat ratio's\n * Doel glucose waarde\n * Insuline sensitiviteit\n * DIA\n\n in iAPS instellingen > Configuratie.\n\nSlechte of ongeldige profielinstellingen kunnen desastreuze effecten hebben!"; @@ -2063,7 +2081,7 @@ Eenvoudig gezegd, de Dynamische Carb Ratio past de koolhydraatverhouding aan op "Adjust Dynamic ISF constant" = "Dynamische ISF-constante aanpassen"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individuele aanpassing van de berekende dynamische verhoudingen. De standaardwaarde is 0,5. Hoe hoger de waarde, hoe groter de correctie van je ISF/CR zal zijn voor een hoge of lage bloedglucosewaarde.\n\nDe maximale/minimale correctie wordt bepaald door de Autosens min/max instellingen.\\Voor de Sigmoid functie wordt een aanpassingsfactor van 0.4 - 0.5 aanbevolen om mee te beginnen.n\nVoor de logaritmische formule is er minder overeenstemming, maar beginnen rond de 0.8 is waarschijnlijk goed voor de meeste volwassen gebruikers. Voor jongere gebruikers is het aan te raden om nog lager te beginnen met de logaritmische formule, om een te agressieve behandeling te voorkomen."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Gebruik Sigmoid functie"; @@ -2155,7 +2173,7 @@ Eenvoudig gezegd, de Dynamische Carb Ratio past de koolhydraatverhouding aan op "Horizontal Scroll View Visible hours" = "Horizontale scrolweergave zichtbare uren"; /* UI/UX option */ -"Display Time Interval Setting Button" = "Display Time Interval Setting Button"; +"Display Time Interval Setting Button" = "Knop voor tijdinterval weergeven"; /* Setting title */ "Bolus Calculator" = "Bolus calculator"; diff --git a/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings index be5270d8b0..60cdaddbbd 100644 --- a/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Enact"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manual Temp Basal"; @@ -361,6 +376,9 @@ Połączono z Nightscout!"; /* Allow remote control from NS */ "Remote control" = "Remote control"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2061,7 +2079,7 @@ Połączono z Nightscout!"; "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings index 7d4331b80f..5262083892 100644 --- a/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Executar"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Basal Temporária Manual"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Controle remoto"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings index d4de4b553d..1da1a40fbf 100644 --- a/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Executar"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Basal Temporária Manual"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Controle remoto"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; diff --git a/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings index 1050bf1d57..3028ee4640 100644 --- a/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "из"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "Дистанционный Болюс "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "был введен"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " минут назад, запущенный удаленно из Nightscout лицом, осуществляющим уход, или родителем. Вы все еще хотите выполнить болюс?\n\nПрогнозируемый уровень глюкозы, если вы не подтверждаете болюс, составляет: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "Дистанционный Болюс был только что введен!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Принято в"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Запустить"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Ручная ВБС"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Удаленное управление"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Разрешить дистанционное управление iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nПожалуйста, проверьте все ваши новые настройки:\n\n* Настройки базала\n * Углеводные коэффициенты\n * Целевой диапазон\n * Чувствительность к инсулину\n\n в настройках iAPS Настройки > Конфигурация.\n\nНекорректные настройки профиля могут привести к катастрофическим последствиям."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Настроить константу динамического ISF"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Индивидуальная настройка рассчитанных динамических коэффициентов. Значение по умолчанию равно 0.5. Чем выше значение, тем больше будет коррекция вашего ISF/CR для высокого или низкого уровня глюкозы в крови. Максимальная/минимальная коррекция определяется настройками autosens min/max.\n\nДля сигмоидной функции рекомендуется для начала использовать коэффициент 0.4 - 0.5.\n\nДля логарифмической формулы существует меньшее единодушие, но для большинства взрослых пользователей, вероятно, подходит значение, начинающееся примерно с 0.8. Для более молодых пользователей рекомендуется начинать с еще меньшего значения при использовании логарифмической формулы, чтобы избежать чрезмерно агрессивного лечения."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Использовать Сигмоидную функцию"; diff --git a/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings index e7db241ce8..d48dcc1be8 100644 --- a/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "z"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Uskutočnené o"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Vykonať"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manuálny dočasný bazál"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Vzdialené ovládanie"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\\Teraz dôkladne skontrolujte všetky nové nastavenia:\n\n* Bazálne nastavenia\n * Pomery uhľohydrátov\n * Cieľové hodnoty glukózy\n * Citlivosť na inzulín\n * DIA\n\n v iAPS Nastavenia > Konfigurácia.\n\nZlé alebo neplatné nastavenia profilu by mohli mať škodlivé účinky."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Nastavenie konštanty Dynamic ISF"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individuálne nastavenie vypočítaných dynamických pomerov. Predvolená hodnota je 0,5. Čím vyššia je táto hodnota, tým väčšia bude korekcia vášho ISF/CR pre vysokú alebo nízku hladinu glukózy v krvi. Maximálna/minimálna korekcia je určená nastavením min/max v programe Autosens.\n\nPre sigmoidnú funkciu sa na začiatok odporúča korekčný faktor 0,4 - 0,5.\n\nPre logaritmický vzorec existuje menej konsenzu, ale začiatok okolo 0,8 je pravdepodobne vhodný pre väčšinu dospelých používateľov. U mladších používateľov sa pri používaní logaritmickej formuly odporúča začať ešte nižšie, aby sa zabránilo príliš agresívnej liečbe."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Použitie funkcie Sigmoid"; diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index 868e47317b..117e263219 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -56,7 +56,7 @@ "was delivered" = "gavs för"; /* Remote Bolus Alert, Part 3 */ -" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minuter sedan, aktiverad från Nightscout, av en assistent eller förälder. Vill du fortfarande ge en ny bolus?\n\nBeräknad blodsockerprognos, om du inte ger bolus, är: "; +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minuter sedan, aktiverad från Nightscout, av en assistent eller förälder. Vill du fortfarande ge en ny bolus?\n\nBeräknad blodsockerprognos, om du inte ger bolus, är: "; /* Remote Bolus Alert, Title */ "A Remote Bolus Was Just Delivered!" = "En fjärrstyrd bolus gavs precis!"; @@ -314,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Utför"; +/* Start a temp target or a profile override */ +"Start" = "Starta"; + /* */ "Manual Temp Basal" = "Manuell temporär basal"; @@ -371,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Fjärrstyrning"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Tillåt fjärrstyrning från Nightscout"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nKontrollera nu alla dina nya pumpinställningar noga:\n\n* Basalinställningar\n * Insulinkvoter\n * Målvärden\n * Insulinkänslighet\n\n i Inställningar > Konfiguration.\n\nDåliga eller ogiltiga pumpinställningar kan gå katastrofala följder."; @@ -2071,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Ändra AF-konstant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individuell justering av hur din insulinkänslighet och insulinkvot (om du använder dyamisk insulinkvot) räknas ut. Stnadarvärde är 0.5. Ett högre värde betyder mer aggressiv justering.\n\nFör S-formad dynamisk inställning rekommendaras att börja med 0.3-0-4. För logaritmisk inställning rekommenderas att börja med 0.5-0.8."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individuell justering av hur din insulinkänslighet och insulinkvot (om du använder dyamisk insulinkvot) räknas ut. Standardvärde är 0.5. Ett högre värde betyder mer aggressiv justering.\n\nFör S-formad dynamisk inställning rekommendaras att börja med 0.3-0-4. För logaritmisk inställning rekommenderas att börja med 0.5-0.8."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Använd S-formad dynamisk insulinkänslighet"; diff --git a/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings index cc89fbb7c1..d3a315b1b8 100644 --- a/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Başlat"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "Manuel Geçici Bazal"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Uzaktan kontrol"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Dinamik İDF sabitini ayarla"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Sigmoid Fonksiyonunu Kullan"; diff --git a/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings index 4b52afda99..a3242e732f 100644 --- a/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "із"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "Віддалений Болюс "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "було доставлено"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = "хвилин тому, активовано дистанційно з Nightscout опікуном або батьком. Ви все ще хочете вводити болюс?\n\nПрогнозований кінцевий рівень глюкози, якщо ви не вводите болюс, становить:"; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "Дистанційний болюс щойно був доставлений!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Виконано в"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Запустити"; +/* Start a temp target or a profile override */ +"Start" = "Почати"; + /* */ "Manual Temp Basal" = "Ручна Тимчасова Базальна Швидкість (ТБШ)"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Віддалене керування"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Дозволити дистанційне керування iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nТепер уважно перевірте всі ваші нові налаштування:\n\n* Базальні параметри\n * Вуглеводні співвідношення\n * Цільові показники глюкози\n * Чутливість до інсуліну\n\n у меню «Налаштування iAPS» > «Конфігурація».\n\nПоганий або недійсний профіль налаштування можуть мати згубні наслідки."; @@ -2059,7 +2077,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Налаштувати константу Динамічного ISF"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Індивідуальне налаштування розрахованих динамічних коефіцієнтів. За замовчуванням 0,5. Чим вище значення, тим більшою буде корекція вашого ISF/CR для високого або низького рівня глюкози в крові. Максимальна/мінімальна корекція визначається мінімальними/максимальними налаштуваннями Autosens.\n\nДля сигмоїдної функції спочатку рекомендується коригувальний коефіцієнт 0,4–0,5.\n\nДля логаритмічної формули три є менш узгодженими, але починаючи приблизно з 0,8 ймовірно підходить для більшості дорослих користувачів. Для молодших користувачів рекомендується починати ще нижче при використанні логарифмічної формули, щоб уникнути занадто агресивного лікування."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Індивідуальне налаштування розрахованих динамічних коефіцієнтів. За замовчуванням 0,5. Чим вище значення, тим більшою буде корекція вашого ISF/CR для високого або низького рівня глюкози в крові. Максимальна/мінімальна корекція визначається мінімальними/максимальними налаштуваннями Autosens.\n\nДля сигмоїдної функції спочатку рекомендується коригувальний коефіцієнт 0,4–0,5.\n\nДля логаритмічної формули три є менш узгодженими, але починаючи приблизно з 0,8 ймовірно підходить для більшості дорослих користувачів. Для молодших користувачів рекомендується починати ще нижче при використанні логарифмічної формули, щоб уникнути занадто агресивного лікування."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Використовувати Сігмоїдну Функцію"; diff --git a/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings index da92463af7..b52a42f746 100644 --- a/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "của"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "Một liều Bolus từ xa "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "vừa được hoàn thành"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " phút trước, được kích hoạt từ xa từ Nightscout, bởi người chăm sóc hoặc phụ huynh. Bạn vẫn muốn bolus?\n\nDự đoán lượng đường cuối cùng, nếu bạn không bolus, là: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "Một liều Bolus từ xa vừa được hoàn thành!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Thực hiện ở"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "Chấp nhận"; +/* Start a temp target or a profile override */ +"Start" = "Khởi chạy"; + /* */ "Manual Temp Basal" = "Liều cơ bản thủ công"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "Điều khiển từ xa"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Cho phép điều khiển iAPS từ xa"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\n Bây giờ xin hãy xác minh lại tất cả các cài đặt của bạn kỹ lưỡng:\n\n* Cài đặt liều nền\n * Tỷ lệ Carb\n * Mục tiêu đường huyết \n * Độ nhạy của Insulin\n * Thời gian hoạt động của insulin\n\n trong iAPS Cài đặt > Cấu hình.\n\n Cấu hình không hợp lệ hoặc tồi có thể có tác động thảm họa."; @@ -486,7 +504,7 @@ Enact a temp Basal or a temp target */ "Devices" = "Thiết bị"; /* */ -"Pump" = "Bơm"; +"Pump" = "Bơm Insulin"; /* */ "Watch" = "Đồng hồ"; @@ -609,7 +627,7 @@ Enact a temp Basal or a temp target */ "Create Events in Calendar" = "Tạo sự kiện trong Calendar"; /* */ -"Calendar" = "Calendar"; +"Calendar" = "Lập lịch"; /* Automatic delivered treatments */ "Automatic" = "Tự động"; @@ -852,10 +870,10 @@ Enact a temp Basal or a temp target */ "Valid for footer" = "Hợp lệ"; /* */ -"Edit calibrations" = "Thêm kết quả hiệu chuẩn"; +"Edit calibrations" = "Chỉnh sửa hiệu chuẩn"; /* */ -"edit calibration clicked" = "Nhấp vào để hiệu chuẩn"; +"edit calibration clicked" = "nhấp vào để chỉnh sửa hiệu chuẩn"; /* */ "Delete CGM" = "Xóa CGM"; @@ -894,7 +912,7 @@ Enact a temp Basal or a temp target */ "Saved to %@" = "Đã lưu vào %@"; /* */ -"No logs available" = "Không có nhật ký"; +"No logs available" = "Không có nhật ký nào"; /* */ "Glucose Notification visibility" = "Khả năng hiển thị thông báo Glucose"; @@ -2060,7 +2078,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Điều chỉnh hằng số ISF động"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Điều chỉnh riêng các tỷ lệ động được tính toán. Mặc định là 0,5. Giá trị càng cao thì mức điều chỉnh ISF/CR của bạn đối với mức đường huyết cao hay thấp càng lớn. Hiệu chỉnh tối đa/tối thiểu được xác định bởi cài đặt tối thiểu/tối đa của Autosens.\n\nĐối với hàm Sigmoid, hệ số điều chỉnh được khuyến nghị là 0,4 - 0,5 để bắt đầu.\n\nĐối với công thức logarit, có ít sự đồng thuận hơn, nhưng bắt đầu từ khoảng 0,8 là có lẽ phù hợp với hầu hết người dùng trưởng thành. Đối với người dùng trẻ tuổi, nên bắt đầu ở mức thấp hơn nữa khi sử dụng công thức logarit để tránh điều trị quá tích cực."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Điều chỉnh riêng các tỷ lệ động được tính toán. Mặc định là 0,5. Giá trị càng cao thì mức điều chỉnh ISF/CR của bạn đối với mức đường huyết cao hay thấp càng lớn. Hiệu chỉnh tối đa/tối thiểu được xác định bởi cài đặt tối thiểu/tối đa của Autosens.\n\nĐối với hàm Sigmoid, hệ số điều chỉnh được khuyến nghị là 0,4 - 0,5 để bắt đầu.\n\nĐối với công thức logarit, có ít sự đồng thuận hơn, nhưng bắt đầu từ khoảng 0,8 là có lẽ phù hợp với hầu hết người dùng trưởng thành. Đối với người dùng trẻ tuổi, nên bắt đầu ở mức thấp hơn nữa khi sử dụng công thức logarit để tránh điều trị quá tích cực."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Sử dụng hàm Sigmoid (SF)"; diff --git a/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings index 1e966eb0d0..e71a87abe2 100644 --- a/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings @@ -49,6 +49,18 @@ /* Bolus progress view */ "of" = "of"; +/* Remote Bolus Alert, Part 1 */ +"A Remote Bolus " = "A Remote Bolus "; + +/* Remote Bolus Alert, Part 2 */ +"was delivered" = "was delivered"; + +/* Remote Bolus Alert, Part 3 */ +" minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; + +/* Remote Bolus Alert, Title */ +"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; + /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Enacted at"; @@ -302,6 +314,9 @@ Enact a temp Basal or a temp target */ "Enact" = "执行"; +/* Start a temp target or a profile override */ +"Start" = "Start"; + /* */ "Manual Temp Basal" = "手动设置临时基础"; @@ -359,6 +374,9 @@ Enact a temp Basal or a temp target */ /* Allow remote control from NS */ "Remote control" = "远程控制"; +/* Allow remote control from NS */ +"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; + /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects."; @@ -2061,7 +2079,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Adjust Dynamic ISF constant"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula threre is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Use Sigmoid Function"; From 2e22ef8a8eabf96c497c8a7e786ce4c9052d4543 Mon Sep 17 00:00:00 2001 From: bjornoleh Date: Sun, 25 Feb 2024 21:39:41 +0100 Subject: [PATCH 09/44] Remove steps related to syncing of the "alive" branch - name: Sync upstream changes - name: New commits found - name: No new commits - name: Show value of 'has_new_commits Create the "alive" branch from main, not dev The "alive" branch is still automatically created, and "keep alive" commits will be added to the "alive" branch to avoid a stale repository. This will avoid errors when updating the alive branch causes merge conflicts. --- .github/workflows/build_iAPS.yml | 39 +++----------------------------- 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/.github/workflows/build_iAPS.yml b/.github/workflows/build_iAPS.yml index c230c21e31..f67f1c6735 100644 --- a/.github/workflows/build_iAPS.yml +++ b/.github/workflows/build_iAPS.yml @@ -69,9 +69,9 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - # Get ref for Artificial-Pancreas/iAPS:dev + # Get ref for Artificial-Pancreas/iAPS:main SHA=$(curl -sS https://api.github.com/repos/${{ env.UPSTREAM_REPO }}/git/refs \ - | jq '.[] | select(.ref == "refs/heads/dev" ) | .object.sha' \ + | jq '.[] | select(.ref == "refs/heads/main" ) | .object.sha' \ | tr -d '"' ); @@ -84,7 +84,6 @@ jobs: -f ref='refs/heads/alive' \ -f sha=$SHA - # Checks for changes in upstream repository; if changes exist prompts sync for build # Performs keepalive to avoid stale fork check_latest_from_upstream: needs: [validate, check_alive_and_permissions] @@ -102,39 +101,7 @@ jobs: with: token: ${{ secrets.GH_PAT }} ref: alive - - - name: Sync upstream changes - if: | # do not run the upstream sync action on the upstream repository - needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && - vars.SCHEDULED_SYNC != 'false' && github.repository_owner != 'Artificial-Pancreas' - id: sync - uses: aormsby/Fork-Sync-With-Upstream-action@v3.4 - with: - target_sync_branch: ${{ env.ALIVE_BRANCH }} - shallow_since: 6 months ago - target_repo_token: ${{ secrets.GH_PAT }} - upstream_sync_branch: ${{ env.UPSTREAM_BRANCH }} - upstream_sync_repo: ${{ env.UPSTREAM_REPO }} - - # Display a sample message based on the sync output var 'has_new_commits' - - name: New commits found - if: | - needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && - vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'true' - run: echo "New commits were found to sync." - - - name: No new commits - if: | - needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && - vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'false' - run: echo "There were no new commits." - - - name: Show value of 'has_new_commits' - if: needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && vars.SCHEDULED_SYNC != 'false' - run: | - echo ${{ steps.sync.outputs.has_new_commits }} - echo "NEW_COMMITS=${{ steps.sync.outputs.has_new_commits }}" >> $GITHUB_OUTPUT - + # Keep repository "alive": add empty commits to ALIVE_BRANCH after "time_elapsed" days of inactivity to avoid inactivation of scheduled workflows - name: Keep alive if: | From 24d026264098b2d7d563caaec602a8ea999a61b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Mon, 26 Feb 2024 13:21:54 +0100 Subject: [PATCH 10/44] Support for new Dexcom One+ sensors. Connect using the G7 Manager in iAPS. --- .../G7SensorKit/G7SensorKit/G7CGMManager/G7Sensor.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dependencies/G7SensorKit/G7SensorKit/G7CGMManager/G7Sensor.swift b/Dependencies/G7SensorKit/G7SensorKit/G7CGMManager/G7Sensor.swift index 3453929105..20667e9f00 100644 --- a/Dependencies/G7SensorKit/G7SensorKit/G7CGMManager/G7Sensor.swift +++ b/Dependencies/G7SensorKit/G7SensorKit/G7CGMManager/G7Sensor.swift @@ -215,7 +215,8 @@ public final class G7Sensor: G7BluetoothManagerDelegate { } /// The Dexcom G7 advertises a peripheral name of "DXCMxx", and later reports a full name of "Dexcomxx" - if name.hasPrefix("DXCM") { + /// Dexcom One+ peripheral name start with "DX02" + if name.hasPrefix("DXCM") || name.hasPrefix("DX02"){ // If we're following this name or if we're scanning, connect if let sensorName = sensorID, name.suffix(2) == sensorName.suffix(2) { return .makeActive From 15dfe72396103c52f2425a43b4f0cacc519fb528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Mon, 26 Feb 2024 13:22:49 +0100 Subject: [PATCH 11/44] Bump version --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index b7be5bd145..5ea7ece82f 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 3.1.4 +APP_VERSION = 3.1.5 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## From 1fd623fb0915e22812cd8087c8be8d148eb315a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Tue, 27 Feb 2024 11:37:35 +0100 Subject: [PATCH 12/44] Refactor Remove duplicate code in APSManager. Clean up code in OpenAPSManager. Don't delete those overides that run to completion in Nigtscout. Bump version. --- Config.xcconfig | 2 +- FreeAPS/Sources/APS/APSManager.swift | 545 ++++++++---------- FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift | 69 +-- .../Sources/APS/Storage/CoreDataStorage.swift | 71 +++ .../Sources/APS/Storage/OverrideStorage.swift | 12 + FreeAPS/Sources/Models/Configs.swift | 2 + .../Sources/Modules/Home/HomeStateModel.swift | 18 +- .../OverrideProfilesStateModel.swift | 4 +- .../Services/Network/NightscoutManager.swift | 4 +- README.md | 3 +- 10 files changed, 372 insertions(+), 358 deletions(-) diff --git a/Config.xcconfig b/Config.xcconfig index 5ea7ece82f..98b9644695 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 3.1.5 +APP_VERSION = 3.1.6 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## diff --git a/FreeAPS/Sources/APS/APSManager.swift b/FreeAPS/Sources/APS/APSManager.swift index 5a0e280d77..226cda4351 100644 --- a/FreeAPS/Sources/APS/APSManager.swift +++ b/FreeAPS/Sources/APS/APSManager.swift @@ -123,7 +123,7 @@ final class BaseAPSManager: APSManager, Injectable { init(resolver: Resolver) { injectServices(resolver) - openAPS = OpenAPS(storage: storage) + openAPS = OpenAPS(storage: storage, nightscout: nightscout) subscribe() lastLoopDateSubject.send(lastLoopDate) @@ -964,312 +964,267 @@ final class BaseAPSManager: APSManager, Injectable { guard hour > 20 else { return } - coredataContext.performAndWait { [self] in - var stats = [StatsData]() - let requestStats = StatsData.fetchRequest() as NSFetchRequest - let sortStats = NSSortDescriptor(key: "lastrun", ascending: false) - requestStats.sortDescriptors = [sortStats] - requestStats.fetchLimit = 1 - try? stats = coredataContext.fetch(requestStats) - // Only save and upload once per day - guard (-1 * (stats.first?.lastrun ?? .distantPast).timeIntervalSinceNow.hours) > 22 else { return } - - let units = self.settingsManager.settings.units - let preferences = settingsManager.preferences - - // Carbs - var carbs = [Carbohydrates]() - var carbTotal: Decimal = 0 - let requestCarbs = Carbohydrates.fetchRequest() as NSFetchRequest - let daysAgo = Date().addingTimeInterval(-1.days.timeInterval) - requestCarbs.predicate = NSPredicate(format: "carbs > 0 AND date > %@", daysAgo as NSDate) - let sortCarbs = NSSortDescriptor(key: "date", ascending: true) - requestCarbs.sortDescriptors = [sortCarbs] - try? carbs = coredataContext.fetch(requestCarbs) - carbTotal = carbs.map({ carbs in carbs.carbs as? Decimal ?? 0 }).reduce(0, +) - - // TDD - var tdds = [TDD]() - var currentTDD: Decimal = 0 - var tddTotalAverage: Decimal = 0 - let requestTDD = TDD.fetchRequest() as NSFetchRequest - let sort = NSSortDescriptor(key: "timestamp", ascending: false) - let daysOf14Ago = Date().addingTimeInterval(-14.days.timeInterval) - requestTDD.predicate = NSPredicate(format: "timestamp > %@", daysOf14Ago as NSDate) - requestTDD.sortDescriptors = [sort] - try? tdds = coredataContext.fetch(requestTDD) - - if !tdds.isEmpty { - currentTDD = tdds[0].tdd?.decimalValue ?? 0 - let tddArray = tdds.compactMap({ insulin in insulin.tdd as? Decimal ?? 0 }) - tddTotalAverage = tddArray.reduce(0, +) / Decimal(tddArray.count) - } - var algo_ = "Oref0" + let stats = CoreDataStorage().fetchStats() + // Only save and upload once per day + guard (-1 * (stats.first?.lastrun ?? .distantPast).timeIntervalSinceNow.hours) > 22 else { return } + + let units = settingsManager.settings.units + let preferences = settingsManager.preferences + + // Carbs + let carbs = CoreDataStorage().fetcarbs(interval: DateFilter().day) + var carbTotal: Decimal = 0 + carbTotal = carbs.map({ carbs in carbs.carbs as? Decimal ?? 0 }).reduce(0, +) + + // TDD + let tdds = CoreDataStorage().fetchTDD(interval: DateFilter().fourteen) + var currentTDD: Decimal = 0 + var tddTotalAverage: Decimal = 0 + if !tdds.isEmpty { + currentTDD = tdds[0].tdd?.decimalValue ?? 0 + let tddArray = tdds.compactMap({ insulin in insulin.tdd as? Decimal ?? 0 }) + tddTotalAverage = tddArray.reduce(0, +) / Decimal(tddArray.count) + } + + var algo_ = "Oref0" - if preferences.sigmoid, preferences.enableDynamicCR { - algo_ = "Dynamic ISF + CR: Sigmoid" - } else if preferences.sigmoid, !preferences.enableDynamicCR { - algo_ = "Dynamic ISF: Sigmoid" - } else if preferences.useNewFormula, preferences.enableDynamicCR { - algo_ = "Dynamic ISF + CR: Logarithmic" - } else if preferences.useNewFormula, !preferences.sigmoid,!preferences.enableDynamicCR { - algo_ = "Dynamic ISF: Logarithmic" - } - let af = preferences.adjustmentFactor - let insulin_type = preferences.curve - let buildDate = Bundle.main.buildDate - let version = Bundle.main.releaseVersionNumber - let build = Bundle.main.buildVersionNumber - - // Read branch information from branch.txt instead of infoDictionary - var branch = "Unknown" - if let branchFileURL = Bundle.main.url(forResource: "branch", withExtension: "txt"), - let branchFileContent = try? String(contentsOf: branchFileURL) - { - let lines = branchFileContent.components(separatedBy: .newlines) - for line in lines { - let components = line.components(separatedBy: "=") - if components.count == 2 { - let key = components[0].trimmingCharacters(in: .whitespaces) - let value = components[1].trimmingCharacters(in: .whitespaces) - - if key == "BRANCH" { - branch = value - break - } + if preferences.sigmoid, preferences.enableDynamicCR { + algo_ = "Dynamic ISF + CR: Sigmoid" + } else if preferences.sigmoid, !preferences.enableDynamicCR { + algo_ = "Dynamic ISF: Sigmoid" + } else if preferences.useNewFormula, preferences.enableDynamicCR { + algo_ = "Dynamic ISF + CR: Logarithmic" + } else if preferences.useNewFormula, !preferences.sigmoid,!preferences.enableDynamicCR { + algo_ = "Dynamic ISF: Logarithmic" + } + let af = preferences.adjustmentFactor + let insulin_type = preferences.curve + let buildDate = Bundle.main.buildDate + let version = Bundle.main.releaseVersionNumber + let build = Bundle.main.buildVersionNumber + + // Read branch information from branch.txt instead of infoDictionary + var branch = "Unknown" + if let branchFileURL = Bundle.main.url(forResource: "branch", withExtension: "txt"), + let branchFileContent = try? String(contentsOf: branchFileURL) + { + let lines = branchFileContent.components(separatedBy: .newlines) + for line in lines { + let components = line.components(separatedBy: "=") + if components.count == 2 { + let key = components[0].trimmingCharacters(in: .whitespaces) + let value = components[1].trimmingCharacters(in: .whitespaces) + + if key == "BRANCH" { + branch = value + break } } - } else { - branch = "Unknown" } + } else { + branch = "Unknown" + } - let copyrightNotice_ = Bundle.main.infoDictionary?["NSHumanReadableCopyright"] as? String ?? "" - let pump_ = pumpManager?.localizedTitle ?? "" - let cgm = settingsManager.settings.cgm - let file = OpenAPS.Monitor.statistics - var iPa: Decimal = 75 - if preferences.useCustomPeakTime { - iPa = preferences.insulinPeakTime - } else if preferences.curve.rawValue == "rapid-acting" { - iPa = 65 - } else if preferences.curve.rawValue == "ultra-rapid" { - iPa = 50 - } - // CGM Readings - var glucose_24 = [Readings]() // Day - var glucose_7 = [Readings]() // Week - var glucose_30 = [Readings]() // Month - var glucose = [Readings]() // Total - let filter = DateFilter() - // 24h - let requestGFS_24 = Readings.fetchRequest() as NSFetchRequest - let sortGlucose_24 = NSSortDescriptor(key: "date", ascending: false) - requestGFS_24.predicate = NSPredicate(format: "glucose > 0 AND date > %@", filter.day) - requestGFS_24.sortDescriptors = [sortGlucose_24] - try? glucose_24 = coredataContext.fetch(requestGFS_24) - // Week - let requestGFS_7 = Readings.fetchRequest() as NSFetchRequest - let sortGlucose_7 = NSSortDescriptor(key: "date", ascending: false) - requestGFS_7.predicate = NSPredicate(format: "glucose > 0 AND date > %@", filter.week) - requestGFS_7.sortDescriptors = [sortGlucose_7] - try? glucose_7 = coredataContext.fetch(requestGFS_7) - // Month - let requestGFS_30 = Readings.fetchRequest() as NSFetchRequest - let sortGlucose_30 = NSSortDescriptor(key: "date", ascending: false) - requestGFS_30.predicate = NSPredicate(format: "glucose > 0 AND date > %@", filter.month) - requestGFS_30.sortDescriptors = [sortGlucose_30] - try? glucose_30 = coredataContext.fetch(requestGFS_30) - // Total - let requestGFS = Readings.fetchRequest() as NSFetchRequest - let sortGlucose = NSSortDescriptor(key: "date", ascending: false) - requestGFS.predicate = NSPredicate(format: "glucose > 0 AND date > %@", filter.total) - requestGFS.sortDescriptors = [sortGlucose] - try? glucose = coredataContext.fetch(requestGFS) - - // First date - let previous = glucose.last?.date ?? Date() - // Last date (recent) - let current = glucose.first?.date ?? Date() - // Total time in days - let numberOfDays = (current - previous).timeInterval / 8.64E4 - - // Get glucose computations for every case - let oneDayGlucose = glucoseStats(glucose_24) - let sevenDaysGlucose = glucoseStats(glucose_7) - let thirtyDaysGlucose = glucoseStats(glucose_30) - let totalDaysGlucose = glucoseStats(glucose) - - let median = Durations( - day: roundDecimal(Decimal(oneDayGlucose.median), 1), - week: roundDecimal(Decimal(sevenDaysGlucose.median), 1), - month: roundDecimal(Decimal(thirtyDaysGlucose.median), 1), - total: roundDecimal(Decimal(totalDaysGlucose.median), 1) - ) + let copyrightNotice_ = Bundle.main.infoDictionary?["NSHumanReadableCopyright"] as? String ?? "" + let pump_ = pumpManager?.localizedTitle ?? "" + let cgm = settingsManager.settings.cgm + let file = OpenAPS.Monitor.statistics + var iPa: Decimal = 75 + if preferences.useCustomPeakTime { + iPa = preferences.insulinPeakTime + } else if preferences.curve.rawValue == "rapid-acting" { + iPa = 65 + } else if preferences.curve.rawValue == "ultra-rapid" { + iPa = 50 + } + // CGM Readings + let glucose_24 = CoreDataStorage().fetchGlucose(interval: DateFilter().day) // Day + let glucose_7 = CoreDataStorage().fetchGlucose(interval: DateFilter().week) // Week + let glucose_30 = CoreDataStorage().fetchGlucose(interval: DateFilter().month) // Month + let glucose = CoreDataStorage().fetchGlucose(interval: DateFilter().total) // Total + + // First date + let previous = glucose.last?.date ?? Date() + // Last date (recent) + let current = glucose.first?.date ?? Date() + // Total time in days + let numberOfDays = (current - previous).timeInterval / 8.64E4 + + // Get glucose computations for every case + let oneDayGlucose = glucoseStats(glucose_24) + let sevenDaysGlucose = glucoseStats(glucose_7) + let thirtyDaysGlucose = glucoseStats(glucose_30) + let totalDaysGlucose = glucoseStats(glucose) + + let median = Durations( + day: roundDecimal(Decimal(oneDayGlucose.median), 1), + week: roundDecimal(Decimal(sevenDaysGlucose.median), 1), + month: roundDecimal(Decimal(thirtyDaysGlucose.median), 1), + total: roundDecimal(Decimal(totalDaysGlucose.median), 1) + ) - let overrideHbA1cUnit = settingsManager.settings.overrideHbA1cUnit - - let hbs = Durations( - day: ((units == .mmolL && !overrideHbA1cUnit) || (units == .mgdL && overrideHbA1cUnit)) ? - roundDecimal(Decimal(oneDayGlucose.ifcc), 1) : roundDecimal(Decimal(oneDayGlucose.ngsp), 1), - week: ((units == .mmolL && !overrideHbA1cUnit) || (units == .mgdL && overrideHbA1cUnit)) ? - roundDecimal(Decimal(sevenDaysGlucose.ifcc), 1) : roundDecimal(Decimal(sevenDaysGlucose.ngsp), 1), - month: ((units == .mmolL && !overrideHbA1cUnit) || (units == .mgdL && overrideHbA1cUnit)) ? - roundDecimal(Decimal(thirtyDaysGlucose.ifcc), 1) : roundDecimal(Decimal(thirtyDaysGlucose.ngsp), 1), - total: ((units == .mmolL && !overrideHbA1cUnit) || (units == .mgdL && overrideHbA1cUnit)) ? - roundDecimal(Decimal(totalDaysGlucose.ifcc), 1) : roundDecimal(Decimal(totalDaysGlucose.ngsp), 1) - ) + let overrideHbA1cUnit = settingsManager.settings.overrideHbA1cUnit + + let hbs = Durations( + day: ((units == .mmolL && !overrideHbA1cUnit) || (units == .mgdL && overrideHbA1cUnit)) ? + roundDecimal(Decimal(oneDayGlucose.ifcc), 1) : roundDecimal(Decimal(oneDayGlucose.ngsp), 1), + week: ((units == .mmolL && !overrideHbA1cUnit) || (units == .mgdL && overrideHbA1cUnit)) ? + roundDecimal(Decimal(sevenDaysGlucose.ifcc), 1) : roundDecimal(Decimal(sevenDaysGlucose.ngsp), 1), + month: ((units == .mmolL && !overrideHbA1cUnit) || (units == .mgdL && overrideHbA1cUnit)) ? + roundDecimal(Decimal(thirtyDaysGlucose.ifcc), 1) : roundDecimal(Decimal(thirtyDaysGlucose.ngsp), 1), + total: ((units == .mmolL && !overrideHbA1cUnit) || (units == .mgdL && overrideHbA1cUnit)) ? + roundDecimal(Decimal(totalDaysGlucose.ifcc), 1) : roundDecimal(Decimal(totalDaysGlucose.ngsp), 1) + ) - var oneDay_: (TIR: Double, hypos: Double, hypers: Double, normal_: Double) = (0.0, 0.0, 0.0, 0.0) - var sevenDays_: (TIR: Double, hypos: Double, hypers: Double, normal_: Double) = (0.0, 0.0, 0.0, 0.0) - var thirtyDays_: (TIR: Double, hypos: Double, hypers: Double, normal_: Double) = (0.0, 0.0, 0.0, 0.0) - var totalDays_: (TIR: Double, hypos: Double, hypers: Double, normal_: Double) = (0.0, 0.0, 0.0, 0.0) - // Get TIR computations for every case - oneDay_ = tir(glucose_24) - sevenDays_ = tir(glucose_7) - thirtyDays_ = tir(glucose_30) - totalDays_ = tir(glucose) - - let tir = Durations( - day: roundDecimal(Decimal(oneDay_.TIR), 1), - week: roundDecimal(Decimal(sevenDays_.TIR), 1), - month: roundDecimal(Decimal(thirtyDays_.TIR), 1), - total: roundDecimal(Decimal(totalDays_.TIR), 1) - ) - let hypo = Durations( - day: Decimal(oneDay_.hypos), - week: Decimal(sevenDays_.hypos), - month: Decimal(thirtyDays_.hypos), - total: Decimal(totalDays_.hypos) - ) - let hyper = Durations( - day: Decimal(oneDay_.hypers), - week: Decimal(sevenDays_.hypers), - month: Decimal(thirtyDays_.hypers), - total: Decimal(totalDays_.hypers) - ) - let normal = Durations( - day: Decimal(oneDay_.normal_), - week: Decimal(sevenDays_.normal_), - month: Decimal(thirtyDays_.normal_), - total: Decimal(totalDays_.normal_) - ) - let range = Threshold( - low: units == .mmolL ? roundDecimal(settingsManager.settings.low.asMmolL, 1) : - roundDecimal(settingsManager.settings.low, 0), - high: units == .mmolL ? roundDecimal(settingsManager.settings.high.asMmolL, 1) : - roundDecimal(settingsManager.settings.high, 0) - ) - let TimeInRange = TIRs( - TIR: tir, - Hypos: hypo, - Hypers: hyper, - Threshold: range, - Euglycemic: normal - ) - let avgs = Durations( - day: roundDecimal(Decimal(oneDayGlucose.average), 1), - week: roundDecimal(Decimal(sevenDaysGlucose.average), 1), - month: roundDecimal(Decimal(thirtyDaysGlucose.average), 1), - total: roundDecimal(Decimal(totalDaysGlucose.average), 1) - ) - let avg = Averages(Average: avgs, Median: median) - // Standard Deviations - let standardDeviations = Durations( - day: roundDecimal(Decimal(oneDayGlucose.sd), 1), - week: roundDecimal(Decimal(sevenDaysGlucose.sd), 1), - month: roundDecimal(Decimal(thirtyDaysGlucose.sd), 1), - total: roundDecimal(Decimal(totalDaysGlucose.sd), 1) - ) - // CV = standard deviation / sample mean x 100 - let cvs = Durations( - day: roundDecimal(Decimal(oneDayGlucose.cv), 1), - week: roundDecimal(Decimal(sevenDaysGlucose.cv), 1), - month: roundDecimal(Decimal(thirtyDaysGlucose.cv), 1), - total: roundDecimal(Decimal(totalDaysGlucose.cv), 1) - ) - let variance = Variance(SD: standardDeviations, CV: cvs) - - // Loops - var lsr = [LoopStatRecord]() - let requestLSR = LoopStatRecord.fetchRequest() as NSFetchRequest - requestLSR.predicate = NSPredicate( - format: "interval > 0 AND start > %@", - Date().addingTimeInterval(-24.hours.timeInterval) as NSDate - ) - let sortLSR = NSSortDescriptor(key: "start", ascending: false) - requestLSR.sortDescriptors = [sortLSR] - try? lsr = coredataContext.fetch(requestLSR) - // Compute LoopStats for 24 hours - let oneDayLoops = loops(lsr) - let loopstat = LoopCycles( - loops: oneDayLoops.loops, - errors: oneDayLoops.errors, - readings: Int(oneDayGlucose.readings), - success_rate: oneDayLoops.success_rate, - avg_interval: oneDayLoops.avg_interval, - median_interval: oneDayLoops.median_interval, - min_interval: oneDayLoops.min_interval, - max_interval: oneDayLoops.max_interval, - avg_duration: oneDayLoops.avg_duration, - median_duration: oneDayLoops.median_duration, - min_duration: oneDayLoops.max_duration, - max_duration: oneDayLoops.max_duration - ) + var oneDay_: (TIR: Double, hypos: Double, hypers: Double, normal_: Double) = (0.0, 0.0, 0.0, 0.0) + var sevenDays_: (TIR: Double, hypos: Double, hypers: Double, normal_: Double) = (0.0, 0.0, 0.0, 0.0) + var thirtyDays_: (TIR: Double, hypos: Double, hypers: Double, normal_: Double) = (0.0, 0.0, 0.0, 0.0) + var totalDays_: (TIR: Double, hypos: Double, hypers: Double, normal_: Double) = (0.0, 0.0, 0.0, 0.0) + // Get TIR computations for every case + oneDay_ = tir(glucose_24) + sevenDays_ = tir(glucose_7) + thirtyDays_ = tir(glucose_30) + totalDays_ = tir(glucose) + + let tir = Durations( + day: roundDecimal(Decimal(oneDay_.TIR), 1), + week: roundDecimal(Decimal(sevenDays_.TIR), 1), + month: roundDecimal(Decimal(thirtyDays_.TIR), 1), + total: roundDecimal(Decimal(totalDays_.TIR), 1) + ) + let hypo = Durations( + day: Decimal(oneDay_.hypos), + week: Decimal(sevenDays_.hypos), + month: Decimal(thirtyDays_.hypos), + total: Decimal(totalDays_.hypos) + ) + let hyper = Durations( + day: Decimal(oneDay_.hypers), + week: Decimal(sevenDays_.hypers), + month: Decimal(thirtyDays_.hypers), + total: Decimal(totalDays_.hypers) + ) + let normal = Durations( + day: Decimal(oneDay_.normal_), + week: Decimal(sevenDays_.normal_), + month: Decimal(thirtyDays_.normal_), + total: Decimal(totalDays_.normal_) + ) + let range = Threshold( + low: units == .mmolL ? roundDecimal(settingsManager.settings.low.asMmolL, 1) : + roundDecimal(settingsManager.settings.low, 0), + high: units == .mmolL ? roundDecimal(settingsManager.settings.high.asMmolL, 1) : + roundDecimal(settingsManager.settings.high, 0) + ) + let TimeInRange = TIRs( + TIR: tir, + Hypos: hypo, + Hypers: hyper, + Threshold: range, + Euglycemic: normal + ) + let avgs = Durations( + day: roundDecimal(Decimal(oneDayGlucose.average), 1), + week: roundDecimal(Decimal(sevenDaysGlucose.average), 1), + month: roundDecimal(Decimal(thirtyDaysGlucose.average), 1), + total: roundDecimal(Decimal(totalDaysGlucose.average), 1) + ) + let avg = Averages(Average: avgs, Median: median) + // Standard Deviations + let standardDeviations = Durations( + day: roundDecimal(Decimal(oneDayGlucose.sd), 1), + week: roundDecimal(Decimal(sevenDaysGlucose.sd), 1), + month: roundDecimal(Decimal(thirtyDaysGlucose.sd), 1), + total: roundDecimal(Decimal(totalDaysGlucose.sd), 1) + ) + // CV = standard deviation / sample mean x 100 + let cvs = Durations( + day: roundDecimal(Decimal(oneDayGlucose.cv), 1), + week: roundDecimal(Decimal(sevenDaysGlucose.cv), 1), + month: roundDecimal(Decimal(thirtyDaysGlucose.cv), 1), + total: roundDecimal(Decimal(totalDaysGlucose.cv), 1) + ) + let variance = Variance(SD: standardDeviations, CV: cvs) + + // Loops + var lsr = [LoopStatRecord]() + let requestLSR = LoopStatRecord.fetchRequest() as NSFetchRequest + requestLSR.predicate = NSPredicate( + format: "interval > 0 AND start > %@", + Date().addingTimeInterval(-24.hours.timeInterval) as NSDate + ) + let sortLSR = NSSortDescriptor(key: "start", ascending: false) + requestLSR.sortDescriptors = [sortLSR] + try? lsr = coredataContext.fetch(requestLSR) + // Compute LoopStats for 24 hours + let oneDayLoops = loops(lsr) + let loopstat = LoopCycles( + loops: oneDayLoops.loops, + errors: oneDayLoops.errors, + readings: Int(oneDayGlucose.readings), + success_rate: oneDayLoops.success_rate, + avg_interval: oneDayLoops.avg_interval, + median_interval: oneDayLoops.median_interval, + min_interval: oneDayLoops.min_interval, + max_interval: oneDayLoops.max_interval, + avg_duration: oneDayLoops.avg_duration, + median_duration: oneDayLoops.median_duration, + min_duration: oneDayLoops.max_duration, + max_duration: oneDayLoops.max_duration + ) - // Insulin - var insulinDistribution = [InsulinDistribution]() - var insulin = Ins( - TDD: 0, - bolus: 0, - temp_basal: 0, - scheduled_basal: 0, - total_average: 0 - ) - let requestInsulinDistribution = InsulinDistribution.fetchRequest() as NSFetchRequest - let sortInsulin = NSSortDescriptor(key: "date", ascending: false) - requestInsulinDistribution.sortDescriptors = [sortInsulin] - try? insulinDistribution = coredataContext.fetch(requestInsulinDistribution) - insulin = Ins( - TDD: roundDecimal(currentTDD, 2), - bolus: insulinDistribution.first != nil ? ((insulinDistribution.first?.bolus ?? 0) as Decimal) : 0, - temp_basal: insulinDistribution.first != nil ? ((insulinDistribution.first?.tempBasal ?? 0) as Decimal) : 0, - scheduled_basal: insulinDistribution - .first != nil ? ((insulinDistribution.first?.scheduledBasal ?? 0) as Decimal) : 0, - total_average: roundDecimal(tddTotalAverage, 1) - ) + // Insulin + let insulinDistribution = CoreDataStorage().fetchInsulinDistribution() + var insulin = Ins( + TDD: 0, + bolus: 0, + temp_basal: 0, + scheduled_basal: 0, + total_average: 0 + ) - let hbA1cUnit = !overrideHbA1cUnit ? (units == .mmolL ? "mmol/mol" : "%") : (units == .mmolL ? "%" : "mmol/mol") - - let dailystat = Statistics( - created_at: Date(), - iPhone: UIDevice.current.getDeviceId, - iOS: UIDevice.current.getOSInfo, - Build_Version: version ?? "", - Build_Number: build ?? "1", - Branch: branch, - CopyRightNotice: String(copyrightNotice_.prefix(32)), - Build_Date: buildDate, - Algorithm: algo_, - AdjustmentFactor: af, - Pump: pump_, - CGM: cgm.rawValue, - insulinType: insulin_type.rawValue, - peakActivityTime: iPa, - Carbs_24h: carbTotal, - GlucoseStorage_Days: Decimal(roundDouble(numberOfDays, 1)), - Statistics: Stats( - Distribution: TimeInRange, - Glucose: avg, - HbA1c: hbs, Units: Units(Glucose: units.rawValue, HbA1c: hbA1cUnit), - LoopCycles: loopstat, - Insulin: insulin, - Variance: variance - ) + insulin = Ins( + TDD: roundDecimal(currentTDD, 2), + bolus: insulinDistribution.first != nil ? ((insulinDistribution.first?.bolus ?? 0) as Decimal) : 0, + temp_basal: insulinDistribution.first != nil ? ((insulinDistribution.first?.tempBasal ?? 0) as Decimal) : 0, + scheduled_basal: insulinDistribution + .first != nil ? ((insulinDistribution.first?.scheduledBasal ?? 0) as Decimal) : 0, + total_average: roundDecimal(tddTotalAverage, 1) + ) + + let hbA1cUnit = !overrideHbA1cUnit ? (units == .mmolL ? "mmol/mol" : "%") : (units == .mmolL ? "%" : "mmol/mol") + + let dailystat = Statistics( + created_at: Date(), + iPhone: UIDevice.current.getDeviceId, + iOS: UIDevice.current.getOSInfo, + Build_Version: version ?? "", + Build_Number: build ?? "1", + Branch: branch, + CopyRightNotice: String(copyrightNotice_.prefix(32)), + Build_Date: buildDate, + Algorithm: algo_, + AdjustmentFactor: af, + Pump: pump_, + CGM: cgm.rawValue, + insulinType: insulin_type.rawValue, + peakActivityTime: iPa, + Carbs_24h: carbTotal, + GlucoseStorage_Days: Decimal(roundDouble(numberOfDays, 1)), + Statistics: Stats( + Distribution: TimeInRange, + Glucose: avg, + HbA1c: hbs, Units: Units(Glucose: units.rawValue, HbA1c: hbA1cUnit), + LoopCycles: loopstat, + Insulin: insulin, + Variance: variance ) - storage.save(dailystat, as: file) - nightscout.uploadStatistics(dailystat: dailystat) + ) + storage.save(dailystat, as: file) + nightscout.uploadStatistics(dailystat: dailystat) + coredataContext.performAndWait { [self] in let saveStatsCoreData = StatsData(context: self.coredataContext) saveStatsCoreData.lastrun = Date() try? self.coredataContext.save() diff --git a/FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift b/FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift index 7ec6521575..df15f16109 100644 --- a/FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift +++ b/FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift @@ -6,13 +6,14 @@ import JavaScriptCore final class OpenAPS { private let jsWorker = JavaScriptWorker() private let processQueue = DispatchQueue(label: "OpenAPS.processQueue", qos: .utility) - private let storage: FileStorage + private let nightscout: NightscoutManager let coredataContext = CoreDataStack.shared.persistentContainer.viewContext // newBackgroundContext() - init(storage: FileStorage) { + init(storage: FileStorage, nightscout: NightscoutManager) { self.storage = storage + self.nightscout = nightscout } func determineBasal(currentTemp: TempBasal, clock: Date = Date()) -> Future { @@ -125,37 +126,17 @@ final class OpenAPS { let wp = preferences?.weightPercentage ?? 1 let smbMinutes = (preferences?.maxSMBBasalMinutes ?? 30) as NSDecimalNumber let uamMinutes = (preferences?.maxUAMSMBBasalMinutes ?? 30) as NSDecimalNumber - - let tenDaysAgo = Date().addingTimeInterval(-10.days.timeInterval) let twoHoursAgo = Date().addingTimeInterval(-2.hours.timeInterval) - var uniqueEvents = [TDD]() - let requestTDD = TDD.fetchRequest() as NSFetchRequest - requestTDD.predicate = NSPredicate(format: "timestamp > %@ AND tdd > 0", tenDaysAgo as NSDate) - let sortTDD = NSSortDescriptor(key: "timestamp", ascending: true) - requestTDD.sortDescriptors = [sortTDD] - try? uniqueEvents = coredataContext.fetch(requestTDD) - - var sliderArray = [TempTargetsSlider]() - let requestIsEnbled = TempTargetsSlider.fetchRequest() as NSFetchRequest - let sortIsEnabled = NSSortDescriptor(key: "date", ascending: false) - requestIsEnbled.sortDescriptors = [sortIsEnabled] - // requestIsEnbled.fetchLimit = 1 - try? sliderArray = coredataContext.fetch(requestIsEnbled) - - var overrideArray = [Override]() - let requestOverrides = Override.fetchRequest() as NSFetchRequest - let sortOverride = NSSortDescriptor(key: "date", ascending: false) - requestOverrides.sortDescriptors = [sortOverride] - // requestOverrides.fetchLimit = 1 - try? overrideArray = coredataContext.fetch(requestOverrides) - - var tempTargetsArray = [TempTargets]() - let requestTempTargets = TempTargets.fetchRequest() as NSFetchRequest - let sortTT = NSSortDescriptor(key: "date", ascending: false) - requestTempTargets.sortDescriptors = [sortTT] - requestTempTargets.fetchLimit = 1 - try? tempTargetsArray = coredataContext.fetch(requestTempTargets) + let cd = CoreDataStorage() + // TDD + let uniqueEvents = cd.fetchTDD(interval: DateFilter().tenDays) + // Temp Targets using slider + let sliderArray = cd.fetchTempTargetsSlider() + // Overrides + let overrideArray = OverrideStorage().fetchNumberOfOverrides(numbers: 2) + // Temp Target + let tempTargetsArray = cd.fetchTempTargets() let total = uniqueEvents.compactMap({ each in each.tdd as? Decimal ?? 0 }).reduce(0, +) var indeces = uniqueEvents.count @@ -183,37 +164,21 @@ final class OpenAPS { let average2hours = totalAmount / Decimal(nrOfIndeces) let average14 = total / Decimal(indeces) - - let weight = wp - let weighted_average = weight * average2hours + (1 - weight) * average14 + let weighted_average = wp * average2hours + (1 - wp) * average14 var duration: Decimal = 0 - var newDuration: Decimal = 0 var overrideTarget: Decimal = 0 if useOverride { duration = (overrideArray.first?.duration ?? 0) as Decimal overrideTarget = (overrideArray.first?.target ?? 0) as Decimal - let advancedSettings = overrideArray.first?.advancedSettings ?? false let addedMinutes = Int(duration) let date = overrideArray.first?.date ?? Date() - if date.addingTimeInterval(addedMinutes.minutes.timeInterval) < Date(), - !unlimited - { + if date.addingTimeInterval(addedMinutes.minutes.timeInterval) < Date(), !unlimited { useOverride = false - let saveToCoreData = Override(context: self.coredataContext) - saveToCoreData.enabled = false - saveToCoreData.date = Date() - saveToCoreData.duration = 0 - saveToCoreData.indefinite = false - saveToCoreData.percentage = 100 - let saveToHistory = OverrideHistory(context: self.coredataContext) - let d: Double = -1 * date.addingTimeInterval(addedMinutes.minutes.timeInterval).timeIntervalSinceNow.minutes - print("Duration: \(d) minutes") - saveToHistory.duration = d - saveToHistory.target = Double(overrideTarget) - saveToHistory.date = overrideArray.first?.date ?? Date() - try? self.coredataContext.save() + if OverrideStorage().cancelProfile() != nil { + debug(.nightscout, "Override ended, duration: \(duration) minutes") + } } } diff --git a/FreeAPS/Sources/APS/Storage/CoreDataStorage.swift b/FreeAPS/Sources/APS/Storage/CoreDataStorage.swift index 8225eb856a..bd2da30edf 100644 --- a/FreeAPS/Sources/APS/Storage/CoreDataStorage.swift +++ b/FreeAPS/Sources/APS/Storage/CoreDataStorage.swift @@ -19,4 +19,75 @@ final class CoreDataStorage { } return fetchGlucose } + + func fetchTDD(interval: NSDate) -> [TDD] { + var uniqueEvents = [TDD]() + coredataContext.performAndWait { + let requestTDD = TDD.fetchRequest() as NSFetchRequest + requestTDD.predicate = NSPredicate(format: "timestamp > %@ AND tdd > 0", interval) + let sortTDD = NSSortDescriptor(key: "timestamp", ascending: true) + requestTDD.sortDescriptors = [sortTDD] + try? uniqueEvents = coredataContext.fetch(requestTDD) + } + return uniqueEvents + } + + func fetchTempTargetsSlider() -> [TempTargetsSlider] { + var sliderArray = [TempTargetsSlider]() + coredataContext.performAndWait { + let requestIsEnbled = TempTargetsSlider.fetchRequest() as NSFetchRequest + let sortIsEnabled = NSSortDescriptor(key: "date", ascending: false) + requestIsEnbled.sortDescriptors = [sortIsEnabled] + // requestIsEnbled.fetchLimit = 1 + try? sliderArray = coredataContext.fetch(requestIsEnbled) + } + return sliderArray + } + + func fetchTempTargets() -> [TempTargets] { + var tempTargetsArray = [TempTargets]() + coredataContext.performAndWait { + let requestTempTargets = TempTargets.fetchRequest() as NSFetchRequest + let sortTT = NSSortDescriptor(key: "date", ascending: false) + requestTempTargets.sortDescriptors = [sortTT] + requestTempTargets.fetchLimit = 1 + try? tempTargetsArray = coredataContext.fetch(requestTempTargets) + } + return tempTargetsArray + } + + func fetcarbs(interval: NSDate) -> [Carbohydrates] { + var carbs = [Carbohydrates]() + coredataContext.performAndWait { + let requestCarbs = Carbohydrates.fetchRequest() as NSFetchRequest + requestCarbs.predicate = NSPredicate(format: "carbs > 0 AND date > %@", interval) + let sortCarbs = NSSortDescriptor(key: "date", ascending: true) + requestCarbs.sortDescriptors = [sortCarbs] + try? carbs = coredataContext.fetch(requestCarbs) + } + return carbs + } + + func fetchStats() -> [StatsData] { + var stats = [StatsData]() + coredataContext.performAndWait { + let requestStats = StatsData.fetchRequest() as NSFetchRequest + let sortStats = NSSortDescriptor(key: "lastrun", ascending: false) + requestStats.sortDescriptors = [sortStats] + requestStats.fetchLimit = 1 + try? stats = coredataContext.fetch(requestStats) + } + return stats + } + + func fetchInsulinDistribution() -> [InsulinDistribution] { + var insulinDistribution = [InsulinDistribution]() + coredataContext.performAndWait { + let requestInsulinDistribution = InsulinDistribution.fetchRequest() as NSFetchRequest + let sortInsulin = NSSortDescriptor(key: "date", ascending: false) + requestInsulinDistribution.sortDescriptors = [sortInsulin] + try? insulinDistribution = coredataContext.fetch(requestInsulinDistribution) + } + return insulinDistribution + } } diff --git a/FreeAPS/Sources/APS/Storage/OverrideStorage.swift b/FreeAPS/Sources/APS/Storage/OverrideStorage.swift index 9b2490a668..7e7d74cd61 100644 --- a/FreeAPS/Sources/APS/Storage/OverrideStorage.swift +++ b/FreeAPS/Sources/APS/Storage/OverrideStorage.swift @@ -32,6 +32,18 @@ final class OverrideStorage { return overrideArray } + func fetchNumberOfOverrides(numbers: Int) -> [Override] { + var overrideArray = [Override]() + coredataContext.performAndWait { + let requestOverrides = Override.fetchRequest() as NSFetchRequest + let sortOverride = NSSortDescriptor(key: "date", ascending: false) + requestOverrides.sortDescriptors = [sortOverride] + requestOverrides.fetchLimit = numbers + try? overrideArray = self.coredataContext.fetch(requestOverrides) + } + return overrideArray + } + func fetchOverrideHistory(interval: NSDate) -> [OverrideHistory] { var overrideArray = [OverrideHistory]() coredataContext.performAndWait { diff --git a/FreeAPS/Sources/Models/Configs.swift b/FreeAPS/Sources/Models/Configs.swift index da9b8959a6..c9842279c4 100644 --- a/FreeAPS/Sources/Models/Configs.swift +++ b/FreeAPS/Sources/Models/Configs.swift @@ -8,6 +8,8 @@ struct DateFilter { var week = Date().addingTimeInterval(-7.days.timeInterval) as NSDate var month = Date().addingTimeInterval(-30.days.timeInterval) as NSDate var total = Date().addingTimeInterval(-90.days.timeInterval) as NSDate + var tenDays = Date().addingTimeInterval(-10.days.timeInterval) as NSDate + var fourteen = Date().addingTimeInterval(-14.days.timeInterval) as NSDate } public enum IAPSconfig { diff --git a/FreeAPS/Sources/Modules/Home/HomeStateModel.swift b/FreeAPS/Sources/Modules/Home/HomeStateModel.swift index bde45c94ba..72c4499b3c 100644 --- a/FreeAPS/Sources/Modules/Home/HomeStateModel.swift +++ b/FreeAPS/Sources/Modules/Home/HomeStateModel.swift @@ -239,13 +239,21 @@ extension Home { func cancelProfile() { let os = OverrideStorage() - + // Is there a saved Override? if let activeOveride = os.fetchLatestOverride().first { let presetName = os.isPresetName() - let nsString = presetName != nil ? presetName : activeOveride.percentage.formatted() - - if let duration = os.cancelProfile() { - nightscoutManager.editOverride(nsString!, duration, activeOveride.date ?? Date.now) + // Is the Override a Preset? + if let preset = presetName { + if let duration = os.cancelProfile() { + // Update in Nightscout + nightscoutManager.editOverride(preset, duration, activeOveride.date ?? Date.now) + } + } else { + let nsString = activeOveride.percentage.formatted() != "100" ? activeOveride.percentage + .formatted() + " %" : "Custom" + if let duration = os.cancelProfile() { + nightscoutManager.editOverride(nsString, duration, activeOveride.date ?? Date.now) + } } } setupOverrideHistory() diff --git a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift index 85ceaf0c52..3098a7b5cf 100644 --- a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift +++ b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift @@ -86,7 +86,9 @@ extension OverrideProfilesConfig { if let preset = OverrideStorage().isPresetName(), let duration = OverrideStorage().cancelProfile() { ns.editOverride(preset, duration, last?.date ?? Date.now) } else if let duration = OverrideStorage().cancelProfile() { - ns.editOverride("Custom", duration, last?.date ?? Date.now) + let nsString = active.percentage.formatted() != "100" ? active.percentage + .formatted() + " %" : "Custom" + ns.editOverride(nsString, duration, last?.date ?? Date.now) } } else { let duration = (self.duration as NSDecimalNumber) == 0 ? 2880 : Int(self.duration as NSDecimalNumber) diff --git a/FreeAPS/Sources/Services/Network/NightscoutManager.swift b/FreeAPS/Sources/Services/Network/NightscoutManager.swift index 75c4271681..0b871352c5 100644 --- a/FreeAPS/Sources/Services/Network/NightscoutManager.swift +++ b/FreeAPS/Sources/Services/Network/NightscoutManager.swift @@ -790,15 +790,13 @@ final class BaseNightscoutManager: NightscoutManager, Injectable { notes: profile )] - print("Override uploaded: \(exercise)") - processQueue.async { nightscout.uploadEcercises(exercise) // nightscout.uploadTreatments(override) .sink { completion in switch completion { case .finished: - debug(.nightscout, "Override Uploaded to NS, date: \(date)") + debug(.nightscout, "Override Uploaded to NS, date: \(date), override: \(exercise)") case let .failure(error): debug(.nightscout, "Upload of Override failed: " + error.localizedDescription) } diff --git a/README.md b/README.md index 489f343041..e48430fae2 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,8 @@ https://loopkit.github.io/loopdocs/gh-actions/gh-overview/ - Dexcom G5 - Dexcom G6 -- Dexcom ONE +- Dexcom ONE +- Dexcom ONE + - Dexcom G7 - Libre 1 - Libre 2 (European) From 8ee9755d1965034ecf39802b353e3d32e16cf2c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Tue, 27 Feb 2024 13:44:46 +0100 Subject: [PATCH 13/44] Crowdin updates (#547) --- .../Sources/Localizations/Main/it.lproj/Localizable.strings | 5 +++-- .../Sources/Localizations/Main/nl.lproj/Localizable.strings | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings index d978889098..92eaf90b4a 100644 --- a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings @@ -315,7 +315,7 @@ Enact a temp Basal or a temp target */ "Enact" = "Attiva"; /* Start a temp target or a profile override */ -"Start" = "Start"; +"Start" = "Avvia"; /* */ "Manual Temp Basal" = "Basale temporanea manuale"; @@ -2077,7 +2077,8 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Regola i rapporti dinamici della costante ISF"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Aggiustamenti individuali dei rapporti dinamici calcolati. Il valore predefinito è 0,5. Più alto è il valore, maggiore sarà la correzione del tuo ISF/CR per una glicemia alta o bassa. La correzione massima/minima è determinata dalle impostazioni Autosens min/max.\n\nPer la funzione sigmoidea si consiglia di iniziare con un fattore di correzione di 0,4 - 0,5.\n\n Per la formula logaritmica c'è meno consenso; iniziare con 0,8 è appropriato per la maggior parte degli utenti adulti. +Per gli utenti più giovani si consiglia di iniziare con un dosaggio ancora più basso quando si utilizza la formula logaritmica, per evitare un trattamento eccessivamente aggressivo."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Usa Funzione Sigmoid"; diff --git a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings index e9fe7cc3d9..2010d18134 100644 --- a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings @@ -2081,7 +2081,7 @@ Eenvoudig gezegd, de Dynamische Carb Ratio past de koolhydraatverhouding aan op "Adjust Dynamic ISF constant" = "Dynamische ISF-constante aanpassen"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individuele aanpassing van de berekende dynamische verhoudingen. De standaardwaarde is 0,5. Hoe hoger de waarde, hoe groter de correctie van uw ISF/CR zal zijn voor een hoge of lage bloedglucosewaarde. De maximale/minimale correctie wordt bepaald door de Autosens min/max instellingen.\n\nVoor de Sigmoid functie wordt een aanpassingsfactor van 0.4 - 0.5 aanbevolen om mee te beginnen.\n\nVoor de logaritmische formule is er minder consensus, maar beginnen rond 0.8 is waarschijnlijk goed voor de meeste volwassen gebruikers. Voor jongere gebruikers wordt aanbevolen om nog lager te beginnen met de logaritmische formule, om een te agressieve behandeling te voorkomen."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Gebruik Sigmoid functie"; From 6f58d531f145cf431413b53a7dd3540db2715b82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Tue, 27 Feb 2024 13:47:14 +0100 Subject: [PATCH 14/44] Crowdin (#556) --- .../Sources/Localizations/Main/it.lproj/Localizable.strings | 5 +++-- .../Sources/Localizations/Main/nl.lproj/Localizable.strings | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings index d978889098..92eaf90b4a 100644 --- a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings @@ -315,7 +315,7 @@ Enact a temp Basal or a temp target */ "Enact" = "Attiva"; /* Start a temp target or a profile override */ -"Start" = "Start"; +"Start" = "Avvia"; /* */ "Manual Temp Basal" = "Basale temporanea manuale"; @@ -2077,7 +2077,8 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Regola i rapporti dinamici della costante ISF"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Aggiustamenti individuali dei rapporti dinamici calcolati. Il valore predefinito è 0,5. Più alto è il valore, maggiore sarà la correzione del tuo ISF/CR per una glicemia alta o bassa. La correzione massima/minima è determinata dalle impostazioni Autosens min/max.\n\nPer la funzione sigmoidea si consiglia di iniziare con un fattore di correzione di 0,4 - 0,5.\n\n Per la formula logaritmica c'è meno consenso; iniziare con 0,8 è appropriato per la maggior parte degli utenti adulti. +Per gli utenti più giovani si consiglia di iniziare con un dosaggio ancora più basso quando si utilizza la formula logaritmica, per evitare un trattamento eccessivamente aggressivo."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Usa Funzione Sigmoid"; diff --git a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings index e9fe7cc3d9..2010d18134 100644 --- a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings @@ -2081,7 +2081,7 @@ Eenvoudig gezegd, de Dynamische Carb Ratio past de koolhydraatverhouding aan op "Adjust Dynamic ISF constant" = "Dynamische ISF-constante aanpassen"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individuele aanpassing van de berekende dynamische verhoudingen. De standaardwaarde is 0,5. Hoe hoger de waarde, hoe groter de correctie van uw ISF/CR zal zijn voor een hoge of lage bloedglucosewaarde. De maximale/minimale correctie wordt bepaald door de Autosens min/max instellingen.\n\nVoor de Sigmoid functie wordt een aanpassingsfactor van 0.4 - 0.5 aanbevolen om mee te beginnen.\n\nVoor de logaritmische formule is er minder consensus, maar beginnen rond 0.8 is waarschijnlijk goed voor de meeste volwassen gebruikers. Voor jongere gebruikers wordt aanbevolen om nog lager te beginnen met de logaritmische formule, om een te agressieve behandeling te voorkomen."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Gebruik Sigmoid functie"; From 559093e6bfd06df390fbbc725c4abd0b7590d862 Mon Sep 17 00:00:00 2001 From: SteveAnderson <3172431+SteveAnderson@users.noreply.github.com> Date: Wed, 28 Feb 2024 23:47:00 +0100 Subject: [PATCH 15/44] Update build_iAPS.yml (#557) Replaced actions/checkout@v3 with actions/checkout@v4 to avoid build errors "Node.js 16 actions are deprecated". --- .github/workflows/build_iAPS.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_iAPS.yml b/.github/workflows/build_iAPS.yml index f67f1c6735..e3bd655e49 100644 --- a/.github/workflows/build_iAPS.yml +++ b/.github/workflows/build_iAPS.yml @@ -97,7 +97,7 @@ jobs: if: | needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && (vars.SCHEDULED_BUILD != 'false' || vars.SCHEDULED_SYNC != 'false') - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: token: ${{ secrets.GH_PAT }} ref: alive @@ -142,7 +142,7 @@ jobs: if: | needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && vars.SCHEDULED_SYNC == 'true' - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: token: ${{ secrets.GH_PAT }} ref: ${{ env.TARGET_BRANCH }} @@ -182,7 +182,7 @@ jobs: echo "NEW_COMMITS=${{ steps.sync.outputs.has_new_commits }}" >> $GITHUB_OUTPUT - name: Checkout Repo for building - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: token: ${{ secrets.GH_PAT }} submodules: recursive From dfab3611bb271c0af8dc907bb5f1aac592d047f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sat, 2 Mar 2024 20:46:21 +0100 Subject: [PATCH 16/44] Glucose Simulator Bug fix Prevent Division by zero. --- FreeAPS/Sources/APS/CGM/GlucoseSimulatorSource.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/FreeAPS/Sources/APS/CGM/GlucoseSimulatorSource.swift b/FreeAPS/Sources/APS/CGM/GlucoseSimulatorSource.swift index 5dbb0efebb..b8054421f6 100644 --- a/FreeAPS/Sources/APS/CGM/GlucoseSimulatorSource.swift +++ b/FreeAPS/Sources/APS/CGM/GlucoseSimulatorSource.swift @@ -182,10 +182,11 @@ class IntelligentGenerator: BloodGlucoseGenerator { } private func makeStepInTrend() { - currentGlucose += - Int(Double((trendTargetValue - currentGlucose) / trendStepsLeft) * [0.3, 0.6, 1, 1.3, 1.6, 2.0].randomElement()!) - trendStepsLeft -= 1 - if trendStepsLeft == 0 { + if trendStepsLeft > 0 { + currentGlucose += + Int(Double((trendTargetValue - currentGlucose) / trendStepsLeft) * [0.3, 0.6, 1, 1.3, 1.6, 2.0].randomElement()!) + trendStepsLeft -= 1 + } else { generateNewTrend() } } From 3e3e1403afd5f57abf55a3b3289ae1d30abaf65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sun, 3 Mar 2024 01:00:09 +0100 Subject: [PATCH 17/44] Add missing string. "Replace" when pod has expired. --- .../Sources/Localizations/Main/en.lproj/Localizable.strings | 3 +++ 1 file changed, 3 insertions(+) diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index 4edbf8f15f..c6dc940b66 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Add Simulator"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Model"; From e88e4f51f26b2bc2276c23944e64860c84cf4684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Sun, 3 Mar 2024 01:19:04 +0100 Subject: [PATCH 18/44] Display Time Zone Offset (#562) --- .../Modules/Home/View/Header/PumpView.swift | 12 +++++++++++- .../Sources/Modules/Home/View/HomeRootView.swift | 2 +- FreeAPS/Sources/Views/ViewModifiers.swift | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/FreeAPS/Sources/Modules/Home/View/Header/PumpView.swift b/FreeAPS/Sources/Modules/Home/View/Header/PumpView.swift index 918b38bd42..0d8d268d76 100644 --- a/FreeAPS/Sources/Modules/Home/View/Header/PumpView.swift +++ b/FreeAPS/Sources/Modules/Home/View/Header/PumpView.swift @@ -6,6 +6,7 @@ struct PumpView: View { @Binding var name: String @Binding var expiresAtDate: Date? @Binding var timerDate: Date + @Binding var timeZone: TimeZone? @State var state: Home.StateModel @@ -71,6 +72,11 @@ struct PumpView: View { .frame(maxHeight: 15) .foregroundColor(batteryColor) .offset(x: 0, y: -4) + .overlay { + if let timeZone = timeZone, timeZone.secondsFromGMT() != TimeZone.current.secondsFromGMT() { + ClockOffset(mdtPump: true) + } + } } if let date = expiresAtDate { @@ -79,7 +85,11 @@ struct PumpView: View { .frame(width: IAPSconfig.iconSize * 1.15, height: IAPSconfig.iconSize * 1.6) .foregroundColor(colorScheme == .dark ? .secondary : .white) .offset(x: 0, y: -5) - + .overlay { + if let timeZone = timeZone, timeZone.secondsFromGMT() != TimeZone.current.secondsFromGMT() { + ClockOffset(mdtPump: false) + } + } remainingTime(time: date.timeIntervalSince(timerDate)) .font(.pumpFont) .offset(x: -7, y: 0) diff --git a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift index 16144fb271..5df98514df 100644 --- a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift +++ b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift @@ -120,7 +120,7 @@ extension Home { battery: $state.battery, name: $state.pumpName, expiresAtDate: $state.pumpExpiresAtDate, - timerDate: $state.timerDate, + timerDate: $state.timerDate, timeZone: $state.timeZone, state: state ) .onTapGesture { diff --git a/FreeAPS/Sources/Views/ViewModifiers.swift b/FreeAPS/Sources/Views/ViewModifiers.swift index 4172b65855..883f302b75 100644 --- a/FreeAPS/Sources/Views/ViewModifiers.swift +++ b/FreeAPS/Sources/Views/ViewModifiers.swift @@ -156,6 +156,21 @@ struct HeaderBackground: View { } } +struct ClockOffset: View { + let mdtPump: Bool + var body: some View { + ZStack { + Image(systemName: "clock.fill") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(maxHeight: 20) + .symbolRenderingMode(.palette) + .foregroundStyle(Color(.warning)) + .offset(x: 10, y: !mdtPump ? -20 : -13) + } + } +} + struct ChartBackground: ViewModifier { @Environment(\.colorScheme) var colorScheme From 3898219eb08ebf56224c3ea5a799e978b0890fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Sun, 3 Mar 2024 19:43:52 +0100 Subject: [PATCH 19/44] Make UI update (#561) --- .../OverrideProfilesStateModel.swift | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift index 3098a7b5cf..365f5cdda4 100644 --- a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift +++ b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift @@ -46,6 +46,17 @@ extension OverrideProfilesConfig { // Is other override already active? let last = OverrideStorage().fetchLatestOverride().last + // Is other already active? + if let active = last, active.enabled { + if let preset = OverrideStorage().isPresetName(), let duration = OverrideStorage().cancelProfile() { + ns.editOverride(preset, duration, last?.date ?? Date.now) + } else if let duration = OverrideStorage().cancelProfile() { + let nsString = active.percentage.formatted() != "100" ? active.percentage + .formatted() + " %" : "Custom" + ns.editOverride(nsString, duration, last?.date ?? Date.now) + } + } + coredataContext.perform { [self] in let saveOverride = Override(context: self.coredataContext) saveOverride.duration = self.duration as NSDecimalNumber @@ -82,18 +93,8 @@ extension OverrideProfilesConfig { saveOverride.uamMinutes = uamMinutes as NSDecimalNumber } - if let active = last, active.enabled { - if let preset = OverrideStorage().isPresetName(), let duration = OverrideStorage().cancelProfile() { - ns.editOverride(preset, duration, last?.date ?? Date.now) - } else if let duration = OverrideStorage().cancelProfile() { - let nsString = active.percentage.formatted() != "100" ? active.percentage - .formatted() + " %" : "Custom" - ns.editOverride(nsString, duration, last?.date ?? Date.now) - } - } else { - let duration = (self.duration as NSDecimalNumber) == 0 ? 2880 : Int(self.duration as NSDecimalNumber) - ns.uploadOverride(self.percentage.formatted(), Double(duration), saveOverride.date ?? Date.now) - } + let duration = (self.duration as NSDecimalNumber) == 0 ? 2880 : Int(self.duration as NSDecimalNumber) + ns.uploadOverride(self.percentage.formatted(), Double(duration), saveOverride.date ?? Date.now) try? self.coredataContext.save() } @@ -145,7 +146,18 @@ extension OverrideProfilesConfig { // Is other already active? let last = OverrideStorage().fetchLatestOverride().last - + var date = Date() + + // If replacing an active override + if let active = last, active.enabled { + if let preset = OverrideStorage().isPresetName(), let duration = OverrideStorage().cancelProfile() { + ns.editOverride(preset, duration, last?.date ?? Date.now) + } else if let duration = OverrideStorage().cancelProfile() { + let nsString = active.percentage.formatted() != "100" ? active.percentage + .formatted() + " %" : "Custom" + ns.editOverride(nsString, duration, last?.date ?? Date.now) + } + } coredataContext.performAndWait { var profileArray = [OverridePresets]() let requestProfiles = OverridePresets.fetchRequest() as NSFetchRequest @@ -185,13 +197,11 @@ extension OverrideProfilesConfig { saveOverride.smbMinutes = (profile.smbMinutes ?? 0) as NSDecimalNumber saveOverride.uamMinutes = (profile.uamMinutes ?? 0) as NSDecimalNumber } - - if let alreadyActive = last, alreadyActive.enabled, let duration = OverrideStorage().cancelProfile() { - ns.editOverride(profile.name ?? "Custom", duration, alreadyActive.date ?? Date.now) - } else { - ns.uploadOverride(profile.name ?? "", Double(saveOverride.duration ?? 0), saveOverride.date ?? Date()) - } - + date = saveOverride.date ?? Date.now + // Upload + let duration = ((profile.duration ?? 0) as NSDecimalNumber) == 0 ? 2880 : + Int((profile.duration ?? 0) as NSDecimalNumber) + ns.uploadOverride(profile.name ?? "", Double(duration), date) try? self.coredataContext.save() } } From 85479058e216325c40bd5c6b413e93447fd6f986 Mon Sep 17 00:00:00 2001 From: "Jon B.M" Date: Sun, 3 Mar 2024 19:47:36 +0100 Subject: [PATCH 20/44] Bump version --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index 98b9644695..41fb21fb52 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 3.1.6 +APP_VERSION = 3.1.7 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## From cb407ad0e4eab52142611182198ea44082391596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Mon, 4 Mar 2024 18:33:39 +0100 Subject: [PATCH 21/44] Add Support for Profile Override iOS Shortcuts. (#560) --- Config.xcconfig | 2 +- FreeAPS.xcodeproj/project.pbxproj | 14 +- .../Colors/Violet.colorset/Contents.json | 6 +- .../APS/FetchAnnouncementsManager.swift | 5 +- .../APS/Storage/AnnouncementsStorage.swift | 4 +- .../Sources/APS/Storage/OverrideStorage.swift | 38 ++- .../Home/View/Chart/MainChartView.swift | 20 +- .../OverrideProfilesStateModel.swift | 205 +++++++--------- FreeAPS/Sources/Shortcuts/AppShortcuts.swift | 14 ++ .../Shortcuts/BaseIntentsRequest.swift | 3 + .../Overrides/OverrideShortcuts.swift | 230 ++++++++++++++++++ 11 files changed, 390 insertions(+), 151 deletions(-) create mode 100644 FreeAPS/Sources/Shortcuts/Overrides/OverrideShortcuts.swift diff --git a/Config.xcconfig b/Config.xcconfig index 41fb21fb52..988d84a9f9 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 3.1.7 +APP_VERSION = 3.1.8 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## diff --git a/FreeAPS.xcodeproj/project.pbxproj b/FreeAPS.xcodeproj/project.pbxproj index c46dd2246e..5ccc6f8098 100644 --- a/FreeAPS.xcodeproj/project.pbxproj +++ b/FreeAPS.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ 1935364028496F7D001E0B16 /* Oref2_variables.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1935363F28496F7D001E0B16 /* Oref2_variables.swift */; }; 193F6CDD2A512C8F001240FD /* Loops.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193F6CDC2A512C8F001240FD /* Loops.swift */; }; 194297512B815938006B8A0B /* OverridesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194297502B815938006B8A0B /* OverridesView.swift */; }; + 194C32772B93A9BF0016FB2A /* OverrideShortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194C32762B93A9BF0016FB2A /* OverrideShortcuts.swift */; }; 1956FB212AFF79E200C7B4FF /* CoreDataStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1956FB202AFF79E200C7B4FF /* CoreDataStorage.swift */; }; 195D80B42AF6973A00D25097 /* DynamicRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B32AF6973A00D25097 /* DynamicRootView.swift */; }; 195D80B72AF697B800D25097 /* DynamicDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B62AF697B800D25097 /* DynamicDataFlow.swift */; }; @@ -573,6 +574,7 @@ 193F1E3C2B44C14800525770 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = ""; }; 193F6CDC2A512C8F001240FD /* Loops.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Loops.swift; sourceTree = ""; }; 194297502B815938006B8A0B /* OverridesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverridesView.swift; sourceTree = ""; }; + 194C32762B93A9BF0016FB2A /* OverrideShortcuts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverrideShortcuts.swift; sourceTree = ""; }; 1956FB202AFF79E200C7B4FF /* CoreDataStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataStorage.swift; sourceTree = ""; }; 195D80B32AF6973A00D25097 /* DynamicRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRootView.swift; sourceTree = ""; }; 195D80B62AF697B800D25097 /* DynamicDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicDataFlow.swift; sourceTree = ""; }; @@ -1145,6 +1147,14 @@ path = View; sourceTree = ""; }; + 196579A52B924BD400642E8E /* Overrides */ = { + isa = PBXGroup; + children = ( + 194C32762B93A9BF0016FB2A /* OverrideShortcuts.swift */, + ); + path = Overrides; + sourceTree = ""; + }; 198377CF266BFEDE004DE65E /* Localizations */ = { isa = PBXGroup; children = ( @@ -2252,9 +2262,10 @@ CE7CA3422A064973004BE681 /* Shortcuts */ = { isa = PBXGroup; children = ( - CE1856F32ADC4835007E39C7 /* Carbs */, CE7CA3432A064973004BE681 /* AppShortcuts.swift */, CE7CA3442A064973004BE681 /* BaseIntentsRequest.swift */, + CE1856F32ADC4835007E39C7 /* Carbs */, + 196579A52B924BD400642E8E /* Overrides */, CE7CA3452A064973004BE681 /* TempPresets */, CE7CA34B2A064973004BE681 /* State */, ); @@ -3007,6 +3018,7 @@ F90692D3274B9A130037068D /* AppleHealthKitRootView.swift in Sources */, 3862CC1F273FDC9200BF832C /* CalibrationsChart.swift in Sources */, 19E1F7EC29D082FE005C8D20 /* IconConfigStateModel.swift in Sources */, + 194C32772B93A9BF0016FB2A /* OverrideShortcuts.swift in Sources */, 711C0CB42CAABE788916BC9D /* ManualTempBasalDataFlow.swift in Sources */, BF1667ADE69E4B5B111CECAE /* ManualTempBasalProvider.swift in Sources */, F90692D6274B9A450037068D /* HealthKitStateModel.swift in Sources */, diff --git a/FreeAPS/Resources/Assets.xcassets/Colors/Violet.colorset/Contents.json b/FreeAPS/Resources/Assets.xcassets/Colors/Violet.colorset/Contents.json index 3d1aa91f0d..54ae9361f8 100644 --- a/FreeAPS/Resources/Assets.xcassets/Colors/Violet.colorset/Contents.json +++ b/FreeAPS/Resources/Assets.xcassets/Colors/Violet.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "extended-srgb", "components" : { "alpha" : "1.000", - "blue" : "86", - "green" : "55", - "red" : "95" + "blue" : "121", + "green" : "28", + "red" : "88" } }, "idiom" : "universal" diff --git a/FreeAPS/Sources/APS/FetchAnnouncementsManager.swift b/FreeAPS/Sources/APS/FetchAnnouncementsManager.swift index 4bc35f8dd9..2f61f7ac13 100644 --- a/FreeAPS/Sources/APS/FetchAnnouncementsManager.swift +++ b/FreeAPS/Sources/APS/FetchAnnouncementsManager.swift @@ -13,7 +13,7 @@ final class BaseFetchAnnouncementsManager: FetchAnnouncementsManager, Injectable @Injected() var settingsManager: SettingsManager! private var lifetime = Lifetime() - private let timer = DispatchTimer(timeInterval: 5.minutes.timeInterval) + private let timer = DispatchTimer(timeInterval: 4.minutes.timeInterval) init(resolver: Resolver) { injectServices(resolver) @@ -43,12 +43,13 @@ final class BaseFetchAnnouncementsManager: FetchAnnouncementsManager, Injectable } guard let last = announcements - .filter({ $0.createdAt < Date.now && $0.createdAt > self.announcementsStorage.syncDate() }) + .filter({ $0.createdAt < Date.now }) .sorted(by: { $0.createdAt < $1.createdAt }) .last else { return } self.announcementsStorage.storeAnnouncements([last], enacted: false) + if self.settingsManager.settings.allowAnnouncements, let recent = self.announcementsStorage.recent(), recent.action != nil { diff --git a/FreeAPS/Sources/APS/Storage/AnnouncementsStorage.swift b/FreeAPS/Sources/APS/Storage/AnnouncementsStorage.swift index 3cb982cf69..e76f94de34 100644 --- a/FreeAPS/Sources/APS/Storage/AnnouncementsStorage.swift +++ b/FreeAPS/Sources/APS/Storage/AnnouncementsStorage.swift @@ -28,8 +28,8 @@ final class BaseAnnouncementsStorage: AnnouncementsStorage, Injectable { self.storage.transaction { storage in storage.append(announcements, to: file, uniqBy: \.createdAt) let uniqEvents = storage.retrieve(file, as: [Announcement].self)? - .sorted { $0.createdAt > $1.createdAt } ?? [] .filter { $0.createdAt.addingTimeInterval(1.days.timeInterval) > Date() } + .sorted { $0.createdAt > $1.createdAt } ?? [] storage.save(Array(uniqEvents), as: file) } } @@ -76,7 +76,7 @@ final class BaseAnnouncementsStorage: AnnouncementsStorage, Injectable { } let enactedEventsLast = enactedEvents.first - if -1 * (enactedEventsLast?.createdAt ?? .distantPast).timeIntervalSinceNow.minutes < 10 { + if -1 * (enactedEventsLast?.createdAt ?? .distantPast).timeIntervalSinceNow.minutes <= 10 { return enactedEventsLast } return nil diff --git a/FreeAPS/Sources/APS/Storage/OverrideStorage.swift b/FreeAPS/Sources/APS/Storage/OverrideStorage.swift index 7e7d74cd61..badd89a15c 100644 --- a/FreeAPS/Sources/APS/Storage/OverrideStorage.swift +++ b/FreeAPS/Sources/APS/Storage/OverrideStorage.swift @@ -66,9 +66,11 @@ final class OverrideStorage { let history = OverrideHistory(context: self.coredataContext) if let latest = scheduled { history.duration = -1 * (latest.date ?? Date()).timeIntervalSinceNow.minutes - print("History duration: \(history.duration) min") history.date = latest.date ?? Date() - history.target = Double(latest.target ?? 100) + // Looks better in Home View Main Chart when target isn't == 0. + if Double(latest.target ?? 100) < 6 { + history.target = 6 + } else { history.target = Double(latest.target ?? 100) } duration = history.duration } profiles.enabled = false @@ -95,6 +97,7 @@ final class OverrideStorage { save.isfAndCr = preset.isfAndCr save.percentage = preset.percentage save.smbIsAlwaysOff = preset.smbIsAlwaysOff + save.smbIsOff = preset.smbIsOff save.smbMinutes = preset.smbMinutes save.uamMinutes = preset.uamMinutes save.target = preset.target @@ -102,10 +105,9 @@ final class OverrideStorage { } } - func fetchProfile(_ name: String) -> Override? { + func fetchProfilePreset(_ name: String) -> OverridePresets? { var presetsArray = [OverridePresets]() - var overrideArray = [Override]() - var override: Override? + var preset: OverridePresets? coredataContext.performAndWait { let requestPresets = OverridePresets.fetchRequest() as NSFetchRequest requestPresets.predicate = NSPredicate( @@ -113,27 +115,15 @@ final class OverrideStorage { ) try? presetsArray = self.coredataContext.fetch(requestPresets) - guard let preset = presetsArray.first else { - return - } - guard let id = preset.id else { - return - } - let requestOverrides = Override.fetchRequest() as NSFetchRequest - requestOverrides.predicate = NSPredicate( - format: "id == %@", id - ) - try? overrideArray = self.coredataContext.fetch(requestOverrides) - - guard let override_ = overrideArray.first else { + guard let overidePreset = presetsArray.first else { return } - override = override_ + preset = overidePreset } - return override + return preset } - func fetchProfiles() -> OverridePresets? { + func fetchProfile() -> OverridePresets? { var presetsArray = [OverridePresets]() coredataContext.performAndWait { let requestPresets = OverridePresets.fetchRequest() as NSFetchRequest @@ -186,6 +176,7 @@ final class OverrideStorage { save.isfAndCr = override.isfAndCr save.percentage = override.percentage save.smbIsAlwaysOff = override.smbIsAlwaysOff + save.smbIsOff = override.smbIsOff save.smbMinutes = override.smbMinutes save.uamMinutes = override.uamMinutes save.target = override.target @@ -276,9 +267,12 @@ final class OverrideStorage { save.isfAndCr = preset.isfAndCr save.percentage = preset.percentage save.smbIsAlwaysOff = preset.smbIsAlwaysOff + save.smbIsOff = preset.smbIsOff save.smbMinutes = preset.smbMinutes save.uamMinutes = preset.uamMinutes - save.target = preset.target + if (preset.target ?? 0) as Decimal > 6 { + save.target = preset.target + } else { save.target = 6 } try? coredataContext.save() } } diff --git a/FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift b/FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift index c3f3e90aa1..c44f5f69ed 100644 --- a/FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift +++ b/FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift @@ -1102,19 +1102,21 @@ extension MainChartView { height: 8 ) } - if latest?.enabled ?? false { + // Display active Override + if let last = latest, last.enabled { var old = Array(rects) - let duration = Double(latest?.duration ?? 0) + let duration = Double(last.duration ?? 0) + // Looks better when target isn't == 0 in Home View Main Chart + let targetRaw = last.target ?? 0 + let target = Int(targetRaw) < 6 ? 6 : targetRaw + if duration > 0 { let x1 = timeToXCoordinate((latest?.date ?? Date.now).timeIntervalSince1970, fullSize: fullSize) - let plusNow = (latest?.date ?? Date.now).addingTimeInterval(Int(latest?.duration ?? 0).minutes.timeInterval) + let plusNow = (last.date ?? Date.now).addingTimeInterval(Int(latest?.duration ?? 0).minutes.timeInterval) let x2 = timeToXCoordinate(plusNow.timeIntervalSince1970, fullSize: fullSize) let oneMore = CGRect( x: x1, - y: glucoseToYCoordinate( - Int(Double(latest?.target ?? 100)), - fullSize: fullSize - ), + y: glucoseToYCoordinate(Int(target), fullSize: fullSize) - 3, width: x2 - x1, height: 8 ) @@ -1126,11 +1128,11 @@ extension MainChartView { overridesPath = path } } else { - let x1 = timeToXCoordinate((latest?.date ?? Date.now).timeIntervalSince1970, fullSize: fullSize) + let x1 = timeToXCoordinate((last.date ?? Date.now).timeIntervalSince1970, fullSize: fullSize) let x2 = timeToXCoordinate(Date.now.timeIntervalSince1970, fullSize: fullSize) let oneMore = CGRect( x: x1, - y: glucoseToYCoordinate(Int(Double(latest?.target ?? 100)), fullSize: fullSize), + y: glucoseToYCoordinate(Int(target), fullSize: fullSize) - 3, width: x2 - x1 + additionalWidth(viewWidth: fullSize.width), height: 8 ) diff --git a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift index 365f5cdda4..78df86370b 100644 --- a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift +++ b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift @@ -110,7 +110,7 @@ extension OverrideProfilesConfig { saveOverride.name = self.profileName saveOverride.emoji = self.emoji id = UUID().uuidString - self.isPreset.toggle() + self.isPreset = true saveOverride.id = id saveOverride.date = Date() if override_target { @@ -142,133 +142,116 @@ extension OverrideProfilesConfig { } func selectProfile(id_: String) { - guard id_ != "" else { return } + guard !id_.isEmpty else { return } - // Is other already active? - let last = OverrideStorage().fetchLatestOverride().last - var date = Date() + // Double Check that preset actually still exist in databasa (shouldn't really be necessary) + let profileArray = OverrideStorage().fetchProfiles() + guard let profile = profileArray.filter({ $0.id == id_ }).first else { return } - // If replacing an active override - if let active = last, active.enabled { - if let preset = OverrideStorage().isPresetName(), let duration = OverrideStorage().cancelProfile() { - ns.editOverride(preset, duration, last?.date ?? Date.now) - } else if let duration = OverrideStorage().cancelProfile() { - let nsString = active.percentage.formatted() != "100" ? active.percentage - .formatted() + " %" : "Custom" - ns.editOverride(nsString, duration, last?.date ?? Date.now) - } + // Is there already an active override? + let last = OverrideStorage().fetchLatestOverride().last + let lastPreset = OverrideStorage().isPresetName() + if let alreadyActive = last, alreadyActive.enabled, let duration = OverrideStorage().cancelProfile() { + ns.editOverride((last?.isPreset ?? false) ? lastPreset! : "Custom", duration, alreadyActive.date ?? Date.now) } - coredataContext.performAndWait { - var profileArray = [OverridePresets]() - let requestProfiles = OverridePresets.fetchRequest() as NSFetchRequest - try? profileArray = coredataContext.fetch(requestProfiles) - - guard let profile = profileArray.filter({ $0.id == id_ }).first else { return } + // New Override properties + let saveOverride = Override(context: coredataContext) + saveOverride.duration = (profile.duration ?? 0) as NSDecimalNumber + saveOverride.indefinite = profile.indefinite + saveOverride.percentage = profile.percentage + saveOverride.enabled = true + saveOverride.smbIsOff = profile.smbIsOff + saveOverride.isPreset = true + saveOverride.date = Date() + saveOverride.id = id_ - let saveOverride = Override(context: self.coredataContext) - saveOverride.duration = (profile.duration ?? 0) as NSDecimalNumber - saveOverride.indefinite = profile.indefinite - saveOverride.percentage = profile.percentage - saveOverride.enabled = true - saveOverride.smbIsOff = profile.smbIsOff - saveOverride.isPreset = true - saveOverride.date = Date() - saveOverride.id = id_ - - if let tar = profile.target, tar == 0 { - saveOverride.target = 6 - } else { - saveOverride.target = profile.target - } + if let tar = profile.target, tar == 0 { + saveOverride.target = 6 + } else { + saveOverride.target = profile.target + } - if profile.advancedSettings { - saveOverride.advancedSettings = true - if !isfAndCr { - saveOverride.isfAndCr = false - saveOverride.isf = profile.isf - saveOverride.cr = profile.cr - } else { saveOverride.isfAndCr = true } - if profile.smbIsAlwaysOff { - saveOverride.smbIsAlwaysOff = true - saveOverride.start = profile.start - saveOverride.end = profile.end - } else { saveOverride.smbIsAlwaysOff = false } + if profile.advancedSettings { + saveOverride.advancedSettings = true + if !isfAndCr { + saveOverride.isfAndCr = false + saveOverride.isf = profile.isf + saveOverride.cr = profile.cr + } else { saveOverride.isfAndCr = true } + if profile.smbIsAlwaysOff { + saveOverride.smbIsAlwaysOff = true + saveOverride.start = profile.start + saveOverride.end = profile.end + } else { saveOverride.smbIsAlwaysOff = false } - saveOverride.smbMinutes = (profile.smbMinutes ?? 0) as NSDecimalNumber - saveOverride.uamMinutes = (profile.uamMinutes ?? 0) as NSDecimalNumber - } - date = saveOverride.date ?? Date.now - // Upload - let duration = ((profile.duration ?? 0) as NSDecimalNumber) == 0 ? 2880 : - Int((profile.duration ?? 0) as NSDecimalNumber) - ns.uploadOverride(profile.name ?? "", Double(duration), date) - try? self.coredataContext.save() + saveOverride.smbMinutes = (profile.smbMinutes ?? 0) as NSDecimalNumber + saveOverride.uamMinutes = (profile.uamMinutes ?? 0) as NSDecimalNumber } + // Saves + coredataContext.perform { try? self.coredataContext.save() } + + // Uploads new Override to NS + ns.uploadOverride(profile.name ?? "", Double(saveOverride.duration ?? 0), saveOverride.date ?? Date()) } func savedSettings() { - coredataContext.performAndWait { - var overrideArray = [Override]() - let requestEnabled = Override.fetchRequest() as NSFetchRequest - let sortIsEnabled = NSSortDescriptor(key: "date", ascending: false) - requestEnabled.sortDescriptors = [sortIsEnabled] - // requestEnabled.fetchLimit = 1 - try? overrideArray = coredataContext.fetch(requestEnabled) - isEnabled = overrideArray.first?.enabled ?? false - percentage = overrideArray.first?.percentage ?? 100 - _indefinite = overrideArray.first?.indefinite ?? true - duration = (overrideArray.first?.duration ?? 0) as Decimal - smbIsOff = overrideArray.first?.smbIsOff ?? false - advancedSettings = overrideArray.first?.advancedSettings ?? false - isfAndCr = overrideArray.first?.isfAndCr ?? true - smbIsAlwaysOff = overrideArray.first?.smbIsAlwaysOff ?? false - - if advancedSettings { - if !isfAndCr { - isf = overrideArray.first?.isf ?? false - cr = overrideArray.first?.cr ?? false - } - if smbIsAlwaysOff { - start = (overrideArray.first?.start ?? 0) as Decimal - end = (overrideArray.first?.end ?? 0) as Decimal - } + guard let overrideArray = OverrideStorage().fetchLatestOverride().first else { + return + } + isEnabled = overrideArray.enabled + percentage = overrideArray.percentage + _indefinite = overrideArray.indefinite + duration = (overrideArray.duration ?? 0) as Decimal + smbIsOff = overrideArray.smbIsOff + advancedSettings = overrideArray.advancedSettings + isfAndCr = overrideArray.isfAndCr + smbIsAlwaysOff = overrideArray.smbIsAlwaysOff - if (overrideArray[0].smbMinutes as Decimal?) != nil { - smbMinutes = (overrideArray.first?.smbMinutes ?? 30) as Decimal - } + if advancedSettings { + if !isfAndCr { + isf = overrideArray.isf + cr = overrideArray.cr + } + if smbIsAlwaysOff { + start = (overrideArray.start ?? 0) as Decimal + end = (overrideArray.end ?? 0) as Decimal + } - if (overrideArray[0].uamMinutes as Decimal?) != nil { - uamMinutes = (overrideArray.first?.uamMinutes ?? 30) as Decimal - } + if (overrideArray.smbMinutes as Decimal?) != nil { + smbMinutes = (overrideArray.smbMinutes ?? 30) as Decimal } - let overrideTarget = (overrideArray.first?.target ?? 0) as Decimal - var newDuration = Double(duration) - if isEnabled { - let duration = overrideArray.first?.duration ?? 0 - let addedMinutes = Int(duration as Decimal) - let date = overrideArray.first?.date ?? Date() - if date.addingTimeInterval(addedMinutes.minutes.timeInterval) < Date(), !_indefinite { - isEnabled = false - } - newDuration = Date().distance(to: date.addingTimeInterval(addedMinutes.minutes.timeInterval)).minutes - if override_target { - target = units == .mmolL ? overrideTarget.asMmolL : overrideTarget - } + if (overrideArray.uamMinutes as Decimal?) != nil { + uamMinutes = (overrideArray.uamMinutes ?? 30) as Decimal } - if newDuration < 0 { newDuration = 0 } else { duration = Decimal(newDuration) } + } - if !isEnabled { - _indefinite = true - percentage = 100 - duration = 0 - target = 0 - override_target = false - smbIsOff = false - advancedSettings = false - smbMinutes = defaultSmbMinutes - uamMinutes = defaultUamMinutes + let overrideTarget = (overrideArray.target ?? 0) as Decimal + var newDuration = Double(duration) + if isEnabled { + let duration = overrideArray.duration ?? 0 + let addedMinutes = Int(duration as Decimal) + let date = overrideArray.date ?? Date() + if date.addingTimeInterval(addedMinutes.minutes.timeInterval) < Date(), !_indefinite { + isEnabled = false } + newDuration = Date().distance(to: date.addingTimeInterval(addedMinutes.minutes.timeInterval)).minutes + if override_target { + target = units == .mmolL ? overrideTarget.asMmolL : overrideTarget + } + } + if newDuration < 0 { newDuration = 0 } else { duration = Decimal(newDuration) } + + if !isEnabled { + _indefinite = true + percentage = 100 + duration = 0 + target = 0 + override_target = false + smbIsOff = false + advancedSettings = false + smbMinutes = defaultSmbMinutes + uamMinutes = defaultUamMinutes } } diff --git a/FreeAPS/Sources/Shortcuts/AppShortcuts.swift b/FreeAPS/Sources/Shortcuts/AppShortcuts.swift index 026ba87999..d9c9233b9c 100644 --- a/FreeAPS/Sources/Shortcuts/AppShortcuts.swift +++ b/FreeAPS/Sources/Shortcuts/AppShortcuts.swift @@ -24,5 +24,19 @@ import Foundation "\(.applicationName) allows to add carbs" ] ) + AppShortcut( + intent: ApplyOverrideIntent(), + phrases: [ + "Activate an \(.applicationName) Override Preset", + "Activates an \(.applicationName) Override Preset" + ] + ) + AppShortcut( + intent: CancelOverrideIntent(), + phrases: [ + "Cancel \(.applicationName) Overide", + "Cancels an active \(.applicationName) override" + ] + ) } } diff --git a/FreeAPS/Sources/Shortcuts/BaseIntentsRequest.swift b/FreeAPS/Sources/Shortcuts/BaseIntentsRequest.swift index 34224ed335..3bf23e6ebe 100644 --- a/FreeAPS/Sources/Shortcuts/BaseIntentsRequest.swift +++ b/FreeAPS/Sources/Shortcuts/BaseIntentsRequest.swift @@ -13,6 +13,9 @@ import Swinject @Injected() var carbsStorage: CarbsStorage! @Injected() var glucoseStorage: GlucoseStorage! @Injected() var apsManager: APSManager! + @Injected() var nightscoutManager: NightscoutManager! + + let overrideStorage = OverrideStorage() let resolver: Resolver diff --git a/FreeAPS/Sources/Shortcuts/Overrides/OverrideShortcuts.swift b/FreeAPS/Sources/Shortcuts/Overrides/OverrideShortcuts.swift new file mode 100644 index 0000000000..75fd2b6f5f --- /dev/null +++ b/FreeAPS/Sources/Shortcuts/Overrides/OverrideShortcuts.swift @@ -0,0 +1,230 @@ +import AppIntents +import Foundation +import Intents + +@available(iOS 16.0, *) struct OverrideEntity: AppEntity, Identifiable { + static var defaultQuery = OverrideQuery() + + var id: UUID + var name: String + var description: String // Currently not displayed in Shortcuts + + var displayRepresentation: DisplayRepresentation { + DisplayRepresentation(title: "\(name)") + } + + static var typeDisplayRepresentation: TypeDisplayRepresentation = "Presets" +} + +enum OverrideIntentError: Error { + case StateIntentUnknownError + case NoPresets +} + +@available(iOS 16.0, *) struct ApplyOverrideIntent: AppIntent { + // Title of the action in the Shortcuts app + static var title: LocalizedStringResource = "Activate an Override Preset" + + // Description of the action in the Shortcuts app + static var description = IntentDescription("Allow to activate an overrride preset.") + + internal var intentRequest: OverrideIntentRequest + + init() { + intentRequest = OverrideIntentRequest() + } + + @Parameter(title: "Preset") var preset: OverrideEntity? + + @Parameter( + title: "Confirm Before activating", + description: "If toggled, you will need to confirm before activating", + default: true + ) var confirmBeforeApplying: Bool + + static var parameterSummary: some ParameterSummary { + When(\ApplyOverrideIntent.$confirmBeforeApplying, .equalTo, true, { + Summary("Applying \(\.$preset)") { + \.$confirmBeforeApplying + } + }, otherwise: { + Summary("Immediately applying \(\.$preset)") { + \.$confirmBeforeApplying + } + }) + } + + @MainActor func perform() async throws -> some ProvidesDialog { + do { + let presetToApply: OverrideEntity + if let preset = preset { + presetToApply = preset + } else { + presetToApply = try await $preset.requestDisambiguation( + among: intentRequest.fetchPresets(), + dialog: "Which override preset would you like to activate?" + ) + } + + let displayName: String = presetToApply.name + if confirmBeforeApplying { + try await requestConfirmation( + result: .result(dialog: "Are you sure you want to activate the Override Preset \(displayName)?") + ) + } + + let preset = try intentRequest.findPreset(displayName) + let finalOverrideApply = try intentRequest.enactPreset(preset) + let isDone = finalOverrideApply != nil ? finalOverrideApply?.isPreset ?? false : false + + let displayDetail: String = isDone ? + "The Profile Override \(displayName) is now activated" : "Override Activation Failed" + return .result( + dialog: IntentDialog(stringLiteral: displayDetail) + ) + } catch { + throw error + } + } +} + +@available(iOS 16.0, *) struct CancelOverrideIntent: AppIntent { + static var title: LocalizedStringResource = "Cancel active override" + static var description = IntentDescription("Cancel active override.") + + internal var intentRequest: OverrideIntentRequest + + init() { + intentRequest = OverrideIntentRequest() + } + + @MainActor func perform() async throws -> some ProvidesDialog { + do { + try intentRequest.cancelOverride() + return .result( + dialog: IntentDialog(stringLiteral: "Override canceled") + ) + } catch { + throw error + } + } +} + +@available(iOS 16.0, *) struct OverrideQuery: EntityQuery { + internal var intentRequest: OverrideIntentRequest + + init() { + intentRequest = OverrideIntentRequest() + } + + func entities(for identifiers: [OverrideEntity.ID]) async throws -> [OverrideEntity] { + let presets = intentRequest.fetchIDs(identifiers) + return presets + } + + func suggestedEntities() async throws -> [OverrideEntity] { + let presets = try intentRequest.fetchPresets() + return presets + } +} + +@available(iOS 16.0, *) final class OverrideIntentRequest: BaseIntentsRequest { + func fetchPresets() throws -> ([OverrideEntity]) { + let presets = overrideStorage.fetchProfiles().flatMap { preset -> [OverrideEntity] in + let percentage = preset.percentage != 100 ? preset.percentage.formatted() : "" + let targetRaw = settingsManager.settings + .units == .mgdL ? Decimal(Double(preset.target ?? 0)) : Double(preset.target ?? 0) + .asMmolL + let target = (preset.target != 0 || preset.target != 6) ? + (glucoseFormatter.string(from: targetRaw as NSNumber) ?? "") : "" + let string = percentage != "" ? percentage + ", " + target : target + + return [OverrideEntity( + id: UUID(uuidString: preset.id ?? "") ?? UUID(), + name: preset.name ?? "", + description: string + )] + } + return presets + } + + private var glucoseFormatter: NumberFormatter { + let formatter = NumberFormatter() + formatter.numberStyle = .decimal + formatter.maximumFractionDigits = 0 + if settingsManager.settings.units == .mmolL { + formatter.minimumFractionDigits = 1 + formatter.maximumFractionDigits = 1 + } + formatter.roundingMode = .halfUp + return formatter + } + + func findPreset(_ name: String) throws -> OverridePresets { + let presetFound = overrideStorage.fetchProfiles().filter({ $0.name == name }) + guard let preset = presetFound.first else { throw OverrideIntentError.NoPresets } + return preset + } + + func fetchIDs(_ id: [OverrideEntity.ID]) -> [OverrideEntity] { + let presets = overrideStorage.fetchProfiles().filter { id.contains(UUID(uuidString: $0.id ?? "")!) } + .map { preset -> OverrideEntity in + let percentage = preset.percentage != 100 ? preset.percentage.formatted() : "" + let targetRaw = settingsManager.settings + .units == .mgdL ? Decimal(Double(preset.target ?? 0)) : Double(preset.target ?? 0) + .asMmolL + let target = (preset.target != 0 || preset.target != 6) ? + (glucoseFormatter.string(from: targetRaw as NSNumber) ?? "") : "" + let string = percentage != "" ? percentage + ", " + target : target + + return OverrideEntity( + id: UUID(uuidString: preset.id ?? "") ?? UUID(), + name: preset.name ?? "", + description: string + ) + } + return presets + } + + func enactPreset(_ preset: OverridePresets) throws -> Override? { + guard let overridePreset = overrideStorage.fetchProfilePreset(preset.name ?? "") else { + return nil + } + let lastActiveOveride = overrideStorage.fetchLatestOverride().first + let isActive = lastActiveOveride?.enabled ?? false + + // Cancel the eventual current active override first + if isActive { + let presetName = overrideStorage.isPresetName() + if let duration = overrideStorage.cancelProfile(), let last = lastActiveOveride { + // let presetName = overrideStorage.isPresetName() + let nsString = presetName != nil ? presetName : last.percentage.formatted() + nightscoutManager.editOverride(nsString!, duration, last.date ?? Date()) + } + } + overrideStorage.overrideFromPreset(overridePreset) + let currentActiveOveride = overrideStorage.fetchLatestOverride().first + nightscoutManager.uploadOverride(preset.name ?? "", Double(preset.duration ?? 0), currentActiveOveride?.date ?? Date.now) + return currentActiveOveride + } + + func cancelOverride() throws { + // Is there even a saved Override? + if let activeOveride = overrideStorage.fetchLatestOverride().first { + let presetName = overrideStorage.isPresetName() + // Is the Override a Preset? + if let preset = presetName { + if let duration = overrideStorage.cancelProfile() { + // Update in Nightscout + nightscoutManager.editOverride(preset, duration, activeOveride.date ?? Date.now) + } + } else { + let nsString = activeOveride.percentage.formatted() != "100" ? activeOveride.percentage + .formatted() + " %" : "Custom" + if let duration = overrideStorage.cancelProfile() { + nightscoutManager.editOverride(nsString, duration, activeOveride.date ?? Date.now) + } + } + } + } +} From 81b64ecb2775bc5bad46fdbe264e93d58a911438 Mon Sep 17 00:00:00 2001 From: dsnallfot <72826201+dsnallfot@users.noreply.github.com> Date: Mon, 4 Mar 2024 19:53:20 +0100 Subject: [PATCH 22/44] Test/Attempt to adress and possible fix bug with duplicate carbs entries in data table and apple health. - Use default dispatchqueue instead of global to see if this prevents race conditions/conflicts --- .../Modules/DataTable/DataTableStateModel.swift | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift b/FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift index 490f7d3c9b..0cd11e1de3 100644 --- a/FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift +++ b/FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift @@ -33,8 +33,17 @@ extension DataTable { broadcaster.register(GlucoseObserver.self, observer: self) } + private let processQueue = + DispatchQueue(label: "setupTreatments.processQueue") // Ensure that only one instance of this function can execute at a time + private func setupTreatments() { - DispatchQueue.global().async { + // Log that the function is starting for testing purposes + debug(.service, "setupTreatments() started") + + // DispatchQueue.global().async { // Original code with global concurrent queue + + // Ensure that only one instance of this function can execute at a time by using a serial queue + processQueue.async { let units = self.settingsManager.settings.units var date = Date.now let carbs = self.provider.carbs() From 2b7fbb77b9881e4c98d8e7b43ff142693ee7d04d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Tue, 5 Mar 2024 13:46:34 +0100 Subject: [PATCH 23/44] Crowdin updates (#563) --- .../Main/ar.lproj/Localizable.strings | 3 +++ .../Main/da.lproj/Localizable.strings | 3 +++ .../Main/de.lproj/Localizable.strings | 19 +++++++++++-------- .../Main/es.lproj/Localizable.strings | 4 ++++ .../Main/fi.lproj/Localizable.strings | 3 +++ .../Main/fr.lproj/Localizable.strings | 5 ++++- .../Main/he.lproj/Localizable.strings | 3 +++ .../Main/hu.lproj/Localizable.strings | 3 +++ .../Main/it.lproj/Localizable.strings | 3 +++ .../Main/nb.lproj/Localizable.strings | 3 +++ .../Main/nl.lproj/Localizable.strings | 3 +++ .../Main/pl.lproj/Localizable.strings | 3 +++ .../Main/pt-BR.lproj/Localizable.strings | 3 +++ .../Main/pt-PT.lproj/Localizable.strings | 3 +++ .../Main/ru.lproj/Localizable.strings | 3 +++ .../Main/sk.lproj/Localizable.strings | 3 +++ .../Main/sv.lproj/Localizable.strings | 3 +++ .../Main/tr.lproj/Localizable.strings | 3 +++ .../Main/uk.lproj/Localizable.strings | 3 +++ .../Main/vi.lproj/Localizable.strings | 3 +++ .../Main/zh-Hans.lproj/Localizable.strings | 3 +++ 21 files changed, 73 insertions(+), 9 deletions(-) diff --git a/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings index a1f2376c0a..64ef7ca9b7 100644 --- a/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Add Simulator"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Model"; diff --git a/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings index a6deae607b..160b197b2a 100644 --- a/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Tilføj Simulator"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Model"; diff --git a/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings index ab59a27e46..77facf1e99 100644 --- a/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings @@ -50,16 +50,16 @@ "of" = "von"; /* Remote Bolus Alert, Part 1 */ -"A Remote Bolus " = "A Remote Bolus "; +"A Remote Bolus " = "Ein entfernter Bolus "; /* Remote Bolus Alert, Part 2 */ -"was delivered" = "was delivered"; +"was delivered" = "wurde inijiziert"; /* Remote Bolus Alert, Part 3 */ " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; /* Remote Bolus Alert, Title */ -"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; +"A Remote Bolus Was Just Delivered!" = "Ein Remote Bolus wurde gerade abgegeben!"; /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Letzte Berechnung um"; @@ -375,7 +375,7 @@ Enact a temp Basal or a temp target */ "Remote control" = "Fernbedienung"; /* Allow remote control from NS */ -"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; +"Allow Remote control of iAPS" = "Erlaube Fernsteuerung von iAPS"; /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nBitte überprüfen Sie jetzt alle Ihre neuen Einstellungen gründlich:\n\n* Basaleinstellungen\n * Carb Ratios\n * Glukose-Ziele\n * Insulinempfindlichkeiten\n * DIA\n\n in iAPS-Einstellungen > Konfiguration.\n\nSchlechte oder ungültige Profileinstellungen können abscheuliche Effekte haben."; @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Simulator hinzufügen"; +/* View/Header when pod expired */ +"Replace" = "Pod ersetzen!"; + /* Insulin model */ "Model" = "Modell"; @@ -2056,7 +2059,7 @@ Enact a temp Basal or a temp target */ "Enable Dynamic ISF" = "Aktiviere Dynamic ISF"; /* Headline "Enable Dynamic ISF" */ -"Enable Dynamic ISF" = "Aktiviere Dynamic ISF"; +"Enable Dynamic ISF" = "Dynamischen Insulinempfindlichkeitsfaktor (ISF) aktivieren"; /* Enable Dynamic ISF */ "Calculate a new Insulin Sensitivity Setting (ISF) upon every loop cycle. The new ISF will be based on your current Glucose, total daily dose of insulin (TDD, past 24 hours of all delivered insulin) and an individual Adjustment Factor (recommendation to start with is 0.5 if using Sigmoid Function and 0.8 if not).\n\nAll of the Dynamic ISF and CR adjustments will be limited by your autosens.min/max limits." = "Berechnen Sie bei jedem Loop-Zyklus eine neue Insulinempfindlichkeitseinstellung (ISF). Die neue ISF basiert auf Ihrem aktuellen Blutzucker, der täglichen Gesamtinsulindosis (TDD, alle in den letzten 24 Stunden abgegebenen Insuline) und einem individuellen Anpassungsfaktor (die Empfehlung für den Anfang ist 0,5, wenn Sie die Sigmoid-Funktion verwenden, und 0,8, wenn nicht).\n\nAlle dynamischen ISF- und CR-Anpassungen werden durch Ihre autosens.min/max-Grenzwerte begrenzt."; @@ -2074,10 +2077,10 @@ Enact a temp Basal or a temp target */ "Activate Dynamic Carb Ratio (CR)" = "Dynamisches Carb Ratio (CR) aktivieren"; /* Headline "Adjust Dynamic ISF constant" */ -"Adjust Dynamic ISF constant" = "Dynamic ISF-Konstante anpassen"; +"Adjust Dynamic ISF constant" = "Dynamische ISF-Konstante anpassen"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individuelle Anpassung der berechneten dynamischen Verhältnisse. Die Voreinstellung ist 0,5. Je höher der Wert, desto größer ist die Korrektur Ihres ISF/CR für einen hohen oder niedrigen Blutzuckerwert. Die maximale/minimale Korrektur wird durch die Min/Max-Einstellungen von Autosens bestimmt.\n\nFür die Sigmoid-Funktion wird für den Anfang ein Anpassungsfaktor von 0,4 - 0,5 empfohlen.\n\nFür die logarithmische Formel gibt es weniger Konsens, aber ein Wert von 0,8 ist wahrscheinlich für die meisten erwachsenen Benutzer angemessen. Für jüngere Anwender wird empfohlen, bei der logaritmischen Formel noch niedriger anzusetzen, um eine zu aggressive Behandlung zu vermeiden."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Sigmoid-Funktion verwenden"; @@ -2187,7 +2190,7 @@ Enact a temp Basal or a temp target */ "Show Live activity" = "Live Aktivitäten anzeigen"; /* Live Activity Footer */ -"Live activity displays blood glucose live on the lock screen and on the dynamic island (if available)" = "Die Live-Aktivität zeigt die Blutzucker live auf dem Sperrbildschirm und auf der dynamischen Insel (falls verfügbar)"; +"Live activity displays blood glucose live on the lock screen and on the dynamic island (if available)" = "Live-Aktivität zeigt den Blutzucker live auf dem Sperrbildschirm und auf der dynamischen Insel (falls verfügbar) an"; /* Live Activity Footer when off */ "Live activities are turned OFF in system settings. To enable live activities, go to Settings app -> iAPS -> Turn live Activities ON.\n\n" = "Live-Aktivitäten werden in den Systemeinstellungen AUS aktiviert. Um Live-Aktivitäten zu aktivieren, gehen Sie zu Einstellungen -> iAPS -> Live-Aktivitäten einschalten.\n\n"; diff --git a/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings index 3ad7d73d19..07301ddc02 100644 --- a/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Añadir simulador"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Modelo"; @@ -614,6 +617,7 @@ Enact a temp Basal or a temp target */ /* */ "Unable to change anything" = "Unable to change anything"; + /* Calendar and Libre transmitter settings --------------- */ /* */ diff --git a/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings index aabe297b82..a2e5f2229c 100644 --- a/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Add Simulator"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Model"; diff --git a/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings index 68681405d4..3edbae4fee 100644 --- a/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Ajouter un simulateur"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Modèle"; @@ -2050,7 +2053,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Ajuster la constante du FSI Dynamique"; /* Adjust Dynamic ISF constant */ -"Adjust Dynamic ISF constant" = "Ajuster la constante du FSI Dynamique"; +"Adjust Dynamic ISF constant" = "Ajuster la constante ISF Dynamique"; /* Enable Dynamic ISF, Headline */ "Enable Dynamic ISF" = "Activer le facteur de sensibilité à l'insuline (FSI) dynamique"; diff --git a/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings index a1f2376c0a..64ef7ca9b7 100644 --- a/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Add Simulator"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Model"; diff --git a/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings index 0c8c55d624..307a180bed 100644 --- a/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Szimulátor hozzáadása"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Típus"; diff --git a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings index 92eaf90b4a..e677a888ac 100644 --- a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Aggiungi Simulazione microinfusore"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Modello"; diff --git a/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings index 0a649755a6..ddc3670fc0 100644 --- a/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Legg til Simulator"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Modell"; diff --git a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings index 2010d18134..3bbb74b7ea 100644 --- a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Simulator toevoegen"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Model"; diff --git a/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings index 60cdaddbbd..7b58666ad3 100644 --- a/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings @@ -427,6 +427,9 @@ Połączono z Nightscout!"; /* Add Simulator pump */ "Add Simulator" = "Add Simulator"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Model"; diff --git a/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings index 5262083892..193b025fc3 100644 --- a/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Adicionar Simulador"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Modelo"; diff --git a/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings index 1da1a40fbf..2159921002 100644 --- a/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Adicionar Simulador"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Modelo"; diff --git a/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings index 3028ee4640..d8d671635f 100644 --- a/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Добавить Cимулятор"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Модель"; diff --git a/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings index d48dcc1be8..9ba21173d8 100644 --- a/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Pridať simulátor"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Model"; diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index 117e263219..18520e8e70 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Lägg till simulator"; +/* View/Header when pod expired */ +"Replace" = "Byt!"; + /* Insulin model */ "Model" = "Modell"; diff --git a/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings index d3a315b1b8..a4ef6669f6 100644 --- a/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Simülatör ekle"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "Model"; diff --git a/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings index a3242e732f..2f676e946c 100644 --- a/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Додати Симулятор"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "МОДЕЛЬ"; diff --git a/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings index b52a42f746..14378bb5c3 100644 --- a/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "Thêm Bơm mô phỏng"; +/* View/Header when pod expired */ +"Replace" = "Thay thế"; + /* Insulin model */ "Model" = "Model"; diff --git a/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings index e71a87abe2..c4707379ed 100644 --- a/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings @@ -425,6 +425,9 @@ Enact a temp Basal or a temp target */ /* Add Simulator pump */ "Add Simulator" = "添加模拟器"; +/* View/Header when pod expired */ +"Replace" = "Replace"; + /* Insulin model */ "Model" = "模型"; From eb4d929914c29d4faa2987c6c45eb1574975bae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 6 Mar 2024 03:52:27 +0100 Subject: [PATCH 24/44] Preview of Loop Statistics. Add Loop statistics for today in Home View. Add new Loops / Readings percentage, as this is the most important data for evaluating iAPS app status/health. Added to help the Dana developers. Center align both previews (TIR and Loops). --- FreeAPS.xcodeproj/project.pbxproj | 20 +- .../Sources/APS/Storage/CoreDataStorage.swift | 14 ++ .../Sources/Modules/Home/HomeStateModel.swift | 3 + .../Home/View/Header/Previews/LoopsView.swift | 61 ++++++ .../TIRView.swift} | 202 +++++++++--------- .../Modules/Home/View/HomeRootView.swift | 19 +- .../OverrideProfilesStateModel.swift | 2 +- 7 files changed, 214 insertions(+), 107 deletions(-) create mode 100644 FreeAPS/Sources/Modules/Home/View/Header/Previews/LoopsView.swift rename FreeAPS/Sources/Modules/Home/View/Header/{PreviewView.swift => Previews/TIRView.swift} (53%) diff --git a/FreeAPS.xcodeproj/project.pbxproj b/FreeAPS.xcodeproj/project.pbxproj index 5ccc6f8098..9c732bb210 100644 --- a/FreeAPS.xcodeproj/project.pbxproj +++ b/FreeAPS.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ 193F6CDD2A512C8F001240FD /* Loops.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193F6CDC2A512C8F001240FD /* Loops.swift */; }; 194297512B815938006B8A0B /* OverridesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194297502B815938006B8A0B /* OverridesView.swift */; }; 194C32772B93A9BF0016FB2A /* OverrideShortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194C32762B93A9BF0016FB2A /* OverrideShortcuts.swift */; }; + 194D7E6E2B974F9F007A38C1 /* LoopsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194D7E6D2B974F9F007A38C1 /* LoopsView.swift */; }; 1956FB212AFF79E200C7B4FF /* CoreDataStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1956FB202AFF79E200C7B4FF /* CoreDataStorage.swift */; }; 195D80B42AF6973A00D25097 /* DynamicRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B32AF6973A00D25097 /* DynamicRootView.swift */; }; 195D80B72AF697B800D25097 /* DynamicDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195D80B62AF697B800D25097 /* DynamicDataFlow.swift */; }; @@ -42,7 +43,7 @@ 19A910302A24BF6300C8951B /* StatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A9102F2A24BF6300C8951B /* StatsView.swift */; }; 19A910362A24D6D700C8951B /* Configs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A910352A24D6D700C8951B /* Configs.swift */; }; 19A910382A24EF3200C8951B /* ChartsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A910372A24EF3200C8951B /* ChartsView.swift */; }; - 19AEF4322B1F5A98006FFE8B /* PreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19AEF4312B1F5A98006FFE8B /* PreviewView.swift */; }; + 19AEF4322B1F5A98006FFE8B /* TIRView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19AEF4312B1F5A98006FFE8B /* TIRView.swift */; }; 19B0EF2128F6D66200069496 /* Statistics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B0EF2028F6D66200069496 /* Statistics.swift */; }; 19B60B782B5E7E97002F4F74 /* Threshold.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B60B772B5E7E97002F4F74 /* Threshold.swift */; }; 19D466A329AA2B80004D5F33 /* FPUConfigDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19D466A229AA2B80004D5F33 /* FPUConfigDataFlow.swift */; }; @@ -575,6 +576,7 @@ 193F6CDC2A512C8F001240FD /* Loops.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Loops.swift; sourceTree = ""; }; 194297502B815938006B8A0B /* OverridesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverridesView.swift; sourceTree = ""; }; 194C32762B93A9BF0016FB2A /* OverrideShortcuts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverrideShortcuts.swift; sourceTree = ""; }; + 194D7E6D2B974F9F007A38C1 /* LoopsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopsView.swift; sourceTree = ""; }; 1956FB202AFF79E200C7B4FF /* CoreDataStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataStorage.swift; sourceTree = ""; }; 195D80B32AF6973A00D25097 /* DynamicRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRootView.swift; sourceTree = ""; }; 195D80B62AF697B800D25097 /* DynamicDataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicDataFlow.swift; sourceTree = ""; }; @@ -609,7 +611,7 @@ 19A9102F2A24BF6300C8951B /* StatsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsView.swift; sourceTree = ""; }; 19A910352A24D6D700C8951B /* Configs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configs.swift; sourceTree = ""; }; 19A910372A24EF3200C8951B /* ChartsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartsView.swift; sourceTree = ""; }; - 19AEF4312B1F5A98006FFE8B /* PreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewView.swift; sourceTree = ""; }; + 19AEF4312B1F5A98006FFE8B /* TIRView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TIRView.swift; sourceTree = ""; }; 19B0EF2028F6D66200069496 /* Statistics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Statistics.swift; sourceTree = ""; }; 19B60B772B5E7E97002F4F74 /* Threshold.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Threshold.swift; sourceTree = ""; }; 19C166682756EFBD00ED12E3 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -1128,6 +1130,15 @@ name = "Recovered References"; sourceTree = ""; }; + 194D7E6C2B974EA4007A38C1 /* Previews */ = { + isa = PBXGroup; + children = ( + 19AEF4312B1F5A98006FFE8B /* TIRView.swift */, + 194D7E6D2B974F9F007A38C1 /* LoopsView.swift */, + ); + path = Previews; + sourceTree = ""; + }; 195D80B22AF696EE00D25097 /* Dynamic */ = { isa = PBXGroup; children = ( @@ -1602,7 +1613,7 @@ 383420D525FFE38C002D46C1 /* LoopView.swift */, 38AAF85425FFF846004AF583 /* CurrentGlucoseView.swift */, 38DAB27F260CBB7F00F74C1A /* PumpView.swift */, - 19AEF4312B1F5A98006FFE8B /* PreviewView.swift */, + 194D7E6C2B974EA4007A38C1 /* Previews */, ); path = Header; sourceTree = ""; @@ -2788,6 +2799,7 @@ 3811DEB125C9D88300A708ED /* Keychain.swift in Sources */, 382C133725F13A1E00715CE1 /* InsulinSensitivities.swift in Sources */, 19D466A529AA2BD4004D5F33 /* FPUConfigProvider.swift in Sources */, + 194D7E6E2B974F9F007A38C1 /* LoopsView.swift in Sources */, 383948D625CD4D8900E91849 /* FileStorage.swift in Sources */, 3811DE4125C9D4A100A708ED /* SettingsRootView.swift in Sources */, 38192E04261B82FA0094D973 /* ReachabilityManager.swift in Sources */, @@ -2910,7 +2922,7 @@ CE1856F72ADC4869007E39C7 /* CarbPresetIntentRequest.swift in Sources */, BD2B464E0745FBE7B79913F4 /* NightscoutConfigProvider.swift in Sources */, 9825E5E923F0B8FA80C8C7C7 /* NightscoutConfigStateModel.swift in Sources */, - 19AEF4322B1F5A98006FFE8B /* PreviewView.swift in Sources */, + 19AEF4322B1F5A98006FFE8B /* TIRView.swift in Sources */, 38A43598262E0E4900E80935 /* FetchAnnouncementsManager.swift in Sources */, 642F76A05A4FF530463A9FD0 /* NightscoutConfigRootView.swift in Sources */, BD7DA9AC2AE06EB900601B20 /* BolusCalculatorConfigRootView.swift in Sources */, diff --git a/FreeAPS/Sources/APS/Storage/CoreDataStorage.swift b/FreeAPS/Sources/APS/Storage/CoreDataStorage.swift index bd2da30edf..edfa2f4104 100644 --- a/FreeAPS/Sources/APS/Storage/CoreDataStorage.swift +++ b/FreeAPS/Sources/APS/Storage/CoreDataStorage.swift @@ -20,6 +20,20 @@ final class CoreDataStorage { return fetchGlucose } + func fetchLoopStats(interval: NSDate) -> [LoopStatRecord] { + var fetchLoopStats = [LoopStatRecord]() + coredataContext.performAndWait { + let requestLoopStats = LoopStatRecord.fetchRequest() as NSFetchRequest + let sort = NSSortDescriptor(key: "start", ascending: false) + requestLoopStats.sortDescriptors = [sort] + requestLoopStats.predicate = NSPredicate( + format: "interval > 0 AND start > %@", interval + ) + try? fetchLoopStats = self.coredataContext.fetch(requestLoopStats) + } + return fetchLoopStats + } + func fetchTDD(interval: NSDate) -> [TDD] { var uniqueEvents = [TDD]() coredataContext.performAndWait { diff --git a/FreeAPS/Sources/Modules/Home/HomeStateModel.swift b/FreeAPS/Sources/Modules/Home/HomeStateModel.swift index 72c4499b3c..f54c6c10f9 100644 --- a/FreeAPS/Sources/Modules/Home/HomeStateModel.swift +++ b/FreeAPS/Sources/Modules/Home/HomeStateModel.swift @@ -66,6 +66,7 @@ extension Home { @Published var totalBolus: Decimal = 0 @Published var isStatusPopupPresented: Bool = false @Published var readings: [Readings] = [] + @Published var loopStats: [LoopStatRecord] = [] @Published var standing: Bool = false @Published var preview: Bool = true @Published var useTargetButton: Bool = false @@ -280,6 +281,7 @@ extension Home { self.isManual = self.provider.manualGlucose(hours: self.filteredHours) self.glucose = self.provider.filteredGlucose(hours: self.filteredHours) self.readings = CoreDataStorage().fetchGlucose(interval: DateFilter().today) + self.loopStats = CoreDataStorage().fetchLoopStats(interval: DateFilter().today) self.recentGlucose = self.glucose.last if self.glucose.count >= 2 { self.glucoseDelta = (self.recentGlucose?.glucose ?? 0) - (self.glucose[self.glucose.count - 2].glucose ?? 0) @@ -373,6 +375,7 @@ extension Home { DispatchQueue.main.async { [weak self] in guard let self = self else { return } self.overrideHistory = self.provider.overrideHistory() + self.loopStats = CoreDataStorage().fetchLoopStats(interval: DateFilter().today) } } diff --git a/FreeAPS/Sources/Modules/Home/View/Header/Previews/LoopsView.swift b/FreeAPS/Sources/Modules/Home/View/Header/Previews/LoopsView.swift new file mode 100644 index 0000000000..fa0d99e531 --- /dev/null +++ b/FreeAPS/Sources/Modules/Home/View/Header/Previews/LoopsView.swift @@ -0,0 +1,61 @@ +import Charts +import Foundation +import SwiftUI + +struct LoopsView: View { + @Binding var fetchedReadings: [Readings] + @Binding var fetchedLoops: [LoopStatRecord] + + var body: some View { + VStack { + // Data + let loops = fetchedLoops.compactMap({ each in each.duration }).count + let readings = fetchedReadings.compactMap({ each in each.glucose }).count + let percentage = Double(loops) / Double(readings) * 100 + + Text("Loops / Readings").padding(.bottom, 10).font(.previewHeadline) + + loopChart(percentage: percentage) + + HStack { + Text("Average Interval") + let average = -1 * (DateFilter().today.timeIntervalSinceNow / 60) / + Double(loops) + Text(average.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))) + " min") + }.font(.loopFont) + + HStack { + Text("Readings") + Text("\(fetchedReadings.compactMap({ each in each.glucose }).count)") + }.font(.loopFont) + + HStack { + Text("Loops") + Text("\(fetchedLoops.compactMap({ each in each.duration }).count)") + }.font(.loopFont) + } + .padding(.top, 20) + .padding(.bottom, 15) + .dynamicTypeSize(...DynamicTypeSize.accessibility1) + } + + func loopChart(percentage: Double) -> some View { + VStack { + Chart { + BarMark( + x: .value("LoopPercentage", percentage) + ) + .foregroundStyle( + percentage >= 90 ? Color(.darkGreen) : percentage >= 75 ? .orange : .red + ) + .annotation(position: .overlay) { + Text(percentage.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))) + " %") + .font(.loopFont) + .dynamicTypeSize(...DynamicTypeSize.accessibility1) + } + } + .chartXAxis(.hidden) + .frame(maxWidth: 200, maxHeight: 25) + } + } +} diff --git a/FreeAPS/Sources/Modules/Home/View/Header/PreviewView.swift b/FreeAPS/Sources/Modules/Home/View/Header/Previews/TIRView.swift similarity index 53% rename from FreeAPS/Sources/Modules/Home/View/Header/PreviewView.swift rename to FreeAPS/Sources/Modules/Home/View/Header/Previews/TIRView.swift index 3bfec68903..17215dc5de 100644 --- a/FreeAPS/Sources/Modules/Home/View/Header/PreviewView.swift +++ b/FreeAPS/Sources/Modules/Home/View/Header/Previews/TIRView.swift @@ -7,6 +7,7 @@ struct PreviewChart: View { @Binding var highLimit: Decimal @Environment(\.colorScheme) var colorScheme + @Environment(\.sizeCategory) private var fontSize private var tirFormatter: NumberFormatter { let formatter = NumberFormatter() @@ -102,116 +103,117 @@ struct PreviewChart: View { } } - return HStack { - VStack { - Chart(data) { item in - BarMark( - x: .value("TIR", item.type), - y: .value("Percentage", item.percentage), - width: .fixed(60) - ) - .foregroundStyle(by: .value("Group", item.group)) - .annotation(position: .trailing) { - if item.group == NSLocalizedString("In Range", comment: ""), item.percentage > 0 { - HStack { - if item.percentage < 1 { - Text("< 1%") - } else { - Text((tirFormatter.string(from: item.percentage as NSNumber) ?? "") + "%") - } - Text(item.group) - }.font(.previewNormal) - .padding(.leading, 20) - } else if item.group == NSLocalizedString( - "Low", - comment: "" - ), item.percentage > 0.0 { - HStack { - if item.percentage < 1 { - Text("< 1%") - } else { - Text((tirFormatter.string(from: item.percentage as NSNumber) ?? "") + "%") - } - Text(item.group) - } - .font(.previewSmall) - .padding(.leading, 20) - } else if item.group == NSLocalizedString( - "High", - comment: "" - ), item.percentage > 0 { - HStack { - if item.percentage < 1 { - Text("< 1%") - } else { - Text((tirFormatter.string(from: item.percentage as NSNumber) ?? "") + "%") - } - Text(item.group) - } - .font(.previewSmall) - .padding(.leading, 20) - } else if item.group == NSLocalizedString( - "Very High", - comment: "" - ), item.percentage > 0 { - HStack { - if item.percentage < 1 { - Text("< 1%") - } else { - Text((tirFormatter.string(from: item.percentage as NSNumber) ?? "") + "%") - } - Text(item.group) - } - .offset(x: 0, y: -5) - .font(.previewSmall) - .padding(.leading, 20) - } else if item.group == NSLocalizedString( - "Very Low", - comment: "" - ), item.percentage > 0 { - HStack { - if item.percentage < 1 { - Text("< 1%") - } else { - Text((tirFormatter.string(from: item.percentage as NSNumber) ?? "") + "%") - } - Text(item.group) + return VStack { + Text("Time In Range").padding(.bottom, 10).font(.previewHeadline) + + Chart(data) { item in + BarMark( + x: .value("TIR", item.type), + y: .value("Percentage", item.percentage), + width: .fixed(60) + ) + .foregroundStyle(by: .value("Group", item.group)) + .annotation(position: .trailing) { + if item.group == NSLocalizedString("In Range", comment: ""), item.percentage > 0 { + HStack { + if item.percentage < 1 { + Text("< 1%") + } else { + Text((tirFormatter.string(from: item.percentage as NSNumber) ?? "") + "%") } - .offset(x: 0, y: 5) - .font(.previewSmall) + Text(item.group) + }.font(.previewNormal) .padding(.leading, 20) - } - } - } - .chartForegroundStyleScale([ - NSLocalizedString( + } else if item.group == NSLocalizedString( "Low", comment: "" - ): .red, - NSLocalizedString("In Range", comment: ""): .darkGreen, - NSLocalizedString( + ), item.percentage > 0.0 { + HStack { + if item.percentage < 1 { + Text("< 1%") + } else { + Text((tirFormatter.string(from: item.percentage as NSNumber) ?? "") + "%") + } + Text(item.group) + } + .font(.loopFont) + .padding(.leading, 20) + } else if item.group == NSLocalizedString( "High", comment: "" - ): .yellow, - NSLocalizedString( + ), item.percentage > 0 { + HStack { + if item.percentage < 1 { + Text("< 1%") + } else { + Text((tirFormatter.string(from: item.percentage as NSNumber) ?? "") + "%") + } + Text(item.group) + } + .font(.loopFont) + .padding(.leading, 20) + } else if item.group == NSLocalizedString( "Very High", comment: "" - ): .red, - NSLocalizedString( + ), item.percentage > 0 { + HStack { + if item.percentage < 1 { + Text("< 1%") + } else { + Text((tirFormatter.string(from: item.percentage as NSNumber) ?? "") + "%") + } + Text(item.group) + } + .offset(x: 0, y: -5) + .font(.loopFont) + .padding(.leading, 20) + } else if item.group == NSLocalizedString( "Very Low", comment: "" - ): .darkRed, - "Separator": colorScheme == .dark ? .black : .white - ]) - .chartXAxis(.hidden) - .chartYAxis(.hidden) - .chartLegend(.hidden) - .padding(.bottom, 15) - .frame(maxWidth: UIScreen.main.bounds.width / 5, alignment: .leading) - }.frame(maxHeight: 200) - } - .padding(.top, 20).padding(.leading, 20) - .dynamicTypeSize(...DynamicTypeSize.accessibility1) + ), item.percentage > 0 { + HStack { + if item.percentage < 1 { + Text("< 1%") + } else { + Text((tirFormatter.string(from: item.percentage as NSNumber) ?? "") + "%") + } + Text(item.group) + } + .offset(x: 0, y: 5) + .font(.loopFont) + .padding(.leading, 20) + } + } + } + .chartForegroundStyleScale([ + NSLocalizedString( + "Low", + comment: "" + ): .red, + NSLocalizedString("In Range", comment: ""): .darkGreen, + NSLocalizedString( + "High", + comment: "" + ): .yellow, + NSLocalizedString( + "Very High", + comment: "" + ): .red, + NSLocalizedString( + "Very Low", + comment: "" + ): .darkRed, + "Separator": colorScheme == .dark ? .black : .white + ]) + .chartXAxis(.hidden) + .chartYAxis(.hidden) + .chartLegend(.hidden) + .padding(.bottom, 15) + .frame(maxWidth: UIScreen.main.bounds.width / 5) + .offset(x: fontSize > .extraExtraLarge ? -60 : 0, y: 0) + }.frame(maxHeight: 200) + .padding(.top, 20) + .dynamicTypeSize(...DynamicTypeSize.accessibility1) } private func previewTir() -> [(decimal: Decimal, string: String)] { diff --git a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift index 5df98514df..44badb41a1 100644 --- a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift +++ b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift @@ -461,8 +461,8 @@ extension Home { var preview: some View { addBackground() - .frame(maxWidth: .infinity, minHeight: 170, alignment: .topLeading) - .overlay(alignment: .topLeading) { + .frame(minHeight: 200) + .overlay { PreviewChart(readings: $state.readings, lowLimit: $state.lowGlucose, highLimit: $state.highGlucose) } .clipShape(RoundedRectangle(cornerRadius: 15)) @@ -473,6 +473,20 @@ extension Home { } } + var loopPreview: some View { + addBackground() + .frame(minHeight: 190) + .overlay { + LoopsView(fetchedReadings: $state.readings, fetchedLoops: $state.loopStats) + } + .clipShape(RoundedRectangle(cornerRadius: 15)) + .addShadows() + .padding(.horizontal, 10) + .onTapGesture { + state.showModal(for: .statistics) + } + } + var profileView: some View { HStack(spacing: 0) { if let override = fetchedPercent.first { @@ -589,6 +603,7 @@ extension Home { RaisedRectangle() chart preview.padding(.top, 15) + loopPreview.padding(.top, 15) } } .scrollIndicators(.hidden) diff --git a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift index 78df86370b..4f09bd98e8 100644 --- a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift +++ b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift @@ -189,7 +189,7 @@ extension OverrideProfilesConfig { } // Saves coredataContext.perform { try? self.coredataContext.save() } - + // Uploads new Override to NS ns.uploadOverride(profile.name ?? "", Double(saveOverride.duration ?? 0), saveOverride.date ?? Date()) } From 474a7163d0ac020d42bd5c05fb7a7139ca875622 Mon Sep 17 00:00:00 2001 From: "Jon B.M" Date: Wed, 6 Mar 2024 03:54:50 +0100 Subject: [PATCH 25/44] Bump version --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index 988d84a9f9..7970e9023f 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 3.1.8 +APP_VERSION = 3.1.9 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## From b73530326e53bd28fc07b37c448b822af9869b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 6 Mar 2024 14:27:08 +0100 Subject: [PATCH 26/44] Fix alignment of TIR preview to hopefully fit all translations. Structure the code groups. --- FreeAPS.xcodeproj/project.pbxproj | 2 +- .../Home/View/{Header => }/Previews/LoopsView.swift | 0 .../Home/View/{Header => }/Previews/TIRView.swift | 12 ++++++------ 3 files changed, 7 insertions(+), 7 deletions(-) rename FreeAPS/Sources/Modules/Home/View/{Header => }/Previews/LoopsView.swift (100%) rename FreeAPS/Sources/Modules/Home/View/{Header => }/Previews/TIRView.swift (96%) diff --git a/FreeAPS.xcodeproj/project.pbxproj b/FreeAPS.xcodeproj/project.pbxproj index 9c732bb210..e585487ded 100644 --- a/FreeAPS.xcodeproj/project.pbxproj +++ b/FreeAPS.xcodeproj/project.pbxproj @@ -1397,6 +1397,7 @@ 3811DE2E25C9D49500A708ED /* HomeRootView.swift */, 3833B51E260264AC003021B3 /* Chart */, 3833B51F260264B6003021B3 /* Header */, + 194D7E6C2B974EA4007A38C1 /* Previews */, ); path = View; sourceTree = ""; @@ -1613,7 +1614,6 @@ 383420D525FFE38C002D46C1 /* LoopView.swift */, 38AAF85425FFF846004AF583 /* CurrentGlucoseView.swift */, 38DAB27F260CBB7F00F74C1A /* PumpView.swift */, - 194D7E6C2B974EA4007A38C1 /* Previews */, ); path = Header; sourceTree = ""; diff --git a/FreeAPS/Sources/Modules/Home/View/Header/Previews/LoopsView.swift b/FreeAPS/Sources/Modules/Home/View/Previews/LoopsView.swift similarity index 100% rename from FreeAPS/Sources/Modules/Home/View/Header/Previews/LoopsView.swift rename to FreeAPS/Sources/Modules/Home/View/Previews/LoopsView.swift diff --git a/FreeAPS/Sources/Modules/Home/View/Header/Previews/TIRView.swift b/FreeAPS/Sources/Modules/Home/View/Previews/TIRView.swift similarity index 96% rename from FreeAPS/Sources/Modules/Home/View/Header/Previews/TIRView.swift rename to FreeAPS/Sources/Modules/Home/View/Previews/TIRView.swift index 17215dc5de..9812cadf77 100644 --- a/FreeAPS/Sources/Modules/Home/View/Header/Previews/TIRView.swift +++ b/FreeAPS/Sources/Modules/Home/View/Previews/TIRView.swift @@ -123,7 +123,7 @@ struct PreviewChart: View { } Text(item.group) }.font(.previewNormal) - .padding(.leading, 20) + .padding(.leading, 10) } else if item.group == NSLocalizedString( "Low", comment: "" @@ -137,7 +137,7 @@ struct PreviewChart: View { Text(item.group) } .font(.loopFont) - .padding(.leading, 20) + .padding(.leading, 10) } else if item.group == NSLocalizedString( "High", comment: "" @@ -151,7 +151,7 @@ struct PreviewChart: View { Text(item.group) } .font(.loopFont) - .padding(.leading, 20) + .padding(.leading, 10) } else if item.group == NSLocalizedString( "Very High", comment: "" @@ -166,7 +166,7 @@ struct PreviewChart: View { } .offset(x: 0, y: -5) .font(.loopFont) - .padding(.leading, 20) + .padding(.leading, 10) } else if item.group == NSLocalizedString( "Very Low", comment: "" @@ -181,7 +181,7 @@ struct PreviewChart: View { } .offset(x: 0, y: 5) .font(.loopFont) - .padding(.leading, 20) + .padding(.leading, 10) } } } @@ -210,7 +210,7 @@ struct PreviewChart: View { .chartLegend(.hidden) .padding(.bottom, 15) .frame(maxWidth: UIScreen.main.bounds.width / 5) - .offset(x: fontSize > .extraExtraLarge ? -60 : 0, y: 0) + .offset(x: -UIScreen.main.bounds.width / 5, y: 0) }.frame(maxHeight: 200) .padding(.top, 20) .dynamicTypeSize(...DynamicTypeSize.accessibility1) From 1c1b169d50b52893f2e66a470d288f824833d249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 6 Mar 2024 16:35:08 +0100 Subject: [PATCH 27/44] Battery Optimizations. Only compute once every Loop cycle and cgm reading, not continuously . Avoid eventual division by zero (Swift should already have support for this, but still). --- .../Sources/Modules/Home/HomeStateModel.swift | 29 ++++++++++++++----- .../Modules/Home/View/HomeRootView.swift | 2 +- .../Home/View/Previews/LoopsView.swift | 17 +++++------ 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/FreeAPS/Sources/Modules/Home/HomeStateModel.swift b/FreeAPS/Sources/Modules/Home/HomeStateModel.swift index f54c6c10f9..ef3e92719c 100644 --- a/FreeAPS/Sources/Modules/Home/HomeStateModel.swift +++ b/FreeAPS/Sources/Modules/Home/HomeStateModel.swift @@ -66,7 +66,7 @@ extension Home { @Published var totalBolus: Decimal = 0 @Published var isStatusPopupPresented: Bool = false @Published var readings: [Readings] = [] - @Published var loopStats: [LoopStatRecord] = [] + @Published var loopStatistics: (Int, Int, Double, String) = (0, 0, 0, "") @Published var standing: Bool = false @Published var preview: Bool = true @Published var useTargetButton: Bool = false @@ -91,6 +91,7 @@ extension Home { setupAnnouncements() setupCurrentPumpTimezone() setupOverrideHistory() + setupLoopStats() suggestion = provider.suggestion overrideHistory = provider.overrideHistory() @@ -281,7 +282,6 @@ extension Home { self.isManual = self.provider.manualGlucose(hours: self.filteredHours) self.glucose = self.provider.filteredGlucose(hours: self.filteredHours) self.readings = CoreDataStorage().fetchGlucose(interval: DateFilter().today) - self.loopStats = CoreDataStorage().fetchLoopStats(interval: DateFilter().today) self.recentGlucose = self.glucose.last if self.glucose.count >= 2 { self.glucoseDelta = (self.recentGlucose?.glucose ?? 0) - (self.glucose[self.glucose.count - 2].glucose ?? 0) @@ -375,10 +375,25 @@ extension Home { DispatchQueue.main.async { [weak self] in guard let self = self else { return } self.overrideHistory = self.provider.overrideHistory() - self.loopStats = CoreDataStorage().fetchLoopStats(interval: DateFilter().today) } } + private func setupLoopStats() { + let loopStats = CoreDataStorage().fetchLoopStats(interval: DateFilter().today) + let loops = loopStats.compactMap({ each in each.loopStatus }).count + let readings = CoreDataStorage().fetchGlucose(interval: DateFilter().today).compactMap({ each in each.glucose }) + .count + let percentage = readings != 0 ? (Double(loops) / Double(readings) * 100) : 0 + let average = loops != 0 ? (-1 * (DateFilter().today.timeIntervalSinceNow / 60) / Double(loops)) : + (DateFilter().today.timeIntervalSinceNow / 60) + loopStatistics = ( + loops, + readings, + percentage, + average.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))) + " min" + ) + } + private func setupOverrides() { DispatchQueue.main.async { [weak self] in guard let self = self else { return } @@ -480,13 +495,9 @@ extension Home.StateModel: PumpReservoirObserver, PumpTimeZoneObserver { - /* - func overridesDidUpdate(_: [Override]) { - setupOverrides() - }*/ - func glucoseDidUpdate(_: [BloodGlucose]) { setupGlucose() + setupLoopStats() } func suggestionDidUpdate(_ suggestion: Suggestion) { @@ -494,6 +505,7 @@ extension Home.StateModel: carbsRequired = suggestion.carbsReq setStatusTitle() setupOverrideHistory() + setupLoopStats() } func settingsDidChange(_ settings: FreeAPSSettings) { @@ -546,6 +558,7 @@ extension Home.StateModel: enactedSuggestion = suggestion setStatusTitle() setupOverrideHistory() + setupLoopStats() } func pumpBatteryDidChange(_: Battery) { diff --git a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift index 44badb41a1..6256c69510 100644 --- a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift +++ b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift @@ -477,7 +477,7 @@ extension Home { addBackground() .frame(minHeight: 190) .overlay { - LoopsView(fetchedReadings: $state.readings, fetchedLoops: $state.loopStats) + LoopsView(loopStatistics: $state.loopStatistics) } .clipShape(RoundedRectangle(cornerRadius: 15)) .addShadows() diff --git a/FreeAPS/Sources/Modules/Home/View/Previews/LoopsView.swift b/FreeAPS/Sources/Modules/Home/View/Previews/LoopsView.swift index fa0d99e531..c7c25b131b 100644 --- a/FreeAPS/Sources/Modules/Home/View/Previews/LoopsView.swift +++ b/FreeAPS/Sources/Modules/Home/View/Previews/LoopsView.swift @@ -3,15 +3,14 @@ import Foundation import SwiftUI struct LoopsView: View { - @Binding var fetchedReadings: [Readings] - @Binding var fetchedLoops: [LoopStatRecord] + @Binding var loopStatistics: (Int, Int, Double, String) var body: some View { VStack { // Data - let loops = fetchedLoops.compactMap({ each in each.duration }).count - let readings = fetchedReadings.compactMap({ each in each.glucose }).count - let percentage = Double(loops) / Double(readings) * 100 + let loops = loopStatistics.0 + let readings = loopStatistics.1 + let percentage = loopStatistics.2 Text("Loops / Readings").padding(.bottom, 10).font(.previewHeadline) @@ -19,19 +18,17 @@ struct LoopsView: View { HStack { Text("Average Interval") - let average = -1 * (DateFilter().today.timeIntervalSinceNow / 60) / - Double(loops) - Text(average.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))) + " min") + Text(loopStatistics.3) }.font(.loopFont) HStack { Text("Readings") - Text("\(fetchedReadings.compactMap({ each in each.glucose }).count)") + Text("\(readings)") }.font(.loopFont) HStack { Text("Loops") - Text("\(fetchedLoops.compactMap({ each in each.duration }).count)") + Text("\(loops)") }.font(.loopFont) } .padding(.top, 20) From 23ea19a0b00bd1ea42b4824c754ac77affcee54d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 6 Mar 2024 17:04:28 +0100 Subject: [PATCH 28/44] Localizations --- .../Sources/Localizations/Main/en.lproj/Localizable.strings | 6 ++++++ .../Sources/Localizations/Main/sv.lproj/Localizable.strings | 6 ++++++ FreeAPS/Sources/Modules/Home/View/Previews/LoopsView.swift | 3 ++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index c6dc940b66..a81499ccfa 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -1709,6 +1709,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Average"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Median"; diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index 18520e8e70..0c67b21d05 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -1706,6 +1706,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Medelvärde"; +/* TIR Preview Headline */ +"Time In Range" = "Tid inom intervallet"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Medelintervall"; + /* Median BG */ "Median" = "Medianvärde"; diff --git a/FreeAPS/Sources/Modules/Home/View/Previews/LoopsView.swift b/FreeAPS/Sources/Modules/Home/View/Previews/LoopsView.swift index c7c25b131b..07542bb256 100644 --- a/FreeAPS/Sources/Modules/Home/View/Previews/LoopsView.swift +++ b/FreeAPS/Sources/Modules/Home/View/Previews/LoopsView.swift @@ -12,7 +12,8 @@ struct LoopsView: View { let readings = loopStatistics.1 let percentage = loopStatistics.2 - Text("Loops / Readings").padding(.bottom, 10).font(.previewHeadline) + Text(NSLocalizedString("Loops", comment: "") + " / " + NSLocalizedString("Readings", comment: "")) + .padding(.bottom, 10).font(.previewHeadline) loopChart(percentage: percentage) From 748b9c1269981bc53d49cf98ee0c8093922393ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 6 Mar 2024 21:07:30 +0100 Subject: [PATCH 29/44] Max 100 % --- FreeAPS/Sources/Modules/Home/HomeStateModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FreeAPS/Sources/Modules/Home/HomeStateModel.swift b/FreeAPS/Sources/Modules/Home/HomeStateModel.swift index ef3e92719c..7e5b85dda7 100644 --- a/FreeAPS/Sources/Modules/Home/HomeStateModel.swift +++ b/FreeAPS/Sources/Modules/Home/HomeStateModel.swift @@ -383,7 +383,7 @@ extension Home { let loops = loopStats.compactMap({ each in each.loopStatus }).count let readings = CoreDataStorage().fetchGlucose(interval: DateFilter().today).compactMap({ each in each.glucose }) .count - let percentage = readings != 0 ? (Double(loops) / Double(readings) * 100) : 0 + let percentage = min(readings != 0 ? (Double(loops) / Double(readings) * 100) : 0, 100) let average = loops != 0 ? (-1 * (DateFilter().today.timeIntervalSinceNow / 60) / Double(loops)) : (DateFilter().today.timeIntervalSinceNow / 60) loopStatistics = ( From c5645164aa09aa0c4d02ad52796e376ec7505ae1 Mon Sep 17 00:00:00 2001 From: Joe Moran Date: Thu, 7 Mar 2024 05:15:45 -0800 Subject: [PATCH 30/44] Backport of OmniBLE #113 and OmniKit #27 (fixes Loop issue #2117) (#554) * Backport of OmniBLE #114 and OmniKit #27 (fixes Loop issue #2117) UI fixes and improvements for various pod setup restart situations + Gracefully handle restarts when prime or insert cannula is in progress + Have the view model init funcs test for and handle resume cases + Improved PodPairer to include the pumpManager podCommState var + Fix PodPairer.podIsActivated to properly handle a paired pod + Start with pairAndPrime state when prime has not finalized + Update PairPodViewModelState priming value to use an optional + Rename func & enum names from pair to pairAndPrime for clarity + Improved CannulaInserter to include cannulaInsertionSuccessfullyStarted var * For an in-progress insert cannula compute a wait time on remaining bolus + Fix checkCannulaInsertionFinished() to use checkingInsertion state + Add cannulaInsertionSuccessfullyStarted var to podState + Update PairPodViewModelState priming value to use an optional + Update PumpStatusHighlight to "Finish Setup" while activating a paired pod New resetPerPodPumpManagerState func called when starting/forgetting pod + Reset podAttachmentConfirmed state variable for each new pod + Reset state.acknowledgedTimeOffsetAlert var in case it gets used + Reset all per pod PumpManagerAlerts for each new pod + Use retractAlert func to handle the state.activeAlerts removal + Add comment noting that podCommState.deactivating value is never returned + Add some missing state initializion for simulator in OmniKit jumpStartPod() * Updates to virtually eliminate user retries on pod setup resumes + Have PairAndPrime ViewModel do an automatic retry on error + Have InsertCannula ViewModel do an automatic retry on error + Add resumingPodSetup func to attempt a getStatus and sleep on errors + Added some improved and updated pumpManager comments + Have pumpManager detect pod setup resumes to invoke resumingPodSetup() + Added additional isConnected handling to OmniBLE resumingPodSetup() + Correct & relocate OmniKit insulinType guard as per OmniBLE + Update OmniKit SessionsRunResult variable use to match OmniBLE * Updates to virtually eliminate user retries on pod setup resumes + Have PairAndPrime ViewModel do an automatic retry on error + Have InsertCannula ViewModel do an automatic retry on error + Add resumingPodSetup func to attempt a getStatus and sleep on errors + Added some improved and updated pumpManager comments + Have pumpManager detect pod setup resumes to invoke resumingPodSetup() + Added additional isConnected handling to OmniBLE resumingPodSetup() + Correct & relocate OmniKit insulinType guard as per OmniBLE + Update OmniKit SessionsRunResult variable use to match OmniBLE --- .../PumpManager/OmniBLEPumpManager.swift | 73 ++++++++++-- .../OmniBLE/PumpManager/PodCommsSession.swift | 6 +- .../OmniBLE/PumpManager/PodState.swift | 4 + .../ViewControllers/DashUICoordinator.swift | 16 +-- .../ViewModels/InsertCannulaViewModel.swift | 62 +++++----- .../ViewModels/PairPodViewModel.swift | 70 ++++++++---- .../ViewModels/PodLifeState.swift | 2 +- .../Views/InsertCannulaView.swift | 5 +- .../PumpManager/OmnipodPumpManager.swift | 107 ++++++++++++++---- .../OmniKit/PumpManager/PodCommsSession.swift | 6 +- .../OmniKit/PumpManager/PodState.swift | 4 + .../OmnipodUICoordinator.swift | 14 +-- .../ViewModels/InsertCannulaViewModel.swift | 62 +++++----- .../ViewModels/PairPodViewModel.swift | 68 +++++++---- .../OmniKitUI/ViewModels/PodLifeState.swift | 2 +- .../OmniKitUI/Views/InsertCannulaView.swift | 4 +- 16 files changed, 343 insertions(+), 162 deletions(-) diff --git a/Dependencies/OmniBLE/OmniBLE/PumpManager/OmniBLEPumpManager.swift b/Dependencies/OmniBLE/OmniBLE/PumpManager/OmniBLEPumpManager.swift index 6c7641f8d3..1e9769d3a9 100644 --- a/Dependencies/OmniBLE/OmniBLE/PumpManager/OmniBLEPumpManager.swift +++ b/Dependencies/OmniBLE/OmniBLE/PumpManager/OmniBLEPumpManager.swift @@ -455,7 +455,7 @@ extension OmniBLEPumpManager { } else if !podState.isSetupComplete { return .activating } - return .deactivating + return .deactivating // Can't be reached and thus will never be returned } public var podCommState: PodCommState { @@ -596,7 +596,7 @@ extension OmniBLEPumpManager { switch podCommState(for: state) { case .activating: return PumpStatusHighlight( - localizedMessage: LocalizedString("Finish Pairing", comment: "Status highlight that when pod is activating."), + localizedMessage: LocalizedString("Finish Setup", comment: "Status highlight that when pod is activating."), imageName: "exclamationmark.circle.fill", state: .warning) case .deactivating: @@ -707,6 +707,25 @@ extension OmniBLEPumpManager { } } + // Reset all the per pod state kept in pump manager state which doesn't span pods + fileprivate func resetPerPodPumpManagerState() { + + // Reset any residual per pod slot based pump manager alerts + // (i.e., all but timeOffsetChangeDetected which isn't actually used) + let podAlerts = state.activeAlerts.filter { $0 != .timeOffsetChangeDetected } + for alert in podAlerts { + self.retractAlert(alert: alert) + } + + self.setState { (state) in + // Reset alertsWithPendingAcknowledgment which are all pod slot based + state.alertsWithPendingAcknowledgment = [] + + // Reset other miscellaneous state variables that are actually per pod + state.podAttachmentConfirmed = false + state.acknowledgedTimeOffsetAlert = false + } + } // MARK: - Pod comms @@ -734,13 +753,14 @@ extension OmniBLEPumpManager { self.podComms.forgetPod() + self.resetPerPodPumpManagerState() + if let dosesToStore = state.podState?.dosesToStore { store(doses: dosesToStore, completion: { error in self.setState({ (state) in if error != nil { state.unstoredDoses.append(contentsOf: dosesToStore) } - state.alertsWithPendingAcknowledgment = [] }) self.prepForNewPod() completion() @@ -775,6 +795,8 @@ extension OmniBLEPumpManager { self.podComms.delegate = self self.podComms.messageLogger = self + self.resetPerPodPumpManagerState() + setState({ (state) in state.updatePodStateFromPodComms(podState) state.scheduledExpirationReminderOffset = state.defaultExpirationReminderOffset @@ -856,14 +878,13 @@ extension OmniBLEPumpManager { }) if needsPairing { - - self.log.default("Pairing pod before priming") - guard let insulinType = insulinType else { completion(.failure(.configuration(OmniBLEPumpManagerError.insulinTypeNotConfigured))) return } + self.log.default("Pairing pod before priming") + connectToNewPod(completion: { result in switch result { case .failure(let error): @@ -872,6 +893,9 @@ extension OmniBLEPumpManager { self.podComms.pairAndSetupPod(timeZone: .currentFixed, insulinType: insulinType, messageLogger: self) { (result) in + // Have new podState, reset all the per pod pump manager state + self.resetPerPodPumpManagerState() + // Calls completion primeSession(result) } @@ -882,6 +906,9 @@ extension OmniBLEPumpManager { } else { self.log.default("Pod already paired. Continuing.") + // Resuming the pod setup, try to ensure pod comms will work right away + self.resumingPodSetup() + self.podComms.runSession(withName: "Prime pod") { (result) in // Calls completion primeSession(result) @@ -941,6 +968,10 @@ extension OmniBLEPumpManager { self.podComms.runSession(withName: "Insert cannula") { (result) in switch result { case .success(let session): + if self.state.podState?.setupProgress.cannulaInsertionSuccessfullyStarted == true { + // Resuming the pod setup, try to ensure pod comms will work right away + self.resumingPodSetup() + } do { if self.state.podState?.setupProgress.needsInitialBasalSchedule == true { let scheduleOffset = timeZone.scheduleOffset(forDate: Date()) @@ -991,6 +1022,33 @@ extension OmniBLEPumpManager { #endif } + // Called when resuming a pod setup operation which sometimes can fail on the first pod command in various situations. + // Attempting a getStatus and sleeping a couple of seconds on errors greatly improves the odds for first pod command success. + fileprivate func resumingPodSetup() { + let sleepTime:UInt32 = 2 + + if !isConnected { + self.log.debug("### Pod setup resume pod not connected, sleeping %d seconds", sleepTime) + sleep(sleepTime) + } + + podComms.runSession(withName: "Resuming pod setup") { (result) in + switch result { + case .success(let session): + let status = try? session.getStatus() + if status == nil { + self.log.debug("### Pod setup resume getStatus failed, sleeping %d seconds", sleepTime) + sleep(sleepTime) + } + case .failure(let error): + self.log.debug("### Pod setup resume session failure, sleeping %d seconds: %@", sleepTime, error.localizedDescription) + sleep(sleepTime) + } + } + } + + // MARK: - Pump Commands + public func getPodStatus(completion: ((_ result: PumpManagerResult) -> Void)? = nil) { guard state.hasActivePod else { completion?(.failure(PumpManagerError.configuration(OmniBLEPumpManagerError.noPodPaired))) @@ -1046,9 +1104,6 @@ extension OmniBLEPumpManager { } } - - // MARK: - Pump Commands - public func acknowledgePodAlerts(_ alertsToAcknowledge: AlertSet, completion: @escaping (_ alerts: AlertSet?) -> Void) { guard self.hasActivePod else { completion(nil) diff --git a/Dependencies/OmniBLE/OmniBLE/PumpManager/PodCommsSession.swift b/Dependencies/OmniBLE/OmniBLE/PumpManager/PodCommsSession.swift index 739a9a5104..a3c2e0d0a8 100644 --- a/Dependencies/OmniBLE/OmniBLE/PumpManager/PodCommsSession.swift +++ b/Dependencies/OmniBLE/OmniBLE/PumpManager/PodCommsSession.swift @@ -436,7 +436,6 @@ public class PodCommsSession { public func insertCannula(optionalAlerts: [PodAlert] = [], silent: Bool) throws -> TimeInterval { let cannulaInsertionUnits = Pod.cannulaInsertionUnits + Pod.cannulaInsertionUnitsExtra - let insertionWait: TimeInterval = .seconds(cannulaInsertionUnits / Pod.primeDeliveryRate) guard podState.activatedAt != nil else { throw PodCommsError.noPodPaired @@ -448,7 +447,8 @@ public class PodCommsSession { if status.podProgressStatus == .insertingCannula { podState.setupProgress = .cannulaInserting podState.updateFromStatusResponse(status, at: currentDate) - return insertionWait // Not sure when it started, wait full time to be sure + // return a non-zero wait time based on the bolus not yet delivered + return (status.bolusNotDelivered / Pod.primeDeliveryRate) + 1 } if status.podProgressStatus.readyForDelivery { markSetupProgressCompleted(statusResponse: status) @@ -477,7 +477,7 @@ public class PodCommsSession { podState.updateFromStatusResponse(status2, at: currentDate) podState.setupProgress = .cannulaInserting - return insertionWait + return status2.bolusNotDelivered / Pod.primeDeliveryRate // seconds for the cannula insert bolus to finish } public func checkInsertionCompleted() throws { diff --git a/Dependencies/OmniBLE/OmniBLE/PumpManager/PodState.swift b/Dependencies/OmniBLE/OmniBLE/PumpManager/PodState.swift index 7c55d73890..dc71bde07e 100644 --- a/Dependencies/OmniBLE/OmniBLE/PumpManager/PodState.swift +++ b/Dependencies/OmniBLE/OmniBLE/PumpManager/PodState.swift @@ -42,6 +42,10 @@ public enum SetupProgress: Int { public var needsCannulaInsertion: Bool { return self.rawValue < SetupProgress.completed.rawValue } + + public var cannulaInsertionSuccessfullyStarted: Bool { + return self.rawValue > SetupProgress.startingInsertCannula.rawValue + } } // TODO: Mutating functions aren't guaranteed to synchronize read/write calls. diff --git a/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewControllers/DashUICoordinator.swift b/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewControllers/DashUICoordinator.swift index 7dc5f50352..13c6634858 100644 --- a/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewControllers/DashUICoordinator.swift +++ b/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewControllers/DashUICoordinator.swift @@ -19,7 +19,7 @@ enum DashUIScreen { case expirationReminderSetup case lowReservoirReminderSetup case insulinTypeSelection - case pairPod + case pairAndPrime case insertCannula case confirmAttachment case checkInsertedCannula @@ -38,8 +38,8 @@ enum DashUIScreen { case .lowReservoirReminderSetup: return .insulinTypeSelection case .insulinTypeSelection: - return .pairPod - case .pairPod: + return .pairAndPrime + case .pairAndPrime: return .confirmAttachment case .confirmAttachment: return .insertCannula @@ -54,7 +54,7 @@ enum DashUIScreen { case .uncertaintyRecovered: return nil case .deactivate: - return .pairPod + return .pairAndPrime case .settings: return nil } @@ -171,7 +171,7 @@ class DashUICoordinator: UINavigationController, PumpManagerOnboarding, Completi } let view = OmniBLESettingsView(viewModel: viewModel, supportedInsulinTypes: allowedInsulinTypes) return hostingController(rootView: view) - case .pairPod: + case .pairAndPrime: pumpManagerOnboardingDelegate?.pumpManagerOnboarding(didCreatePumpManager: pumpManager) let viewModel = PairPodViewModel(podPairer: pumpManager) @@ -185,7 +185,7 @@ class DashUICoordinator: UINavigationController, PumpManagerOnboarding, Completi viewModel.didRequestDeactivation = { [weak self] in self?.navigateTo(.deactivate) } - + let view = hostingController(rootView: PairPodView(viewModel: viewModel)) view.navigationItem.title = LocalizedString("Pair Pod", comment: "Title for pod pairing screen") view.navigationItem.backButtonDisplayMode = .generic @@ -350,13 +350,13 @@ class DashUICoordinator: UINavigationController, PumpManagerOnboarding, Completi if pumpManager.podAttachmentConfirmed { return .insertCannula } else { - return .confirmAttachment + return .pairAndPrime // need to finish the priming } } else if !pumpManager.isOnboarded { if !pumpManager.initialConfigurationCompleted { return .firstRunScreen } - return .pairPod + return .pairAndPrime // pair and prime a new pod } else { return .settings } diff --git a/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewModels/InsertCannulaViewModel.swift b/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewModels/InsertCannulaViewModel.swift index 21648b1f4a..733fc36b4f 100644 --- a/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewModels/InsertCannulaViewModel.swift +++ b/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewModels/InsertCannulaViewModel.swift @@ -12,9 +12,14 @@ import LoopKitUI public protocol CannulaInserter { func insertCannula(completion: @escaping (Result) -> ()) func checkCannulaInsertionFinished(completion: @escaping (OmniBLEPumpManagerError?) -> Void) + var cannulaInsertionSuccessfullyStarted: Bool { get } } -extension OmniBLEPumpManager: CannulaInserter { } +extension OmniBLEPumpManager: CannulaInserter { + public var cannulaInsertionSuccessfullyStarted: Bool { + return state.podState?.setupProgress.cannulaInsertionSuccessfullyStarted == true + } +} class InsertCannulaViewModel: ObservableObject, Identifiable { @@ -28,9 +33,9 @@ class InsertCannulaViewModel: ObservableObject, Identifiable { var actionButtonAccessibilityLabel: String { switch self { - case .ready, .startingInsertion: + case .ready: return LocalizedString("Slide Button to insert Cannula", comment: "Insert cannula slider button accessibility label while ready to pair") - case .inserting: + case .inserting, .startingInsertion: return LocalizedString("Inserting. Please wait.", comment: "Insert cannula action button accessibility label while pairing") case .checkingInsertion: return LocalizedString("Checking Insertion", comment: "Insert cannula action button accessibility label checking insertion") @@ -139,25 +144,21 @@ class InsertCannulaViewModel: ObservableObject, Identifiable { var didRequestDeactivation: (() -> Void)? var cannulaInserter: CannulaInserter - + + var autoRetryAttempted: Bool + init(cannulaInserter: CannulaInserter) { self.cannulaInserter = cannulaInserter + self.autoRetryAttempted = false + + // If resuming, don't wait for the button action + if cannulaInserter.cannulaInsertionSuccessfullyStarted { + insertCannula() + } } - -// private func handleEvent(_ event: ActivationStep2Event) { -// switch event { -// case .insertingCannula: -// let finishTime = TimeInterval(Pod.estimatedCannulaInsertionDuration) -// state = .inserting(finishTime: CACurrentMediaTime() + finishTime) -// case .step2Completed: -// state = .finished -// default: -// break -// } -// } - + private func checkCannulaInsertionFinished() { - state = .startingInsertion + state = .checkingInsertion cannulaInserter.checkCannulaInsertionFinished() { (error) in DispatchQueue.main.async { if let error = error { @@ -171,7 +172,7 @@ class InsertCannulaViewModel: ObservableObject, Identifiable { private func insertCannula() { state = .startingInsertion - + cannulaInserter.insertCannula { (result) in DispatchQueue.main.async { switch(result) { @@ -186,17 +187,21 @@ class InsertCannulaViewModel: ObservableObject, Identifiable { self.state = .finished } case .failure(let error): - self.state = .error(error) + if self.autoRetryAttempted { + self.autoRetryAttempted = false // allow for an auto retry on the next user attempt + self.state = .error(error) + } else { + self.autoRetryAttempted = true + let autoRetryPauseTime = TimeInterval(seconds: 3) + print("### insertCannula encountered error \(error.localizedDescription), retrying after \(autoRetryPauseTime) seconds") + DispatchQueue.global(qos: .utility).async { + Thread.sleep(forTimeInterval: autoRetryPauseTime) + + self.insertCannula() + } + } } } - - -// switch status { -// case .error(let error): -// self.state = .error(error) -// case .event(let event): -// self.handleEvent(event) -// } } } @@ -214,7 +219,6 @@ class InsertCannulaViewModel: ObservableObject, Identifiable { insertCannula() } } - } public extension OmniBLEPumpManagerError { diff --git a/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewModels/PairPodViewModel.swift b/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewModels/PairPodViewModel.swift index dc6a4b912b..4e3ec32483 100644 --- a/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewModels/PairPodViewModel.swift +++ b/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewModels/PairPodViewModel.swift @@ -38,7 +38,7 @@ class PairPodViewModel: ObservableObject, Identifiable { enum PairPodViewModelState { case ready case pairing - case priming(finishTime: CFTimeInterval) + case priming(finishTime: CFTimeInterval?) case error(DashPairingError) case finished @@ -84,14 +84,6 @@ class PairPodViewModel: ObservableObject, Identifiable { } var navBarButtonAction: NavBarButtonAction { -// switch self { -// case .error(_, let podCommState): -// if podCommState == .activating { -// return .discard -// } -// default: -// break -// } return .cancel } @@ -118,7 +110,11 @@ class PairPodViewModel: ObservableObject, Identifiable { case .pairing: return .indeterminantProgress case .priming(let finishTime): - return .timedProgress(finishTime: finishTime) + if let finishTime { + return .timedProgress(finishTime: finishTime) + } else { + return .indeterminantProgress + } case .finished: return .completed } @@ -151,9 +147,9 @@ class PairPodViewModel: ObservableObject, Identifiable { @Published var state: PairPodViewModelState = .ready var podIsActivated: Bool { - return false // podPairer.podCommState != .noPod + return podPairer.podCommState != .noPod } - + var backButtonHidden: Bool { if case .pairing = state { return true @@ -172,19 +168,44 @@ class PairPodViewModel: ObservableObject, Identifiable { var podPairer: PodPairer + var autoRetryAttempted: Bool + init(podPairer: PodPairer) { self.podPairer = podPairer + self.autoRetryAttempted = false + + // If resuming, don't wait for the button action + if podPairer.podCommState == .activating { + pairAndPrime() + } } - - private func pair() { - state = .pairing - - podPairer.pair { (status) in + + private func pairAndPrime() { + if podPairer.podCommState == .noPod { + state = .pairing + } else { + // Already paired, so resume with the prime + state = .priming(finishTime: nil) + } + + podPairer.pairAndPrimePod { (status) in DispatchQueue.main.async { switch status { case .failure(let error): - let pairingError = DashPairingError.pumpManagerError(error) - self.state = .error(pairingError) + if self.autoRetryAttempted { + self.autoRetryAttempted = false // allow for an auto retry on the next user attempt + let pairAndPrimeError = DashPairingError.pumpManagerError(error) + self.state = .error(pairAndPrimeError) + } else { + self.autoRetryAttempted = true + let autoRetryPauseTime = TimeInterval(seconds: 3) + print("### pairAndPrimePod encountered error \(error.localizedDescription), retrying after \(autoRetryPauseTime) seconds") + DispatchQueue.global(qos: .utility).async { + Thread.sleep(forTimeInterval: autoRetryPauseTime) + + self.pairAndPrime() // handles both pairing or priming failures + } + } case .success(let duration): if duration > 0 { @@ -207,14 +228,14 @@ class PairPodViewModel: ObservableObject, Identifiable { self.didRequestDeactivation?() } else { // Retry - pair() + pairAndPrime() } case .finished: didFinish?() default: - pair() + pairAndPrime() } - } + } } // Pairing recovery suggestions @@ -245,15 +266,16 @@ enum DashPairingError : LocalizedError { } public protocol PodPairer { - func pair(completion: @escaping (PumpManagerResult) -> Void) + func pairAndPrimePod(completion: @escaping (PumpManagerResult) -> Void) func discardPod(completion: @escaping (Bool) -> ()) + var podCommState: PodCommState { get } } extension OmniBLEPumpManager: PodPairer { public func discardPod(completion: @escaping (Bool) -> ()) { } - public func pair(completion: @escaping (PumpManagerResult) -> Void) { + public func pairAndPrimePod(completion: @escaping (PumpManagerResult) -> Void) { pairAndPrime(completion: completion) } } diff --git a/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewModels/PodLifeState.swift b/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewModels/PodLifeState.swift index 4fce7b928e..d1b082a67b 100644 --- a/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewModels/PodLifeState.swift +++ b/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/ViewModels/PodLifeState.swift @@ -72,7 +72,7 @@ enum PodLifeState { var nextPodLifecycleAction: DashUIScreen { switch self { case .podActivating, .noPod: - return .pairPod + return .pairAndPrime default: return .deactivate } diff --git a/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/Views/InsertCannulaView.swift b/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/Views/InsertCannulaView.swift index b3636434d1..3c7d29efd8 100644 --- a/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/Views/InsertCannulaView.swift +++ b/Dependencies/OmniBLE/OmniBLE/PumpManagerUI/Views/InsertCannulaView.swift @@ -120,10 +120,11 @@ struct InsertCannulaView: View { secondaryButton: .default(FrameworkLocalText("No, Continue With Pod", comment: "Continue pairing button title of in pairing cancel modal")) ) } + } class MockCannulaInserter: CannulaInserter { - public func insertCannula(completion: @escaping (Result) -> Void) { + func insertCannula(completion: @escaping (Result) -> Void) { let mockDelay = TimeInterval(seconds: 3) let result :Result = .success(mockDelay) completion(result) @@ -132,6 +133,8 @@ class MockCannulaInserter: CannulaInserter { func checkCannulaInsertionFinished(completion: @escaping (OmniBLEPumpManagerError?) -> Void) { completion(nil) } + + var cannulaInsertionSuccessfullyStarted: Bool = false } struct InsertCannulaView_Previews: PreviewProvider { diff --git a/Dependencies/OmniKit/OmniKit/PumpManager/OmnipodPumpManager.swift b/Dependencies/OmniKit/OmniKit/PumpManager/OmnipodPumpManager.swift index d0b578fbcb..dbe6f45d4e 100644 --- a/Dependencies/OmniKit/OmniKit/PumpManager/OmnipodPumpManager.swift +++ b/Dependencies/OmniKit/OmniKit/PumpManager/OmnipodPumpManager.swift @@ -320,7 +320,7 @@ extension OmnipodPumpManager { switch podCommState(for: state) { case .activating: return PumpStatusHighlight( - localizedMessage: LocalizedString("Finish Pairing", comment: "Status highlight that when pod is activating."), + localizedMessage: LocalizedString("Finish Setup", comment: "Status highlight that when pod is activating."), imageName: "exclamationmark.circle.fill", state: .warning) case .deactivating: @@ -583,7 +583,7 @@ extension OmnipodPumpManager { } else if !podState.isSetupComplete { return .activating } - return .deactivating + return .deactivating // Can't be reached and thus will never be returned } public var podCommState: PodCommState { @@ -666,6 +666,25 @@ extension OmnipodPumpManager { return date } + // Reset all the per pod state kept in pump manager state which doesn't span pods + fileprivate func resetPerPodPumpManagerState() { + + // Reset any residual per pod slot based pump manager alerts + // (i.e., all but timeOffsetChangeDetected which isn't actually used) + let podAlerts = state.activeAlerts.filter { $0 != .timeOffsetChangeDetected } + for alert in podAlerts { + self.retractAlert(alert: alert) + } + + self.setState { (state) in + // Reset alertsWithPendingAcknowledgment which are all pod slot based + state.alertsWithPendingAcknowledgment = [] + + // Reset other miscellaneous state variables that are actually per pod + state.podAttachmentConfirmed = false + state.acknowledgedTimeOffsetAlert = false + } + } // MARK: - Pod comms @@ -683,6 +702,8 @@ extension OmnipodPumpManager { podComms.forgetPod() + self.resetPerPodPumpManagerState() + if let dosesToStore = self.state.podState?.dosesToStore { self.store(doses: dosesToStore, completion: { error in self.setState({ (state) in @@ -701,7 +722,7 @@ extension OmnipodPumpManager { completion() } } - + // MARK: Testing #if targetEnvironment(simulator) private func jumpStartPod(address: UInt32, lot: UInt32, tid: UInt32, fault: DetailedStatus? = nil, startDate: Date? = nil, mockFault: Bool) { @@ -716,8 +737,14 @@ extension OmnipodPumpManager { podComms = PodComms(podState: podState) + self.podComms.delegate = self + self.podComms.messageLogger = self + + self.resetPerPodPumpManagerState() + setState({ (state) in state.updatePodStateFromPodComms(podState) + state.scheduledExpirationReminderOffset = state.defaultExpirationReminderOffset }) } #endif @@ -727,11 +754,6 @@ extension OmnipodPumpManager { // Called on the main thread public func pairAndPrime(completion: @escaping (PumpManagerResult) -> Void) { - guard let insulinType = insulinType else { - completion(.failure(.configuration(nil))) - return - } - #if targetEnvironment(simulator) // If we're in the simulator, create a mock PodState let mockFaultDuringPairing = false @@ -754,22 +776,22 @@ extension OmnipodPumpManager { let deviceSelector = self.rileyLinkDeviceProvider.firstConnectedDevice let primeSession = { (result: PodComms.SessionRunResult) in switch result { - case .success(let messageSender): + case .success(let session): // We're on the session queue - messageSender.assertOnSessionQueue() + session.assertOnSessionQueue() self.log.default("Beginning pod prime") // Clean up any previously un-stored doses if needed let unstoredDoses = self.state.unstoredDoses - if self.store(doses: unstoredDoses, in: messageSender) { + if self.store(doses: unstoredDoses, in: session) { self.setState({ (state) in state.unstoredDoses.removeAll() }) } do { - let primeFinishedAt = try messageSender.prime() + let primeFinishedAt = try session.prime() completion(.success(primeFinishedAt)) } catch let error { completion(.failure(PumpManagerError.communication(error as? LocalizedError))) @@ -789,9 +811,16 @@ extension OmnipodPumpManager { }) if needsPairing { + guard let insulinType = insulinType else { + completion(.failure(.configuration(OmnipodPumpManagerError.insulinTypeNotConfigured))) + return + } + self.log.default("Pairing pod before priming") - // Create random address with 20 bits to match PDM, could easily use 24 bits instead + // Create random address with 20 bits to match PDM, could easily use 24 bits instead. + // This value is stashed the the OmnipodPumpManagerState as this value cannot vary + // on consecutive Eros pairing attempts to avoid losing the pod in some situations. if self.state.pairingAttemptAddress == nil { self.lockedState.mutate { (state) in state.pairingAttemptAddress = 0x1f000000 | (arc4random() & 0x000fffff) @@ -811,7 +840,10 @@ extension OmnipodPumpManager { state.pairingAttemptAddress = nil } } - + + // Have new podState, reset all the per pod pump manager state + self.resetPerPodPumpManagerState() + // Calls completion primeSession(result) } @@ -819,6 +851,10 @@ extension OmnipodPumpManager { self.log.default("Pod already paired. Continuing.") self.podComms.runSession(withName: "Prime pod", using: deviceSelector) { (result) in + + // Resuming the pod setup, try to ensure pod comms will work right away + self.resumingPodSetup() + // Calls completion primeSession(result) } @@ -877,14 +913,18 @@ extension OmnipodPumpManager { let rileyLinkSelector = self.rileyLinkDeviceProvider.firstConnectedDevice self.podComms.runSession(withName: "Insert cannula", using: rileyLinkSelector) { (result) in switch result { - case .success(let messageSender): + case .success(let session): + if self.state.podState?.setupProgress.cannulaInsertionSuccessfullyStarted == true { + // Resuming the pod setup, try to ensure pod comms will work right away + self.resumingPodSetup() + } do { if self.state.podState?.setupProgress.needsInitialBasalSchedule == true { let scheduleOffset = timeZone.scheduleOffset(forDate: Date()) - try messageSender.programInitialBasalSchedule(self.state.basalSchedule, scheduleOffset: scheduleOffset) + try session.programInitialBasalSchedule(self.state.basalSchedule, scheduleOffset: scheduleOffset) - messageSender.dosesForStorage() { (doses) -> Bool in - return self.store(doses: doses, in: messageSender) + session.dosesForStorage() { (doses) -> Bool in + return self.store(doses: doses, in: session) } } @@ -894,7 +934,7 @@ extension OmnipodPumpManager { .lowReservoir(units: self.state.lowReservoirReminderValue) ] - let finishWait = try messageSender.insertCannula(optionalAlerts: alerts, silent: self.silencePod) + let finishWait = try session.insertCannula(optionalAlerts: alerts, silent: self.silencePod) completion(.success(finishWait)) } catch let error { completion(.failure(.communication(error))) @@ -913,9 +953,9 @@ extension OmnipodPumpManager { let deviceSelector = self.rileyLinkDeviceProvider.firstConnectedDevice self.podComms.runSession(withName: "Check cannula insertion finished", using: deviceSelector) { (result) in switch result { - case .success(let messageSender): + case .success(let session): do { - try messageSender.checkInsertionCompleted() + try session.checkInsertionCompleted() completion(nil) } catch let error { self.log.error("Failed to fetch pod status: %{public}@", String(describing: error)) @@ -929,6 +969,27 @@ extension OmnipodPumpManager { #endif } + // Called when resuming a pod setup operation which sometimes can fail on the first pod command in various situations. + // Attempting a getStatus and sleeping a couple of seconds on errors greatly improves the odds for first pod command success. + fileprivate func resumingPodSetup() { + let sleepTime:UInt32 = 2 + + let rileyLinkSelector = self.rileyLinkDeviceProvider.firstConnectedDevice + podComms.runSession(withName: "Resuming pod setup", using: rileyLinkSelector) { (result) in + switch result { + case .success(let session): + let status = try? session.getStatus() + if status == nil { + self.log.debug("### Pod setup resume getStatus failed, sleeping %d seconds", sleepTime) + sleep(sleepTime) + } + case .failure(let error): + self.log.debug("### Pod setup resume session failure, sleeping %d seconds: %@", sleepTime, error.localizedDescription) + sleep(sleepTime) + } + } + } + // MARK: - Pump Commands public func getPodStatus(completion: ((_ result: PumpManagerResult) -> Void)? = nil) { @@ -1134,9 +1195,9 @@ extension OmnipodPumpManager { let rileyLinkSelector = self.rileyLinkDeviceProvider.firstConnectedDevice self.podComms.runSession(withName: "Deactivate pod", using: rileyLinkSelector) { (result) in switch result { - case .success(let messageSender): + case .success(let session): do { - try messageSender.deactivatePod() + try session.deactivatePod() completion(nil) } catch let error { completion(OmnipodPumpManagerError.communication(error)) diff --git a/Dependencies/OmniKit/OmniKit/PumpManager/PodCommsSession.swift b/Dependencies/OmniKit/OmniKit/PumpManager/PodCommsSession.swift index e1f042e5c8..086834fcbf 100644 --- a/Dependencies/OmniKit/OmniKit/PumpManager/PodCommsSession.swift +++ b/Dependencies/OmniKit/OmniKit/PumpManager/PodCommsSession.swift @@ -441,7 +441,6 @@ public class PodCommsSession { public func insertCannula(optionalAlerts: [PodAlert] = [], silent: Bool) throws -> TimeInterval { let cannulaInsertionUnits = Pod.cannulaInsertionUnits + Pod.cannulaInsertionUnitsExtra - let insertionWait: TimeInterval = .seconds(cannulaInsertionUnits / Pod.primeDeliveryRate) guard podState.activatedAt != nil else { throw PodCommsError.noPodPaired @@ -453,7 +452,8 @@ public class PodCommsSession { if status.podProgressStatus == .insertingCannula { podState.setupProgress = .cannulaInserting podState.updateFromStatusResponse(status, at: currentDate) - return insertionWait // Not sure when it started, wait full time to be sure + // return a non-zero wait time based on the bolus not yet delivered + return (status.bolusNotDelivered / Pod.primeDeliveryRate) + 1 } if status.podProgressStatus.readyForDelivery { markSetupProgressCompleted(statusResponse: status) @@ -482,7 +482,7 @@ public class PodCommsSession { podState.updateFromStatusResponse(status2, at: currentDate) podState.setupProgress = .cannulaInserting - return insertionWait + return status2.bolusNotDelivered / Pod.primeDeliveryRate // seconds for the cannula insert bolus to finish } public func checkInsertionCompleted() throws { diff --git a/Dependencies/OmniKit/OmniKit/PumpManager/PodState.swift b/Dependencies/OmniKit/OmniKit/PumpManager/PodState.swift index 354d1265cf..b330fe1957 100644 --- a/Dependencies/OmniKit/OmniKit/PumpManager/PodState.swift +++ b/Dependencies/OmniKit/OmniKit/PumpManager/PodState.swift @@ -41,6 +41,10 @@ public enum SetupProgress: Int { public var needsCannulaInsertion: Bool { return self.rawValue < SetupProgress.completed.rawValue } + + public var cannulaInsertionSuccessfullyStarted: Bool { + return self.rawValue > SetupProgress.startingInsertCannula.rawValue + } } // TODO: Mutating functions aren't guaranteed to synchronize read/write calls. diff --git a/Dependencies/OmniKit/OmniKitUI/ViewControllers/OmnipodUICoordinator.swift b/Dependencies/OmniKit/OmniKitUI/ViewControllers/OmnipodUICoordinator.swift index 1101e3d933..6e486f3643 100644 --- a/Dependencies/OmniKit/OmniKitUI/ViewControllers/OmnipodUICoordinator.swift +++ b/Dependencies/OmniKit/OmniKitUI/ViewControllers/OmnipodUICoordinator.swift @@ -24,7 +24,7 @@ enum OmnipodUIScreen { case lowReservoirReminderSetup case insulinTypeSelection case rileyLinkSetup - case pairPod + case pairAndPrime case insertCannula case confirmAttachment case checkInsertedCannula @@ -45,8 +45,8 @@ enum OmnipodUIScreen { case .insulinTypeSelection: return .rileyLinkSetup case .rileyLinkSetup: - return .pairPod - case .pairPod: + return .pairAndPrime + case .pairAndPrime: return .confirmAttachment case .confirmAttachment: return .insertCannula @@ -61,7 +61,7 @@ enum OmnipodUIScreen { case .uncertaintyRecovered: return nil case .deactivate: - return .pairPod + return .pairAndPrime case .settings: return nil } @@ -199,7 +199,7 @@ class OmnipodUICoordinator: UINavigationController, PumpManagerOnboarding, Compl let view = OmnipodSettingsView(viewModel: viewModel, rileyLinkListDataSource: rileyLinkListDataSource, handleRileyLinkSelection: handleRileyLinkSelection, supportedInsulinTypes: allowedInsulinTypes) return hostingController(rootView: view) - case .pairPod: + case .pairAndPrime: pumpManagerOnboardingDelegate?.pumpManagerOnboarding(didCreatePumpManager: pumpManager) let viewModel = PairPodViewModel(podPairer: pumpManager) @@ -410,13 +410,13 @@ class OmnipodUICoordinator: UINavigationController, PumpManagerOnboarding, Compl if pumpManager.podAttachmentConfirmed { return .insertCannula } else { - return .confirmAttachment + return .pairAndPrime // need to finish the priming } } else if !pumpManager.isOnboarded { if !pumpManager.initialConfigurationCompleted { return .firstRunScreen } - return .pairPod + return .pairAndPrime // pair and prime a new pod } else { return .settings } diff --git a/Dependencies/OmniKit/OmniKitUI/ViewModels/InsertCannulaViewModel.swift b/Dependencies/OmniKit/OmniKitUI/ViewModels/InsertCannulaViewModel.swift index 029ef7d2bd..ff80f133d9 100644 --- a/Dependencies/OmniKit/OmniKitUI/ViewModels/InsertCannulaViewModel.swift +++ b/Dependencies/OmniKit/OmniKitUI/ViewModels/InsertCannulaViewModel.swift @@ -13,9 +13,14 @@ import OmniKit public protocol CannulaInserter { func insertCannula(completion: @escaping (Result) -> ()) func checkCannulaInsertionFinished(completion: @escaping (OmnipodPumpManagerError?) -> Void) + var cannulaInsertionSuccessfullyStarted: Bool { get } } -extension OmnipodPumpManager: CannulaInserter {} +extension OmnipodPumpManager: CannulaInserter { + public var cannulaInsertionSuccessfullyStarted: Bool { + return state.podState?.setupProgress.cannulaInsertionSuccessfullyStarted == true + } +} class InsertCannulaViewModel: ObservableObject, Identifiable { @@ -29,9 +34,9 @@ class InsertCannulaViewModel: ObservableObject, Identifiable { var actionButtonAccessibilityLabel: String { switch self { - case .ready, .startingInsertion: + case .ready: return LocalizedString("Slide Button to insert Cannula", comment: "Insert cannula slider button accessibility label while ready to pair") - case .inserting: + case .inserting, .startingInsertion: return LocalizedString("Inserting. Please wait.", comment: "Insert cannula action button accessibility label while pairing") case .checkingInsertion: return LocalizedString("Checking Insertion", comment: "Insert cannula action button accessibility label checking insertion") @@ -139,25 +144,21 @@ class InsertCannulaViewModel: ObservableObject, Identifiable { var didRequestDeactivation: (() -> Void)? var cannulaInserter: CannulaInserter - + + var autoRetryAttempted: Bool + init(cannulaInserter: CannulaInserter) { self.cannulaInserter = cannulaInserter + self.autoRetryAttempted = false + + // If resuming, don't wait for the button action + if cannulaInserter.cannulaInsertionSuccessfullyStarted { + insertCannula() + } } - -// private func handleEvent(_ event: ActivationStep2Event) { -// switch event { -// case .insertingCannula: -// let finishTime = TimeInterval(Pod.estimatedCannulaInsertionDuration) -// state = .inserting(finishTime: CACurrentMediaTime() + finishTime) -// case .step2Completed: -// state = .finished -// default: -// break -// } -// } - + private func checkCannulaInsertionFinished() { - state = .startingInsertion + state = .checkingInsertion cannulaInserter.checkCannulaInsertionFinished() { (error) in DispatchQueue.main.async { if let error = error { @@ -171,7 +172,7 @@ class InsertCannulaViewModel: ObservableObject, Identifiable { private func insertCannula() { state = .startingInsertion - + cannulaInserter.insertCannula { (result) in DispatchQueue.main.async { switch(result) { @@ -186,17 +187,21 @@ class InsertCannulaViewModel: ObservableObject, Identifiable { self.state = .finished } case .failure(let error): - self.state = .error(error) + if self.autoRetryAttempted { + self.autoRetryAttempted = false // allow for an auto retry on the next user attempt + self.state = .error(error) + } else { + self.autoRetryAttempted = true + let autoRetryPauseTime = TimeInterval(seconds: 3) + print("### insertCannula encountered error \(error.localizedDescription), retrying after \(autoRetryPauseTime) seconds") + DispatchQueue.global(qos: .utility).async { + Thread.sleep(forTimeInterval: autoRetryPauseTime) + + self.insertCannula() + } + } } } - - -// switch status { -// case .error(let error): -// self.state = .error(error) -// case .event(let event): -// self.handleEvent(event) -// } } } @@ -214,7 +219,6 @@ class InsertCannulaViewModel: ObservableObject, Identifiable { insertCannula() } } - } public extension OmnipodPumpManagerError { diff --git a/Dependencies/OmniKit/OmniKitUI/ViewModels/PairPodViewModel.swift b/Dependencies/OmniKit/OmniKitUI/ViewModels/PairPodViewModel.swift index c7c560b039..45f5dc197d 100644 --- a/Dependencies/OmniKit/OmniKitUI/ViewModels/PairPodViewModel.swift +++ b/Dependencies/OmniKit/OmniKitUI/ViewModels/PairPodViewModel.swift @@ -39,7 +39,7 @@ class PairPodViewModel: ObservableObject, Identifiable { enum PairPodViewModelState { case ready case pairing - case priming(finishTime: CFTimeInterval) + case priming(finishTime: CFTimeInterval?) case error(OmnipodPairingError) case finished @@ -85,14 +85,6 @@ class PairPodViewModel: ObservableObject, Identifiable { } var navBarButtonAction: NavBarButtonAction { -// switch self { -// case .error(_, let podCommState): -// if podCommState == .activating { -// return .discard -// } -// default: -// break -// } return .cancel } @@ -119,7 +111,11 @@ class PairPodViewModel: ObservableObject, Identifiable { case .pairing: return .indeterminantProgress case .priming(let finishTime): - return .timedProgress(finishTime: finishTime) + if let finishTime { + return .timedProgress(finishTime: finishTime) + } else { + return .indeterminantProgress + } case .finished: return .completed } @@ -152,7 +148,7 @@ class PairPodViewModel: ObservableObject, Identifiable { @Published var state: PairPodViewModelState = .ready var podIsActivated: Bool { - return false // podPairer.podCommState != .noPod + return podPairer.podCommState != .noPod } var backButtonHidden: Bool { @@ -173,19 +169,44 @@ class PairPodViewModel: ObservableObject, Identifiable { var podPairer: PodPairer + var autoRetryAttempted: Bool + init(podPairer: PodPairer) { self.podPairer = podPairer + self.autoRetryAttempted = false + + // If resuming, don't wait for the button action + if podPairer.podCommState == .activating { + pairAndPrime() + } } - - private func pair() { - state = .pairing - - podPairer.pair { (status) in + + private func pairAndPrime() { + if podPairer.podCommState == .noPod { + state = .pairing + } else { + // Already paired, so resume with the prime + state = .priming(finishTime: nil) + } + + podPairer.pairAndPrimePod { (status) in DispatchQueue.main.async { switch status { case .failure(let error): - let pairingError = OmnipodPairingError.pumpManagerError(error) - self.state = .error(pairingError) + if self.autoRetryAttempted { + self.autoRetryAttempted = false // allow for an auto retry on the next user attempt + let pairAndPrimeError = OmnipodPairingError.pumpManagerError(error) + self.state = .error(pairAndPrimeError) + } else { + self.autoRetryAttempted = true + let autoRetryPauseTime = TimeInterval(seconds: 3) + print("### pairAndPrimePod encountered error \(error.localizedDescription), retrying after \(autoRetryPauseTime) seconds") + DispatchQueue.global(qos: .utility).async { + Thread.sleep(forTimeInterval: autoRetryPauseTime) + + self.pairAndPrime() // handles both pairing or priming failures + } + } case .success(let duration): if duration > 0 { @@ -208,14 +229,14 @@ class PairPodViewModel: ObservableObject, Identifiable { self.didRequestDeactivation?() } else { // Retry - pair() + pairAndPrime() } case .finished: didFinish?() default: - pair() + pairAndPrime() } - } + } } // Pairing recovery suggestions @@ -246,15 +267,16 @@ enum OmnipodPairingError : LocalizedError { } public protocol PodPairer { - func pair(completion: @escaping (PumpManagerResult) -> Void) + func pairAndPrimePod(completion: @escaping (PumpManagerResult) -> Void) func discardPod(completion: @escaping (Bool) -> ()) + var podCommState: PodCommState { get } } extension OmnipodPumpManager: PodPairer { public func discardPod(completion: @escaping (Bool) -> ()) { } - public func pair(completion: @escaping (PumpManagerResult) -> Void) { + public func pairAndPrimePod(completion: @escaping (PumpManagerResult) -> Void) { pairAndPrime(completion: completion) } } diff --git a/Dependencies/OmniKit/OmniKitUI/ViewModels/PodLifeState.swift b/Dependencies/OmniKit/OmniKitUI/ViewModels/PodLifeState.swift index 76494d1464..340d5b571e 100644 --- a/Dependencies/OmniKit/OmniKitUI/ViewModels/PodLifeState.swift +++ b/Dependencies/OmniKit/OmniKitUI/ViewModels/PodLifeState.swift @@ -72,7 +72,7 @@ enum PodLifeState { var nextPodLifecycleAction: OmnipodUIScreen { switch self { case .podActivating, .noPod: - return .pairPod + return .pairAndPrime default: return .deactivate } diff --git a/Dependencies/OmniKit/OmniKitUI/Views/InsertCannulaView.swift b/Dependencies/OmniKit/OmniKitUI/Views/InsertCannulaView.swift index 37a6e740e6..7d27272210 100644 --- a/Dependencies/OmniKit/OmniKitUI/Views/InsertCannulaView.swift +++ b/Dependencies/OmniKit/OmniKitUI/Views/InsertCannulaView.swift @@ -124,7 +124,7 @@ struct InsertCannulaView: View { } class MockCannulaInserter: CannulaInserter { - public func insertCannula(completion: @escaping (Result) -> Void) { + func insertCannula(completion: @escaping (Result) -> Void) { let mockDelay = TimeInterval(seconds: 3) let result :Result = .success(mockDelay) completion(result) @@ -133,6 +133,8 @@ class MockCannulaInserter: CannulaInserter { func checkCannulaInsertionFinished(completion: @escaping (OmnipodPumpManagerError?) -> Void) { completion(nil) } + + var cannulaInsertionSuccessfullyStarted: Bool = false } struct InsertCannulaView_Previews: PreviewProvider { From cd287280be626a82413aa3b07a836a0b2bb11912 Mon Sep 17 00:00:00 2001 From: "Jon B.M" Date: Thu, 7 Mar 2024 14:26:16 +0100 Subject: [PATCH 31/44] Bump version --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index 7970e9023f..21df7c8792 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 3.1.9 +APP_VERSION = 3.3.0 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## From 7e88768e3334b21a9ca32734c0be9a8e83307731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Fri, 8 Mar 2024 12:44:37 +0100 Subject: [PATCH 32/44] Use same calculation for loops in Loops preview as in loops statistics chart view. --- .../Sources/Modules/Home/HomeStateModel.swift | 10 +++--- .../Sources/Modules/Stat/View/StatsView.swift | 34 ++++++++----------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/FreeAPS/Sources/Modules/Home/HomeStateModel.swift b/FreeAPS/Sources/Modules/Home/HomeStateModel.swift index 7e5b85dda7..124b7ee7fe 100644 --- a/FreeAPS/Sources/Modules/Home/HomeStateModel.swift +++ b/FreeAPS/Sources/Modules/Home/HomeStateModel.swift @@ -381,11 +381,13 @@ extension Home { private func setupLoopStats() { let loopStats = CoreDataStorage().fetchLoopStats(interval: DateFilter().today) let loops = loopStats.compactMap({ each in each.loopStatus }).count - let readings = CoreDataStorage().fetchGlucose(interval: DateFilter().today).compactMap({ each in each.glucose }) - .count + let readings = CoreDataStorage().fetchGlucose(interval: DateFilter().today).compactMap({ each in each.glucose }).count let percentage = min(readings != 0 ? (Double(loops) / Double(readings) * 100) : 0, 100) - let average = loops != 0 ? (-1 * (DateFilter().today.timeIntervalSinceNow / 60) / Double(loops)) : - (DateFilter().today.timeIntervalSinceNow / 60) + // First loop date + let time = (loopStats.last?.start ?? Date.now).addingTimeInterval(-5.minutes.timeInterval) + + let average = -1 * (time.timeIntervalSinceNow / 60) / max(Double(loops), 1) + loopStatistics = ( loops, readings, diff --git a/FreeAPS/Sources/Modules/Stat/View/StatsView.swift b/FreeAPS/Sources/Modules/Stat/View/StatsView.swift index b5f272e412..326e20d5c1 100644 --- a/FreeAPS/Sources/Modules/Stat/View/StatsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/StatsView.swift @@ -34,7 +34,7 @@ struct StatsView: View { ) { _fetchRequest = FetchRequest( sortDescriptors: [NSSortDescriptor(key: "start", ascending: false)], - predicate: NSPredicate(format: "interval > 0 AND start > %@", filter) + predicate: NSPredicate(format: "start > %@", filter) ) _fetchRequestReadings = FetchRequest( @@ -50,32 +50,26 @@ struct StatsView: View { var loops: some View { let loops = fetchRequest - // First date - let previous = loops.last?.end ?? Date() - // Last date (recent) - let current = loops.first?.start ?? Date() - // Total time in days - let totalTime = (current - previous).timeInterval / 8.64E4 - + // First loop date + let previous = (loops.last?.start ?? Date.now).addingTimeInterval(-5.minutes.timeInterval) + // Time in days + let days = -1 * previous.timeIntervalSinceNow / 8.64E4 + // Calculations let durationArray = loops.compactMap({ each in each.duration }) - let durationArrayCount = durationArray.count - // var durationAverage = durationArray.reduce(0, +) / Double(durationArrayCount) let medianDuration = medianCalculationDouble(array: durationArray) let successsNR = loops.compactMap({ each in each.loopStatus }).filter({ each in each!.contains("Success") }).count - let errorNR = durationArrayCount - successsNR - let total = Double(successsNR + errorNR) == 0 ? 1 : Double(successsNR + errorNR) - let successRate: Double? = (Double(successsNR) / total) * 100 - let loopNr = totalTime <= 1 ? total : round(total / (totalTime != 0 ? totalTime : 1)) - let intervalArray = loops.compactMap({ each in each.interval as Double }) - let count = intervalArray.count != 0 ? intervalArray.count : 1 - let intervalAverage = intervalArray.reduce(0, +) / Double(count) - // let maximumInterval = intervalArray.max() - // let minimumInterval = intervalArray.min() + let loopCount = loops.compactMap({ each in each.loopStatus }).count + let successRate: Double? = (Double(successsNR) / max(Double(loopCount), 1)) * 100 + let intervalAverage = -1 * (previous.timeIntervalSinceNow / 60) / max(Double(loopCount), 1) + + // Round + let loopsPerDay = round(Double(loopCount) / max(days, 1)) + return VStack(spacing: 10) { HStack(spacing: 35) { VStack(spacing: 5) { Text("Loops").font(.subheadline).foregroundColor(headline) - Text(loopNr.formatted()) + Text(loopsPerDay.formatted()) } VStack(spacing: 5) { Text("Interval").font(.subheadline).foregroundColor(headline) From 75dcb61ea67d0d307120a87bea56f07bb1bb009b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Fri, 8 Mar 2024 18:41:48 +0100 Subject: [PATCH 33/44] Clarify bolusInProgress error. Refactor display of days of data in statistics View. --- FreeAPS/Sources/APS/APSManager.swift | 8 +++++++- FreeAPS/Sources/Modules/Stat/View/StatsView.swift | 10 +++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/FreeAPS/Sources/APS/APSManager.swift b/FreeAPS/Sources/APS/APSManager.swift index 226cda4351..e17d49a5b9 100644 --- a/FreeAPS/Sources/APS/APSManager.swift +++ b/FreeAPS/Sources/APS/APSManager.swift @@ -37,6 +37,7 @@ protocol APSManager { enum APSError: LocalizedError { case pumpError(Error) case invalidPumpState(message: String) + case bolusInProgress(message: String) case glucoseError(message: String) case apsError(message: String) case deviceSyncError(message: String) @@ -48,6 +49,8 @@ enum APSError: LocalizedError { return "Pump error: \(error.localizedDescription)" case let .invalidPumpState(message): return "Error: Invalid Pump State: \(message)" + case let .bolusInProgress(message): + return "Error: Pump is Busy. \(message)" case let .glucoseError(message): return "Error: Invalid glucose: \(message)" case let .apsError(message): @@ -301,7 +304,10 @@ final class BaseAPSManager: APSManager, Injectable { let status = pump.status.pumpStatus guard !status.bolusing else { - return APSError.invalidPumpState(message: "Pump is bolusing") + return APSError + .bolusInProgress( + message: "Can't enact the new loop cycle recommendation, because a Bolus is in progress. Wait for next loop cycle" + ) } guard !status.suspended else { diff --git a/FreeAPS/Sources/Modules/Stat/View/StatsView.swift b/FreeAPS/Sources/Modules/Stat/View/StatsView.swift index 326e20d5c1..078e919816 100644 --- a/FreeAPS/Sources/Modules/Stat/View/StatsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/StatsView.swift @@ -127,10 +127,8 @@ struct StatsView: View { let glucose = fetchRequestReadings // First date let previous = glucose.last?.date ?? Date() - // Last date (recent) - let current = glucose.first?.date ?? Date() - // Total time in days - let numberOfDays = (current - previous).timeInterval / 8.64E4 + // Days + let numberOfDays = -1 * previous.timeIntervalSinceNow / 8.64E4 let hba1cString = ( useUnit == .mmolL ? hba1cs.ifcc @@ -171,9 +169,7 @@ struct StatsView: View { // First date let previous = glucose.last?.date ?? Date() // Last date (recent) - let current = glucose.first?.date ?? Date() - // Total time in days - let numberOfDays = (current - previous).timeInterval / 8.64E4 + let numberOfDays = -1 * previous.timeIntervalSinceNow / 8.64E4 VStack(spacing: 5) { Text(numberOfDays < 1 ? "Readings" : "Readings / 24h").font(.subheadline) From 3c7b91331b94bf0087a58be6652b4f6cf46dade7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Fri, 8 Mar 2024 18:47:35 +0100 Subject: [PATCH 34/44] Bump version --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index 21df7c8792..42c2970d70 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 3.3.0 +APP_VERSION = 3.3.1 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## From 15e4ccd7da5173667cd2c81040a75db8f95961a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Fri, 8 Mar 2024 20:43:33 +0100 Subject: [PATCH 35/44] New localizable strings. --- .../Localizations/en.lproj/Localizable.strings | 15 +++++++++++++++ .../Resources/en.lproj/Localizable.strings | 12 ++++++++++++ .../Main/en.lproj/Localizable.strings | 8 ++++++++ 3 files changed, 35 insertions(+) diff --git a/Dependencies/OmniBLE/Localizations/en.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/en.lproj/Localizable.strings index ecc6fc321d..eebb4b7cd3 100644 --- a/Dependencies/OmniBLE/Localizations/en.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/en.lproj/Localizable.strings @@ -835,3 +835,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Done"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/en.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/en.lproj/Localizable.strings index a80e3136f9..b1f561685e 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/en.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/en.lproj/Localizable.strings @@ -815,3 +815,15 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index a81499ccfa..23a9863c86 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -1434,6 +1434,14 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Display Protein & Fat"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ From 2a27bbe300ae90fc63e1dc62998f917d83bf01f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Fri, 8 Mar 2024 20:52:22 +0100 Subject: [PATCH 36/44] New localizable strings --- .../Localizations/Main/en.lproj/Localizable.strings | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index 23a9863c86..5d380f2888 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Done"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Wait please"; From b2e7a530581774d2d3e11d3a09ffe07114225b13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Fri, 8 Mar 2024 23:41:16 +0100 Subject: [PATCH 37/44] Update Localizable.strings --- .../Sources/Localizations/Main/en.lproj/Localizable.strings | 3 +++ 1 file changed, 3 insertions(+) diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index 5d380f2888..5640ce77b9 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -1454,6 +1454,9 @@ Enact a temp Basal or a temp target */ /* Display future data table entries */ "Show Future" = "Show Future"; +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ From 6a46a2aaa7bbbf9aafaf0088e9f849452e0d28e8 Mon Sep 17 00:00:00 2001 From: "Jon B.M" Date: Sat, 9 Mar 2024 01:46:16 +0100 Subject: [PATCH 38/44] Refactor Fastfile Remove 19 duplicate strings (!). Use a constant for the Bundle ID: APP_IDENTIFIER --- fastlane/Fastfile | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 275e90f0de..aa3541aaca 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -22,6 +22,7 @@ FASTLANE_KEY = ENV["FASTLANE_KEY"] DEVICE_NAME = ENV["DEVICE_NAME"] DEVICE_ID = ENV["DEVICE_ID"] ENV["FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT"] = "120" +APP_IDENTIFIER = "ru.artpancreas.#{TEAMID}.FreeAPS" platform :ios do desc "Build iAPS" @@ -40,7 +41,7 @@ platform :ios do ) previous_build_number = latest_testflight_build_number( - app_identifier: "ru.artpancreas.#{TEAMID}.FreeAPS", + app_identifier: "#{APP_IDENTIFIER}", api_key: api_key, ) @@ -55,15 +56,15 @@ platform :ios do type: "appstore", git_basic_authorization: Base64.strict_encode64("#{GITHUB_REPOSITORY_OWNER}:#{GH_PAT}"), app_identifier: [ - "ru.artpancreas.#{TEAMID}.FreeAPS", - "ru.artpancreas.#{TEAMID}.FreeAPS.watchkitapp", - "ru.artpancreas.#{TEAMID}.FreeAPS.watchkitapp.watchkitextension", - "ru.artpancreas.#{TEAMID}.FreeAPS.LiveActivity" + "#{APP_IDENTIFIER}", + "#{APP_IDENTIFIER}.watchkitapp", + "#{APP_IDENTIFIER}.watchkitapp.watchkitextension", + "#{APP_IDENTIFIER}.LiveActivity" ] ) previous_build_number = latest_testflight_build_number( - app_identifier: "ru.artpancreas.#{TEAMID}.FreeAPS", + app_identifier: "#{APP_IDENTIFIER}", api_key: api_key, ) @@ -80,27 +81,27 @@ platform :ios do update_code_signing_settings( path: "#{GITHUB_WORKSPACE}/FreeAPS.xcodeproj", - profile_name: mapping["ru.artpancreas.#{TEAMID}.FreeAPS"], + profile_name: mapping["#{APP_IDENTIFIER}"], code_sign_identity: "iPhone Distribution", targets: ["FreeAPS"] ) update_code_signing_settings( path: "#{GITHUB_WORKSPACE}/FreeAPS.xcodeproj", - profile_name: mapping["ru.artpancreas.#{TEAMID}.FreeAPS.watchkitapp.watchkitextension"], + profile_name: mapping["#{APP_IDENTIFIER}.watchkitapp.watchkitextension"], code_sign_identity: "iPhone Distribution", targets: ["FreeAPSWatch WatchKit Extension"] ) update_code_signing_settings( path: "#{GITHUB_WORKSPACE}/FreeAPS.xcodeproj", - profile_name: mapping["ru.artpancreas.#{TEAMID}.FreeAPS.watchkitapp"], + profile_name: mapping["#{APP_IDENTIFIER}.watchkitapp"], code_sign_identity: "iPhone Distribution", targets: ["FreeAPSWatch"] ) update_code_signing_settings( path: "#{GITHUB_WORKSPACE}/FreeAPS.xcodeproj", - profile_name: mapping["ru.artpancreas.#{TEAMID}.FreeAPS.LiveActivity"], + profile_name: mapping["#{APP_IDENTIFIER}.LiveActivity"], code_sign_identity: "iPhone Distribution", targets: ["LiveActivityExtension"] ) @@ -155,22 +156,22 @@ platform :ios do } end - configure_bundle_id("FreeAPS", "ru.artpancreas.#{TEAMID}.FreeAPS", [ + configure_bundle_id("FreeAPS", "#{APP_IDENTIFIER}", [ Spaceship::ConnectAPI::BundleIdCapability::Type::APP_GROUPS, Spaceship::ConnectAPI::BundleIdCapability::Type::HEALTHKIT, Spaceship::ConnectAPI::BundleIdCapability::Type::NFC_TAG_READING ]) - configure_bundle_id("FreeAPSWatch WatchKit Extension", "ru.artpancreas.#{TEAMID}.FreeAPS.watchkitapp.watchkitextension", [ + configure_bundle_id("FreeAPSWatch WatchKit Extension", "#{APP_IDENTIFIER}.watchkitapp.watchkitextension", [ Spaceship::ConnectAPI::BundleIdCapability::Type::APP_GROUPS, Spaceship::ConnectAPI::BundleIdCapability::Type::HEALTHKIT ]) - configure_bundle_id("FreeAPSWatch", "ru.artpancreas.#{TEAMID}.FreeAPS.watchkitapp", [ + configure_bundle_id("FreeAPSWatch", "#{APP_IDENTIFIER}.watchkitapp", [ Spaceship::ConnectAPI::BundleIdCapability::Type::APP_GROUPS ]) - configure_bundle_id("LiveActivityExtension", "ru.artpancreas.#{TEAMID}.FreeAPS.LiveActivity", [ + configure_bundle_id("LiveActivityExtension", "#{APP_IDENTIFIER}.LiveActivity", [ Spaceship::ConnectAPI::BundleIdCapability::Type::APP_GROUPS ]) @@ -192,10 +193,10 @@ platform :ios do force: true, git_basic_authorization: Base64.strict_encode64("#{GITHUB_REPOSITORY_OWNER}:#{GH_PAT}"), app_identifier: [ - "ru.artpancreas.#{TEAMID}.FreeAPS", - "ru.artpancreas.#{TEAMID}.FreeAPS.watchkitapp.watchkitextension", - "ru.artpancreas.#{TEAMID}.FreeAPS.watchkitapp", - "ru.artpancreas.#{TEAMID}.FreeAPS.LiveActivity" + "#{APP_IDENTIFIER}", + "#{APP_IDENTIFIER}.watchkitapp.watchkitextension", + "#{APP_IDENTIFIER}.watchkitapp", + "#{APP_IDENTIFIER}.LiveActivity" ] ) end @@ -215,7 +216,7 @@ platform :ios do bundle_id = Spaceship::ConnectAPI::BundleId.find(identifier) end - find_bundle_id("ru.artpancreas.#{TEAMID}.FreeAPS") + find_bundle_id("#{APP_IDENTIFIER}") match( type: "appstore", From da9c1b7727a652c0eadf120c54a319373385dd30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Sat, 9 Mar 2024 14:40:39 +0100 Subject: [PATCH 39/44] Crowdin (#574) Swedish and Vietnamese --- .../es.lproj/Localizable.strings | 2 +- .../G7SensorKit/es.lproj/Localizable.strings | 2 +- .../ar.lproj/Localizable.strings | 15 + .../da.lproj/Localizable.strings | 21 +- .../de.lproj/Localizable.strings | 17 +- .../es.lproj/Localizable.strings | 37 ++- .../fi.lproj/Localizable.strings | 15 + .../fr.lproj/Localizable.strings | 19 +- .../he.lproj/Localizable.strings | 15 + .../hu.lproj/Localizable.strings | 15 + .../it.lproj/Localizable.strings | 15 + .../nb.lproj/Localizable.strings | 15 + .../nl.lproj/Localizable.strings | 19 +- .../pl.lproj/Localizable.strings | 15 + .../pt-BR.lproj/Localizable.strings | 15 + .../pt-PT.lproj/Localizable.strings | 15 + .../ru.lproj/Localizable.strings | 15 + .../sk.lproj/Localizable.strings | 15 + .../sv.lproj/Localizable.strings | 15 + .../tr.lproj/Localizable.strings | 15 + .../uk.lproj/Localizable.strings | 17 +- .../vi.lproj/Localizable.strings | 17 +- .../zh-Hans.lproj/Localizable.strings | 21 +- .../Resources/ar.lproj/Localizable.strings | 12 + .../Resources/da.lproj/Localizable.strings | 12 + .../Resources/de.lproj/Localizable.strings | 12 + .../Resources/es.lproj/Localizable.strings | 12 + .../Resources/fi.lproj/Localizable.strings | 12 + .../Resources/fr.lproj/Localizable.strings | 16 +- .../Resources/he.lproj/Localizable.strings | 12 + .../Resources/hu.lproj/Localizable.strings | 12 + .../Resources/it.lproj/Localizable.strings | 12 + .../Resources/nb.lproj/Localizable.strings | 12 + .../Resources/nl.lproj/Localizable.strings | 12 + .../Resources/pl.lproj/Localizable.strings | 12 + .../Resources/pt-BR.lproj/Localizable.strings | 12 + .../Resources/pt-PT.lproj/Localizable.strings | 12 + .../Resources/ru.lproj/Localizable.strings | 12 + .../Resources/sk.lproj/Localizable.strings | 12 + .../Resources/sv.lproj/Localizable.strings | 12 + .../Resources/tr.lproj/Localizable.strings | 12 + .../Resources/uk.lproj/Localizable.strings | 12 + .../Resources/vi.lproj/Localizable.strings | 12 + .../zh-Hans.lproj/Localizable.strings | 12 + .../Main/ar.lproj/Localizable.strings | 29 ++ .../Main/da.lproj/Localizable.strings | 29 ++ .../Main/de.lproj/Localizable.strings | 31 +- .../Main/es.lproj/Localizable.strings | 298 ++++++++++-------- .../Main/fi.lproj/Localizable.strings | 29 ++ .../Main/fr.lproj/Localizable.strings | 61 +++- .../Main/he.lproj/Localizable.strings | 29 ++ .../Main/hu.lproj/Localizable.strings | 29 ++ .../Main/it.lproj/Localizable.strings | 29 ++ .../Main/nb.lproj/Localizable.strings | 29 ++ .../Main/nl.lproj/Localizable.strings | 31 +- .../Main/pl.lproj/Localizable.strings | 29 ++ .../Main/pt-BR.lproj/Localizable.strings | 29 ++ .../Main/pt-PT.lproj/Localizable.strings | 29 ++ .../Main/ru.lproj/Localizable.strings | 29 ++ .../Main/sk.lproj/Localizable.strings | 29 ++ .../Main/sv.lproj/Localizable.strings | 23 ++ .../Main/tr.lproj/Localizable.strings | 29 ++ .../Main/uk.lproj/Localizable.strings | 31 +- .../Main/vi.lproj/Localizable.strings | 29 ++ .../Main/zh-Hans.lproj/Localizable.strings | 29 ++ 65 files changed, 1352 insertions(+), 181 deletions(-) diff --git a/Dependencies/G7SensorKit/G7SensorKitUI/es.lproj/Localizable.strings b/Dependencies/G7SensorKit/G7SensorKitUI/es.lproj/Localizable.strings index 5f2c696e3a..9632d7d041 100644 --- a/Dependencies/G7SensorKit/G7SensorKitUI/es.lproj/Localizable.strings +++ b/Dependencies/G7SensorKit/G7SensorKitUI/es.lproj/Localizable.strings @@ -26,7 +26,7 @@ "Continue" = "Continuar"; /* Button label for removing CGM */ -"Delete CGM" = "Delete CGM"; +"Delete CGM" = "Eliminar MCG"; /* Navigation bar title for G7SettingsView Title on WelcomeView */ diff --git a/Dependencies/G7SensorKit/es.lproj/Localizable.strings b/Dependencies/G7SensorKit/es.lproj/Localizable.strings index 2372e386d3..894cda96c2 100644 --- a/Dependencies/G7SensorKit/es.lproj/Localizable.strings +++ b/Dependencies/G7SensorKit/es.lproj/Localizable.strings @@ -76,7 +76,7 @@ "Scan for new sensor" = "Scan for new sensor"; /* Button label for removing CGM */ -"Delete CGM" = "Delete CGM"; +"Delete CGM" = "Eliminar MCG"; /* No glucose value representation (3 dashes for mg/dL) */ "– – –" = "– – –"; diff --git a/Dependencies/OmniBLE/Localizations/ar.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/ar.lproj/Localizable.strings index 0f30a43591..12fae7f3ed 100644 --- a/Dependencies/OmniBLE/Localizations/ar.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/ar.lproj/Localizable.strings @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Done"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/da.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/da.lproj/Localizable.strings index 3952235a6a..ced13a1782 100644 --- a/Dependencies/OmniBLE/Localizations/da.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/da.lproj/Localizable.strings @@ -571,7 +571,7 @@ "This is a reminder that you scheduled when you paired your current Pod." = "Dette er en påmindelse om, at du planlagde, hvornår du parrede din nuværende Pod."; /* */ -"Scheduled Reminder" = "Scheduled Reminder"; +"Scheduled Reminder" = "Planlagt Påmindelse"; /* Footer text for low reservoir value row */ "The App notifies you when the amount of insulin in the Pod reaches this level." = "Appen giver dig besked, når mængden af insulin i Pod'en når dette niveau."; @@ -588,7 +588,7 @@ "Time" = "Tid"; /* Value text for no expiration reminder */ -"No Reminder" = "No Reminder"; +"No Reminder" = "Ingen Påmindelse"; /* Label for low reservoir reminder row */ "Low Reservoir Reminder" = "Påmindelse om lavt reservoir"; @@ -718,7 +718,7 @@ "The App notifies you when the amount of insulin in the Pod reaches this level (50-10 U).\n\nScroll to set the number of units at which you would like to be reminded." = "Appen giver dig besked, når mængden af insulin i Pod'en når dette niveau (50-10 E)\n\nIndstil antallet enheder, du vil bruge som påmindelse."; /* Label text for low reservoir value row */ -"Low Reservoir" = "Lavt Reservoir"; +"Low Reservoir" = "Low Reservoir"; /* */ "Save" = "Gem"; @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "OK"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/de.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/de.lproj/Localizable.strings index 74f3ad9e61..8002b68443 100644 --- a/Dependencies/OmniBLE/Localizations/de.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/de.lproj/Localizable.strings @@ -493,7 +493,7 @@ "Wait until insertion is completed." = "Warten Sie, bis die Einführung abgeschlossen ist."; /* Label text for step one of insert cannula instructions */ -"Slide the switch below to start cannula insertion." = "Schieben Sie den Schalter unten, um mit dem Einfügen von Kanülen zu beginnen."; +"Slide the switch below to start cannula insertion." = "Verschieben Sie den Schalter unten, um mit der Kanüleneinfügen zu beginnen."; /* Label text indicating insertion finished. */ "Inserted" = "Eingeführt"; @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Pod-Status ablesen"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Fertig"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings index 319f7028b2..0babcad144 100644 --- a/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings @@ -75,10 +75,10 @@ "Pod Activated" = "Pod Activated"; /* */ -"Notification Settings" = "Notification Settings"; +"Notification Settings" = "Configuración de las notificaciones"; /* */ -"Confidence Reminders" = "Confidence Reminders"; +"Confidence Reminders" = "Recordatorios de confianza"; /* Text for suspend resume button when insulin delivery active */ "Suspend Insulin Delivery" = "Suspend Insulin Delivery"; @@ -93,7 +93,7 @@ "No Pod" = "No Pod"; /* Settings page link description when next lifecycle action is to pair new pod */ -"Pair Pod" = "Pair Pod"; +"Pair Pod" = "Emparejar Pod"; /* Pairing action button accessibility label while ready to pair */ "Pair pod." = "Pair pod."; @@ -240,7 +240,7 @@ "Signal Loss" = "Signal Loss"; /* Status highlight when manual temp basal is running. */ -"Manual Basal" = "Manual Basal"; +"Manual Basal" = "Basal temporal manual"; /* */ "Insert Cannula" = "Insertar Cánula"; @@ -475,7 +475,7 @@ "Continue" = "Continuar"; /* */ -"Attach Pod" = "Attach Pod"; +"Attach Pod" = "Adherir Pod"; /* Alert title for confirm pod attachment */ "Confirm Pod Attachment" = "Confirm Pod Attachment"; @@ -520,7 +520,7 @@ "Priming..." = "Priming..."; /* */ -"Deactivating..." = "Deactivating..."; +"Deactivating..." = "Desactivando..."; /* Pod state when pod has been deactivated */ "Deactivated" = "Deactivated"; @@ -582,7 +582,7 @@ /* Description text for critical alerts */ "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; /* navigation title for notification settings */ -"Notification Settings" = "Notification Settings"; +"Notification Settings" = "Configuración de las notificaciones"; /* Label for scheduled reminder value row */ "Time" = "Tiempo"; @@ -599,16 +599,16 @@ "Change Pod now. Insulin delivery will stop in %1$@ or when no more insulin remains." = "Change Pod now. Insulin delivery will stop in %1$@ or when no more insulin remains."; /* Title string for BeepPreference.silent */ -"Disabled" = "Disabled"; +"Disabled" = "Desactivado"; /* Title string for BeepPreference.manualCommands */ "Enabled" = "Habilitado"; /* Title string for BeepPreference.extended */ -"Extended" = "Extended"; +"Extended" = "Extendido"; /* Description for BeepPreference.silent */ -"No confidence reminders are used." = "No confidence reminders are used."; +"No confidence reminders are used." = "No se utilizan recordatorios de confianza."; /* Description for BeepPreference.manualCommands */ "Confidence reminders will sound for commands you initiate, like bolus, cancel bolus, suspend, resume, save notification reminders, etc. When the app automatically adjusts delivery, no confidence reminders are used." = "Confidence reminders will sound for commands you initiate, like bolus, cancel bolus, suspend, resume, save notification reminders, etc. When the app automatically adjusts delivery, no confidence reminders are used."; @@ -652,7 +652,7 @@ "Expiration Reminder Default" = "Expiration Reminder Default"; /* Text for previous pod information row */ -"Previous Pod Information" = "Previous Pod Information"; +"Previous Pod Information" = "Información del Pod anterior"; /* Text shown in insulin remaining space when no pod is paired (Please keep the '\n' while translating!) */ "No\nDelivery" = "No\nDelivery"; @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Hecho"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/fi.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/fi.lproj/Localizable.strings index dd72854034..a0dcac2815 100644 --- a/Dependencies/OmniBLE/Localizations/fi.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/fi.lproj/Localizable.strings @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Valmis"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/fr.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/fr.lproj/Localizable.strings index 25bd63b4fe..ea1dc5176d 100644 --- a/Dependencies/OmniBLE/Localizations/fr.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/fr.lproj/Localizable.strings @@ -442,7 +442,7 @@ "Fill a new pod with U-100 Insulin (leave blue Pod needle cap on)." = "Remplissez une nouvelle cartouche avec de l'insuline U-100 (laissez le capuchon bleu sur le pod)."; /* Label text for step 1 of pair pod instructions */ -"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Remove the Pod's blue needle cap and check cannula. Then remove paper backing."; +"Remove the Pod's blue needle cap and check cannula. Then remove paper backing." = "Retirez le bouchon d'aiguille bleu du pod et vérifiez la canule. Retirez ensuite le support en papier."; /* Label text for step 2 of pair pod instructions */ "Listen for 2 beeps." = "Écoutez deux bips."; @@ -493,7 +493,7 @@ "Wait until insertion is completed." = "Attendez que l'insertion soit terminée."; /* Label text for step one of insert cannula instructions */ -"Slide the switch below to start cannula insertion." = "Slide the switch below to start cannula insertion."; +"Slide the switch below to start cannula insertion." = "Glissez le bouton ci-dessous pour démarrer l'insertion de la canule."; /* Label text indicating insertion finished. */ "Inserted" = "Inséré"; @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Lire l’état de la pompe"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Terminé"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Diagnostics du pod"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Lire le temps d'activation"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Lire les alertes déclenchées"; diff --git a/Dependencies/OmniBLE/Localizations/he.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/he.lproj/Localizable.strings index 0f30a43591..12fae7f3ed 100644 --- a/Dependencies/OmniBLE/Localizations/he.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/he.lproj/Localizable.strings @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Done"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/hu.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/hu.lproj/Localizable.strings index f7d770d78c..657f3602a8 100644 --- a/Dependencies/OmniBLE/Localizations/hu.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/hu.lproj/Localizable.strings @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Kész"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/it.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/it.lproj/Localizable.strings index b86b78b414..901f56e282 100644 --- a/Dependencies/OmniBLE/Localizations/it.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/it.lproj/Localizable.strings @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Leggi stato microinfusore"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Fine"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/nb.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/nb.lproj/Localizable.strings index 998ff46ebf..215e1a45b9 100644 --- a/Dependencies/OmniBLE/Localizations/nb.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/nb.lproj/Localizable.strings @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Les Pod-status"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Ferdig"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/nl.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/nl.lproj/Localizable.strings index 9c15f8104f..ee85e14b3f 100644 --- a/Dependencies/OmniBLE/Localizations/nl.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/nl.lproj/Localizable.strings @@ -682,7 +682,7 @@ "Pod Activated" = "Pod geactiveerd"; /* description label for active time pod details row */ -"Active Time" = "Activatie tijd"; +"Active Time" = "Actieve duur"; /* description label for last status date pod details row */ "Last Status" = "Laatste status"; @@ -718,7 +718,7 @@ "The App notifies you when the amount of insulin in the Pod reaches this level (50-10 U).\n\nScroll to set the number of units at which you would like to be reminded." = "iAPS geeft een melding als de hoeveelheid insuline in de Pod dit niveau bereikt (50-10 E).\n\nScroll om in te stellen bij welk aantal eenheden je wilt worden herinnerd."; /* Label text for low reservoir value row */ -"Low Reservoir" = "Reservoir bijna leeg"; +"Low Reservoir" = "Laag reservoir niveau"; /* */ "Save" = "Opslaan"; @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Lees pompstatus"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "OK"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/pl.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/pl.lproj/Localizable.strings index 5e75acc908..5ccfa9e4a5 100644 --- a/Dependencies/OmniBLE/Localizations/pl.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/pl.lproj/Localizable.strings @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Done"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/pt-BR.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/pt-BR.lproj/Localizable.strings index 56dea73cba..63c341e3ad 100644 --- a/Dependencies/OmniBLE/Localizations/pt-BR.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/pt-BR.lproj/Localizable.strings @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "OK"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/pt-PT.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/pt-PT.lproj/Localizable.strings index 9e8f1a98a3..6e6e68ec94 100644 --- a/Dependencies/OmniBLE/Localizations/pt-PT.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/pt-PT.lproj/Localizable.strings @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "OK"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/ru.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/ru.lproj/Localizable.strings index 73292c094b..abc2c4f650 100644 --- a/Dependencies/OmniBLE/Localizations/ru.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/ru.lproj/Localizable.strings @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Получить статус Пода"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Готово"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/sk.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/sk.lproj/Localizable.strings index 86f00bc053..6c53076062 100644 --- a/Dependencies/OmniBLE/Localizations/sk.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/sk.lproj/Localizable.strings @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Zistiť stav Podu"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Hotovo"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/sv.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/sv.lproj/Localizable.strings index 1f3880fd91..50dd52beeb 100644 --- a/Dependencies/OmniBLE/Localizations/sv.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/sv.lproj/Localizable.strings @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Läd poddstatus"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Klar"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Poddiagnostik"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Läs pulslogg plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Läs aktiveringstid"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Läs utlösta varningar"; diff --git a/Dependencies/OmniBLE/Localizations/tr.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/tr.lproj/Localizable.strings index 0b4864c333..150bcf9bb8 100644 --- a/Dependencies/OmniBLE/Localizations/tr.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/tr.lproj/Localizable.strings @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Tamam"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniBLE/Localizations/uk.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/uk.lproj/Localizable.strings index a2cf90837b..d16d7d3d6a 100644 --- a/Dependencies/OmniBLE/Localizations/uk.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/uk.lproj/Localizable.strings @@ -582,7 +582,7 @@ /* Description text for critical alerts */ "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "Нагадування вище не звучатимуть, якщо ваш пристрій перебуває в беззвучному режимі або режимі «Не турбувати».\n\nІснують інші важливі сповіщення та будильники Podʼу, які лунатимуть, навіть якщо на пристрої встановлено режим «Без звуку» або «Не турбувати»."; /* navigation title for notification settings */ -"Notification Settings" = "Параметри Сповіщень"; +"Notification Settings" = "Параметри сповіщень"; /* Label for scheduled reminder value row */ "Time" = "Час"; @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Отримати статус Pod'у"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Готово"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Діагностика Pod'у"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Читати Журнал Подій"; + +/* Text for read activation time title */ +"Read Activation Time" = "Прочитайте час активації"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Читайте Тригерні Сповіщення"; diff --git a/Dependencies/OmniBLE/Localizations/vi.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/vi.lproj/Localizable.strings index 89f649d4cd..1323043ea0 100644 --- a/Dependencies/OmniBLE/Localizations/vi.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/vi.lproj/Localizable.strings @@ -697,7 +697,7 @@ "You will now begin the process of configuring your reminders, filling your Pod with insulin, pairing to your device and placing it on your body." = "Bạn bắt đầu quá trình cài đặt các lời nhắc, đổ đầy thuốc vào pod, ghép đôi thiết bị và gắn pod lên người."; /* Cancel button title */ -"Cancel" = "Bỏ qua"; +"Cancel" = "Hủy"; /* Text for continue button on PodSetupView */ "Continue" = "Tiếp tục"; @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Đọc tình trạng pod"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "Xong"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Chẩn đoán Pod"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Đọc thời gian kích hoạt"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Đọc cảnh báo được kích hoạt"; diff --git a/Dependencies/OmniBLE/Localizations/zh-Hans.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/zh-Hans.lproj/Localizable.strings index da4bfaabe7..b001f71493 100644 --- a/Dependencies/OmniBLE/Localizations/zh-Hans.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/zh-Hans.lproj/Localizable.strings @@ -571,7 +571,7 @@ "This is a reminder that you scheduled when you paired your current Pod." = "This is a reminder that you scheduled when you paired your current Pod."; /* */ -"Scheduled Reminder" = "Scheduled Reminder"; +"Scheduled Reminder" = "预约提醒"; /* Footer text for low reservoir value row */ "The App notifies you when the amount of insulin in the Pod reaches this level." = "The App notifies you when the amount of insulin in the Pod reaches this level."; @@ -588,7 +588,7 @@ "Time" = "时间"; /* Value text for no expiration reminder */ -"No Reminder" = "No Reminder"; +"No Reminder" = "无提醒"; /* Label for low reservoir reminder row */ "Low Reservoir Reminder" = "Low Reservoir Reminder"; @@ -718,7 +718,7 @@ "The App notifies you when the amount of insulin in the Pod reaches this level (50-10 U).\n\nScroll to set the number of units at which you would like to be reminded." = "The App notifies you when the amount of insulin in the Pod reaches this level (50-10 U).\n\nScroll to set the number of units at which you would like to be reminded."; /* Label text for low reservoir value row */ -"Low Reservoir" = "低药量"; +"Low Reservoir" = "Low Reservoir"; /* */ "Save" = "保存​​"; @@ -829,3 +829,18 @@ /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title of done button on OmnipodSettingsView */ +"Done" = "完成"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/ar.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/ar.lproj/Localizable.strings index 147f3748f1..2ddc8246bf 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/ar.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/ar.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Silence Pod"; /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/da.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/da.lproj/Localizable.strings index 84d63a6985..f763189490 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/da.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/da.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Silence Pod"; /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/de.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/de.lproj/Localizable.strings index 6356abd2d9..013744198d 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/de.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/de.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Stille Pod"; /* Text for read pod status navigation link */ "Read Pod Status" = "Pod-Status ablesen"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/es.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/es.lproj/Localizable.strings index e5712e4a0c..2e1e0324ed 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/es.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/es.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Silence Pod"; /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/fi.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/fi.lproj/Localizable.strings index 586d92eced..00b8ca1f3c 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/fi.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/fi.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Silence Pod"; /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/fr.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/fr.lproj/Localizable.strings index d179be1a32..cc35561753 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/fr.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/fr.lproj/Localizable.strings @@ -193,7 +193,7 @@ "Slide to Deactivate Pod" = "Glisser pour désactiver le Pod"; /* Label text for step one of insert cannula instructions */ -"Slide the switch below to start cannula insertion." = "Slide the switch below to start cannula insertion."; +"Slide the switch below to start cannula insertion." = "Glissez le bouton ci-dessous pour démarrer l'insertion de la canule."; /* Label text showing pod is deactivated */ "Deactivated" = "Désactivé"; @@ -285,7 +285,7 @@ "Fault" = "Erreur"; /* Label text for step 1 of pair pod instructions */ -"Fill a new pod with U-100 Insulin (leave clear Pod needle cap on). Listen for 2 beeps." = "Fill a new pod with U-100 Insulin (leave clear Pod needle cap on). Listen for 2 beeps."; +"Fill a new pod with U-100 Insulin (leave clear Pod needle cap on). Listen for 2 beeps." = "Remplissez un nouveau pod avec de l'insuline U-100 (laissez le capuchon transparent sur le pod). Attendez d'entendre 2 bips."; /* Settings page link description when next lifecycle action is to finish deactivation */ "Finish deactivation" = "Terminer la désactivation"; @@ -814,3 +814,15 @@ Silence Pod" = "Pod silencieux"; /* Text for read pod status navigation link */ "Read Pod Status" = "Lire l’état de la pompe"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Diagnostics du pod"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Lire le temps d'activation"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Lire les alertes déclenchées"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/he.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/he.lproj/Localizable.strings index 72e9c910d0..7203c0e472 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/he.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/he.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Silence Pod"; /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/hu.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/hu.lproj/Localizable.strings index 1b5c0b8463..edf20b28fd 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/hu.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/hu.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Silence Pod"; /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/it.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/it.lproj/Localizable.strings index 2968f98312..225c5fcc4c 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/it.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/it.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Pod Silenziato"; /* Text for read pod status navigation link */ "Read Pod Status" = "Leggi stato microinfusore"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/nb.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/nb.lproj/Localizable.strings index d6898a4b17..c926aa4d93 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/nb.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/nb.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Stillemodus"; /* Text for read pod status navigation link */ "Read Pod Status" = "Les Pod-status"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/nl.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/nl.lproj/Localizable.strings index 43a8fb43b4..f3e167ed1f 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/nl.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/nl.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Gedempt"; /* Text for read pod status navigation link */ "Read Pod Status" = "Lees pompstatus"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/pl.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/pl.lproj/Localizable.strings index 4b2fbeb602..6f5dfe68eb 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/pl.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/pl.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Silence Pod"; /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/pt-BR.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/pt-BR.lproj/Localizable.strings index 54d785d3ad..4203360b94 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/pt-BR.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/pt-BR.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Silence Pod"; /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/pt-PT.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/pt-PT.lproj/Localizable.strings index b2357348ca..efad293992 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/pt-PT.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/pt-PT.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Silence Pod"; /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/ru.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/ru.lproj/Localizable.strings index 847aaf1dcd..701d00ef32 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/ru.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/ru.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Беззвучный Под"; /* Text for read pod status navigation link */ "Read Pod Status" = "Получить статус Пода"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/sk.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/sk.lproj/Localizable.strings index 23df402336..a89c60a98f 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/sk.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/sk.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Umlčané"; /* Text for read pod status navigation link */ "Read Pod Status" = "Zistiť stav Podu"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/sv.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/sv.lproj/Localizable.strings index b303fe3ed2..c6ebb8edb8 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/sv.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/sv.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Tysta podden"; /* Text for read pod status navigation link */ "Read Pod Status" = "Läd poddstatus"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Poddiagnostik"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Läs pulslogg plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Läs aktiveringstid"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Läs utlösta varningar"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/tr.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/tr.lproj/Localizable.strings index 2b0865b40e..d0d84050ff 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/tr.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/tr.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Silence Pod"; /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/uk.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/uk.lproj/Localizable.strings index 03d58e64a7..e5f0bc3c7a 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/uk.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/uk.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Silence Pod"; /* Text for read pod status navigation link */ "Read Pod Status" = "Отримати статус Pod'у"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Діагностика Pod'у"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Читати Журнал Подій"; + +/* Text for read activation time title */ +"Read Activation Time" = "Прочитайте час активації"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Читайте Тригерні Сповіщення"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/vi.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/vi.lproj/Localizable.strings index 94c2972acb..8198c589bb 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/vi.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/vi.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Pod im lặng"; /* Text for read pod status navigation link */ "Read Pod Status" = "Đọc tình trạng pod"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Chẩn đoán Pod"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Đọc thời gian kích hoạt"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Đọc cảnh báo được kích hoạt"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/zh-Hans.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/zh-Hans.lproj/Localizable.strings index 415c345980..6b2db039a9 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/zh-Hans.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/zh-Hans.lproj/Localizable.strings @@ -814,3 +814,15 @@ Silence Pod" = "Silence Pod"; /* Text for read pod status navigation link */ "Read Pod Status" = "Read Pod Status"; + +/* Title for the pod diagnostic view */ +"Pod Diagnostics" = "Pod Diagnostics"; + +/* Text for read pulse log plus title */ +"Read Pulse Log Plus" = "Read Pulse Log Plus"; + +/* Text for read activation time title */ +"Read Activation Time" = "Read Activation Time"; + +/* Text for read triggered alerts title */ +"Read Triggered Alerts" = "Read Triggered Alerts"; diff --git a/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings index 64ef7ca9b7..11ae120310 100644 --- a/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Done"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Wait please"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Display Protein & Fat"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Average"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Median"; diff --git a/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings index 160b197b2a..bd470bc095 100644 --- a/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "OK"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Vent venligst"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Display Protein & Fat"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Average"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Median"; diff --git a/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings index 77facf1e99..1411c90286 100644 --- a/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Fertig"; +/* Calender Option */ +"Display Emojis as Labels" = "Emojis als Etiketten benutzen"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Bitte warten"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Zeige Eiweiß & Fett"; + +/* Time of new meal entry */ +"Now" = "Jetzt"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Mittelwert"; +/* TIR Preview Headline */ +"Time In Range" = "Zeit im Zielbereich"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Durchschnittliches Zeitintervall"; + /* Median BG */ "Median" = "Median"; @@ -2190,7 +2219,7 @@ Enact a temp Basal or a temp target */ "Show Live activity" = "Live Aktivitäten anzeigen"; /* Live Activity Footer */ -"Live activity displays blood glucose live on the lock screen and on the dynamic island (if available)" = "Live-Aktivität zeigt den Blutzucker live auf dem Sperrbildschirm und auf der dynamischen Insel (falls verfügbar) an"; +"Live activity displays blood glucose live on the lock screen and on the dynamic island (if available)" = "Live-Aktivität zeigt den Blutzucker live auf dem Sperrbildschirm und auf der dynamischen Insel an (falls verfügbar)"; /* Live Activity Footer when off */ "Live activities are turned OFF in system settings. To enable live activities, go to Settings app -> iAPS -> Turn live Activities ON.\n\n" = "Live-Aktivitäten werden in den Systemeinstellungen AUS aktiviert. Um Live-Aktivitäten zu aktivieren, gehen Sie zu Einstellungen -> iAPS -> Live-Aktivitäten einschalten.\n\n"; diff --git a/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings index 07301ddc02..2c33b4450f 100644 --- a/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Hecho"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Espere por favor"; @@ -315,7 +327,7 @@ Enact a temp Basal or a temp target */ "Enact" = "Ejecutar"; /* Start a temp target or a profile override */ -"Start" = "Start"; +"Start" = "Iniciar"; /* */ "Manual Temp Basal" = "Basal temporal manual"; @@ -411,10 +423,10 @@ Enact a temp Basal or a temp target */ "\nMismatching glucose units in Nightscout and Pump Settings. Import settings aborted." = "Las unidades de glucosa de Nightscout y la bomba no coinciden. Ajustes de importación cancelados."; /* Import Error */ -"Can't find the default Nightscout Profile." = "Can't find the default Nightscout Profile."; +"Can't find the default Nightscout Profile." = "No se puede encontrar el perfil de Nightscout por defecto."; /* Add Blood Glucose Test, header */ -"Blood Glucose Test" = "Blood Glucose Test"; +"Blood Glucose Test" = "Prueba de glucosa en sangre"; /* Add Medtronic pump */ "Add Medtronic" = "Añadir Medtronic"; @@ -426,7 +438,7 @@ Enact a temp Basal or a temp target */ "Add Simulator" = "Añadir simulador"; /* View/Header when pod expired */ -"Replace" = "Replace"; +"Replace" = "Sustituir"; /* Insulin model */ "Model" = "Modelo"; @@ -450,7 +462,7 @@ Enact a temp Basal or a temp target */ "Max Bolus" = "Bolo máximo"; /* Max setting */ -"Max Carbs" = "Max Carbs"; +"Max Carbs" = "Carbohidratos máximos"; /* */ "Pump Settings" = "Configuración de la bomba"; @@ -510,40 +522,40 @@ Enact a temp Basal or a temp target */ "Pump" = "Bomba"; /* */ -"Watch" = "Watch"; +"Watch" = "Ver"; /* */ -"Watch Configuration" = "Watch Configuration"; +"Watch Configuration" = "Configuración del reloj"; /* */ "Apple Watch" = "Apple Watch"; /* */ -"Display on Watch" = "Display on Watch"; +"Display on Watch" = "Mostrar en reloj"; /* */ -"Garmin Watch" = "Garmin Watch"; +"Garmin Watch" = "Reloj de Garmin"; /* */ -"Add devices" = "Add devices"; +"Add devices" = "Añadir dispositivo"; /* */ -"Glucose Target" = "Glucose Target"; +"Glucose Target" = "Objetivo de glucosa"; /* */ -"Heart Rate" = "Heart Rate"; +"Heart Rate" = "Ritmo cardíaco"; /* */ -"Steps" = "Steps"; +"Steps" = "Pasos"; /* */ -"ISF" = "ISF"; +"ISF" = "ISF (Factor Sensibilidad Insulina)"; /* */ -"The app Garmin Connect must be installed to use for iAPS.\n Go to App Store to download it" = "The app Garmin Connect must be installed to use for iAPS.\n Go to App Store to download it"; +"The app Garmin Connect must be installed to use for iAPS.\n Go to App Store to download it" = "La aplicación Garmin Connect debe estar instalada para usar con iAPS.\n Vaya a la App Store para descargarla"; /* */ -"Garmin is not available" = "Garmin is not available"; +"Garmin is not available" = "Garmin no está disponible"; /* */ "Services" = "Servicios"; @@ -552,7 +564,7 @@ Enact a temp Basal or a temp target */ "Settings" = "Ajustes"; /* Recommendation for a Manual Bolus */ -"Recommended Bolus Percentage" = "Recommended Bolus Percentage"; +"Recommended Bolus Percentage" = "Porcentaje de Bolo Recomendado"; /* 2 log files to share */ "Share logs" = "Compartir registros"; @@ -576,10 +588,10 @@ Enact a temp Basal or a temp target */ "History" = "Historial"; /* Nightscout option */ -"Upload" = "Upload"; +"Upload" = "Cargar"; /* Nightscout option */ -"Allow Uploads" = "Allow Uploads"; +"Allow Uploads" = "Permitir subida de datos"; /* Type of CGM or glucose source */ "Type" = "Tipo"; @@ -594,19 +606,19 @@ Enact a temp Basal or a temp target */ "Other" = "Otro"; /* Whatch app alert */ -"Set temp targets presets on iPhone first" = "Set temp targets presets on iPhone first"; +"Set temp targets presets on iPhone first" = "Establecer primero los objetivos temporales en el iPhone"; /* Updating Watch app */ -"Updating..." = "Updating..."; +"Updating..." = "Actualizando..."; /* Header for Temp targets in Watch app */ -"Temp Targets" = "Temp Targets"; +"Temp Targets" = "Objetivos temporales"; /* Delete carbs from data table and Nightscout */ -"Delete Carbs?" = "Delete Carbs?"; +"Delete Carbs?" = "¿Eliminar carbohidratos?"; /* Delete insulin from pump history and Nightscout */ -"Delete Insulin?" = "Delete Insulin?"; +"Delete Insulin?" = "¿Eliminar insulina?"; /* Treatments list */ "Treatments" = "Tratamientos"; @@ -615,7 +627,7 @@ Enact a temp Basal or a temp target */ " min" = " min"; /* */ -"Unable to change anything" = "Unable to change anything"; +"Unable to change anything" = "No se pudo cambiar nada"; /* Calendar and Libre transmitter settings --------------- @@ -627,25 +639,25 @@ Enact a temp Basal or a temp target */ "Calibrations" = "Calibraciones"; /* */ -"Create Events in Calendar" = "Create Events in Calendar"; +"Create Events in Calendar" = "Crear eventos en el calendario"; /* */ "Calendar" = "Calendario"; /* Automatic delivered treatments */ -"Automatic" = "Automatic"; +"Automatic" = "Automático"; /* External insulin treatments */ -"External" = "External"; +"External" = "Externo"; /* */ "Other" = "Otro"; /* */ -"Libre Transmitter" = "Libre Transmitter"; +"Libre Transmitter" = "Transmisor Libre"; /* */ -"Libre Transmitters" = "Libre Transmitters"; +"Libre Transmitters" = "Transmisores Libre"; /* */ "Bluetooth Transmitters" = "Transmisores Bluetooth"; @@ -660,7 +672,7 @@ Enact a temp Basal or a temp target */ "Select the third party transmitter you want to connect to" = "Seleccione el transmisor de terceros al que desea conectarse"; /* State was restored */ -"State was restored" = "State was restored"; +"State was restored" = "Conexión restablecida"; /* The short unit display string for millimoles of glucose per liter */ "mmol/L" = "mmol/L"; @@ -672,16 +684,16 @@ Enact a temp Basal or a temp target */ "Add calibration" = "Añadir calibración"; /* When adding capillary glucose meater reading */ -"Meter glucose" = "Meter glucose"; +"Meter glucose" = "Glucosa del medidor"; /* */ "Info" = "Info"; /*v*/ -"Slope" = "Slope"; +"Slope" = "Pendiente"; /* */ -"Intercept" = "Intercept"; +"Intercept" = "Interceptar"; /* */ "Chart" = "Gráfica"; @@ -696,13 +708,14 @@ Enact a temp Basal or a temp target */ "Remove All" = "Eliminar todos"; /* */ -"About the Process" = "About the Process"; +"About the Process" = "Acerca del proceso"; /* */ -"Please make sure that your Libre 2 sensor is already activated and finished warming up. If you have other apps connecting to the sensor via bluetooth, these need to be shut down or uninstalled. \n\n You can only have one app communicating with the sensor via bluetooth. Then press the \"pariring and connection\" button below to start the process. Please note that the bluetooth connection might take up to a couple of minutes before it starts working." = "Please make sure that your Libre 2 sensor is already activated and finished warming up. If you have other apps connecting to the sensor via bluetooth, these need to be shut down or uninstalled. \n\n You can only have one app communicating with the sensor via bluetooth. Then press the \"pariring and connection\" button below to start the process. Please note that the bluetooth connection might take up to a couple of minutes before it starts working."; +"Please make sure that your Libre 2 sensor is already activated and finished warming up. If you have other apps connecting to the sensor via bluetooth, these need to be shut down or uninstalled. \n\n You can only have one app communicating with the sensor via bluetooth. Then press the \"pariring and connection\" button below to start the process. Please note that the bluetooth connection might take up to a couple of minutes before it starts working." = "Por favor asegúrate de que el sensor Libre 2 ya ha terminado de calentar y está activo. Si tienes otras apps conectadas al sensor vía bluetooth, necesitas revocar el permiso de las mismas. +Solamente puedes emparejar una app con el sensor vía bluetooth. A continuación, pulsa el botón más abajo de \"Enlazado y conexión\" para empezar el proceso. Ten en cuenta que la conexión puede tardar hasta unos minutos antes de funcionar correctamente."; /* */ -"Pairinginfo" = "Pairinginfo"; +"Pairinginfo" = "Info de enlazado"; /* */ "PatchInfo" = "Info del parche"; @@ -870,94 +883,94 @@ Enact a temp Basal or a temp target */ "Factory Calibration Parameters" = "Parámetros de calibración de fábrica"; /* */ -"Valid for footer" = "Valid for footer"; +"Valid for footer" = "Válido para pie de página"; /* */ -"Edit calibrations" = "Edit calibrations"; +"Edit calibrations" = "Editar calibraciones"; /* */ -"edit calibration clicked" = "edit calibration clicked"; +"edit calibration clicked" = "Editar calibración seleccionada"; /* */ -"Delete CGM" = "Delete CGM"; +"Delete CGM" = "Eliminar MCG"; /* */ -"Are you sure you want to remove this cgm from loop?" = "Are you sure you want to remove this cgm from loop?"; +"Are you sure you want to remove this cgm from loop?" = "¿Estás seguro de que deseas eliminar esta MCG del lazo cerrado?"; /* */ -"There is no undo" = "There is no undo"; +"There is no undo" = "No se puede deshacer"; /* */ -"Advanced" = "Advanced"; +"Advanced" = "Avanzado"; /* */ "Alarms" = "Alarmas"; /* */ -"Glucose Settings" = "Glucose Settings"; +"Glucose Settings" = "Ajustes de glucosa"; /* */ -"Notifications" = "Notifications"; +"Notifications" = "Notificaciones"; /* */ -"Export logs" = "Export logs"; +"Export logs" = "Exportar registros"; /* */ -"Export not available" = "Export not available"; +"Export not available" = "Exportación no disponible"; /* */ -"Log export requires ios 15" = "Log export requires ios 15"; +"Log export requires ios 15" = "Exportar registros requiere iOS 15"; /* */ -"Got it!" = "Got it!"; +"Got it!" = "¡Entendido!"; /* */ -"Saved to %@" = "Saved to %@"; +"Saved to %@" = "Guardado en %@"; /* */ -"No logs available" = "No logs available"; +"No logs available" = "No hay registros disponibles"; /* */ -"Glucose Notification visibility" = "Glucose Notification visibility"; +"Glucose Notification visibility" = "Valor de glucosa en sangre en notificaciones"; /* */ -"Always Notify Glucose" = "Always Notify Glucose"; +"Always Notify Glucose" = "Notificar siempre la glucosa"; /* */ -"Notify per reading" = "Notify per reading"; +"Notify per reading" = "Notificar por lectura"; /* */ -"Value" = "Value"; +"Value" = "Valor"; /* */ -"Adds Phone Battery" = "Adds Phone Battery"; +"Adds Phone Battery" = "Añade batería del teléfono"; /* */ -"Adds Transmitter Battery" = "Adds Transmitter Battery"; +"Adds Transmitter Battery" = "Añade batería del transmisor"; /* */ -"Also vibrate" = "Also vibrate"; +"Also vibrate" = "Vibrar también"; /* */ -"Additional notification types" = "Additional notification types"; +"Additional notification types" = "Tipos de notificación adicionales"; /* */ -"Misc" = "Misc"; +"Misc" = "Varios"; /* */ -"Unit override" = "Unit override"; +"Unit override" = "Sobreescribir unidad"; /* */ -"Low" = "Low"; +"Low" = "Bajo"; /* */ -"High" = "High"; +"High" = "Alto"; /* */ -"glucose" = "glucose"; +"glucose" = "glucosa"; /* */ -"Schedule " = "Schedule "; +"Schedule " = "Programa "; /* */ "tapped save schedules" = "tapped save schedules"; @@ -966,61 +979,61 @@ Enact a temp Basal or a temp target */ "Error" = "Error"; /* */ -"Some ui element was incorrectly specified" = "Some ui element was incorrectly specified"; +"Some ui element was incorrectly specified" = "Se especificó incorrectamente algún elemento de la interfaz"; /* */ -"Success" = "Success"; +"Success" = "Completado"; /* */ -"Schedules were saved successfully!" = "Schedules were saved successfully!"; +"Schedules were saved successfully!" = "¡Los cambios se han guardado correctamente!"; /* */ -"High Glucose Alarm active" = "High Glucose Alarm active"; +"High Glucose Alarm active" = "Alarma de glucosa alta activa"; /* */ -"Low Glucose Alarm active" = "Low Glucose Alarm active"; +"Low Glucose Alarm active" = "Alarma de glucosa baja activa"; /* */ -"No Glucose Alarm active" = "No Glucose Alarm active"; +"No Glucose Alarm active" = "No hay alarma de glucosa activa"; /* */ -"snoozing until %@" = "snoozing until %@"; +"snoozing until %@" = "posponer hasta %@"; /* */ -"not snoozing" = "not snoozing"; +"not snoozing" = "no posponer"; /* */ -"nothing to see here" = "nothing to see here"; +"nothing to see here" = "nada para ver aquí"; /* */ -"snooze from testview clicked" = "snooze from testview clicked"; +"snooze from testview clicked" = "posponer desde pulsación de la vista de prueba"; /* */ -"will snooze for %@ until %@" = "will snooze for %@ until %@"; +"will snooze for %@ until %@" = "se pospondrá por %@ hasta %@"; /* */ -"Click to Snooze Alerts" = "Click to Snooze Alerts"; +"Click to Snooze Alerts" = "Pulsar para posponer alertas"; /* */ -"Strength" = "Strength"; +"Strength" = "Potencia"; /* */ -"Hold the top of your iPhone near the sensor to pair" = "Hold the top of your iPhone near the sensor to pair"; +"Hold the top of your iPhone near the sensor to pair" = "Mantén la parte superior de tu iPhone cerca del sensor para emparejar"; /* */ -"Sensor not found" = "Sensor not found"; +"Sensor not found" = "Sensor no encontrado"; /* */ -"Also play alert sound" = "Also play alert sound"; +"Also play alert sound" = "Reproducir también sonido de alerta"; /* */ -"Notification Settings" = "Notification Settings"; +"Notification Settings" = "Configuración de las notificaciones"; /* */ -"Found devices: %d" = "Found devices: %d"; +"Found devices: %d" = "Dispositivos encontrados: %d"; /* */ -"Backfill options" = "Backfill options"; +"Backfill options" = "Opciones de relleno"; /* */ "Backfilling from trend is currently not well supported by Loop" = "El relleno de las tendencias no está bien soportado por Loop"; @@ -1176,10 +1189,10 @@ Enact a temp Basal or a temp target */ "Pump History" = "Historial de la bomba"; /* Debug option view Target Ranges */ -"Target ranges" = "Target ranges"; +"Target ranges" = "Rangos objetivo"; /* Debug option view Temp targets */ -"Temp targets" = "Temp targets"; +"Temp targets" = "Objetivos temporales"; /* Debug option view Meal */ "Meal" = "Meal"; @@ -1219,10 +1232,10 @@ Enact a temp Basal or a temp target */ "Connect to Apple Health" = "Connect to Apple Health"; /* Show when have not permissions for writing to Health */ -"For write data to Apple Health you must give permissions in Settings > Health > Data Access" = "For write data to Apple Health you must give permissions in Settings > Health > Data Access"; +"For write data to Apple Health you must give permissions in Settings > Health > Data Access" = "Para escribir datos en Apple Health debes dar permisos en Ajustes > Salud > Acceso a datos"; /* */ -"This allows iAPS to read from and write to Apple Heath. You must also give permissions in Settings > Health > Data Access. If you enter a glucose value into Apple Health, open iAPS to confirm it shows up." = "This allows iAPS to read from and write to Apple Heath. You must also give permissions in Settings > Health > Data Access. If you enter a glucose value into Apple Health, open iAPS to confirm it shows up."; +"This allows iAPS to read from and write to Apple Heath. You must also give permissions in Settings > Health > Data Access. If you enter a glucose value into Apple Health, open iAPS to confirm it shows up." = "Esto permite a iAPS leer y escribir en Apple Heath. También debe dar permisos en Ajustes > Salud > Acceso a datos. Si ingresas un valor de glucosa en Apple Health, abre iAPS para confirmar que aparece."; /* New ALerts ------------------------- */ /* Info title */ @@ -1241,16 +1254,16 @@ Enact a temp Basal or a temp target */ "SMB" = "SMB"; /* A manually entered dose of external insulin */ -"External Insulin" = "External Insulin"; +"External Insulin" = "Insulina externa"; /* Status highlight when manual temp basal is running. */ -"Manual Basal" = "Manual Basal"; +"Manual Basal" = "Basal temporal manual"; /* Current Manual Temp basal */ -" - Manual Basal ⚠️" = " - Manual Basal ⚠️"; +" - Manual Basal ⚠️" = " - Basal temporal manual ⚠️"; /* Total AT / Scheduled basal insulin */ -" U/day" = " U/day"; +" U/day" = " U/día"; /* Total AT / Scheduled basal insulin */ "Total" = "Total"; @@ -1258,81 +1271,81 @@ Enact a temp Basal or a temp target */ /* -------------------------------------------- FPU Strings ------------------------------------------------------*/ /* Enable FPU */ -"Enable" = "Enable"; +"Enable" = "Habilitar"; /* Header */ -"Conversion settings" = "Conversion settings"; +"Conversion settings" = "Configuración de la conversión"; /* Delay */ -"Delay In Minutes" = "Delay In Minutes"; +"Delay In Minutes" = "Demora en minutos"; /* Duration */ -"Maximum Duration In Hours" = "Maximum Duration In Hours"; +"Maximum Duration In Hours" = "Duración máxima en horas"; /* Interval */ -"Interval In Minutes" = "Interval In Minutes"; +"Interval In Minutes" = "Intervalo en minutos"; /* Override */ -"Override With A Factor Of " = "Override With A Factor Of "; +"Override With A Factor Of " = "Reemplazar con un Factor de "; /* Description */ -"Allows fat and protein to be converted into future carb equivalents using the Warsaw formula of kilocalories divided by 10.\n\nThis spreads the carb equivilants over a maximum duration setting that can be configured from 5-12 hours.\n\nDelay is time from now until the first future carb entry.\n\nInterval in minutes is how many minutes are between entries. The shorter the interval, the smoother the result. 10, 15, 20, 30, or 60 are reasonable choices.\n\nAdjustment factor is how much effect the fat and protein has on the entries. 1.0 is full effect (original Warsaw Method) and 0.5 is half effect. Note that you may find that your normal carb ratio needs to increase to a larger number if you begin adding fat and protein entries. For this reason, it is best to start with a factor of about 0.5 to ease into it.\n\nDefault settings: Time Cap: 8 h, Interval: 30 min, Factor: 0.5, Delay 60 min" = "Allows fat and protein to be converted into future carb equivalents using the Warsaw formula of kilocalories divided by 10.\n\nThis spreads the carb equivilants over a maximum duration setting that can be configured from 5-12 hours.\n\nDelay is time from now until the first future carb entry.\n\nInterval in minutes is how many minutes are between entries. The shorter the interval, the smoother the result. 10, 15, 20, 30, or 60 are reasonable choices.\n\nAdjustment factor is how much effect the fat and protein has on the entries. 1.0 is full effect (original Warsaw Method) and 0.5 is half effect. Note that you may find that your normal carb ratio needs to increase to a larger number if you begin adding fat and protein entries. For this reason, it is best to start with a factor of about 0.5 to ease into it.\n\nDefault settings: Time Cap: 8 h, Interval: 30 min, Factor: 0.5, Delay 60 min"; +"Allows fat and protein to be converted into future carb equivalents using the Warsaw formula of kilocalories divided by 10.\n\nThis spreads the carb equivilants over a maximum duration setting that can be configured from 5-12 hours.\n\nDelay is time from now until the first future carb entry.\n\nInterval in minutes is how many minutes are between entries. The shorter the interval, the smoother the result. 10, 15, 20, 30, or 60 are reasonable choices.\n\nAdjustment factor is how much effect the fat and protein has on the entries. 1.0 is full effect (original Warsaw Method) and 0.5 is half effect. Note that you may find that your normal carb ratio needs to increase to a larger number if you begin adding fat and protein entries. For this reason, it is best to start with a factor of about 0.5 to ease into it.\n\nDefault settings: Time Cap: 8 h, Interval: 30 min, Factor: 0.5, Delay 60 min" = "Permite convertir grasas y proteínas en futuros equivalentes de carbohidratos utilizando la fórmula de kilocalorías de Varsovia dividida por 10.\n\nEsto difunde los glúcidos equivalentes en un ajuste de duración máxima que puede configurarse de 5-12 horas.\n\nLa demora es el tiempo desde ahora hasta la primera entrada futura de carbohidratos.\n\nIntervalo en minutos es cuántos minutos hay entre entradas. Cuanto más corto sea el intervalo, más suave será el resultado, 10, 15, 20, 30 o 60 son opciones razonables.\n\nEl factor de ajuste es cuánto efecto tiene la grasa y la proteína en las entradas. 1.0 tiene efecto completo (método original de Varsovia) y 0.5 es la mitad del efecto. Tenga en cuenta que puede que encuentre que su ratio de carbohidratos usual necesita aumentar a un número mayor si empieza a agregar entradas de grasa y proteínas. Por esta razón, es mejor empezar con un factor de aproximadamente 0,5 para facilitar el ajuste.\n\nAjustes predeterminados: Duración máxima: 8 horas, Intervalo: 30 min, Factor: 0.5, Demora 60 min"; /* FPU Settings Title */ -"Fat and Protein" = "Fat and Protein"; +"Fat and Protein" = "Grasa y proteína"; /* Display fat and protein entities */ -"Fat & Protein" = "Fat & Protein"; +"Fat & Protein" = "Grasa y proteína"; /* */ -"Hide Fat & Protein" = "Hide Fat & Protein"; +"Hide Fat & Protein" = "Ocultar grasa y proteína"; /* Add Fat */ -"Fat" = "Fat"; +"Fat" = "Grasa"; /* Add Protein */ -"Protein" = "Protein"; +"Protein" = "Proteína"; /* Service Section */ -"Fat And Protein Conversion" = "Fat And Protein Conversion"; +"Fat And Protein Conversion" = "Conversión de grasa y proteína"; /* Service Section */ -"Profile Override" = "Profile Override"; +"Profile Override" = "Anulación del perfil"; /* */ -"Override Profiles" = "Override Profiles"; +"Override Profiles" = "Sobreescritura de Perfil"; /* */ "Normal " = "Normal "; -"Currently no Override active" = "Currently no Override active"; +"Currently no Override active" = "Actualmente no hay ninguna sobrescritura activa"; /* */ -"Total Insulin Adjustment" = "Total Insulin Adjustment"; +"Total Insulin Adjustment" = "Ajuste total de insulina"; /* */ -"Override your Basal, ISF, CR and Target profiles" = "Override your Basal, ISF, CR and Target profiles"; +"Override your Basal, ISF, CR and Target profiles" = "Reemplaza tu perfil basal, ISF, CR y objetivo"; /* */ -"Enable indefinitely" = "Enable indefinitely"; +"Enable indefinitely" = "Habilitar indefinidamente"; /* */ -"Override Profile target" = "Override Profile target"; +"Override Profile target" = "Sobreescribir el objetivo del perfil"; /* */ -"Disable SMBs" = "Disable SMBs"; +"Disable SMBs" = "Deshabilitar SMBs"; /* Your normal Profile. Use a short string */ -"Normal Profile" = "Normal Profile"; +"Normal Profile" = "Perfil normal"; /* Custom but unsaved Profile */ -"Custom Profile" = "Custom Profile"; +"Custom Profile" = "Perfil personalizado"; /* */ -"Profiles" = "Profiles"; +"Profiles" = "Perfiles"; /* */ -"More options" = "More options"; +"More options" = "Más opciones"; /* */ "Schedule when SMBs are Off" = "Programar cuándo los SMB están apagados"; @@ -1433,6 +1446,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Mostrar proteínas y grasas"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1496,27 +1520,27 @@ Enact a temp Basal or a temp target */ ". Changing: " = ". Cambiando: "; /* Add insulin without bolusing alert */ -" without bolusing" = " without bolusing"; +" without bolusing" = " sin bolo"; /* ------------------------------------------------------------------------------------------- DASH strings */ -"Attach Pod" = "Attach Pod"; +"Attach Pod" = "Adherir Pod"; "Deactivate Pod" = "Desactivar Pod"; /* */ -"Deactivating..." = "Deactivating..."; +"Deactivating..." = "Desactivando..."; -"Pair Pod" = "Pair Pod"; +"Pair Pod" = "Emparejar Pod"; /* Text for previous pod information row */ -"Previous Pod Information" = "Previous Pod Information"; +"Previous Pod Information" = "Información del Pod anterior"; /* Text for confidence reminders navigation link */ -"Confidence Reminders" = "Confidence Reminders"; +"Confidence Reminders" = "Recordatorios de confianza"; -"Confidence reminders are beeps from the Pod which can be used to acknowledge selected commands when the Pod is not silenced." = "Confidence reminders are beeps from the Pod which can be used to acknowledge selected commands when the Pod is not silenced."; +"Confidence reminders are beeps from the Pod which can be used to acknowledge selected commands when the Pod is not silenced." = "Los recordatorios de confianza son pitidos que emite el Pod que pueden utilizarse para tener certeza de que se han seleccionado comandos cuando no está silenciado."; /* button title for saving low reservoir reminder while saving */ "Saving..." = "Guardando..."; @@ -1525,31 +1549,31 @@ Enact a temp Basal or a temp target */ "Save" = "Guardar"; /* Alert title for error when updating confidence reminder preference */ -"Failed to update confidence reminder preference." = "Failed to update confidence reminder preference."; +"Failed to update confidence reminder preference." = "No se ha podido actualizar la preferencia de recordatorio de confianza."; /* */ -"No Error" = "No Error"; +"No Error" = "Sin error"; /* description label for active time pod details row */ "Active Time" = "Tiempo Activo"; /* Title string for BeepPreference.silent */ -"Disabled" = "Disabled"; +"Disabled" = "Desactivado"; /* Title string for BeepPreference.manualCommands */ "Enabled" = "Habilitado"; /* Title string for BeepPreference.extended */ -"Extended" = "Extended"; +"Extended" = "Extendido"; /* Description for BeepPreference.silent */ -"No confidence reminders are used." = "No confidence reminders are used."; +"No confidence reminders are used." = "No se utilizan recordatorios de confianza."; /* Description for BeepPreference.manualCommands */ -"Confidence reminders will sound for commands you initiate, like bolus, cancel bolus, suspend, resume, save notification reminders, etc. When the app automatically adjusts delivery, no confidence reminders are used." = "Confidence reminders will sound for commands you initiate, like bolus, cancel bolus, suspend, resume, save notification reminders, etc. When the app automatically adjusts delivery, no confidence reminders are used."; +"Confidence reminders will sound for commands you initiate, like bolus, cancel bolus, suspend, resume, save notification reminders, etc. When the app automatically adjusts delivery, no confidence reminders are used." = "Los recordatorios de confianza sonarán para los comandos que inicie, como bolo, cancelar bolo, suspender, reanudar, guardar recordatorios de notificación, etc. Cuando el lazo cerrado ajusta automáticamente la administración de insulina, no se utilizan recordatorios de confianza."; /* Description for BeepPreference.extended */ -"Confidence reminders will sound when the app automatically adjusts delivery as well as for commands you initiate." = "Confidence reminders will sound when the app automatically adjusts delivery as well as for commands you initiate."; +"Confidence reminders will sound when the app automatically adjusts delivery as well as for commands you initiate." = "Los recordatorios de confianza sonarán cuando el lazo cerrado ajuste la administración de insulina, así como para los comandos manuales."; /* Label text for expiration reminder default row */ "Expiration Reminder Default" = "Expiration Reminder Default"; @@ -1662,10 +1686,10 @@ Enact a temp Basal or a temp target */ "Allow Upload of Statistics to NS" = "Allow Upload of Statistics to NS"; /* Low Glucose Threshold in Statistics settings */ -"Low" = "Low"; +"Low" = "Bajo"; /* High Glucose Threshold in Statistics settings */ -"High" = "High"; +"High" = "Alto"; /* In Range */ "In Range" = "In Range"; @@ -1706,6 +1730,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Media"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Mediana"; diff --git a/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings index a2e5f2229c..71aa1e0139 100644 --- a/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Valmis"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Odota"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Display Protein & Fat"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Average"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Median"; diff --git a/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings index 3edbae4fee..9579b205ed 100644 --- a/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Terminé"; +/* Calender Option */ +"Display Emojis as Labels" = "Afficher des émojis en tant qu'étiquettes"; + +/* Calender Option */ +"Display IOB and COB" = "Afficher l'insuline active (IA) et les glucides actifs (GA)"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "Interface et expérience utilisateur"; + /* */ "Wait please" = "Merci de patienter"; @@ -50,16 +62,16 @@ "of" = "de"; /* Remote Bolus Alert, Part 1 */ -"A Remote Bolus " = "A Remote Bolus "; +"A Remote Bolus " = "Un bolus à distance "; /* Remote Bolus Alert, Part 2 */ -"was delivered" = "was delivered"; +"was delivered" = "a été livré"; /* Remote Bolus Alert, Part 3 */ " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: " = " minutes ago, triggered remotely from Nightscout, by a caregiver or a parent. Do you still want to bolus?\n\nPredicted eventual glucose, if you don't bolus, is: "; /* Remote Bolus Alert, Title */ -"A Remote Bolus Was Just Delivered!" = "A Remote Bolus Was Just Delivered!"; +"A Remote Bolus Was Just Delivered!" = "Un bolus à distance vient d'être livré !"; /* Headline in enacted pop up (at: at what time) */ "Enacted at" = "Dernier calcul à"; @@ -375,7 +387,7 @@ Enact a temp Basal or a temp target */ "Remote control" = "Contrôle à distance"; /* Allow remote control from NS */ -"Allow Remote control of iAPS" = "Allow Remote control of iAPS"; +"Allow Remote control of iAPS" = "Autoriser le contrôle à distance d'iAPS"; /* Imported Profiles Alert */ "\nNow please verify all of your new settings thoroughly:\n\n* Basal Settings\n * Carb Ratios\n * Glucose Targets\n * Insulin Sensitivities\n * DIA\n\n in iAPS Settings > Configuration.\n\nBad or invalid profile settings could have disatrous effects." = "\nVeuillez maintenant vérifier soigneusement tous vos nouveaux paramètres:\n\n* Paramètres basaux\n * Ratios glucidiques\n * Objectifs glycémiques\n * Sensibilité à l'insuline\n * DIA\n\n dans iAPS Paramètres > Configuration.\n\nDes paramètres de profil incorrects ou invalides peuvent avoir des effets désastreux."; @@ -426,7 +438,7 @@ Enact a temp Basal or a temp target */ "Add Simulator" = "Ajouter un simulateur"; /* View/Header when pod expired */ -"Replace" = "Replace"; +"Replace" = "Remplacer"; /* Insulin model */ "Model" = "Modèle"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Afficher les protéines et graisses"; + +/* Time of new meal entry */ +"Now" = "Maintenant"; + + +/* Display future data table entries */ +"Show Future" = "Afficher le futur"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1531,7 +1554,7 @@ Enact a temp Basal or a temp target */ "No Error" = "Aucune erreur"; /* description label for active time pod details row */ -"Active Time" = "Heure d’activation"; +"Active Time" = "Durée d’activité"; /* Title string for BeepPreference.silent */ "Disabled" = "Désactivé"; @@ -1604,7 +1627,7 @@ Enact a temp Basal or a temp target */ "This PumpManager has not been configured with a maximum basal rate because it was added before manual temp basal was a feature. Please go to therapy settings -> delivery limits and set a new maximum basal rate." = "Le Gestionnaire de Pompes n'a pas été configuré avec un débit de base maximum car il a été ajouté avant que le Basal temporaire manuel soit une fonctionnalité. Veuillez aller dans les paramètres de thérapie -> limites de délivrance et définir un nouveau taux de basal maximum."; /* description label for active time pod details row */ -"Active Time" = "Heure d’activation"; +"Active Time" = "Durée d’activité"; /* description label for total delivery pod details row */ "Total Delivery" = " Total délivré"; @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Moyenne"; +/* TIR Preview Headline */ +"Time In Range" = "Temps dans la plage cible"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Intervalle moyen"; + /* Median BG */ "Median" = "Médiane"; @@ -2080,7 +2109,7 @@ Enact a temp Basal or a temp target */ "Adjust Dynamic ISF constant" = "Ajuster la constante du FSI Dynamique"; /* Adjust Dynamic ISF constant */ -"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment."; +"Individual adjustment of the computed dynamic ratios. Default is 0.5. The higher the value, the larger the correction of your ISF/CR will be for a high or a low blood glucose. Maximum/minumum correction is determined by the Autosens min/max settings.\n\nFor Sigmoid function an adjustment factor of 0.4 - 0.5 is recommended to begin with.\n\nFor the logaritmic formula there is less consensus, but starting around 0.8 is probably appropiate for most adult users. For younger users it's recommended to start even lower when using logaritmic formula, to avoid overly aggressive treatment." = "Ajustement individuel des ratios dynamiques calculés. La valeur par défaut est de 0,5. Plus la valeur est élevée, plus la correction de votre facteur de sensibilité à l'insuline (ISF) et/ou de votre ratio insuline/glucides (I:G) sera importante en cas de glycémie élevée ou basse. La correction maximale/minimale est déterminée par les réglages min/max dans Autosens.\n\nPour la fonction Sigmoid, un facteur d'ajustement de 0,4 à 0,5 est recommandé pour commencer.\n\nPour la formule logarithmique, il existe moins de consensus, mais un démarrage autour de 0,8 est probablement approprié pour la plupart des utilisateurs adultes. Pour les utilisateurs plus jeunes, il est recommandé de démarrer encore plus bas lors de l'utilisation de la formule logarithmique, afin d'éviter un traitement trop agressif."; /* Headline Use Sigmoid Function */ "Use Sigmoid Function" = "Utiliser la fonction Sigmoid"; @@ -2101,13 +2130,13 @@ Enact a temp Basal or a temp target */ "Minimum Threshold Setting" = "Réglage du seuil minimal"; /* Minimum Threshold Setting, Part 1 */ -"This setting lets you choose a level below which no insulin will be given.\n\nThe threshold is using the largest amount of your threshold setting and the computed threshold:\n\nTarget Glucose - (Target Glucose - 40) / 2\n, here using mg/dl as glucose unit.\n\nFor example, if your Target Glucose is " = "This setting lets you choose a level below which no insulin will be given.\n\nThe threshold is using the largest amount of your threshold setting and the computed threshold:\n\nTarget Glucose - (Target Glucose - 40) / 2\n, here using mg/dl as glucose unit.\n\nFor example, if your Target Glucose is "; +"This setting lets you choose a level below which no insulin will be given.\n\nThe threshold is using the largest amount of your threshold setting and the computed threshold:\n\nTarget Glucose - (Target Glucose - 40) / 2\n, here using mg/dl as glucose unit.\n\nFor example, if your Target Glucose is " = "Ce paramètre vous permet de choisir un niveau endessous duquel aucune insuline ne sera donnée.\n\nLe seuil utilise la plus grande quantité de votre seuil de réglage et le seuil calculé :\n\nGlycémie cible - (Glycémie cible - 40) / 2\n, en utilisant mg/dl comme unité de glucose.\n\nPar exemple, si votre glycémie cible est "; /* Minimum Threshold Setting, Part 2 */ -"the threshold will be " = "the threshold will be "; +"the threshold will be " = "le seuil sera "; /* Minimum Threshold Setting, Part 3 */ -"unless your threshold setting is set higher:" = "unless your threshold setting is set higher:"; +"unless your threshold setting is set higher:" = "à moins que votre seuil ne soit défini plus haut :"; /* Threshold Table Columns Title */ "Setting" = "Paramètre"; @@ -2140,13 +2169,13 @@ Enact a temp Basal or a temp target */ "Display and allow Fat and Protein entries" = "Afficher et autoriser les entrées de matières grasses et protéines"; /* UI/UX option */ -"Add Meal View settings " = "Add Meal View settings "; +"Add Meal View settings " = "Paramètres de : \"Entrer un repas\" "; /* UI/UX option */ "Display Temp Targets Button" = "Afficher le bouton de cible temporaire"; /* UI/UX option */ -"Home View Button Panel " = "Home View Button Panel "; +"Home View Button Panel " = "Panneau des boutons sur la vue d'accueil "; /* UI/UX title */ "Home Chart settings " = "Paramètres du graphique de la page d'accueil "; @@ -2169,10 +2198,10 @@ Enact a temp Basal or a temp target */ "Normally glucose is colored red only when over or under your notification limits for high/low" = "Normalement, la valeur de glucose est en rouge uniquement lorsqu'elle est supérieure ou inférieure à vos limites de notification pour les valeurs hautes/basses"; /* UI/UX option */ -"Horizontal Scroll View Visible hours" = "Horizontal Scroll View Visible hours"; +"Horizontal Scroll View Visible hours" = "Heures visibles dans le défilement horizontal de la graphique principale"; /* UI/UX option */ -"Display Time Interval Setting Button" = "Display Time Interval Setting Button"; +"Display Time Interval Setting Button" = "Afficher le bouton de réglage des heures visibles"; /* Setting title */ "Bolus Calculator" = "Calculateur de Bolus"; @@ -2181,7 +2210,7 @@ Enact a temp Basal or a temp target */ "Dynamic ISF" = "Facteur de sensibilité à l'insuline (FSI) dynamique"; /* Notification option */ -"Live Activity" = "Live Activity"; +"Live Activity" = "Activité en direct"; /* Notification option */ "Live activity displays blood glucose live on the lock screen and on the dynamic island (if available)" = "L'activité en direct affiche la glycémie sur l'écran de verrouillage et sur l'île dynamique (si disponible)"; diff --git a/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings index 64ef7ca9b7..11ae120310 100644 --- a/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Done"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Wait please"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Display Protein & Fat"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Average"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Median"; diff --git a/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings index 307a180bed..11e50821b2 100644 --- a/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Kész"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Kérlek várj"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Display Protein & Fat"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Average"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Median"; diff --git a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings index e677a888ac..4e0a601140 100644 --- a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Fine"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Attendere prego"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Mostra Proteine & Grassi"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Media"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Mediana"; diff --git a/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings index ddc3670fc0..3fbb55c89d 100644 --- a/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Ferdig"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Vennligst vent"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Vis protein og fett"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Gj.snitt"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Median"; diff --git a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings index 3bbb74b7ea..b2e3bb37a3 100644 --- a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "OK"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Wachten"; @@ -426,7 +438,7 @@ Enact a temp Basal or a temp target */ "Add Simulator" = "Simulator toevoegen"; /* View/Header when pod expired */ -"Replace" = "Replace"; +"Replace" = "Vervang"; /* Insulin model */ "Model" = "Model"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Toon vet en eiwit"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Gemiddeld"; +/* TIR Preview Headline */ +"Time In Range" = "Tijd binnen bereik (TIR)"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Gemiddelde interval"; + /* Median BG */ "Median" = "Mediaan"; diff --git a/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings index 7b58666ad3..93cf0fb04c 100644 --- a/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Done"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Proszę czekać"; @@ -1435,6 +1447,17 @@ Połączono z Nightscout!"; /* Watch Config Option */ "Display Protein & Fat" = "Display Protein & Fat"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1708,6 +1731,12 @@ Połączono z Nightscout!"; /* Average BG = */ "Average" = "Average"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Median"; diff --git a/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings index 193b025fc3..1269b28815 100644 --- a/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "OK"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Aguarde"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Display Protein & Fat"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Average"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Median"; diff --git a/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings index 2159921002..86e315529b 100644 --- a/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "OK"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Aguarde"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Display Protein & Fat"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Average"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Median"; diff --git a/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings index d8d671635f..e4a15d63ee 100644 --- a/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Готово"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Подождите"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Отображать белки и жиры"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Средний"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Медиана"; diff --git a/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings index 9ba21173d8..3b1517b0ea 100644 --- a/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Hotovo"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Čakajte prosím"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Zobrazenie bielkovín a tukov"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Priemerný"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Medián"; diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index 0c67b21d05..966743081f 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Klar"; +/* Calender Option */ +"Display Emojis as Labels" = "Visa Emojis"; + +/* Calender Option */ +"Display IOB and COB" = "Visa IOB och COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Bekräfta Bolus snabbare"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Vänta..."; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Visa fett och protein"; + +/* Time of new meal entry */ +"Now" = "Nu"; + + +/* Display future data table entries */ +"Show Future" = "Visa"; + +/* Hide future data table entries */ +"Hide Future" = "Dölj"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ diff --git a/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings index a4ef6669f6..7eb22b58d4 100644 --- a/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Tamam"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Lütfen Bekleyin"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Display Protein & Fat"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Ortalama"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Orta Değer"; diff --git a/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings index 2f676e946c..97b1dccec0 100644 --- a/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Готово"; +/* Calender Option */ +"Display Emojis as Labels" = "Відображати Emojis як Мітки"; + +/* Calender Option */ +"Display IOB and COB" = "Відображення IOB і COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Підтвердити Швидкий Болюс"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Зачекайте"; @@ -426,7 +438,7 @@ Enact a temp Basal or a temp target */ "Add Simulator" = "Додати Симулятор"; /* View/Header when pod expired */ -"Replace" = "Replace"; +"Replace" = "Замінити"; /* Insulin model */ "Model" = "МОДЕЛЬ"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Показати білок і жир"; + +/* Time of new meal entry */ +"Now" = "Щойно"; + + +/* Display future data table entries */ +"Show Future" = "Показати Майбутнє"; + +/* Hide future data table entries */ +"Hide Future" = "Приховати майбутнє"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Середній"; +/* TIR Preview Headline */ +"Time In Range" = "Час в Діапазоні"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Середній Інтервал"; + /* Median BG */ "Median" = "Медіана"; diff --git a/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings index 14378bb5c3..625e305842 100644 --- a/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "Xong"; +/* Calender Option */ +"Display Emojis as Labels" = "Hiển thị biểu tượng cảm xúc"; + +/* Calender Option */ +"Display IOB and COB" = "Hiển thị IOB và COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Xác nhận Bolus nhanh"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "Xin đợi chốc lát"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Hiển thị chất đạm và chất béo"; + +/* Time of new meal entry */ +"Now" = "Bây giờ"; + + +/* Display future data table entries */ +"Show Future" = "Hiển thị tương lai"; + +/* Hide future data table entries */ +"Hide Future" = "Ẩn tương lai"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Average"; +/* TIR Preview Headline */ +"Time In Range" = "Trong phạm vi mục tiêu"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Khoảng thời gian trung bình"; + /* Median BG */ "Median" = "Median"; diff --git a/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings index c4707379ed..7900d35d37 100644 --- a/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings @@ -40,6 +40,18 @@ /* Button */ "Done" = "完成"; +/* Calender Option */ +"Display Emojis as Labels" = "Display Emojis as Labels"; + +/* Calender Option */ +"Display IOB and COB" = "Display IOB and COB"; + +/* Apple Watch App setting */ +"Confirm Bolus Faster" = "Confirm Bolus Faster"; + +/* Setting Section */ +"UI/UX" = "UI/UX"; + /* */ "Wait please" = "请稍候"; @@ -1433,6 +1445,17 @@ Enact a temp Basal or a temp target */ /* Watch Config Option */ "Display Protein & Fat" = "Display Protein & Fat"; + +/* Time of new meal entry */ +"Now" = "Now"; + + +/* Display future data table entries */ +"Show Future" = "Show Future"; + +/* Hide future data table entries */ +"Hide Future" = "Hide Future"; + /* ----------------------- New Bolus Calculator ---------------------------*/ /* Warning about bolus recommendation. Title */ @@ -1706,6 +1729,12 @@ Enact a temp Basal or a temp target */ /* Average BG = */ "Average" = "Average"; +/* TIR Preview Headline */ +"Time In Range" = "Time In Range"; + +/* Average Loop Interval in minutes */ +"Average Interval" = "Average Interval"; + /* Median BG */ "Median" = "Median"; From 1c969ada518b545bcdb87c90780ae3a33871f7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sat, 9 Mar 2024 17:55:01 +0100 Subject: [PATCH 40/44] New string --- .../Sources/Localizations/Main/en.lproj/Localizable.strings | 3 +++ 1 file changed, 3 insertions(+) diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index 5640ce77b9..9bd4f0a886 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -965,6 +965,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "High"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glucose"; From d0f56f6e45e4825e88ebcb03f56e91f21a02afdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sun, 10 Mar 2024 00:26:17 +0100 Subject: [PATCH 41/44] Missing properties for fat and proteing entered via iAPS iOS app-shortcut for carbs. --- FreeAPS/Sources/Shortcuts/Carbs/CarbPresetIntentRequest.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/FreeAPS/Sources/Shortcuts/Carbs/CarbPresetIntentRequest.swift b/FreeAPS/Sources/Shortcuts/Carbs/CarbPresetIntentRequest.swift index 0b99c626a8..ad69a3a7db 100644 --- a/FreeAPS/Sources/Shortcuts/Carbs/CarbPresetIntentRequest.swift +++ b/FreeAPS/Sources/Shortcuts/Carbs/CarbPresetIntentRequest.swift @@ -19,7 +19,8 @@ import Foundation protein: Decimal(quantityProtein), note: "add with shortcuts", enteredBy: CarbsEntry.manual, - isFPU: false, fpuID: nil + isFPU: (quantityFat > 0 || quantityProtein > 0) ? true : false, + fpuID: (quantityFat > 0 || quantityProtein > 0) ? UUID().uuidString : nil )] ) var resultDisplay: String From f673f0df90ae8222d4b1bcb7f37cdd4f6f72137c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sun, 10 Mar 2024 10:40:35 +0100 Subject: [PATCH 42/44] Add method for compact Form section spacing. WIll only be used on devices with iOS 17 and up. --- FreeAPS/Sources/Views/ViewModifiers.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/FreeAPS/Sources/Views/ViewModifiers.swift b/FreeAPS/Sources/Views/ViewModifiers.swift index 883f302b75..a8ebcb7e2b 100644 --- a/FreeAPS/Sources/Views/ViewModifiers.swift +++ b/FreeAPS/Sources/Views/ViewModifiers.swift @@ -37,6 +37,16 @@ struct CapsulaBackground: ViewModifier { } } +struct CompactSectionSpacing: ViewModifier { + func body(content: Content) -> some View { + if #available(iOS 17, *) { + return content + .listSectionSpacing(.compact) + } else { + return content } + } +} + struct AddShadow: ViewModifier { @Environment(\.colorScheme) var colorScheme func body(content: Content) -> some View { @@ -307,6 +317,10 @@ extension View { } } + func compactSectionSpacing() -> some View { + modifier(CompactSectionSpacing()) + } + func asAny() -> AnyView { .init(self) } } From ecc3cb5e4db3917a7ee8a5a30e06007b96028052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sun, 10 Mar 2024 10:45:29 +0100 Subject: [PATCH 43/44] Bolus View and Meal View updates. Clarify when saved and when canceled. Condense the Bolus View using newly created view modifier (for devices running iOS 17). Change "Close" to "Cancel" --- .../Main/en.lproj/Localizable.strings | 6 ++++++ .../Modules/AddCarbs/View/AddCarbsRootView.swift | 4 ++-- .../Bolus/View/AlternativeBolusCalcRootView.swift | 15 +++++++++++---- .../Bolus/View/DefaultBolusCalcRootView.swift | 15 +++++++++++---- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index 9bd4f0a886..c16234614c 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Continue without bolus"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Status"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add "; diff --git a/FreeAPS/Sources/Modules/AddCarbs/View/AddCarbsRootView.swift b/FreeAPS/Sources/Modules/AddCarbs/View/AddCarbsRootView.swift index 93b3c31a8d..60cfadf2c5 100644 --- a/FreeAPS/Sources/Modules/AddCarbs/View/AddCarbsRootView.swift +++ b/FreeAPS/Sources/Modules/AddCarbs/View/AddCarbsRootView.swift @@ -114,7 +114,7 @@ extension AddCarbs { Section { Button { state.add(override, fetch: editMode) } - label: { Text((state.skipBolus && !override && !editMode) ? "Save" : "Continue") } + label: { Text(((state.skipBolus && !override && !editMode) || state.carbs <= 0) ? "Save" : "Continue") } .disabled(empty) .frame(maxWidth: .infinity, alignment: .center) }.listRowBackground(!empty ? Color(.systemBlue) : Color(.systemGray4)) @@ -132,7 +132,7 @@ extension AddCarbs { } .navigationTitle("Add Meal") .navigationBarTitleDisplayMode(.inline) - .navigationBarItems(trailing: Button("Close", action: state.hideModal)) + .navigationBarItems(trailing: Button("Cancel", action: state.hideModal)) } private var presetPopover: some View { diff --git a/FreeAPS/Sources/Modules/Bolus/View/AlternativeBolusCalcRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/AlternativeBolusCalcRootView.swift index 5c922f51a0..9cd207c27d 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/AlternativeBolusCalcRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/AlternativeBolusCalcRootView.swift @@ -66,13 +66,13 @@ extension Bolus { } else { predictionChart } - } header: { Text("Predictions") } + } header: { Text("Status") } Section {} if fetch { Section { mealEntries - } header: { Text("Meal Summary") } + } // header: { Text("Meal Summary") } } Section { @@ -192,10 +192,17 @@ extension Bolus { keepForNextWiew = true state.showModal(for: nil) } - label: { Text("Continue without bolus") }.frame(maxWidth: .infinity, alignment: .center) + label: { + fetch ? + Text("Save Meal without bolus") : + Text("Continue without bolus") } + .frame(maxWidth: .infinity, alignment: .center) + .listRowBackground(Color(.systemBlue)) + .tint(.white) } } } + .compactSectionSpacing() .alert(isPresented: $isRemoteBolusAlertPresented) { remoteBolusAlert! } @@ -214,7 +221,7 @@ extension Bolus { } }, trailing: Button { state.hideModal() } - label: { Text("Close") } + label: { Text("Cancel") } ) .onAppear { configureView { diff --git a/FreeAPS/Sources/Modules/Bolus/View/DefaultBolusCalcRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/DefaultBolusCalcRootView.swift index ad42446220..4971c824be 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/DefaultBolusCalcRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/DefaultBolusCalcRootView.swift @@ -46,12 +46,12 @@ extension Bolus { } else { predictionChart } - } header: { Text("Predictions") } + } header: { Text("Status") } if fetch { Section { mealEntries - } header: { Text("Meal Summary") } + } // header: { Text("Meal Summary") } } Section { @@ -150,10 +150,17 @@ extension Bolus { keepForNextWiew = true state.showModal(for: nil) } - label: { Text("Continue without bolus") }.frame(maxWidth: .infinity, alignment: .center) + label: { + fetch ? + Text("Save Meal without bolus") : + Text("Continue without bolus") } + .frame(maxWidth: .infinity, alignment: .center) + .listRowBackground(Color(.systemBlue)) + .tint(.white) } } } + .compactSectionSpacing() .alert(isPresented: $displayError) { Alert( title: Text("Warning!"), @@ -197,7 +204,7 @@ extension Bolus { } }, trailing: Button { state.hideModal() } - label: { Text("Close") } + label: { Text("Cancel") } ) .popup(isPresented: presentInfo, alignment: .center, direction: .bottom) { bolusInfo From 0fe3ace95376d6bad2c562750e6bbd62b9887a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Sun, 10 Mar 2024 13:40:38 +0100 Subject: [PATCH 44/44] Crowdin updates --- .../Localizations/Main/ar.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/da.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/de.lproj/Localizable.strings | 11 ++++++++++- .../Localizations/Main/es.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/fi.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/fr.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/he.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/hu.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/it.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/nb.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/nl.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/pl.lproj/Localizable.strings | 9 +++++++++ .../Main/pt-BR.lproj/Localizable.strings | 9 +++++++++ .../Main/pt-PT.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/ru.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/sk.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/sv.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/tr.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/uk.lproj/Localizable.strings | 9 +++++++++ .../Localizations/Main/vi.lproj/Localizable.strings | 9 +++++++++ .../Main/zh-Hans.lproj/Localizable.strings | 9 +++++++++ 21 files changed, 190 insertions(+), 1 deletion(-) diff --git a/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings index 11ae120310..8c821338ef 100644 --- a/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Continue without bolus"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "الحالة"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "High"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glucose"; diff --git a/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings index bd470bc095..053f78422c 100644 --- a/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Fortsæt uden bolus"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Status"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nDette er mere insulin end din \"max dosis\" indstilling!\nEr du sikker på at du vil tilføje "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "Høj"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glukose"; diff --git a/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings index 1411c90286..eafb7ec424 100644 --- a/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Ohne Bolusabgabe fortfahren"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Status"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nEingegebener Bolus ist größer als Max Bolus Einstellung! \nTrotzdem hinzufügen? "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "Hoch"; +/* TIR Chart */ +"Very High" = "Sehr hoch"; + /* */ "glucose" = "Blutzucker"; @@ -1182,7 +1191,7 @@ Enact a temp Basal or a temp target */ "Save as your Normal Basal Rates" = "Als deine normalen Basalraten speichern"; /* */ -"Save on Pump" = "Auf Pumpe speichern"; +"Save on Pump" = "Auf der Pumpe speichern"; /* Debug option view Pump History */ "Pump History" = "Insulinpumpen-Speicher"; diff --git a/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings index 2c33b4450f..55ed0849ea 100644 --- a/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Continuar sin administrar bolo"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Estado"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "¡La cantidad es mayor que el ajuste del bolo máximo!\n ¿Está seguro de que desea añadir "; @@ -966,6 +972,9 @@ Solamente puedes emparejar una app con el sensor vía bluetooth. A continuación /* */ "High" = "Alto"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glucosa"; diff --git a/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings index 71aa1e0139..59a9bd5024 100644 --- a/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Continue without bolus"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Tila"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nMäärä on isompi kuin sinun maksimi Bolus asetus\nOletko varma, että haluat lisätä "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "High"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glucose"; diff --git a/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings index 9579b205ed..acb65694ee 100644 --- a/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Continuer sans bonus"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Statut"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nLe montant est supérieur à votre paramètre de Bolus Max ! \nÊtes-vous sûr de vouloir ajouter "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "Élevée"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glycémie"; diff --git a/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings index 11ae120310..01cc6551a7 100644 --- a/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Continue without bolus"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Status"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "High"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glucose"; diff --git a/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings index 11e50821b2..b544650b5e 100644 --- a/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/hu.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Folytatás bólus nélkül"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Status"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nAmount több mint a Max Bólus beállítás! \nBiztos, hogy hozzá szeretnéd adni "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "High"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glucose"; diff --git a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings index 4e0a601140..eee4f293b2 100644 --- a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Continua senza eseguire un bolo"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Stato"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nLa quantità è superiore all'impostazione del bolo massimo! \nSei sicuro di voler aggiungere?"; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "Alto"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glicemie"; diff --git a/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings index 3fbb55c89d..50acfd7c2c 100644 --- a/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Fortsett uten å gi bolus"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Status"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nMengden er høyere enn din Maks bolus-innstilling! \nEr du sikker på at du vil legge til "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "Høy"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "blodsukker"; diff --git a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings index b2e3bb37a3..02dcfacc3e 100644 --- a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Verdergaan zonder bolus"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Status"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nDeze hoeveelheid is meer dan je instelling van je maximale bolus! \nWeet je zeker dat je deze hoeveelheid wilt toedienen? \nDeze hoeveelheid is meer dan je instelling van je maximale bolus! \nWaarschuw bij toedienen van een hoge hoeveelheid zonder te bolussen "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "Hoog"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glucose"; diff --git a/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings index 93cf0fb04c..0063c5163c 100644 --- a/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Kontynuuj bez bolusa"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Status"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add "; @@ -967,6 +973,9 @@ Połączono z Nightscout!"; /* */ "High" = "High"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glucose"; diff --git a/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings index 1269b28815..8656fce65e 100644 --- a/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Continuar sem tomar bolus"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Estado"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "High"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glucose"; diff --git a/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings index 86e315529b..e4e648b0d9 100644 --- a/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Continuar sem tomar bolus"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Status"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "High"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glucose"; diff --git a/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings index e4a15d63ee..12b4778c1c 100644 --- a/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Продолжить без болюса"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Статус"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nКоличество превышает максимальную дозу болюса! \nВы уверены, что хотите добавить "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "Высокий"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "глюкоза"; diff --git a/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings index 3b1517b0ea..0759649f00 100644 --- a/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Pokračovať bez dávky"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Stav"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nDávka prekračuje vaše nastavenie Max Bolus!\nSte si istí, že chcete dávku pridať "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "Vysoká"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glukóza"; diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index 966743081f..62af892328 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Fortsätt utan bolus"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Spara måltid utan bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Status"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nDetta är mer insulin än din maxdos-inställning!\nÄr du säker på att du vill lägga till "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "Högt"; +/* TIR Chart */ +"Very High" = "Mycket Högt"; + /* */ "glucose" = "glukos"; diff --git a/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings index 7eb22b58d4..968d9e3a8a 100644 --- a/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Bolus yapmadan devam edin"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Durum"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "Yüksek"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "glikoz"; diff --git a/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings index 97b1dccec0..97ef6e8463 100644 --- a/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Продовжити без болюсу"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Статус"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nКількість перевищує ваш максимальний болюс! \nВи впевнені, що хочете додати"; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "Високий"; +/* TIR Chart */ +"Very High" = "Дуже Високий"; + /* */ "glucose" = "Глюкоза"; diff --git a/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings index 625e305842..cfd0645a3b 100644 --- a/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/vi.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "Tiếp tục và bỏ qua liều bolus"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "Tình trạng"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nLiều tiêm nhiều hơn liều Max Bolus! \nBạn có chắc chắn muốn thêm "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "High"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "đường huyết"; diff --git a/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings index 7900d35d37..79a1abc8f5 100644 --- a/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings @@ -16,6 +16,12 @@ /* Continue after added carbs without bolus */ "Continue without bolus" = "不输注胰岛素并继续"; +/* Continue after added meal without bolus */ +"Save Meal without bolus" = "Save Meal without bolus"; + +/* Predictions and Meal summary part of the Bolus View. */ +"Status" = "状态"; + /* Alert when adding large amount without bolusing */ "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add " = "\nAmount is more than your Max Bolus setting! \nAre you sure you want to add "; @@ -965,6 +971,9 @@ Enact a temp Basal or a temp target */ /* */ "High" = "高"; +/* TIR Chart */ +"Very High" = "Very High"; + /* */ "glucose" = "葡萄糖";