From 879a4589d291f84e1a9f6067c77e698795e5a447 Mon Sep 17 00:00:00 2001 From: Felipe Giacomini Cocco Date: Thu, 5 Feb 2026 19:56:10 -0300 Subject: [PATCH] Fix strings detections and translates the entire "Extensions" and "Timer" sections --- DynamicIsland/Localizable.xcstrings | 154 +++++++++++++++++- .../Settings/ExtensionsSettings.swift | 16 +- .../components/Settings/SettingsView.swift | 22 +-- DynamicIsland/enums/TimerDisplayMode.swift | 4 +- DynamicIsland/enums/generic.swift | 11 +- DynamicIsland/models/Constants.swift | 11 +- DynamicIsland/models/TimerPreset.swift | 6 +- 7 files changed, 188 insertions(+), 36 deletions(-) diff --git a/DynamicIsland/Localizable.xcstrings b/DynamicIsland/Localizable.xcstrings index a22ccf3..0c4db4d 100644 --- a/DynamicIsland/Localizable.xcstrings +++ b/DynamicIsland/Localizable.xcstrings @@ -1945,6 +1945,16 @@ } } }, + "Adaptive gradient" : { + "localizations" : { + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gradiente Adaptativo" + } + } + } + }, "Add" : { "localizations" : { "ar" : { @@ -3007,6 +3017,36 @@ } } }, + "Allow extension notch experiences" : { + "localizations" : { + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Permitir experiências de extensão no notch" + } + } + } + }, + "Allow interactive web content" : { + "localizations" : { + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Permitir conteúdo web interativo " + } + } + } + }, + "Allow minimalistic overrides" : { + "localizations" : { + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Permitir substituições minimalistas" + } + } + } + }, "Allowed Features" : { "comment" : "A label describing the allowed features for an app extension.", "isCommentAutoGenerated" : true, @@ -3237,7 +3277,7 @@ "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "Nome da Animaçãp" + "value" : "Nome da Animação" } } } @@ -3988,6 +4028,16 @@ } } }, + "Bar" : { + "localizations" : { + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Barra" + } + } + } + }, "battery" : { "localizations" : { "pt-BR" : { @@ -4699,6 +4749,16 @@ } } }, + "Break" : { + "localizations" : { + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Descanso" + } + } + } + }, "Breakdown" : { "comment" : "A label displayed above the breakdown of memory usage.", "isCommentAutoGenerated" : true, @@ -7950,6 +8010,16 @@ } } }, + "Deep Work" : { + "localizations" : { + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Trabalho Focado" + } + } + } + }, "Default" : { "localizations" : { "ar" : { @@ -10786,6 +10856,16 @@ } } }, + "Focus" : { + "localizations" : { + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Foco" + } + } + } + }, "Focus active: %@" : { "comment" : "An accessibility label for the focus widget, describing the currently active focus mode.", "isCommentAutoGenerated" : true, @@ -10839,6 +10919,9 @@ "frosted" : { "shouldTranslate" : false }, + "Frosted Glass" : { + "shouldTranslate" : false + }, "Full Access" : { "localizations" : { "pt-BR" : { @@ -12260,6 +12343,16 @@ }, "shouldTranslate" : false }, + "Hours" : { + "localizations" : { + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Horas" + } + } + } + }, "hover" : { "shouldTranslate" : false }, @@ -13311,6 +13404,9 @@ } } }, + "Liquid Glass" : { + "shouldTranslate" : false + }, "Liquid Glass requires macOS 26 or later." : { "localizations" : { "fr" : { @@ -17060,7 +17156,7 @@ "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "Nenhuma predefinição configurada. Adicione uma predefinição para que ela apareça no pop-over do temporizador." + "value" : "Nenhuma predefinição configurada. Adicione uma predefinição para que ela apareça no menu suspenso do temporizador." } } } @@ -18504,6 +18600,16 @@ } } }, + "Popover" : { + "localizations" : { + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Menu Suspenso" + } + } + } + }, "Popover mode shows clipboard as a dropdown attached to the clipboard button." : { "comment" : "A description of the \"Popover mode\" in the Clipboard Settings view.", "isCommentAutoGenerated" : true, @@ -18511,7 +18617,7 @@ "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "O modo popover mostra a área de transferência como um menu suspenso anexado ao botão da área de transferência." + "value" : "O modo Menu Suspenso mostra a área de transferência como um menu suspenso anexado ao botão da área de transferência." } } } @@ -18521,7 +18627,7 @@ "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "O modo popover mostra o seletor de cores como um menu suspenso anexado ao botão do seletor de cores. O modo painel mostra o seletor de cores em uma janela flutuante." + "value" : "O modo Menu Suspenso mostra o seletor de cores como um menu suspenso anexado ao botão do seletor de cores. O modo painel mostra o seletor de cores em uma janela flutuante." } } } @@ -18531,7 +18637,7 @@ "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "O modo Popover mostra o assistente como um menu suspenso conectado ao botão AI. O modo painel mostra o assistente em uma janela flutuante perto do notch." + "value" : "O modo Menu Suspenso mostra o assistente como um menu suspenso conectado ao botão AI. O modo painel mostra o assistente em uma janela flutuante perto do notch." } } } @@ -18589,7 +18695,7 @@ "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "Nome da predefinições" + "value" : "Nome da predefinição" } } } @@ -18613,7 +18719,7 @@ "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "As predefinições aparecem dentro do pop-over do temporizador com o nome configurado, a duração e a cor de destaque. Reordene-os para alterar a ordem de exibição." + "value" : "As predefinições aparecem dentro do menu suspenso do temporizador com o nome configurado, a duração e a cor de destaque. Reordene-os para alterar a ordem de exibição." } } } @@ -20282,6 +20388,16 @@ } } }, + "Seconds" : { + "localizations" : { + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Segundos" + } + } + } + }, "Segmented" : { "localizations" : { "fr" : { @@ -21316,6 +21432,16 @@ } } }, + "Show extension tabs" : { + "localizations" : { + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mostrar aba de extensão" + } + } + } + }, "Show floating pause/stop controls" : { "localizations" : { "pt-BR" : { @@ -23256,6 +23382,16 @@ } } }, + "Tab" : { + "localizations" : { + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aba" + } + } + } + }, "Take area screenshot" : { "localizations" : { "fr" : { @@ -23354,7 +23490,7 @@ "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "Essa duração alimenta a opção \"Personalizado\" dentro do popover do temporizador para acesso rápido." + "value" : "Essa duração alimenta a opção \"Personalizado\" dentro do menu suspenso do temporizador para acesso rápido." } } } @@ -23628,7 +23764,7 @@ "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "Presets do Temporizador" + "value" : "Pré-Definições do Temporizador" } } } diff --git a/DynamicIsland/components/Settings/ExtensionsSettings.swift b/DynamicIsland/components/Settings/ExtensionsSettings.swift index 05fc9ed..cda6147 100644 --- a/DynamicIsland/components/Settings/ExtensionsSettings.swift +++ b/DynamicIsland/components/Settings/ExtensionsSettings.swift @@ -61,32 +61,32 @@ struct ExtensionsSettingsView: View { private var globalTogglesSection: some View { Section { - Defaults.Toggle("Enable third-party extensions", key: .enableThirdPartyExtensions) + Defaults.Toggle(String(localized:"Enable third-party extensions"), key: .enableThirdPartyExtensions) .settingsHighlight(id: highlightID("Enable third-party extensions")) if Defaults[.enableThirdPartyExtensions] { - Defaults.Toggle("Allow extension live activities", key: .enableExtensionLiveActivities) + Defaults.Toggle(String(localized:"Allow extension live activities"), key: .enableExtensionLiveActivities) .settingsHighlight(id: highlightID("Allow extension live activities")) - Defaults.Toggle("Allow extension lock screen widgets", key: .enableExtensionLockScreenWidgets) + Defaults.Toggle(String(localized:"Allow extension lock screen widgets"), key: .enableExtensionLockScreenWidgets) .settingsHighlight(id: highlightID("Allow extension lock screen widgets")) - Defaults.Toggle("Allow extension notch experiences", key: .enableExtensionNotchExperiences) + Defaults.Toggle(String(localized:"Allow extension notch experiences"), key: .enableExtensionNotchExperiences) .settingsHighlight(id: highlightID("Allow extension notch experiences")) if Defaults[.enableExtensionNotchExperiences] { VStack(alignment: .leading, spacing: 8) { - Defaults.Toggle("Show extension tabs", key: .enableExtensionNotchTabs) + Defaults.Toggle(String(localized:"Show extension tabs"), key: .enableExtensionNotchTabs) .tint(.accentColor) - Defaults.Toggle("Allow minimalistic overrides", key: .enableExtensionNotchMinimalisticOverrides) + Defaults.Toggle(String(localized:"Allow minimalistic overrides"), key: .enableExtensionNotchMinimalisticOverrides) .tint(.accentColor) - Defaults.Toggle("Allow interactive web content", key: .enableExtensionNotchInteractiveWebViews) + Defaults.Toggle(String(localized:"Allow interactive web content"), key: .enableExtensionNotchInteractiveWebViews) .tint(.accentColor) } .padding(.leading, 4) } - Defaults.Toggle("Enable extension diagnostics logging", key: .extensionDiagnosticsLoggingEnabled) + Defaults.Toggle(String(localized:"Enable extension diagnostics logging"), key: .extensionDiagnosticsLoggingEnabled) .settingsHighlight(id: highlightID("Enable extension diagnostics logging")) } } header: { diff --git a/DynamicIsland/components/Settings/SettingsView.swift b/DynamicIsland/components/Settings/SettingsView.swift index 7418137..dac8606 100644 --- a/DynamicIsland/components/Settings/SettingsView.swift +++ b/DynamicIsland/components/Settings/SettingsView.swift @@ -5322,7 +5322,7 @@ struct TimerSettings: View { @ViewBuilder private var timerFeatureSection: some View { Section { - Defaults.Toggle("Enable timer feature", key: .enableTimerFeature) + Defaults.Toggle(String(localized: "Enable timer feature"), key: .enableTimerFeature) .settingsHighlight(id: highlightID("Enable timer feature")) if enableTimerFeature { @@ -5377,11 +5377,11 @@ struct TimerSettings: View { @ViewBuilder private var lockScreenIntegrationSection: some View { Section { - Defaults.Toggle("Show lock screen timer widget", key: .enableLockScreenTimerWidget) + Defaults.Toggle(String(localized:"Show lock screen timer widget"), key: .enableLockScreenTimerWidget) .settingsHighlight(id: highlightID("Show lock screen timer widget")) Picker("Timer surface", selection: timerSurfaceBinding) { ForEach(LockScreenTimerSurfaceMode.allCases) { mode in - Text(mode.rawValue).tag(mode) + Text(mode.localizedName).tag(mode) } } .pickerStyle(.segmented) @@ -5392,7 +5392,7 @@ struct TimerSettings: View { if timerGlassModeIsGlass { Picker("Timer glass material", selection: $lockScreenTimerGlassStyle) { ForEach(LockScreenGlassStyle.allCases) { style in - Text(style.rawValue).tag(style) + Text(style.localizedName).tag(style) } } .disabled(!enableLockScreenTimerWidget) @@ -5452,9 +5452,9 @@ struct TimerSettings: View { Text("Default Custom Timer") .font(.headline) - TimerDurationStepperRow(title: "Hours", value: $customHours, range: 0...23) - TimerDurationStepperRow(title: "Minutes", value: $customMinutes, range: 0...59) - TimerDurationStepperRow(title: "Seconds", value: $customSeconds, range: 0...59) + TimerDurationStepperRow(title: String(localized:"Hours"), value: $customHours, range: 0...23) + TimerDurationStepperRow(title: String(localized:"Minutes"), value: $customMinutes, range: 0...59) + TimerDurationStepperRow(title: String(localized:"Seconds"), value: $customSeconds, range: 0...59) HStack { Text("Current default:") @@ -5504,7 +5504,7 @@ struct TimerSettings: View { Picker("Progress style", selection: $progressStyle) { ForEach(TimerProgressStyle.allCases) { style in - Text(style.rawValue).tag(style) + Text(style.localizedName).tag(style) } } .pickerStyle(.segmented) @@ -5794,9 +5794,9 @@ private struct TimerPresetEditorRow: View { } HStack(spacing: 16) { - TimerPresetComponentControl(title: "Hours", value: hoursBinding, range: 0...23) - TimerPresetComponentControl(title: "Minutes", value: minutesBinding, range: 0...59) - TimerPresetComponentControl(title: "Seconds", value: secondsBinding, range: 0...59) + TimerPresetComponentControl(title: String(localized:"Hours"), value: hoursBinding, range: 0...23) + TimerPresetComponentControl(title: String(localized:"Minutes"), value: minutesBinding, range: 0...59) + TimerPresetComponentControl(title: String(localized:"Seconds"), value: secondsBinding, range: 0...59) } ColorPicker("Accent colour", selection: colorBinding, supportsOpacity: false) diff --git a/DynamicIsland/enums/TimerDisplayMode.swift b/DynamicIsland/enums/TimerDisplayMode.swift index 00835dd..b65fd56 100644 --- a/DynamicIsland/enums/TimerDisplayMode.swift +++ b/DynamicIsland/enums/TimerDisplayMode.swift @@ -27,9 +27,9 @@ public enum TimerDisplayMode: String, CaseIterable, Defaults.Serializable, Ident var displayName: String { switch self { case .tab: - return "Tab" + return String(localized:"Tab") case .popover: - return "Popover" + return String(localized:"Popover") } } diff --git a/DynamicIsland/enums/generic.swift b/DynamicIsland/enums/generic.swift index 0c92bcd..f9a9b8d 100644 --- a/DynamicIsland/enums/generic.swift +++ b/DynamicIsland/enums/generic.swift @@ -133,8 +133,17 @@ enum SliderColorEnum: String, CaseIterable, Defaults.Serializable { enum LockScreenGlassStyle: String, CaseIterable, Defaults.Serializable, Identifiable { case liquid = "Liquid Glass" case frosted = "Frosted Glass" - + var id: String { rawValue } + + var localizedName: String { + switch self { + case .liquid: + return String(localized: "Liquid Glass") + case .frosted: + return String(localized: "Frosted Glass") + } + } } enum LockScreenGlassCustomizationMode: String, CaseIterable, Defaults.Serializable, Identifiable { diff --git a/DynamicIsland/models/Constants.swift b/DynamicIsland/models/Constants.swift index 44aca8b..b1b0ed7 100644 --- a/DynamicIsland/models/Constants.swift +++ b/DynamicIsland/models/Constants.swift @@ -462,8 +462,8 @@ enum TimerIconColorMode: String, CaseIterable, Identifiable, Defaults.Serializab var displayName: String { switch self { - case .adaptive: return "Adaptive gradient" - case .solid: return "Solid colour" + case .adaptive: return String(localized:"Adaptive gradient") + case .solid: return String(localized:"Solid colour") } } } @@ -473,6 +473,13 @@ enum TimerProgressStyle: String, CaseIterable, Identifiable, Defaults.Serializab case ring = "Ring" var id: String { rawValue } + + var localizedName: String { + switch self { + case .bar: return String(localized:"Bar") + case .ring: return String(localized:"Ring") + } + } } enum ReminderPresentationStyle: String, CaseIterable, Identifiable, Defaults.Serializable { diff --git a/DynamicIsland/models/TimerPreset.swift b/DynamicIsland/models/TimerPreset.swift index b733459..cfd0b9f 100644 --- a/DynamicIsland/models/TimerPreset.swift +++ b/DynamicIsland/models/TimerPreset.swift @@ -97,8 +97,8 @@ struct TimerPreset: Identifiable, Codable, Hashable, Defaults.Serializable { } static let defaultPresets: [TimerPreset] = [ - TimerPreset(name: "Focus", duration: 25 * 60, color: Color.orange), - TimerPreset(name: "Break", duration: 5 * 60, color: Color.green), - TimerPreset(name: "Deep Work", duration: 45 * 60, color: Color.purple) + TimerPreset(name: String(localized:"Focus"), duration: 25 * 60, color: Color.orange), + TimerPreset(name: String(localized:"Break"), duration: 5 * 60, color: Color.green), + TimerPreset(name: String(localized:"Deep Work"), duration: 45 * 60, color: Color.purple) ] }