diff --git a/Loop/Extensions/EditMode.swift b/Loop/Extensions/EditMode.swift index b1ff303a43..27c824eb2d 100644 --- a/Loop/Extensions/EditMode.swift +++ b/Loop/Extensions/EditMode.swift @@ -10,7 +10,7 @@ import SwiftUI extension EditMode { var title: String { - self == .active ? "Done" : "Edit" + self == .active ? NSLocalizedString("Done", comment: "") : NSLocalizedString("Edit", comment: "") } mutating func toggle() { diff --git a/Loop/Views/AddEditFavoriteFoodView.swift b/Loop/Views/AddEditFavoriteFoodView.swift index b647523a13..ddd01320b9 100644 --- a/Loop/Views/AddEditFavoriteFoodView.swift +++ b/Loop/Views/AddEditFavoriteFoodView.swift @@ -93,20 +93,40 @@ struct AddEditFavoriteFoodView: View { let foodTypeFocused: Binding = Binding(get: { expandedRow == .foodType }, set: { expandedRow = $0 ? .foodType : nil }) let absorptionTimeFocused: Binding = Binding(get: { expandedRow == .absorptionTime }, set: { expandedRow = $0 ? .absorptionTime : nil }) - TextFieldRow(text: $viewModel.name, isFocused: nameFocused, title: "Name", placeholder: "Apple") + TextFieldRow( + text: $viewModel.name, + isFocused: nameFocused, + title: NSLocalizedString("Name", comment: "Label for name in favorite food entry screen"), + placeholder: NSLocalizedString("Apple", comment: "Placeholder for name in favorite food entry screen") + ) CardSectionDivider() - CarbQuantityRow(quantity: $viewModel.carbsQuantity, isFocused: carbQuantityFocused, title: "Carb Quantity", preferredCarbUnit: viewModel.preferredCarbUnit) + CarbQuantityRow( + quantity: $viewModel.carbsQuantity, + isFocused: carbQuantityFocused, + title: NSLocalizedString("Carb Quantity", comment: "Label for carb quantity in favorite food entry screen"), + preferredCarbUnit: viewModel.preferredCarbUnit + ) CardSectionDivider() - EmojiRow(text: $viewModel.foodType, isFocused: foodTypeFocused, emojiType: .food, title: "Food Type") + EmojiRow( + text: $viewModel.foodType, + isFocused: foodTypeFocused, + emojiType: .food, + title: NSLocalizedString("Food Type", comment: "Label for food type in favorite entry screen") + ) CardSectionDivider() - AbsorptionTimePickerRow(absorptionTime: $viewModel.absorptionTime, isFocused: absorptionTimeFocused, validDurationRange: viewModel.absorptionRimesRange, showHowAbsorptionTimeWorks: $showHowAbsorptionTimeWorks) - .padding(.bottom, 2) + AbsorptionTimePickerRow( + absorptionTime: $viewModel.absorptionTime, + isFocused: absorptionTimeFocused, + validDurationRange: viewModel.absorptionRimesRange, + showHowAbsorptionTimeWorks: $showHowAbsorptionTimeWorks + ) + .padding(.bottom, 2) } .padding(.vertical, 12) .padding(.horizontal) diff --git a/Loop/Views/FavoriteFoodDetailView.swift b/Loop/Views/FavoriteFoodDetailView.swift index 44c7a83150..a0fe7d3eef 100644 --- a/Loop/Views/FavoriteFoodDetailView.swift +++ b/Loop/Views/FavoriteFoodDetailView.swift @@ -35,10 +35,10 @@ public struct FavoriteFoodDetailView: View { Section("Information") { VStack(spacing: 16) { let rows: [(field: String, value: String)] = [ - ("Name", food.name), - ("Carb Quantity", food.carbsString(formatter: carbFormatter)), - ("Food Type", food.foodType), - ("Absorption Time", food.absorptionTimeString(formatter: absorptionTimeFormatter)) + (NSLocalizedString("Name", comment: "Label for name in favorite food entry"), food.name), + (NSLocalizedString("Carb Quantity", comment:"Label for carb quantity in favorite food entry"), food.carbsString(formatter: carbFormatter)), + (NSLocalizedString("Food Type", comment:"Label for food type in favorite food entry"), food.foodType), + (NSLocalizedString("Absorption Time", comment:"Label for absorption time in favorite food entry"), food.absorptionTimeString(formatter: absorptionTimeFormatter)) ] ForEach(rows, id: \.field) { row in HStack { diff --git a/Loop/Views/SettingsView.swift b/Loop/Views/SettingsView.swift index c3ec98b8dd..ed9723d243 100644 --- a/Loop/Views/SettingsView.swift +++ b/Loop/Views/SettingsView.swift @@ -29,31 +29,31 @@ public struct SettingsView: View { var id: String { rawValue } - + case deleteCGMData case deletePumpData } - + enum ActionSheet: String, Identifiable { var id: String { rawValue } - + case cgmPicker case pumpPicker case servicePicker } - + enum Sheet: String, Identifiable { var id: String { rawValue } - + case favoriteFoods case therapySettings } } - + @State private var actionSheet: Destination.ActionSheet? @State private var alert: Destination.Alert? @State private var sheet: Destination.Sheet? @@ -254,7 +254,7 @@ extension SettingsView { } } } - + @ViewBuilder private var alertWarning: some View { if viewModel.alertPermissionsChecker.showWarning || viewModel.alertPermissionsChecker.notificationCenterSettings.scheduledDeliveryEnabled { @@ -369,8 +369,8 @@ extension SettingsView { LargeButton(action: { sheet = .favoriteFoods }, includeArrow: true, imageView: Image("Favorite Foods Icon").renderingMode(.template).foregroundColor(carbTintColor), - label: "Favorite Foods", - descriptiveText: "Simplify Carb Entry") + label: NSLocalizedString("Favorite Foods", comment: "Label for favorite foods in settings view"), + descriptiveText: NSLocalizedString("Simplify Carb Entry", comment: "subheadline of favorite foods in settings view")) } } @@ -493,7 +493,7 @@ extension SettingsView { ) } } - + private func createAppExpirationSection(headerLabel: String, footerLabel: String, expirationLabel: String, updateURL: String, nearExpiration: Bool, expirationMessage: String) -> some View { return Section( header: SectionHeader(label: headerLabel), @@ -557,7 +557,7 @@ fileprivate struct LargeButton: View { let secondaryImageView: SecondaryContent let label: String let descriptiveText: String - + init( action: @escaping () -> Void, includeArrow: Bool = true, @@ -593,15 +593,15 @@ fileprivate struct LargeButton: View { DescriptiveText(label: descriptiveText) } } - + if !(secondaryImageView is EmptyView) || includeArrow { Spacer() } - + if !(secondaryImageView is EmptyView) { secondaryImageView.frame(width: secondaryImageWidth, height: secondaryImageHeight) } - + if includeArrow { // TODO: Ick. I can't use a NavigationLink because we're not Navigating, but this seems worse somehow. Image(systemName: "chevron.right").foregroundColor(.gray).font(.footnote) diff --git a/Loop/de.lproj/Localizable.strings b/Loop/de.lproj/Localizable.strings index dc4c9b5d4b..b44b2ff1bc 100755 --- a/Loop/de.lproj/Localizable.strings +++ b/Loop/de.lproj/Localizable.strings @@ -125,6 +125,9 @@ /* Alert message for a missing pump error */ "A pump must be configured before a bolus can be delivered." = "Eine Pumpe muss konfiguriert werden, bevor ein Bolus abgegeben werden kann."; +/* Label for absorption time in favorite food entry */ +"Absorption Time" = "Resorptionsdauer"; + /* Action to copy the recommended Bolus value to the actual Bolus Field */ "AcceptRecommendedBolus" = "Akzeptiere empfohlenen Bolus"; @@ -143,6 +146,9 @@ /* The string format describing active insulin. (1: localized insulin value description) */ "Active Insulin: %@" = "Aktives Insulin: %@"; +/* No comment provided by engineer. */ +"Add a new favorite food" = "Erstelle einen neuen Favoriten"; + /* Title of the user activity for adding carbs */ "Add Carb Entry" = "KH hinzufügen"; @@ -171,17 +177,24 @@ Notification & Critical Alert Permissions screen title */ "Alert Permissions" = "Benachrichtigungsberechtigungen"; +/* Navigation title for algorithms experiments screen + The title of the Algorithm Experiments section in settings */ +"Algorithm Experiments" = "Algorithmusexperimente"; + +/* Algorithm Experiments description. */ +"Algorithm Experiments are optional modifications to the Loop Algorithm. These modifications are less tested than the standard Loop Algorithm, so please use carefully." = "Algorithmusexperimente sind optionale Modifikationen des Schleifenalgorithmus. Diese Modifikationen sind weniger getestet als der Standard-Loop-Algorithmus. Gehe daher bitte vorsichtig vor!"; + /* The title of the section containing algorithm settings */ "Algorithm Settings" = "Algorithmus-Einstellungen"; -/* Label for when mute alert will end */ -"All alerts muted until" = "Alle Alarme stummgeschaltet bis"; - /* No comment provided by engineer. */ "All Favorites" = "Alle Favoriten"; /* Label for carb quantity entry row on carb entry screen */ -"Amount Consumed" = "KH-Menge gegessen"; +"Amount Consumed" = "Menge gegessen"; + +/* Label for when mute alert will end */ +"All alerts muted until" = "Alle Alarme stummgeschaltet bis"; /* The title of the Amplitude service */ "Amplitude" = "Amplitude"; @@ -210,6 +223,9 @@ /* Settings app profile section */ "App Profile" = "App-Profil"; +/* Placeholder for name in favorite food entry screen */ +"Apple" = "Apfel"; + /* Action sheet confirmation message for pump history deletion */ "Are you sure you want to delete all history entries?" = "Möchtest Du wirklich alle Verlaufseinträge löschen?"; @@ -296,6 +312,10 @@ /* Label for carb entry row on bolus screen */ "Carb Entry" = "KH-Eintrag"; +/* Label for carb quantity entry row on favorite food entry screen + Label for carb quantity in favorite food entry */ +"Carb Quantity" = "KH-Menge"; + /* Details for configuration error when carb ratio schedule is missing */ "Carb Ratio Schedule" = "Zeitplan für das Kohlenhydratverhältnis"; @@ -477,6 +497,9 @@ /* Override error description: duration exceed max (1: max duration in hours). */ "Duration exceeds: %1$.1f hours" = "Dauer überschritten: %1$.1f Stunden"; +/* No comment provided by engineer. */ +"Edit" = "Bearbeiten"; + /* Message to the user to enable bluetooth */ "Enable\nBluetooth" = "Bluetooth einschalten"; @@ -540,6 +563,9 @@ /* No comment provided by engineer. */ "FAVORITE FOODS" = "Favorisiertes Essen"; +/* No comment provided by engineer. */ +"Favorite Foods" = "Favorisiertes Essen"; + /* Title of insulin model preset */ "Fiasp" = "Fiasp"; @@ -549,6 +575,10 @@ /* Secondary text for alerts disabled warning, which appears on the main status screen. */ "Fix now by turning Notifications, Critical Alerts and Time Sensitive Notifications ON." = "Behebe dies jetzt, indem Du Benachrichtigungen, kritische Alarme und zeitkritische Benachrichtigungen einschaltest."; +/* label for food type in favorite entry screen + Label for food type in favorite food entry */ +"Food Type" = "Essensart"; + /* The format string used to describe a finite workout targets duration */ "For %1$@" = "Für %1$@"; @@ -567,6 +597,10 @@ /* The title of the glucose and prediction graph */ "Glucose" = "Blutzucker"; +/* Title for glucose based partial application experiment description + Title of glucose based partial application experiment */ +"Glucose Based Partial Application" = "Glucose Based Partial Application"; + /* The error message when glucose data is too old to be used. (1: glucose data age in minutes) */ "Glucose data is %1$@ old" = "Blutzuckerdaten sind %1$@ alt"; @@ -760,6 +794,10 @@ /* Label for button to mute all alerts */ "Mute All Alerts" = "Alle Alarme stummschalten"; +/* Label for name in favorite food entry + Label for name in favorite food entry screen */ +"Name" = "Name"; + /* Sensor state description for the non-valid state */ "Needs Attention" = "Erfordert Aufmerksamkeit"; @@ -938,15 +976,24 @@ /* The title of the notification action to retry a bolus command */ "Retry" = "Wiederholen"; +/* No comment provided by engineer. */ +"Save" = "Speichern"; + /* Button text to save carbs and/or manual glucose entry and deliver a bolus */ "Save and Deliver" = "Speichern und Bolus abgeben"; +/* No comment provided by engineer. */ +"Save as favorite food" = "Als Favorit speichern"; + /* Button text to save carbs and/or manual glucose entry without a bolus */ "Save without Bolusing" = "Speichern ohne Bolusgabe"; /* Scheduled Delivery status text */ "Scheduled" = "Geplant"; +/* No comment provided by engineer. */ +"Selecting a favorite food in the carb entry screen automatically fills in the carb quantity, food type, and absorption time fields! Tap the add button below to create your first favorite food!" = "Wenn Du auf dem Kohlenhydrat-Eingabebildschirm ein Lieblingslebensmittel auswählst, werden automatisch die Felder Kohlenhydratmenge, Lebensmittelart und Absorptionszeit ausgefüllt! Tippe unten auf die Schaltfläche „Hinzufügen“, um Dein erstes Lieblingsessen zu erstellen!"; + /* The title of the services section in settings */ "Services" = "Dienste"; @@ -965,6 +1012,9 @@ /* Title of simple bolus view when displaying meal entry */ "Simple Meal Calculator" = "Einfacher Mahlzeitenrechner"; +/* subheadline of Favorite Foods */ +"Simplify Carb Entry" = "Vereinfachte KH Eingabe"; + /* Format fragment for a start time */ "since %@" = "seit %@";