diff --git a/ENGAGEHF/Dashboard/Messages/MessageRow.swift b/ENGAGEHF/Dashboard/Messages/MessageRow.swift index e26029ed..5cafed6a 100644 --- a/ENGAGEHF/Dashboard/Messages/MessageRow.swift +++ b/ENGAGEHF/Dashboard/Messages/MessageRow.swift @@ -59,7 +59,12 @@ struct MessageRow: View { return Image(systemName: imageName) .cardSymbolStyle() - .accessibilityLabel(message.action.localizedDescription.localizedString() + " Symbol") + .accessibilityLabel( + String( + localized: "\(message.action.localizedDescription.localizedString()) Symbol", + comment: "Accessibility label for message action icon" + ) + ) } private var processingStateView: some View { diff --git a/ENGAGEHF/Dashboard/Messages/MessagesSection.swift b/ENGAGEHF/Dashboard/Messages/MessagesSection.swift index 8bf7e731..64342037 100644 --- a/ENGAGEHF/Dashboard/Messages/MessagesSection.swift +++ b/ENGAGEHF/Dashboard/Messages/MessagesSection.swift @@ -43,11 +43,16 @@ struct MessagesSection: View { private func constructAccessibilityLabel(from message: Message) -> String { - """ - Message: \(message.title), \ - description: \(message.description ?? "none"), \ - action: \(message.action.localizedDescription.localizedString()). - """ + let title = message.title + let description = message.description ?? String( + localized: "No description", + comment: "Accessibility placeholder for missing message description" + ) + let action = message.action.localizedDescription.localizedString() + return String( + localized: "Message: \(title), description: \(description), action: \(action).", + comment: "Accessibility label for a message card" + ) } } diff --git a/ENGAGEHF/HeartHealth/AddMeasurement/AddMeasurementView.swift b/ENGAGEHF/HeartHealth/AddMeasurement/AddMeasurementView.swift index 026dd2b1..da13d7f7 100644 --- a/ENGAGEHF/HeartHealth/AddMeasurement/AddMeasurementView.swift +++ b/ENGAGEHF/HeartHealth/AddMeasurement/AddMeasurementView.swift @@ -98,16 +98,18 @@ struct AddMeasurementView: View { switch type { case .bloodPressure: self.fields = [ - FieldDetails(title: "Systolic"), - FieldDetails(title: "Diastolic") + FieldDetails(title: String(localized: "Systolic", comment: "Blood pressure field label")), + FieldDetails(title: String(localized: "Diastolic", comment: "Blood pressure field label")) ] case .weight: self.fields = [ - FieldDetails(title: Locale.current.measurementSystem == .us ? "lb" : "kg") + FieldDetails(title: Locale.current.measurementSystem == .us + ? String(localized: "lb", comment: "Unit abbreviation for pounds") + : String(localized: "kg", comment: "Unit abbreviation for kilograms")) ] case .heartRate: self.fields = [ - FieldDetails(title: "BPM") + FieldDetails(title: String(localized: "BPM", comment: "Unit abbreviation for beats per minute")) ] default: self.fields = [] diff --git a/ENGAGEHF/HeartHealth/GraphPicker.swift b/ENGAGEHF/HeartHealth/GraphPicker.swift index 40ef5bea..c8fcacf5 100644 --- a/ENGAGEHF/HeartHealth/GraphPicker.swift +++ b/ENGAGEHF/HeartHealth/GraphPicker.swift @@ -16,7 +16,7 @@ struct GraphPicker: View { var body: some View { Picker("Graph Selection", selection: $selection) { ForEach(GraphSelection.allCases) { selection in - Text(String(describing: selection)) + Text(selection.description) .multilineTextAlignment(.center) } } diff --git a/ENGAGEHF/HeartHealth/SelectionTypes/GraphSelection.swift b/ENGAGEHF/HeartHealth/SelectionTypes/GraphSelection.swift index 33619c87..2cfed674 100644 --- a/ENGAGEHF/HeartHealth/SelectionTypes/GraphSelection.swift +++ b/ENGAGEHF/HeartHealth/SelectionTypes/GraphSelection.swift @@ -26,19 +26,19 @@ enum GraphSelection: CaseIterable, Identifiable, CustomStringConvertible, Equata var description: String { switch self { - case .symptoms: "Symptoms" - case .weight: "Weight" - case .heartRate: "HR" - case .bloodPressure: "BP" + case .symptoms: String(localized: "Symptoms", comment: "Graph selection short label") + case .weight: String(localized: "Weight", comment: "Graph selection short label") + case .heartRate: String(localized: "HR", comment: "Graph selection short label for Heart Rate") + case .bloodPressure: String(localized: "BP", comment: "Graph selection short label for Blood Pressure") } } - + var fullName: String { switch self { - case .symptoms: "Symptom Score" - case .weight: "Body Weight" - case .heartRate: "Heart Rate" - case .bloodPressure: "Blood Pressure" + case .symptoms: String(localized: "Symptom Score", comment: "Graph selection full name") + case .weight: String(localized: "Body Weight", comment: "Graph selection full name") + case .heartRate: String(localized: "Heart Rate", comment: "Graph selection full name") + case .bloodPressure: String(localized: "Blood Pressure", comment: "Graph selection full name") } } diff --git a/ENGAGEHF/HeartHealth/SelectionTypes/SymptomsType.swift b/ENGAGEHF/HeartHealth/SelectionTypes/SymptomsType.swift index 658d867a..1bda372d 100644 --- a/ENGAGEHF/HeartHealth/SelectionTypes/SymptomsType.swift +++ b/ENGAGEHF/HeartHealth/SelectionTypes/SymptomsType.swift @@ -27,25 +27,25 @@ enum SymptomsType: String, CaseIterable, Identifiable, CustomStringConvertible, /// The name displayed in the Picker UI element for selecting the symptom type to be shown var description: String { switch self { - case .overall: "Overall" - case .physical: "Physical" - case .social: "Social" - case .quality: "Quality of Life" - case .specific: "Symptoms" - case .dizziness: "Dizziness" + case .overall: String(localized: "Overall", comment: "Symptom type picker label") + case .physical: String(localized: "Physical", comment: "Symptom type picker label") + case .social: String(localized: "Social", comment: "Symptom type picker label") + case .quality: String(localized: "Quality of Life", comment: "Symptom type picker label") + case .specific: String(localized: "Specific Symptoms", comment: "Symptom type picker label") + case .dizziness: String(localized: "Dizziness", comment: "Symptom type picker label") } } - - + + /// The full name of the score, displayed in the Description Header var fullName: String { switch self { - case .overall: "Overall Score" - case .physical: "Physical Limits Score" - case .social: "Social Limits Score" - case .quality: "Quality of Life Score" - case .specific: "Symptom Frequency Score" - case .dizziness: "Dizziness Score" + case .overall: String(localized: "Overall Score", comment: "Symptom score full name") + case .physical: String(localized: "Physical Limits Score", comment: "Symptom score full name") + case .social: String(localized: "Social Limits Score", comment: "Symptom score full name") + case .quality: String(localized: "Quality of Life Score", comment: "Symptom score full name") + case .specific: String(localized: "Symptom Frequency Score", comment: "Symptom score full name") + case .dizziness: String(localized: "Dizziness Score", comment: "Symptom score full name") } } diff --git a/ENGAGEHF/HeartHealth/SelectionTypes/VitalsType.swift b/ENGAGEHF/HeartHealth/SelectionTypes/VitalsType.swift index 49701df8..130fa2ec 100644 --- a/ENGAGEHF/HeartHealth/SelectionTypes/VitalsType.swift +++ b/ENGAGEHF/HeartHealth/SelectionTypes/VitalsType.swift @@ -18,9 +18,9 @@ enum VitalsType: CustomStringConvertible { var description: String { switch self { - case .weight: "Body Weight" - case .heartRate: "Heart Rate" - case .bloodPressure: "Blood Pressure" + case .weight: String(localized: "Body Weight", comment: "Vitals type label") + case .heartRate: String(localized: "Heart Rate", comment: "Vitals type label") + case .bloodPressure: String(localized: "Blood Pressure", comment: "Vitals type label") } } diff --git a/ENGAGEHF/HeartHealth/Shared/DateGranularity.swift b/ENGAGEHF/HeartHealth/Shared/DateGranularity.swift index 3e431079..24e502e1 100644 --- a/ENGAGEHF/HeartHealth/Shared/DateGranularity.swift +++ b/ENGAGEHF/HeartHealth/Shared/DateGranularity.swift @@ -19,9 +19,9 @@ enum DateGranularity: CustomStringConvertible, CaseIterable, Identifiable { var description: String { switch self { - case .daily: "Daily" - case .weekly: "Weekly" - case .monthly: "Monthly" + case .daily: String(localized: "Daily", comment: "Date granularity picker label") + case .weekly: String(localized: "Weekly", comment: "Date granularity picker label") + case .monthly: String(localized: "Monthly", comment: "Date granularity picker label") } } diff --git a/ENGAGEHF/Managers/MedicationsManager/MedicationDetails.swift b/ENGAGEHF/Managers/MedicationsManager/MedicationDetails.swift index 11ebbe5e..e6b9aa77 100644 --- a/ENGAGEHF/Managers/MedicationsManager/MedicationDetails.swift +++ b/ENGAGEHF/Managers/MedicationsManager/MedicationDetails.swift @@ -21,6 +21,18 @@ enum MedicationRecommendationType: String, Decodable, Comparable { case noActionRequired + var localizedDescription: String { + switch self { + case .targetDoseReached: String(localized: "Target Dose Reached", comment: "Medication recommendation type") + case .personalTargetDoseReached: String(localized: "Personal Target Dose Reached", comment: "Medication recommendation type") + case .improvementAvailable: String(localized: "Improvement Available", comment: "Medication recommendation type") + case .morePatientObservationsRequired: String(localized: "More Patient Observations Required", comment: "Medication recommendation type") + case .moreLabObservationsRequired: String(localized: "More Lab Observations Required", comment: "Medication recommendation type") + case .notStarted: String(localized: "Not Started", comment: "Medication recommendation type") + case .noActionRequired: String(localized: "No Action Required", comment: "Medication recommendation type") + } + } + var style: RecommendationStyle { switch self { case .targetDoseReached: .targetReached diff --git a/ENGAGEHF/Managers/VitalsManager/VitalsUnit.swift b/ENGAGEHF/Managers/VitalsManager/VitalsUnit.swift index 9518ebdc..66e56ad5 100644 --- a/ENGAGEHF/Managers/VitalsManager/VitalsUnit.swift +++ b/ENGAGEHF/Managers/VitalsManager/VitalsUnit.swift @@ -19,10 +19,10 @@ enum VitalsUnit: CustomStringConvertible { var description: String { switch self { - case .lbs: "lb" - case .kgs: "kg" - case .mmHg: "mmHg" - case .bpm: "BPM" + case .lbs: String(localized: "lb", comment: "Unit abbreviation for pounds") + case .kgs: String(localized: "kg", comment: "Unit abbreviation for kilograms") + case .mmHg: String(localized: "mmHg", comment: "Unit abbreviation for millimeters of mercury") + case .bpm: String(localized: "BPM", comment: "Unit abbreviation for beats per minute") } } diff --git a/ENGAGEHF/Medications/MedicationsList.swift b/ENGAGEHF/Medications/MedicationsList.swift index f7aaad2d..6eac5d35 100644 --- a/ENGAGEHF/Medications/MedicationsList.swift +++ b/ENGAGEHF/Medications/MedicationsList.swift @@ -20,10 +20,16 @@ struct MedicationsList: View { if containsRecommendations { List { if !currentlyTakenMedications.isEmpty { - MedicationSection(header: "Current Medications", medications: currentlyTakenMedications) + MedicationSection( + header: String(localized: "Current Medications", comment: "Medication section header"), + medications: currentlyTakenMedications + ) } if !notCurrentlyTakenMedications.isEmpty { - MedicationSection(header: "Medications That May Help", medications: notCurrentlyTakenMedications) + MedicationSection( + header: String(localized: "Medications That May Help", comment: "Medication section header"), + medications: notCurrentlyTakenMedications + ) } ColorLegend() } diff --git a/ENGAGEHF/Medications/RowLabel/MedicationRecommendationSymbol.swift b/ENGAGEHF/Medications/RowLabel/MedicationRecommendationSymbol.swift index 340be07e..3c728aee 100644 --- a/ENGAGEHF/Medications/RowLabel/MedicationRecommendationSymbol.swift +++ b/ENGAGEHF/Medications/RowLabel/MedicationRecommendationSymbol.swift @@ -31,7 +31,12 @@ struct MedicationRecommendationSymbol: View { .resizable() .frame(width: 35, height: 35) .foregroundStyle(type.style.color) - .accessibilityLabel("Medication Label: \(type.rawValue)") + .accessibilityLabel( + String( + localized: "Medication Label: \(type.localizedDescription)", + comment: "Accessibility label for medication recommendation symbol" + ) + ) } } diff --git a/ENGAGEHF/Resources/Localizable.xcstrings b/ENGAGEHF/Resources/Localizable.xcstrings index 779dc5d9..99c5e727 100644 --- a/ENGAGEHF/Resources/Localizable.xcstrings +++ b/ENGAGEHF/Resources/Localizable.xcstrings @@ -60,6 +60,17 @@ } } }, + "%@ Symbol" : { + "comment" : "Accessibility label for message action icon", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ Símbolo" + } + } + } + }, "%@ Unit: %@" : { "comment" : "Accessability label used in DisplayMeasurement.", "localizations" : { @@ -310,6 +321,17 @@ } } }, + "Blood Pressure" : { + "comment" : "Graph selection full name", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Presión arterial" + } + } + } + }, "bloodPressureMissing" : { "comment" : "Displayed in the MeasurementListSection of the Heart Health view when no Blood Pressure history found.", "localizations" : { @@ -338,6 +360,28 @@ } } }, + "Body Weight" : { + "comment" : "Graph selection full name", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Peso corporal" + } + } + } + }, + "BP" : { + "comment" : "Graph selection short label for Blood Pressure", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "PA" + } + } + } + }, "BPM" : { "comment" : "Beats per minute", "localizations" : { @@ -410,6 +454,17 @@ } } }, + "Current Medications" : { + "comment" : "Medication section header", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Medicamentos actuales" + } + } + } + }, "daily" : { "comment" : "Schedule frequency", "localizations" : { @@ -421,6 +476,17 @@ } } }, + "Daily" : { + "comment" : "Date granularity picker label", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Diario" + } + } + } + }, "Date" : { "comment" : "The text displayed in the label of the date DatePicker in the AddMeasurementView and in the LineMark and PointMark of the VitalsGraph.", "localizations" : { @@ -471,6 +537,28 @@ } } }, + "Dizziness" : { + "comment" : "Symptom type picker label", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mareos" + } + } + } + }, + "Dizziness Score" : { + "comment" : "Symptom score full name", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Puntuación de mareos" + } + } + } + }, "Education" : { "comment" : "Displayed in the tab item label and navigation title of the Educations view.", "localizations" : { @@ -689,6 +777,17 @@ } } }, + "Heart Rate" : { + "comment" : "Graph selection full name", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Frecuencia cardíaca" + } + } + } + }, "heartRateMissing" : { "comment" : "Displayed in the MeasurementListSection of the Heart Health view when no heart rate measurements were found.", "localizations" : { @@ -728,6 +827,28 @@ } } }, + "HR" : { + "comment" : "Graph selection short label for Heart Rate", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "FC" + } + } + } + }, + "Improvement Available" : { + "comment" : "Medication recommendation type", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mejora disponible" + } + } + } + }, "Inactivity" : { "comment" : "The text displayed in the toggleRow to control to receive inactivity reminders in the NotificationSettingsView.", "localizations" : { @@ -982,6 +1103,28 @@ } } }, + "kg" : { + "comment" : "Unit abbreviation for kilograms", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "kg" + } + } + } + }, + "lb" : { + "comment" : "Unit abbreviation for pounds", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "lb" + } + } + } + }, "Legend" : { "comment" : "The text displayed in the header of the ColorLegend view.", "localizations" : { @@ -1065,6 +1208,28 @@ } } }, + "Medications That May Help" : { + "comment" : "Medication section header", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Medicamentos que podrían ayudar" + } + } + } + }, + "Message: %@, description: %@, action: %@." : { + "comment" : "Accessibility label for a message card", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mensaje: %1$@, descripción: %2$@, acción: %3$@." + } + } + } + }, "Messages" : { "comment" : "The text displayed in the header of MessagesSection and MessageRow views.", "localizations" : { @@ -1098,6 +1263,17 @@ } } }, + "mmHg" : { + "comment" : "Unit abbreviation for millimeters of mercury", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "mmHg" + } + } + } + }, "Moderate" : { "comment" : "Dizziness symptom score label.", "localizations" : { @@ -1109,6 +1285,17 @@ } } }, + "Monthly" : { + "comment" : "Date granularity picker label", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mensual" + } + } + } + }, "More information is needed to make a recommendation." : { "comment" : "Action required color legend entry.", "localizations" : { @@ -1120,6 +1307,39 @@ } } }, + "More Lab Observations Required" : { + "comment" : "Medication recommendation type", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Se requieren más observaciones de laboratorio" + } + } + } + }, + "More Patient Observations Required" : { + "comment" : "Medication recommendation type", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Se requieren más observaciones del paciente" + } + } + } + }, + "No Action Required" : { + "comment" : "Medication recommendation type", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "No se requiere acción" + } + } + } + }, "No Contacts Available" : { "comment" : "The title displayed in the ContentUnavailableView of the Contacts view.", "localizations" : { @@ -1142,6 +1362,17 @@ } } }, + "No description" : { + "comment" : "Accessibility placeholder for missing message description", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sin descripción" + } + } + } + }, "No Educational Videos" : { "comment" : "The title displayed in the ContentUnavailableView of the Education view.", "localizations" : { @@ -1308,6 +1539,28 @@ } } }, + "Overall" : { + "comment" : "Symptom type picker label", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "General" + } + } + } + }, + "Overall Score" : { + "comment" : "Symptom score full name", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Puntuación general" + } + } + } + }, "PDF" : { "comment" : "The text displayed as one of the options of the shareModeSelector in the HealthSummaryView. ", "localizations" : { @@ -1319,6 +1572,39 @@ } } }, + "Personal Target Dose Reached" : { + "comment" : "Medication recommendation type", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dosis objetivo personal alcanzada" + } + } + } + }, + "Physical" : { + "comment" : "Symptom type picker label", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Físico" + } + } + } + }, + "Physical Limits Score" : { + "comment" : "Symptom score full name", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Puntuación de límites físicos" + } + } + } + }, "Play Video" : { "comment" : "The description of the playVideo MessageAction.", "localizations" : { @@ -1413,6 +1699,28 @@ } } }, + "Quality of Life" : { + "comment" : "Symptom type picker label", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Calidad de vida" + } + } + } + }, + "Quality of Life Score" : { + "comment" : "Symptom score full name", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Puntuación de calidad de vida" + } + } + } + }, "Questionnaire Loading" : { "comment" : "The text displayed in the ProgressView of the QuestionnaireSheetView.", "localizations" : { @@ -1663,6 +1971,39 @@ } } }, + "Social" : { + "comment" : "Symptom type picker label", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Social" + } + } + } + }, + "Social Limits Score" : { + "comment" : "Symptom score full name", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Puntuación de límites sociales" + } + } + } + }, + "Specific Symptoms" : { + "comment" : "Symptom type picker label", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Síntomas específicos" + } + } + } + }, "Start Questionnaire" : { "comment" : "The description of the completeQuestionnaire MessageAction.", "localizations" : { @@ -1685,6 +2026,28 @@ } } }, + "Symptom Frequency Score" : { + "comment" : "Symptom score full name", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Puntuación de frecuencia de síntomas" + } + } + } + }, + "Symptom Score" : { + "comment" : "Graph selection full name", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Puntuación de síntomas" + } + } + } + }, "symptomDizziness" : { "comment" : "A text used in the HeartHealth view.", "localizations" : { @@ -1753,6 +2116,17 @@ } } }, + "Symptoms" : { + "comment" : "Graph selection short label", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Síntomas" + } + } + } + }, "Symptoms Picker Chevron" : { "comment" : "Accessability label for the SymptomsPicker view.", "localizations" : { @@ -1837,6 +2211,17 @@ } } }, + "Target Dose Reached" : { + "comment" : "Medication recommendation type", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dosis objetivo alcanzada" + } + } + } + }, "Thank you for participating in the\nENGAGE-HF study!" : { "comment" : "The title that is displayed in the StudyConcluded view.", "localizations" : { @@ -2124,6 +2509,28 @@ } } }, + "Weekly" : { + "comment" : "Date granularity picker label", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semanal" + } + } + } + }, + "Weight" : { + "comment" : "Graph selection short label", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Peso" + } + } + } + }, "Weight Trends" : { "comment" : "The text displayed in the toggleRow to control to receive weight trend notifications in the NotificationSettingsView.", "localizations" : {