From 921b4ca8a1b019a733f809eb91b3ae821d39f4d8 Mon Sep 17 00:00:00 2001 From: Sergey Kemenov Date: Sat, 23 May 2026 11:00:00 +0300 Subject: [PATCH 01/13] feat(ui): add NumeralSystem enum + Typography.numeralSystem field --- MinimalCountdown.xcodeproj/project.pbxproj | 1 + MinimalCountdown/Models/NumeralSystem.swift | 43 +++++++++++++++++++ MinimalCountdown/Models/Typography.swift | 12 ++++++ .../Resources/Localizable.xcstrings | 17 +++++++- MinimalCountdown/Resources/Resources.swift | 8 ++++ 5 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 MinimalCountdown/Models/NumeralSystem.swift diff --git a/MinimalCountdown.xcodeproj/project.pbxproj b/MinimalCountdown.xcodeproj/project.pbxproj index cd8f19a..3cdc0be 100644 --- a/MinimalCountdown.xcodeproj/project.pbxproj +++ b/MinimalCountdown.xcodeproj/project.pbxproj @@ -43,6 +43,7 @@ Models/EffectStyle.swift, Models/FontWeight.swift, Models/LegacySettings.swift, + Models/NumeralSystem.swift, Models/SafeIntDecodable.swift, Models/SaverSettings.swift, Models/Schedule.swift, diff --git a/MinimalCountdown/Models/NumeralSystem.swift b/MinimalCountdown/Models/NumeralSystem.swift new file mode 100644 index 0000000..9b31848 --- /dev/null +++ b/MinimalCountdown/Models/NumeralSystem.swift @@ -0,0 +1,43 @@ +// +// NumeralSystem.swift +// MinimalCountdown +// +// Created by Sergey Kemenov +// + +import Foundation + +enum NumeralSystem: Int, CaseIterable, Identifiable, SafeIntDecodable, Equatable, Hashable { + case automatic = 0, latin, arabic, persian, devanagari + + // safe and un-optional, defaults to .automatic + init(_ rawValue: Int) { + self = .init(rawValue: rawValue) ?? .automatic + } +} + +extension NumeralSystem { + var id: Self { self } + + /// `nil` for `.automatic` — the caller falls back to the resolved locale's own numbering + /// system (UAE → Latin, Egypt → Arabic). The explicit cases override that. + var numberingSystem: Locale.NumberingSystem? { + switch self { + case .automatic: nil + case .latin: Locale.NumberingSystem("latn") + case .arabic: Locale.NumberingSystem("arab") + case .persian: Locale.NumberingSystem("arabext") + case .devanagari: Locale.NumberingSystem("deva") + } + } + + var label: LocalizedStringResource { + switch self { + case .automatic: Resources.Labels.NumeralSystem.automatic + case .latin: Resources.Labels.NumeralSystem.latin + case .arabic: Resources.Labels.NumeralSystem.arabic + case .persian: Resources.Labels.NumeralSystem.persian + case .devanagari: Resources.Labels.NumeralSystem.devanagari + } + } +} diff --git a/MinimalCountdown/Models/Typography.swift b/MinimalCountdown/Models/Typography.swift index 6da9f3b..a8d53ce 100644 --- a/MinimalCountdown/Models/Typography.swift +++ b/MinimalCountdown/Models/Typography.swift @@ -10,4 +10,16 @@ import Foundation struct Typography: Codable, Equatable, Hashable { var weight: FontWeight var isRounded: Bool + var numeralSystem: NumeralSystem = .automatic +} + +extension Typography { + // Settings written before the Numerals picker have no `numeralSystem` key — decode it + // tolerantly so existing v2 files still load (no schema version bump needed). + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + weight = try container.decode(FontWeight.self, forKey: .weight) + isRounded = try container.decode(Bool.self, forKey: .isRounded) + numeralSystem = try container.decodeIfPresent(NumeralSystem.self, forKey: .numeralSystem) ?? .automatic + } } diff --git a/MinimalCountdown/Resources/Localizable.xcstrings b/MinimalCountdown/Resources/Localizable.xcstrings index 00a1e73..c98531d 100644 --- a/MinimalCountdown/Resources/Localizable.xcstrings +++ b/MinimalCountdown/Resources/Localizable.xcstrings @@ -140,6 +140,12 @@ } } } + }, + "Arabic" : { + + }, + "Automatic" : { + }, "Backlight" : { "localizations" : { @@ -532,6 +538,9 @@ } } } + }, + "Devanagari" : { + }, "Digits" : { "localizations" : { @@ -896,6 +905,9 @@ } } } + }, + "Latin" : { + }, "Low" : { "localizations" : { @@ -1064,6 +1076,9 @@ } } } + }, + "Persian" : { + }, "Pink" : { "localizations" : { @@ -1858,4 +1873,4 @@ } }, "version" : "1.2" -} +} \ No newline at end of file diff --git a/MinimalCountdown/Resources/Resources.swift b/MinimalCountdown/Resources/Resources.swift index c350193..caae7be 100644 --- a/MinimalCountdown/Resources/Resources.swift +++ b/MinimalCountdown/Resources/Resources.swift @@ -72,6 +72,14 @@ enum Resources { static let purple = LocalizedStringResource("Purple", bundle: .app) static let black = LocalizedStringResource("Black", bundle: .app) } + + enum NumeralSystem { + static let automatic = LocalizedStringResource("Automatic", bundle: .app) + static let latin = LocalizedStringResource("Latin", bundle: .app) + static let arabic = LocalizedStringResource("Arabic", bundle: .app) + static let persian = LocalizedStringResource("Persian", bundle: .app) + static let devanagari = LocalizedStringResource("Devanagari", bundle: .app) + } } enum Appearance { From 63c99a80015ad1c8f12b5020f8c1d070a029a635 Mon Sep 17 00:00:00 2001 From: Sergey Kemenov Date: Sat, 23 May 2026 12:30:00 +0300 Subject: [PATCH 02/13] feat(ui): format countdown digits via numeral system; pin countdown row LTR --- .../Extensions/Date+Extensions.swift | 15 +++++++-------- MinimalCountdown/Views/CountdownView.swift | 11 ++++++----- MinimalCountdown/Views/CountdownWindow.swift | 7 ++++++- MinimalCountdown/Views/UIModel.swift | 16 +++++++++++++++- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/MinimalCountdown/Extensions/Date+Extensions.swift b/MinimalCountdown/Extensions/Date+Extensions.swift index 30205c4..d6d6c3c 100644 --- a/MinimalCountdown/Extensions/Date+Extensions.swift +++ b/MinimalCountdown/Extensions/Date+Extensions.swift @@ -9,10 +9,10 @@ import Foundation extension Date { // MARK: - Duration components relative to a reference `now` for target date - func daysString(relativeTo now: Date) -> String { self.duration(from: now, for: .days) } - func hoursString(relativeTo now: Date) -> String { self.duration(from: now, for: .hours) } - func minutesString(relativeTo now: Date) -> String { self.duration(from: now, for: .minutes) } - func secondsString(relativeTo now: Date) -> String { self.duration(from: now, for: .seconds) } + func days(relativeTo now: Date) -> Int { self.duration(from: now, for: .days) } + func hours(relativeTo now: Date) -> Int { self.duration(from: now, for: .hours) } + func minutes(relativeTo now: Date) -> Int { self.duration(from: now, for: .minutes) } + func seconds(relativeTo now: Date) -> Int { self.duration(from: now, for: .seconds) } // MARK: - DatePicker and date verification components func datesInBetween() -> ClosedRange { minDate ... maxDate } @@ -23,19 +23,18 @@ extension Date { // MARK: - Private helpers private extension Date { - func duration(from now: Date, for element: AppearanceStyle) -> String { + func duration(from now: Date, for element: AppearanceStyle) -> Int { // use ceil to fix double-zero issue let total = Int(abs(ceil(self.timeIntervalSince(now)))) - let elementDuration: Int = switch element { + return switch element { case .days: total / .oneDay case .hours: total % .oneDay / .oneHour case .minutes: total % .oneHour / .oneMinute case .seconds: total % .oneMinute } - return String(format: "%02d", elementDuration) } - + func farAvailableDate(isFuture: Bool) -> Self { Date(timeInterval: (isFuture ? .oneYearAndOneDay : -.oneYearAndOneDay), since: self) } diff --git a/MinimalCountdown/Views/CountdownView.swift b/MinimalCountdown/Views/CountdownView.swift index 4b26b4e..7d22fba 100644 --- a/MinimalCountdown/Views/CountdownView.swift +++ b/MinimalCountdown/Views/CountdownView.swift @@ -41,12 +41,13 @@ private extension CountdownView { } func digits(for style: AppearanceStyle) -> String { - switch style { - case .days: settings.schedule.target.daysString(relativeTo: now) - case .hours: settings.schedule.target.hoursString(relativeTo: now) - case .minutes: settings.schedule.target.minutesString(relativeTo: now) - case .seconds: settings.schedule.target.secondsString(relativeTo: now) + let value = switch style { + case .days: settings.schedule.target.days(relativeTo: now) + case .hours: settings.schedule.target.hours(relativeTo: now) + case .minutes: settings.schedule.target.minutes(relativeTo: now) + case .seconds: settings.schedule.target.seconds(relativeTo: now) } + return UIModel.formattedDigits(value, in: render.digitLocale) } } diff --git a/MinimalCountdown/Views/CountdownWindow.swift b/MinimalCountdown/Views/CountdownWindow.swift index 745fa02..ea95d1a 100644 --- a/MinimalCountdown/Views/CountdownWindow.swift +++ b/MinimalCountdown/Views/CountdownWindow.swift @@ -12,8 +12,10 @@ struct CountdownWindow: View { let settings: SaverSettings var isPreview: Bool = false + @Environment(\.locale) private var locale + var body: some View { - let render = UIModel.RenderSettings(settings) + let render = UIModel.RenderSettings(settings, locale: locale) let titleText = UIModel.formattedTitle(settings.title) GeometryReader { geo in @@ -43,6 +45,9 @@ struct CountdownWindow: View { .frame(width: geo.size.width, height: geo.size.height) } } + // The countdown is a clock/number — keep it left-to-right even under an RTL (Arabic) locale + // (HIG: don't reverse the digits in a number). The settings window still mirrors normally. + .environment(\.layoutDirection, .leftToRight) } } diff --git a/MinimalCountdown/Views/UIModel.swift b/MinimalCountdown/Views/UIModel.swift index 8e1e020..80d3cc3 100644 --- a/MinimalCountdown/Views/UIModel.swift +++ b/MinimalCountdown/Views/UIModel.swift @@ -16,8 +16,9 @@ enum UIModel { let isLabelHidden: Bool let effect: EffectStyle let effectGlowColor: Color + let digitLocale: Locale - init(_ settings: SaverSettings) { + init(_ settings: SaverSettings, locale: Locale = .autoupdatingCurrent) { let theme = settings.theme digitsColor = theme.accent.color.opacity(theme.brightness.digitsOpacity) textsColor = theme.accent.color.opacity(theme.brightness.textsOpacity) @@ -28,6 +29,13 @@ enum UIModel { // Glow dimmed by brightness, matching the digit fill: effectColor for glow, accent otherwise. effectGlowColor = (theme.effect == .glow ? theme.effectColor : theme.accent) .color.opacity(theme.brightness.digitsOpacity) + + // Numerals: an explicit pick overrides; `.automatic` falls back to the locale's own + // numbering system (UAE → Latin, Egypt → Arabic). + let numbering = settings.typography.numeralSystem.numberingSystem ?? locale.numberingSystem + var components = Locale.Components(locale: locale) + components.numberingSystem = numbering + digitLocale = Locale(components: components) } } @@ -54,6 +62,12 @@ enum UIModel { return words.joined(separator: separator) } + /// Countdown digit string: zero-padded (min 2, grows for 3-digit day counts) and rendered + /// in `locale`'s numeral system (the resolved `RenderSettings.digitLocale`). + static func formattedDigits(_ value: Int, in locale: Locale) -> String { + value.formatted(.number.precision(.integerLength(2...)).grouping(.never).locale(locale)) + } + /// Effect-section subtitle/tooltip: the base hint + a localized "or"-list of the available /// effect names (lowercased). static var effectsHint: String { From 40cd6335bbe51811331cf81982284424bff8dbaf Mon Sep 17 00:00:00 2001 From: Sergey Kemenov Date: Sat, 23 May 2026 14:00:00 +0300 Subject: [PATCH 03/13] feat(ui): add Numerals picker to the Digits section --- .../ConfigureView/ConfigurationWindow.swift | 21 +++++++++++++++++++ .../Resources/Localizable.xcstrings | 6 ++++++ MinimalCountdown/Resources/Resources.swift | 5 +++++ 3 files changed, 32 insertions(+) diff --git a/MinimalCountdown/ConfigureView/ConfigurationWindow.swift b/MinimalCountdown/ConfigureView/ConfigurationWindow.swift index 1d3de72..b44c4a1 100644 --- a/MinimalCountdown/ConfigureView/ConfigurationWindow.swift +++ b/MinimalCountdown/ConfigureView/ConfigurationWindow.swift @@ -153,6 +153,17 @@ private extension ConfigurationWindow { } } .help(Text(Resources.Digits.roundedHint)) + + Picker(selection: $settings.typography.numeralSystem) { + ForEach(NumeralSystem.allCases) { system in + Text(numeralRow(system)).tag(system) + } + } label: { + Text(Resources.Digits.numerals) + Text(Resources.Digits.numeralsHint) + .subtitleFont + } + .help(Text(Resources.Digits.numeralsHint)) } header: { Text(Resources.Digits.title) } @@ -224,6 +235,16 @@ private extension ConfigurationWindow { return Text(row) } + /// Picker row: the numeral-system name + a `123` glyph sample for the explicit systems. + /// `.automatic` shows the name only — its glyphs depend on the viewer's locale. + func numeralRow(_ system: NumeralSystem) -> String { + let name = String(localized: system.label) + guard let numbering = system.numberingSystem else { return name } + var components = Locale.Components(identifier: "en_US") + components.numberingSystem = numbering + return "\(name) \(UIModel.formattedDigits(123, in: Locale(components: components)))" + } + func prepareForDisplay() { withAnimation(.none) { settings = settingsManager.settings diff --git a/MinimalCountdown/Resources/Localizable.xcstrings b/MinimalCountdown/Resources/Localizable.xcstrings index c98531d..f730413 100644 --- a/MinimalCountdown/Resources/Localizable.xcstrings +++ b/MinimalCountdown/Resources/Localizable.xcstrings @@ -1048,6 +1048,9 @@ } } } + }, + "Numerals" : { + }, "Orange" : { "localizations" : { @@ -1275,6 +1278,9 @@ } } } + }, + "Sets the numerals used for the digits. Automatic follows your system's region." : { + }, "Show only digits, without any labels underneath." : { "localizations" : { diff --git a/MinimalCountdown/Resources/Resources.swift b/MinimalCountdown/Resources/Resources.swift index caae7be..9d1a68a 100644 --- a/MinimalCountdown/Resources/Resources.swift +++ b/MinimalCountdown/Resources/Resources.swift @@ -135,6 +135,11 @@ enum Resources { ) static let rounded = LocalizedStringResource("Round digits", bundle: .app) static let roundedHint = LocalizedStringResource("Renders the digits with the Rounded design.", bundle: .app) + static let numerals = LocalizedStringResource("Numerals", bundle: .app) + static let numeralsHint = LocalizedStringResource( + "Sets the numerals used for the digits. Automatic follows your system's region.", + bundle: .app + ) } enum Title { From ac0b2e73a6928cec89e63bcbee4b99c905a580d6 Mon Sep 17 00:00:00 2001 From: Sergey Kemenov Date: Sat, 23 May 2026 15:30:00 +0300 Subject: [PATCH 04/13] feat(ui): localize Numerals picker (ru/de/es/fr) + refine hint copy --- .../Resources/Localizable.xcstrings | 193 +++++++++++++++++- MinimalCountdown/Resources/Resources.swift | 2 +- 2 files changed, 185 insertions(+), 10 deletions(-) diff --git a/MinimalCountdown/Resources/Localizable.xcstrings b/MinimalCountdown/Resources/Localizable.xcstrings index f730413..93dcb0b 100644 --- a/MinimalCountdown/Resources/Localizable.xcstrings +++ b/MinimalCountdown/Resources/Localizable.xcstrings @@ -142,10 +142,60 @@ } }, "Arabic" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arabisch" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Árabes" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Arabes" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Арабские" + } + } + } }, "Automatic" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatisch" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automático" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatique" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Автоматически" + } + } + } }, "Backlight" : { "localizations" : { @@ -540,7 +590,32 @@ } }, "Devanagari" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Devanagari" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Devanagari" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Devanagari" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Деванагари" + } + } + } }, "Digits" : { "localizations" : { @@ -907,7 +982,32 @@ } }, "Latin" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lateinisch" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Latinos" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Latins" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Латинские" + } + } + } }, "Low" : { "localizations" : { @@ -1050,7 +1150,32 @@ } }, "Numerals" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zahlen" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Números" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Numéros" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Числа" + } + } + } }, "Orange" : { "localizations" : { @@ -1081,7 +1206,32 @@ } }, "Persian" : { - + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Persisch" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Persas" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Persans" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Персидские" + } + } + } }, "Pink" : { "localizations" : { @@ -1279,8 +1429,33 @@ } } }, - "Sets the numerals used for the digits. Automatic follows your system's region." : { - + "Sets the numeral system used for the digits. Automatic follows your Mac's region." : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Legt das Zahlensystem für die Ziffern fest. Automatisch folgt der Region des Mac." + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Define los números usados para los dígitos. Automático sigue la región del Mac." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Définit le système de numération utilisé pour les chiffres. Automatique suit la région du Mac." + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Задаёт систему счисления для цифр. Автоматически следует региону Mac." + } + } + } }, "Show only digits, without any labels underneath." : { "localizations" : { @@ -1879,4 +2054,4 @@ } }, "version" : "1.2" -} \ No newline at end of file +} diff --git a/MinimalCountdown/Resources/Resources.swift b/MinimalCountdown/Resources/Resources.swift index 9d1a68a..90490a0 100644 --- a/MinimalCountdown/Resources/Resources.swift +++ b/MinimalCountdown/Resources/Resources.swift @@ -137,7 +137,7 @@ enum Resources { static let roundedHint = LocalizedStringResource("Renders the digits with the Rounded design.", bundle: .app) static let numerals = LocalizedStringResource("Numerals", bundle: .app) static let numeralsHint = LocalizedStringResource( - "Sets the numerals used for the digits. Automatic follows your system's region.", + "Sets the numeral system used for the digits. Automatic follows your Mac's region.", bundle: .app ) } From 78185ea53db36834063e8ce9798357824479af69 Mon Sep 17 00:00:00 2001 From: Sergey Kemenov Date: Sat, 23 May 2026 17:00:00 +0300 Subject: [PATCH 05/13] feat(ui): add Arabic (ar) localization --- MinimalCountdown.xcodeproj/project.pbxproj | 1 + .../Resources/Localizable.xcstrings | 426 ++++++++++++++++++ 2 files changed, 427 insertions(+) diff --git a/MinimalCountdown.xcodeproj/project.pbxproj b/MinimalCountdown.xcodeproj/project.pbxproj index 3cdc0be..fd908d5 100644 --- a/MinimalCountdown.xcodeproj/project.pbxproj +++ b/MinimalCountdown.xcodeproj/project.pbxproj @@ -203,6 +203,7 @@ de, es, fr, + ar, ); mainGroup = E9B531912B854D60002A2B79; productRefGroup = E9B5319C2B854D60002A2B79 /* Products */; diff --git a/MinimalCountdown/Resources/Localizable.xcstrings b/MinimalCountdown/Resources/Localizable.xcstrings index 93dcb0b..9d723b1 100644 --- a/MinimalCountdown/Resources/Localizable.xcstrings +++ b/MinimalCountdown/Resources/Localizable.xcstrings @@ -3,6 +3,12 @@ "strings" : { "⚠️ Looks better at lighter weights." : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ يبدو أفضل مع أوزان أخف." + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -31,6 +37,12 @@ }, "⚠️ Looks better at Regular weight or higher." : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ يبدو أفضل مع وزن «عادي» أو أعلى." + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -59,6 +71,12 @@ }, "⚠️ Looks better with Rounded enabled." : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ يبدو أفضل عند تفعيل التدوير." + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -87,6 +105,12 @@ }, "Adds an effect to the digits:" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "يضيف تأثيراً على الأرقام:" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -115,6 +139,12 @@ }, "Appearance" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "المظهر" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -143,6 +173,12 @@ }, "Arabic" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "عربية" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -171,6 +207,12 @@ }, "Automatic" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "تلقائي" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -199,6 +241,12 @@ }, "Backlight" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "إضاءة خلفية" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -227,6 +275,12 @@ }, "Black" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "أسود" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -255,6 +309,12 @@ }, "Blue" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "أزرق" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -283,6 +343,12 @@ }, "Blur" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "تمويه" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -311,6 +377,12 @@ }, "Brightness" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "السطوع" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -339,6 +411,12 @@ }, "Close" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "إغلاق" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -367,6 +445,12 @@ }, "Close this window and click Preview to see all the changes in detail, full-screen." : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "أغلق هذه النافذة وانقر على «معاينة» لرؤية جميع التغييرات بالتفصيل على الشاشة الكاملة." + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -395,6 +479,12 @@ }, "Color" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "اللون" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -423,6 +513,12 @@ }, "Could not save settings. Try closing and reopening Settings, restarting your Mac, or reinstalling the screen saver." : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "تعذّر حفظ الإعدادات. حاول إغلاق الإعدادات وإعادة فتحها، أو إعادة تشغيل الـ Mac، أو إعادة تثبيت شاشة التوقف." + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -451,6 +547,12 @@ }, "Cyan" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "سماوي" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -479,6 +581,12 @@ }, "Date" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "التاريخ" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -507,6 +615,12 @@ }, "Day" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "اليوم" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -535,6 +649,12 @@ }, "Days" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "أيام" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -563,6 +683,12 @@ }, "Defaults to midnight." : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "الافتراضي: منتصف الليل." + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -591,6 +717,12 @@ }, "Devanagari" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "ديفاناغاري" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -619,6 +751,12 @@ }, "Digits" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "الأرقام" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -647,6 +785,12 @@ }, "Effect" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "التأثير" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -675,6 +819,12 @@ }, "Effect Color" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "لون التأثير" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -703,6 +853,12 @@ }, "Glow" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "توهج" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -731,6 +887,12 @@ }, "Green" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "أخضر" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -759,6 +921,12 @@ }, "Hide labels" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "إخفاء التسميات" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -787,6 +955,12 @@ }, "Hide title" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "إخفاء العنوان" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -815,6 +989,12 @@ }, "Hides the title even when it isn't empty." : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "يخفي العنوان حتى لو لم يكن فارغاً." + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -843,6 +1023,12 @@ }, "High" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "عالي" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -871,6 +1057,12 @@ }, "Hours" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "ساعات" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -899,6 +1091,12 @@ }, "Indigo" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "نيلي" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -927,6 +1125,12 @@ }, "Inner Glow" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "توهج داخلي" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -955,6 +1159,12 @@ }, "It can be any future date for Timer Mode or any past date for Stopwatch Mode." : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "يمكن أن يكون أي تاريخ مستقبلي لوضع المؤقت أو أي تاريخ ماضٍ لوضع ساعة الإيقاف." + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -983,6 +1193,12 @@ }, "Latin" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "لاتينية" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1011,6 +1227,12 @@ }, "Low" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "منخفض" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1039,6 +1261,12 @@ }, "Medium" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "متوسط" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1067,6 +1295,12 @@ }, "Mint" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "نعناعي" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1095,6 +1329,12 @@ }, "Minutes" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "دقائق" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1123,6 +1363,12 @@ }, "None" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "لا شيء" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1151,6 +1397,12 @@ }, "Numerals" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "الأعداد" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1179,6 +1431,12 @@ }, "Orange" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "برتقالي" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1207,6 +1465,12 @@ }, "Persian" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "فارسية" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1235,6 +1499,12 @@ }, "Pink" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "وردي" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1263,6 +1533,12 @@ }, "Purple" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "بنفسجي" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1291,6 +1567,12 @@ }, "Red" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "أحمر" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1319,6 +1601,12 @@ }, "Renders the digits with the Rounded design." : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "يعرض الأرقام بالتصميم المُدوّر." + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1347,6 +1635,12 @@ }, "Round digits" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "تدوير الأرقام" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1375,6 +1669,12 @@ }, "Seconds" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "ثوانٍ" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1403,6 +1703,12 @@ }, "Sets the digit thickness from Ultra Light to Black." : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "يحدّد سُمك الأرقام من رفيع جداً إلى أسود." + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1431,6 +1737,12 @@ }, "Sets the numeral system used for the digits. Automatic follows your Mac's region." : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "يحدّد نظام الأعداد المُستخدم للأرقام. يتبع الوضع التلقائي منطقة الـ Mac." + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1459,6 +1771,12 @@ }, "Show only digits, without any labels underneath." : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "عرض الأرقام فقط، بدون تسميات أسفلها." + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1487,6 +1805,12 @@ }, "The available range is one year before and after the current date." : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "النطاق المتاح هو سنة واحدة قبل وبعد التاريخ الحالي." + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1515,6 +1839,12 @@ }, "Theme" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "السمة" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1543,6 +1873,12 @@ }, "Think of a cool idea for a screen saver title and write it here" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "فكّر في فكرة رائعة لعنوان شاشة التوقف واكتبها هنا" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1571,6 +1907,12 @@ }, "Time" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "الوقت" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1599,6 +1941,12 @@ }, "Title" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "العنوان" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1627,6 +1975,12 @@ }, "Weight" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "السمك" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1656,6 +2010,12 @@ "Weight.black" : { "extractionState" : "extracted_with_value", "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "أسود" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1691,6 +2051,12 @@ "Weight.bold" : { "extractionState" : "extracted_with_value", "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "عريض" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1726,6 +2092,12 @@ "Weight.heavy" : { "extractionState" : "extracted_with_value", "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "ثقيل" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1761,6 +2133,12 @@ "Weight.light" : { "extractionState" : "extracted_with_value", "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "خفيف" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1796,6 +2174,12 @@ "Weight.medium" : { "extractionState" : "extracted_with_value", "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "متوسط" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1831,6 +2215,12 @@ "Weight.regular" : { "extractionState" : "extracted_with_value", "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "عادي" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1866,6 +2256,12 @@ "Weight.semibold" : { "extractionState" : "extracted_with_value", "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "شبه عريض" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1901,6 +2297,12 @@ "Weight.thin" : { "extractionState" : "extracted_with_value", "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "رفيع" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1936,6 +2338,12 @@ "Weight.ultraLight" : { "extractionState" : "extracted_with_value", "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "رفيع جداً" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1970,6 +2378,12 @@ }, "When the countdown reaches zero, it automatically switches to Stopwatch Mode and starts counting up." : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "عندما يصل العد التنازلي إلى الصفر، يتحول تلقائياً إلى وضع ساعة الإيقاف ويبدأ العد التصاعدي." + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -1998,6 +2412,12 @@ }, "White" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "أبيض" + } + }, "de" : { "stringUnit" : { "state" : "translated", @@ -2026,6 +2446,12 @@ }, "Yellow" : { "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "أصفر" + } + }, "de" : { "stringUnit" : { "state" : "translated", From 934219e64b1b599c9ebf47991b1250c80d383f4e Mon Sep 17 00:00:00 2001 From: Sergey Kemenov Date: Sun, 24 May 2026 13:00:01 +0300 Subject: [PATCH 06/13] feat(ui): add Hebrew (he) localization --- MinimalCountdown.xcodeproj/project.pbxproj | 1 + .../Resources/Localizable.xcstrings | 428 +++++++++++++++++- 2 files changed, 428 insertions(+), 1 deletion(-) diff --git a/MinimalCountdown.xcodeproj/project.pbxproj b/MinimalCountdown.xcodeproj/project.pbxproj index fd908d5..da22ace 100644 --- a/MinimalCountdown.xcodeproj/project.pbxproj +++ b/MinimalCountdown.xcodeproj/project.pbxproj @@ -204,6 +204,7 @@ es, fr, ar, + he, ); mainGroup = E9B531912B854D60002A2B79; productRefGroup = E9B5319C2B854D60002A2B79 /* Products */; diff --git a/MinimalCountdown/Resources/Localizable.xcstrings b/MinimalCountdown/Resources/Localizable.xcstrings index 9d723b1..9900f65 100644 --- a/MinimalCountdown/Resources/Localizable.xcstrings +++ b/MinimalCountdown/Resources/Localizable.xcstrings @@ -27,6 +27,12 @@ "value" : "⚠️ Plus joli avec des épaisseurs plus fines." } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ נראה טוב יותר עם עוביים דקים יותר." + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -61,6 +67,12 @@ "value" : "⚠️ Plus joli à l’épaisseur Normale ou supérieure." } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ נראה טוב יותר עם עובי «רגיל» ומעלה." + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -95,6 +107,12 @@ "value" : "⚠️ Plus joli avec l’arrondi activé." } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ נראה טוב יותר עם העיגול מופעל." + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -129,6 +147,12 @@ "value" : "Ajoute un effet aux chiffres :" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "מוסיף אפקט לספרות:" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -163,6 +187,12 @@ "value" : "Apparence" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "מראה" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -197,6 +227,12 @@ "value" : "Arabes" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "ערבי" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -231,6 +267,12 @@ "value" : "Automatique" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "אוטומטי" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -265,6 +307,12 @@ "value" : "Rétroéclairage" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "תאורה אחורית" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -299,6 +347,12 @@ "value" : "Noir" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "שחור" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -333,6 +387,12 @@ "value" : "Bleu" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "כחול" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -367,6 +427,12 @@ "value" : "Flou" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "טשטוש" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -401,6 +467,12 @@ "value" : "Luminosité" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "בהירות" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -435,6 +507,12 @@ "value" : "Fermer" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "סגור" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -469,6 +547,12 @@ "value" : "Fermez cette fenêtre et cliquez sur « Aperçu » pour voir tous les changements en détail, en plein écran." } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "סגור חלון זה ולחץ על «תצוגה מקדימה» כדי לראות את כל השינויים במסך מלא." + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -503,6 +587,12 @@ "value" : "Couleur" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "צבע" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -537,6 +627,12 @@ "value" : "Impossible d’enregistrer les réglages. Essayez de fermer puis de rouvrir les Réglages, de redémarrer votre Mac ou de réinstaller l’économiseur d’écran." } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "לא ניתן לשמור את ההגדרות. נסה לסגור ולפתוח מחדש את ההגדרות, לאתחל את ה-Mac או להתקין מחדש את שומר המסך." + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -571,6 +667,12 @@ "value" : "Cyan" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "ציאן" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -605,6 +707,12 @@ "value" : "Date" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "תאריך" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -639,6 +747,12 @@ "value" : "Jour" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "יום" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -673,6 +787,12 @@ "value" : "Jours" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "ימים" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -707,6 +827,12 @@ "value" : "Minuit par défaut." } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "ברירת מחדל: חצות." + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -741,6 +867,12 @@ "value" : "Devanagari" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "דוונגרי" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -775,6 +907,12 @@ "value" : "Chiffres" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "ספרות" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -809,6 +947,12 @@ "value" : "Effet" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "אפקט" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -843,6 +987,12 @@ "value" : "Couleur de l’effet" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "צבע האפקט" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -877,6 +1027,12 @@ "value" : "Lueur" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "זוהר" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -911,6 +1067,12 @@ "value" : "Vert" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "ירוק" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -945,6 +1107,12 @@ "value" : "Masquer les étiquettes" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "הסתר תוויות" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -979,6 +1147,12 @@ "value" : "Masquer le titre" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "הסתר כותרת" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1013,6 +1187,12 @@ "value" : "Masque le titre même lorsqu’il n’est pas vide." } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "מסתיר את הכותרת גם כשהיא לא ריקה." + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1047,6 +1227,12 @@ "value" : "Élevée" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "גבוה" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1081,6 +1267,12 @@ "value" : "Heures" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "שעות" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1115,6 +1307,12 @@ "value" : "Indigo" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "אינדיגו" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1149,6 +1347,12 @@ "value" : "Lueur intérieure" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "זוהר פנימי" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1183,6 +1387,12 @@ "value" : "Il peut s’agir de n’importe quelle date future pour le mode Minuteur ou de n’importe quelle date passée pour le mode Chronomètre." } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "יכול להיות כל תאריך עתידי למצב טיימר או כל תאריך עבר למצב שעון עצר." + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1217,6 +1427,12 @@ "value" : "Latins" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "לטיני" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1251,6 +1467,12 @@ "value" : "Faible" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "נמוך" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1285,6 +1507,12 @@ "value" : "Moyenne" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "בינוני" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1319,6 +1547,12 @@ "value" : "Menthe" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "מנטה" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1353,6 +1587,12 @@ "value" : "Minutes" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "דקות" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1387,6 +1627,12 @@ "value" : "Aucun" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "ללא" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1421,6 +1667,12 @@ "value" : "Numéros" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "ספרות" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1455,6 +1707,12 @@ "value" : "Orange" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "כתום" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1489,6 +1747,12 @@ "value" : "Persans" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "פרסי" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1523,6 +1787,12 @@ "value" : "Rose" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "ורוד" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1557,6 +1827,12 @@ "value" : "Violet" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "סגול" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1591,6 +1867,12 @@ "value" : "Rouge" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "אדום" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1625,6 +1907,12 @@ "value" : "Affiche les chiffres avec le style arrondi." } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "מציג את הספרות בעיצוב המעוגל." + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1659,6 +1947,12 @@ "value" : "Arrondir les chiffres" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "עיגול ספרות" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1693,6 +1987,12 @@ "value" : "Secondes" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "שניות" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1727,6 +2027,12 @@ "value" : "Définit l’épaisseur des chiffres, d’Ultrafine à Noire." } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "מגדיר את עובי הספרות מבהיר במיוחד לשחור." + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1761,6 +2067,12 @@ "value" : "Définit le système de numération utilisé pour les chiffres. Automatique suit la région du Mac." } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "קובע את מערכת הספרות המשמשת את האותיות. אוטומטי עוקב אחר אזור ה-Mac שלך." + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1795,6 +2107,12 @@ "value" : "Afficher uniquement les chiffres, sans étiquettes en dessous." } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "הצג רק ספרות, ללא תוויות מתחת." + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1829,6 +2147,12 @@ "value" : "La plage disponible est d’un an avant et après la date actuelle." } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "הטווח הזמין הוא שנה אחת לפני ואחרי התאריך הנוכחי." + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1863,6 +2187,12 @@ "value" : "Thème" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "ערכת נושא" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1897,6 +2227,12 @@ "value" : "Trouvez un titre sympa pour l’économiseur d’écran et écrivez-le ici" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "חשוב על רעיון מגניב לכותרת שומר המסך וכתוב אותו כאן" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1931,6 +2267,12 @@ "value" : "Heure" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "שעה" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1965,6 +2307,12 @@ "value" : "Titre" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "כותרת" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1999,6 +2347,12 @@ "value" : "Épaisseur" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "עובי" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2040,6 +2394,12 @@ "value" : "Noire" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "שחור" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2081,6 +2441,12 @@ "value" : "Grasse" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "מודגש" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2122,6 +2488,12 @@ "value" : "Lourde" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "כבד" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2163,6 +2535,12 @@ "value" : "Légère" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "קל" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2204,6 +2582,12 @@ "value" : "Moyenne" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "בינוני" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2245,6 +2629,12 @@ "value" : "Normale" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "רגיל" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2286,6 +2676,12 @@ "value" : "Demi-grasse" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "בינוני-מודגש" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2327,6 +2723,12 @@ "value" : "Fine" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "דק" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2368,6 +2770,12 @@ "value" : "Ultrafine" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "דק במיוחד" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2402,6 +2810,12 @@ "value" : "Lorsque le compte à rebours atteint zéro, il passe automatiquement en mode Chronomètre et commence à compter le temps écoulé." } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "כאשר הספירה לאחור מגיעה לאפס, הוא עובר אוטומטית למצב שעון עצר ומתחיל לספור כלפי מעלה." + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2436,6 +2850,12 @@ "value" : "Blanc" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "לבן" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2470,6 +2890,12 @@ "value" : "Jaune" } }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "צהוב" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2480,4 +2906,4 @@ } }, "version" : "1.2" -} +} \ No newline at end of file From 945dbdd5ba203c1a5629f12ecbdc2ef4a6acbb25 Mon Sep 17 00:00:00 2001 From: Sergey Kemenov Date: Sun, 24 May 2026 13:01:23 +0300 Subject: [PATCH 07/13] refactor(ui): fix non-latin labels size --- MinimalCountdown/Extensions/CGFloat+Extensions.swift | 2 ++ MinimalCountdown/Views/ElementView.swift | 2 +- MinimalCountdown/Views/UIModel.swift | 6 ++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/MinimalCountdown/Extensions/CGFloat+Extensions.swift b/MinimalCountdown/Extensions/CGFloat+Extensions.swift index 1788c0d..1783e2d 100644 --- a/MinimalCountdown/Extensions/CGFloat+Extensions.swift +++ b/MinimalCountdown/Extensions/CGFloat+Extensions.swift @@ -51,6 +51,8 @@ extension CGFloat { /// Label text size relative to the digits baseline. CGFloat = 1.0 / 5.0 static let labelsToDigitsRatio: CGFloat = 1.0 / 5.0 + /// Non Latin label text size relative to the digits baseline. CGFloat = 1.0 / 3.8 + static let nonLatinLabelsToDigitsRatio: CGFloat = 1.0 / 3.8 /// Title text size relative to the digits baseline. CGFloat = 1.0 / 4.0 static let titleToDigitsRatio: CGFloat = 1.0 / 4.0 /// Inter-element spacing as a fraction of window width. CGFloat = 0.04 diff --git a/MinimalCountdown/Views/ElementView.swift b/MinimalCountdown/Views/ElementView.swift index 4f8d802..360c9d9 100644 --- a/MinimalCountdown/Views/ElementView.swift +++ b/MinimalCountdown/Views/ElementView.swift @@ -37,7 +37,7 @@ private extension ElementView { var labelElement: UIModel.TextElement? { element.render.isLabelHidden ? nil : .init( text: element.label, - size: element.size * .labelsToDigitsRatio, + size: UIModel.labelSize(for: element), color: element.render.textsColor ) } diff --git a/MinimalCountdown/Views/UIModel.swift b/MinimalCountdown/Views/UIModel.swift index 80d3cc3..9172af2 100644 --- a/MinimalCountdown/Views/UIModel.swift +++ b/MinimalCountdown/Views/UIModel.swift @@ -62,6 +62,12 @@ enum UIModel { return words.joined(separator: separator) } + static func labelSize(for element: Element) -> CGFloat { + let localeId = element.render.digitLocale.identifier.lowercased() + let isNeedFixSize = localeId.contains("ar") || localeId.contains("he") + return element.size * (isNeedFixSize ? .nonLatinLabelsToDigitsRatio : .labelsToDigitsRatio) + } + /// Countdown digit string: zero-padded (min 2, grows for 3-digit day counts) and rendered /// in `locale`'s numeral system (the resolved `RenderSettings.digitLocale`). static func formattedDigits(_ value: Int, in locale: Locale) -> String { From 96d0586f644d45770a2c6be252df9de0c6a6befa Mon Sep 17 00:00:00 2001 From: Sergey Kemenov Date: Sun, 24 May 2026 13:04:52 +0300 Subject: [PATCH 08/13] refactor(ui): fix `render` and `titleText` properties re-evaluating --- .../Views/CountdownRootView.swift | 2 + MinimalCountdown/Views/CountdownWindow.swift | 63 +++++++++++-------- MinimalDevApp/PreviewWindow.swift | 3 + 3 files changed, 42 insertions(+), 26 deletions(-) diff --git a/MinimalCountdown/Views/CountdownRootView.swift b/MinimalCountdown/Views/CountdownRootView.swift index 1143ed0..c35a020 100644 --- a/MinimalCountdown/Views/CountdownRootView.swift +++ b/MinimalCountdown/Views/CountdownRootView.swift @@ -12,11 +12,13 @@ struct CountdownRootView: View { let isPreview: Bool @Environment(SettingsManager.self) private var settingsManager + @Environment(\.locale) private var locale var body: some View { CountdownWindow( now: clock.now, settings: settingsManager.settings, + locale: locale, isPreview: isPreview ) } diff --git a/MinimalCountdown/Views/CountdownWindow.swift b/MinimalCountdown/Views/CountdownWindow.swift index ea95d1a..b3835f9 100644 --- a/MinimalCountdown/Views/CountdownWindow.swift +++ b/MinimalCountdown/Views/CountdownWindow.swift @@ -9,42 +9,53 @@ import SwiftUI struct CountdownWindow: View { let now: Date - let settings: SaverSettings + var settings: SaverSettings + var locale: Locale = .current var isPreview: Bool = false - - @Environment(\.locale) private var locale + @State private var render: UIModel.RenderSettings? + @State private var titleText = String() var body: some View { - let render = UIModel.RenderSettings(settings, locale: locale) - let titleText = UIModel.formattedTitle(settings.title) - GeometryReader { geo in - let digitsSize = geo.size.width.digitsSize(isPreview: isPreview) - - ZStack { - settings.theme.background.color - .ignoresSafeArea() + settings.theme.background.color + .ignoresSafeArea() + if let render { VStack(spacing: .zero) { - TitleView( - element: .init( - text: titleText, - size: digitsSize * .titleToDigitsRatio, - color: render.textsColor, - weight: .thin - ) - ) - CountdownView( - now: now, - settings: settings, - render: render, - digitsSize: digitsSize, - spacing: geo.size.width * .elementsSpacingRatio - ) + showTitle(width: geo.size.width, with: render) + showCountdown(width: geo.size.width, with: render) } .frame(width: geo.size.width, height: geo.size.height) } } + .task(id: settings, applySettings) + } +} + +private extension CountdownWindow { + func applySettings() { + render = UIModel.RenderSettings(settings, locale: locale) + titleText = UIModel.formattedTitle(settings.title) + } + + func showTitle(width: CGFloat, with render: UIModel.RenderSettings) -> some View { + TitleView( + element: .init( + text: titleText, + size: width.digitsSize(isPreview: isPreview) * .titleToDigitsRatio, + color: render.textsColor, + weight: .thin + ) + ) + } + func showCountdown(width: CGFloat, with render: UIModel.RenderSettings) -> some View { + CountdownView( + now: now, + settings: settings, + render: render, + digitsSize: width.digitsSize(isPreview: isPreview), + spacing: width * .elementsSpacingRatio + ) // The countdown is a clock/number — keep it left-to-right even under an RTL (Arabic) locale // (HIG: don't reverse the digits in a number). The settings window still mirrors normally. .environment(\.layoutDirection, .leftToRight) diff --git a/MinimalDevApp/PreviewWindow.swift b/MinimalDevApp/PreviewWindow.swift index fa657dd..c6652f1 100644 --- a/MinimalDevApp/PreviewWindow.swift +++ b/MinimalDevApp/PreviewWindow.swift @@ -11,6 +11,7 @@ struct PreviewWindow: View { @Binding var isAnimating: Bool @Binding var isTestPreview: Bool @Environment(SettingsManager.self) private var settingsManager + @Environment(\.locale) private var locale var body: some View { if isAnimating { @@ -18,6 +19,7 @@ struct PreviewWindow: View { CountdownWindow( now: context.date, settings: settingsManager.settings, + locale: locale, isPreview: isTestPreview ) } @@ -25,6 +27,7 @@ struct PreviewWindow: View { CountdownWindow( now: Date(), settings: settingsManager.settings, + locale: locale, isPreview: isTestPreview ) } From 957115c8133e914ea7d9983d34e6e3dad4b44f38 Mon Sep 17 00:00:00 2001 From: Sergey Kemenov Date: Sun, 24 May 2026 17:53:00 +0300 Subject: [PATCH 09/13] feat(ui): add Farsi (fa) localization --- MinimalCountdown.xcodeproj/project.pbxproj | 1 + .../Resources/Localizable.xcstrings | 426 ++++++++++++++++++ 2 files changed, 427 insertions(+) diff --git a/MinimalCountdown.xcodeproj/project.pbxproj b/MinimalCountdown.xcodeproj/project.pbxproj index da22ace..744a401 100644 --- a/MinimalCountdown.xcodeproj/project.pbxproj +++ b/MinimalCountdown.xcodeproj/project.pbxproj @@ -205,6 +205,7 @@ fr, ar, he, + fa, ); mainGroup = E9B531912B854D60002A2B79; productRefGroup = E9B5319C2B854D60002A2B79 /* Products */; diff --git a/MinimalCountdown/Resources/Localizable.xcstrings b/MinimalCountdown/Resources/Localizable.xcstrings index 9900f65..e906371 100644 --- a/MinimalCountdown/Resources/Localizable.xcstrings +++ b/MinimalCountdown/Resources/Localizable.xcstrings @@ -21,6 +21,12 @@ "value" : "⚠️ Se ve mejor con grosores más finos." } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ با ضخامت‌های نازک‌تر بهتر به نظر می‌رسد." + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -61,6 +67,12 @@ "value" : "⚠️ Se ve mejor con el grosor Normal o superior." } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ با ضخامت «معمولی» یا بیشتر بهتر به نظر می‌رسد." + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -101,6 +113,12 @@ "value" : "⚠️ Se ve mejor con el redondeado activado." } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ با فعال بودن گرد کردن بهتر به نظر می‌رسد." + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -141,6 +159,12 @@ "value" : "Añade un efecto a los dígitos:" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "جلوه‌ای به ارقام اضافه می‌کند:" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -181,6 +205,12 @@ "value" : "Aspecto" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "ظاهر" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -221,6 +251,12 @@ "value" : "Árabes" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "عربی" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -261,6 +297,12 @@ "value" : "Automático" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "خودکار" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -301,6 +343,12 @@ "value" : "Retroiluminación" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "نور پس‌زمینه" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -341,6 +389,12 @@ "value" : "Negro" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "سیاه" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -381,6 +435,12 @@ "value" : "Azul" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "آبی" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -421,6 +481,12 @@ "value" : "Desenfoque" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "تاری" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -461,6 +527,12 @@ "value" : "Brillo" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "روشنایی" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -501,6 +573,12 @@ "value" : "Cerrar" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "بستن" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -541,6 +619,12 @@ "value" : "Cierra esta ventana y haz clic en «Previsualizar» para ver todos los cambios en pantalla completa." } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "این پنجره را ببند و روی «پیش‌نمایش» کلیک کن تا تمام تغییرات را در حالت تمام‌صفحه ببینی." + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -581,6 +665,12 @@ "value" : "Color" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "رنگ" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -621,6 +711,12 @@ "value" : "No se pudieron guardar los ajustes. Prueba a cerrar y volver a abrir Ajustes, reiniciar el Mac o reinstalar el salvapantallas." } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "تنظیمات ذخیره نشد. پنجره تنظیمات را ببند و دوباره باز کن، مک را ری‌استارت کن یا محافظ صفحه را دوباره نصب کن." + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -661,6 +757,12 @@ "value" : "Cian" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "فیروزه‌ای" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -701,6 +803,12 @@ "value" : "Fecha" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "تاریخ" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -741,6 +849,12 @@ "value" : "Día" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "روز" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -781,6 +895,12 @@ "value" : "Días" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "روزها" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -821,6 +941,12 @@ "value" : "Por defecto, medianoche." } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "پیش‌فرض: نیمه‌شب." + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -861,6 +987,12 @@ "value" : "Devanagari" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "دواناگری" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -901,6 +1033,12 @@ "value" : "Dígitos" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "ارقام" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -941,6 +1079,12 @@ "value" : "Efecto" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "جلوه" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -981,6 +1125,12 @@ "value" : "Color del efecto" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "رنگ جلوه" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1021,6 +1171,12 @@ "value" : "Resplandor" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "درخشش" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1061,6 +1217,12 @@ "value" : "Verde" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "سبز" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1101,6 +1263,12 @@ "value" : "Ocultar etiquetas" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "پنهان کردن برچسب‌ها" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1141,6 +1309,12 @@ "value" : "Ocultar título" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "پنهان کردن عنوان" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1181,6 +1355,12 @@ "value" : "Oculta el título aunque no esté vacío." } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "عنوان را حتی وقتی خالی نیست پنهان می‌کند." + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1221,6 +1401,12 @@ "value" : "Alto" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "زیاد" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1261,6 +1447,12 @@ "value" : "Horas" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "ساعت‌ها" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1301,6 +1493,12 @@ "value" : "Índigo" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "نیلی" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1341,6 +1539,12 @@ "value" : "Resplandor interior" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "درخشش داخلی" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1381,6 +1585,12 @@ "value" : "Puede ser cualquier fecha futura para el modo Temporizador o cualquier fecha pasada para el modo Cronómetro." } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "می‌تواند هر تاریخ آینده برای حالت تایمر یا هر تاریخ گذشته برای حالت کرونومتر باشد." + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1421,6 +1631,12 @@ "value" : "Latinos" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "لاتین" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1461,6 +1677,12 @@ "value" : "Bajo" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "کم" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1501,6 +1723,12 @@ "value" : "Medio" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "متوسط" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1541,6 +1769,12 @@ "value" : "Menta" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "نعناعی" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1581,6 +1815,12 @@ "value" : "Minutos" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "دقیقه‌ها" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1621,6 +1861,12 @@ "value" : "Ninguno" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "هیچ" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1661,6 +1907,12 @@ "value" : "Números" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "سیستم ارقام" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1701,6 +1953,12 @@ "value" : "Naranja" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "نارنجی" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1741,6 +1999,12 @@ "value" : "Persas" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "فارسی" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1781,6 +2045,12 @@ "value" : "Rosa" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "صورتی" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1821,6 +2091,12 @@ "value" : "Morado" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "بنفش" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1861,6 +2137,12 @@ "value" : "Rojo" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "قرمز" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1901,6 +2183,12 @@ "value" : "Muestra los dígitos con el diseño Redondeado." } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "ارقام را با طراحی گرد نمایش می‌دهد." + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1941,6 +2229,12 @@ "value" : "Redondear dígitos" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "گرد کردن ارقام" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -1981,6 +2275,12 @@ "value" : "Segundos" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "ثانیه‌ها" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2021,6 +2321,12 @@ "value" : "Define el grosor de los dígitos, de Ultrafino a Negro." } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "ضخامت ارقام را از خیلی روشن تا مشکی تنظیم می‌کند." + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2061,6 +2367,12 @@ "value" : "Define los números usados para los dígitos. Automático sigue la región del Mac." } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "سیستم ارقام مورد استفاده برای ارقام را تنظیم می‌کند. خودکار از منطقه مک شما پیروی می‌کند." + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2101,6 +2413,12 @@ "value" : "Mostrar solo los dígitos, sin etiquetas debajo." } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "فقط ارقام را نمایش بده، بدون برچسب زیر آن‌ها." + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2141,6 +2459,12 @@ "value" : "El intervalo disponible es de un año antes y después de la fecha actual." } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "محدوده موجود یک سال قبل و بعد از تاریخ فعلی است." + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2181,6 +2505,12 @@ "value" : "Tema" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "تم" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2221,6 +2551,12 @@ "value" : "Piensa en una genial idea para el título y escríbelo aquí" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "یک ایده عالی برای عنوان محافظ صفحه فکر کن و اینجا بنویس" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2261,6 +2597,12 @@ "value" : "Hora" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "زمان" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2301,6 +2643,12 @@ "value" : "Título" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "عنوان" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2341,6 +2689,12 @@ "value" : "Grosor" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "ضخامت" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2388,6 +2742,12 @@ "value" : "Negro" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "سیاه" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2435,6 +2795,12 @@ "value" : "Negrito" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "ضخیم" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2482,6 +2848,12 @@ "value" : "Grueso" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "سنگین" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2529,6 +2901,12 @@ "value" : "Ligero" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "سبک" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2576,6 +2954,12 @@ "value" : "Medio" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "متوسط" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2623,6 +3007,12 @@ "value" : "Normal" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "معمولی" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2670,6 +3060,12 @@ "value" : "Seminegrito" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "نیمه‌ضخیم" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2717,6 +3113,12 @@ "value" : "Fino" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "نازک" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2764,6 +3166,12 @@ "value" : "Ultrafino" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "بسیار نازک" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2804,6 +3212,12 @@ "value" : "Cuando la cuenta atrás llega a cero, cambia automáticamente al modo Cronómetro y empieza a contar hacia arriba." } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "وقتی شمارش معکوس به صفر برسد، به طور خودکار به حالت کرونومتر تغییر می‌کند و شروع به شمارش رو به بالا می‌کند." + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2844,6 +3258,12 @@ "value" : "Blanco" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "سفید" + } + }, "fr" : { "stringUnit" : { "state" : "translated", @@ -2884,6 +3304,12 @@ "value" : "Amarillo" } }, + "fa" : { + "stringUnit" : { + "state" : "translated", + "value" : "زرد" + } + }, "fr" : { "stringUnit" : { "state" : "translated", From fd62d5c895132d0db745e798c315d3529a124943 Mon Sep 17 00:00:00 2001 From: Sergey Kemenov Date: Sun, 24 May 2026 17:55:43 +0300 Subject: [PATCH 10/13] refactor(ui): fix SaverSettings static properties for preview --- MinimalCountdown/Models/SaverSettings.swift | 6 +++--- MinimalDevApp/PreviewWindow.swift | 10 ++++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/MinimalCountdown/Models/SaverSettings.swift b/MinimalCountdown/Models/SaverSettings.swift index 4daaa3f..8f96f91 100644 --- a/MinimalCountdown/Models/SaverSettings.swift +++ b/MinimalCountdown/Models/SaverSettings.swift @@ -37,7 +37,7 @@ extension SaverSettings { effect: .none, effectColor: .white ), - typography: .init(weight: .ultraLight, isRounded: false), + typography: .init(weight: .ultraLight, isRounded: false, numeralSystem: .automatic), title: .init(text: "", isHidden: true) ) } @@ -45,7 +45,7 @@ extension SaverSettings { #if DEBUG extension SaverSettings { static let preview = SaverSettings( - appearance: .init(style: .days, isLabelHidden: false), + appearance: .init(style: .seconds, isLabelHidden: false), schedule: .init(target: Date(timeIntervalSinceNow: .oneDay * 365)), theme: .init( accent: .white, @@ -54,7 +54,7 @@ extension SaverSettings { effect: .none, effectColor: .white ), - typography: .init(weight: .ultraLight, isRounded: false), + typography: .init(weight: .ultraLight, isRounded: false, numeralSystem: .automatic), title: .init(text: "See you soon", isHidden: false) ) } diff --git a/MinimalDevApp/PreviewWindow.swift b/MinimalDevApp/PreviewWindow.swift index c6652f1..2ee9a1b 100644 --- a/MinimalDevApp/PreviewWindow.swift +++ b/MinimalDevApp/PreviewWindow.swift @@ -34,18 +34,24 @@ struct PreviewWindow: View { } } +#if DEBUG #Preview("Animated") { + @State @Previewable var manager = SettingsManager(saver: MockInMemoryLocalStore(initial: .preview)) PreviewWindow( isAnimating: .constant(true), isTestPreview: .constant(false) ) - .environment(SettingsManager(saver: MockInMemoryLocalStore(initial: .preview))) + .environment(manager) + .onAppear(perform: manager.load) } #Preview("Static") { + @State @Previewable var manager = SettingsManager(saver: MockInMemoryLocalStore(initial: .preview)) PreviewWindow( isAnimating: .constant(false), isTestPreview: .constant(false) ) - .environment(SettingsManager(saver: MockInMemoryLocalStore(initial: .preview))) + .environment(manager) + .onAppear(perform: manager.load) } +#endif From 3a5b5a5daf88f63c0843a455d6fd70af4be72a67 Mon Sep 17 00:00:00 2001 From: Sergey Kemenov Date: Sun, 24 May 2026 18:02:42 +0300 Subject: [PATCH 11/13] refactor(ui): add `nonCapitalizedLanguages` array to fix label size --- MinimalCountdown/Views/ElementView.swift | 2 +- MinimalCountdown/Views/UIModel.swift | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/MinimalCountdown/Views/ElementView.swift b/MinimalCountdown/Views/ElementView.swift index 360c9d9..3482854 100644 --- a/MinimalCountdown/Views/ElementView.swift +++ b/MinimalCountdown/Views/ElementView.swift @@ -37,7 +37,7 @@ private extension ElementView { var labelElement: UIModel.TextElement? { element.render.isLabelHidden ? nil : .init( text: element.label, - size: UIModel.labelSize(for: element), + size: element.size * (element.render.isNeedFixLabelSize ? .nonLatinLabelsToDigitsRatio : .labelsToDigitsRatio), color: element.render.textsColor ) } diff --git a/MinimalCountdown/Views/UIModel.swift b/MinimalCountdown/Views/UIModel.swift index 9172af2..4385261 100644 --- a/MinimalCountdown/Views/UIModel.swift +++ b/MinimalCountdown/Views/UIModel.swift @@ -17,6 +17,7 @@ enum UIModel { let effect: EffectStyle let effectGlowColor: Color let digitLocale: Locale + let isNeedFixLabelSize: Bool init(_ settings: SaverSettings, locale: Locale = .autoupdatingCurrent) { let theme = settings.theme @@ -36,7 +37,10 @@ enum UIModel { var components = Locale.Components(locale: locale) components.numberingSystem = numbering digitLocale = Locale(components: components) + isNeedFixLabelSize = !nonCapitalizedLanguages.map { $0.contains(locale.identifier.lowercased()) }.isEmpty } + + private let nonCapitalizedLanguages = ["ar", "he", "fa"] } struct Element { @@ -62,12 +66,6 @@ enum UIModel { return words.joined(separator: separator) } - static func labelSize(for element: Element) -> CGFloat { - let localeId = element.render.digitLocale.identifier.lowercased() - let isNeedFixSize = localeId.contains("ar") || localeId.contains("he") - return element.size * (isNeedFixSize ? .nonLatinLabelsToDigitsRatio : .labelsToDigitsRatio) - } - /// Countdown digit string: zero-padded (min 2, grows for 3-digit day counts) and rendered /// in `locale`'s numeral system (the resolved `RenderSettings.digitLocale`). static func formattedDigits(_ value: Int, in locale: Locale) -> String { From 9a2f0409858794458091623e752cd54cd14dffb0 Mon Sep 17 00:00:00 2001 From: Sergey Kemenov Date: Sun, 24 May 2026 18:21:54 +0300 Subject: [PATCH 12/13] feat(ui): add Hindi (hi) localization --- MinimalCountdown.xcodeproj/project.pbxproj | 1 + .../Resources/Localizable.xcstrings | 426 ++++++++++++++++++ 2 files changed, 427 insertions(+) diff --git a/MinimalCountdown.xcodeproj/project.pbxproj b/MinimalCountdown.xcodeproj/project.pbxproj index 744a401..11a1a06 100644 --- a/MinimalCountdown.xcodeproj/project.pbxproj +++ b/MinimalCountdown.xcodeproj/project.pbxproj @@ -206,6 +206,7 @@ ar, he, fa, + hi, ); mainGroup = E9B531912B854D60002A2B79; productRefGroup = E9B5319C2B854D60002A2B79 /* Products */; diff --git a/MinimalCountdown/Resources/Localizable.xcstrings b/MinimalCountdown/Resources/Localizable.xcstrings index e906371..f391c89 100644 --- a/MinimalCountdown/Resources/Localizable.xcstrings +++ b/MinimalCountdown/Resources/Localizable.xcstrings @@ -39,6 +39,12 @@ "value" : "⚠️ נראה טוב יותר עם עוביים דקים יותר." } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ हल्की मोटाई में बेहतर दिखता है।" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -85,6 +91,12 @@ "value" : "⚠️ נראה טוב יותר עם עובי «רגיל» ומעלה." } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ «नियमित» या उससे अधिक मोटाई में बेहतर दिखता है।" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -131,6 +143,12 @@ "value" : "⚠️ נראה טוב יותר עם העיגול מופעל." } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ गोलाकार सक्षम होने पर बेहतर दिखता है।" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -177,6 +195,12 @@ "value" : "מוסיף אפקט לספרות:" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "अंकों में प्रभाव जोड़ता है:" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -223,6 +247,12 @@ "value" : "מראה" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "दिखावट" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -269,6 +299,12 @@ "value" : "ערבי" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "अरबी" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -315,6 +351,12 @@ "value" : "אוטומטי" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "स्वचालित" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -361,6 +403,12 @@ "value" : "תאורה אחורית" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "बैकलाइट" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -407,6 +455,12 @@ "value" : "שחור" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "काला" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -453,6 +507,12 @@ "value" : "כחול" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "नीला" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -499,6 +559,12 @@ "value" : "טשטוש" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "धुंधला" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -545,6 +611,12 @@ "value" : "בהירות" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "चमक" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -591,6 +663,12 @@ "value" : "סגור" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "\"बंद करें" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -637,6 +715,12 @@ "value" : "סגור חלון זה ולחץ על «תצוגה מקדימה» כדי לראות את כל השינויים במסך מלא." } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "इस विंडो को बंद करें और «पूर्वावलोकन» पर क्लिक करें ताकि सभी बदलाव पूर्ण स्क्रीन पर देख सकें।" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -683,6 +767,12 @@ "value" : "צבע" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "रंग" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -729,6 +819,12 @@ "value" : "לא ניתן לשמור את ההגדרות. נסה לסגור ולפתוח מחדש את ההגדרות, לאתחל את ה-Mac או להתקין מחדש את שומר המסך." } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "सेटिंग्स सेव नहीं हो सकीं। सेटिंग्स विंडो बंद करके फिर से खोलें, Mac रीस्टार्ट करें या स्क्रीन सेवर दोबारा इंस्टॉल करें।" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -775,6 +871,12 @@ "value" : "ציאן" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "सियान" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -821,6 +923,12 @@ "value" : "תאריך" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "तारीख" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -867,6 +975,12 @@ "value" : "יום" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "दिन" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -913,6 +1027,12 @@ "value" : "ימים" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "दिन" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -959,6 +1079,12 @@ "value" : "ברירת מחדל: חצות." } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "डिफ़ॉल्ट: मध्यरात्रि।" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1005,6 +1131,12 @@ "value" : "דוונגרי" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "देवनागरी" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1051,6 +1183,12 @@ "value" : "ספרות" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "अंक" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1097,6 +1235,12 @@ "value" : "אפקט" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "प्रभाव" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1143,6 +1287,12 @@ "value" : "צבע האפקט" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "प्रभाव का रंग" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1189,6 +1339,12 @@ "value" : "זוהר" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "चमक" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1235,6 +1391,12 @@ "value" : "ירוק" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "हरा" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1281,6 +1443,12 @@ "value" : "הסתר תוויות" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "लेबल छुपाएं" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1327,6 +1495,12 @@ "value" : "הסתר כותרת" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "शीर्षक छुपाएं" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1373,6 +1547,12 @@ "value" : "מסתיר את הכותרת גם כשהיא לא ריקה." } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "शीर्षक को तब भी छुपाता है जब वह खाली न हो।" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1419,6 +1599,12 @@ "value" : "גבוה" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "उच्च" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1465,6 +1651,12 @@ "value" : "שעות" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "घंटे" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1511,6 +1703,12 @@ "value" : "אינדיגו" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "इंडिगो" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1557,6 +1755,12 @@ "value" : "זוהר פנימי" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "आंतरिक चमक" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1603,6 +1807,12 @@ "value" : "יכול להיות כל תאריך עתידי למצב טיימר או כל תאריך עבר למצב שעון עצר." } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "टाइमर मोड के लिए कोई भी भविष्य की तारीख या स्टॉपवॉच मोड के लिए कोई भी पिछली तारीख हो सकती है।" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1649,6 +1859,12 @@ "value" : "לטיני" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "लैटिन" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1695,6 +1911,12 @@ "value" : "נמוך" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "कम" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1741,6 +1963,12 @@ "value" : "בינוני" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "मध्यम" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1787,6 +2015,12 @@ "value" : "מנטה" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "पुदीना" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1833,6 +2067,12 @@ "value" : "דקות" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "मिनट" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1879,6 +2119,12 @@ "value" : "ללא" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "कोई नहीं" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1925,6 +2171,12 @@ "value" : "ספרות" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "अंक प्रणाली" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -1971,6 +2223,12 @@ "value" : "כתום" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "नारंगी" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2017,6 +2275,12 @@ "value" : "פרסי" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "फारसी" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2063,6 +2327,12 @@ "value" : "ורוד" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "गुलाबी" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2109,6 +2379,12 @@ "value" : "סגול" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "बैंगनी" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2155,6 +2431,12 @@ "value" : "אדום" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "लाल" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2201,6 +2483,12 @@ "value" : "מציג את הספרות בעיצוב המעוגל." } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "अंकों को गोल डिज़ाइन में दिखाता है।" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2247,6 +2535,12 @@ "value" : "עיגול ספרות" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "अंकों को गोल करें" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2293,6 +2587,12 @@ "value" : "שניות" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "सेकंड" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2339,6 +2639,12 @@ "value" : "מגדיר את עובי הספרות מבהיר במיוחד לשחור." } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "डिजिट्स की मोटाई अल्ट्रा लाइट से ब्लैक तक सेट करता है।" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2385,6 +2691,12 @@ "value" : "קובע את מערכת הספרות המשמשת את האותיות. אוטומטי עוקב אחר אזור ה-Mac שלך." } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "अंकों के लिए उपयोग की जाने वाली अंक प्रणाली सेट करता है। स्वचालित आपके Mac के क्षेत्र का अनुसरण करता है।" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2431,6 +2743,12 @@ "value" : "הצג רק ספרות, ללא תוויות מתחת." } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "केवल अंक दिखाएं, नीचे कोई लेबल नहीं।" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2477,6 +2795,12 @@ "value" : "הטווח הזמין הוא שנה אחת לפני ואחרי התאריך הנוכחי." } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "उपलब्ध सीमा वर्तमान तारीख से एक वर्ष पहले और बाद की है।" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2523,6 +2847,12 @@ "value" : "ערכת נושא" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "थीम" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2569,6 +2899,12 @@ "value" : "חשוב על רעיון מגניב לכותרת שומר המסך וכתוב אותו כאן" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "स्क्रीन सेवर के लिए एक शानदार शीर्षक का विचार करें और यहां लिखें" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2615,6 +2951,12 @@ "value" : "שעה" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "समय" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2661,6 +3003,12 @@ "value" : "כותרת" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "शीर्षक" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2707,6 +3055,12 @@ "value" : "עובי" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "मोटाई" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2760,6 +3114,12 @@ "value" : "שחור" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "काला (मोटाई)" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2813,6 +3173,12 @@ "value" : "מודגש" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "मोटा" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2866,6 +3232,12 @@ "value" : "כבד" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "भारी" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2919,6 +3291,12 @@ "value" : "קל" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "हल्का" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -2972,6 +3350,12 @@ "value" : "בינוני" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "मध्यम (मोटाई)" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -3025,6 +3409,12 @@ "value" : "רגיל" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "नियमित" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -3078,6 +3468,12 @@ "value" : "בינוני-מודגש" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "अर्ध मोटा" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -3131,6 +3527,12 @@ "value" : "דק" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "पतला" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -3184,6 +3586,12 @@ "value" : "דק במיוחד" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "अति पतला" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -3230,6 +3638,12 @@ "value" : "כאשר הספירה לאחור מגיעה לאפס, הוא עובר אוטומטית למצב שעון עצר ומתחיל לספור כלפי מעלה." } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "जब काउंटडाउन शून्य पर पहुंचे, तो यह स्वचालित रूप से स्टॉपवॉच मोड में बदल जाता है और ऊपर की ओर गिनना शुरू कर देता है।" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -3276,6 +3690,12 @@ "value" : "לבן" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "सफेद" + } + }, "ru" : { "stringUnit" : { "state" : "translated", @@ -3322,6 +3742,12 @@ "value" : "צהוב" } }, + "hi" : { + "stringUnit" : { + "state" : "translated", + "value" : "पीला" + } + }, "ru" : { "stringUnit" : { "state" : "translated", From 123704335236067fcdbf682e86619a17e5b5bae8 Mon Sep 17 00:00:00 2001 From: Sergey Kemenov Date: Sun, 24 May 2026 20:32:35 +0300 Subject: [PATCH 13/13] feat(ui): add Sanskirt (sa) localization --- MinimalCountdown.xcodeproj/project.pbxproj | 1 + .../Resources/Localizable.xcstrings | 428 +++++++++++++++++- 2 files changed, 428 insertions(+), 1 deletion(-) diff --git a/MinimalCountdown.xcodeproj/project.pbxproj b/MinimalCountdown.xcodeproj/project.pbxproj index 11a1a06..3ed2a44 100644 --- a/MinimalCountdown.xcodeproj/project.pbxproj +++ b/MinimalCountdown.xcodeproj/project.pbxproj @@ -207,6 +207,7 @@ he, fa, hi, + sa, ); mainGroup = E9B531912B854D60002A2B79; productRefGroup = E9B5319C2B854D60002A2B79 /* Products */; diff --git a/MinimalCountdown/Resources/Localizable.xcstrings b/MinimalCountdown/Resources/Localizable.xcstrings index f391c89..73bfec5 100644 --- a/MinimalCountdown/Resources/Localizable.xcstrings +++ b/MinimalCountdown/Resources/Localizable.xcstrings @@ -50,6 +50,12 @@ "state" : "translated", "value" : "⚠️ Лучше смотрится на тонких начертаниях." } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ लघु-स्थौल्येषु श्रेष्ठं दृश्यते।" + } } } }, @@ -94,7 +100,7 @@ "hi" : { "stringUnit" : { "state" : "translated", - "value" : "⚠️ «नियमित» या उससे अधिक मोटाई में बेहतर दिखता है।" + "value" : "⚠️ नियमित या उससे अधिक मोटाई में बेहतर दिखता है।" } }, "ru" : { @@ -102,6 +108,12 @@ "state" : "translated", "value" : "⚠️ Лучше смотрится при толщине Обычная или жирнее." } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ «सामान्य» स्थौल्यात् ऊर्ध्वं श्रेष्ठं दृश्यते।" + } } } }, @@ -154,6 +166,12 @@ "state" : "translated", "value" : "⚠️ Лучше смотрится со скруглением." } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "⚠️ वृत्ताकार-सक्षमे श्रेष्ठं दृश्यते।" + } } } }, @@ -206,6 +224,12 @@ "state" : "translated", "value" : "Добавляет эффект к цифрам:" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "अङ्केषु प्रभावं योजयति:" + } } } }, @@ -258,6 +282,12 @@ "state" : "translated", "value" : "Оформление" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "रूपम्" + } } } }, @@ -310,6 +340,12 @@ "state" : "translated", "value" : "Арабские" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "अरबी" + } } } }, @@ -362,6 +398,12 @@ "state" : "translated", "value" : "Автоматически" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "स्वचालितम्" + } } } }, @@ -414,6 +456,12 @@ "state" : "translated", "value" : "Подсветка" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "पृष्ठप्रकाशः" + } } } }, @@ -466,6 +514,12 @@ "state" : "translated", "value" : "Чёрный" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "कृष्णः" + } } } }, @@ -518,6 +572,12 @@ "state" : "translated", "value" : "Синий" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "नीलः" + } } } }, @@ -570,6 +630,12 @@ "state" : "translated", "value" : "Размытие" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "अस्पष्टता" + } } } }, @@ -622,6 +688,12 @@ "state" : "translated", "value" : "Яркость" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "प्रकाशः" + } } } }, @@ -674,6 +746,12 @@ "state" : "translated", "value" : "Закрыть" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "पिधानम्" + } } } }, @@ -726,6 +804,12 @@ "state" : "translated", "value" : "Закройте это окно и нажмите «Просмотр», чтобы в полноэкранном режиме увидеть все изменения." } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "इदं विण्डो पिधाय «पूर्वावलोकन» नुद «सर्वाणि परिवर्तनानि पूर्णपटले द्रष्टुं»।" + } } } }, @@ -778,6 +862,12 @@ "state" : "translated", "value" : "Цвет" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "वर्णः" + } } } }, @@ -830,6 +920,12 @@ "state" : "translated", "value" : "Не удалось сохранить настройки. Попробуйте закрыть и снова открыть «Настройки», перезагрузить Mac или переустановить заставку." } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "सेटिङ्ग्स् रक्षितुं न शक्यते। सेटिङ्ग्स् विण्डो पिधाय पुनः उद्घाटय, Mac पुनः आरभस्व वा स्क्रीनसेवरं पुनः संस्थापय।" + } } } }, @@ -882,6 +978,12 @@ "state" : "translated", "value" : "Голубой" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "नीलहरितः" + } } } }, @@ -934,6 +1036,12 @@ "state" : "translated", "value" : "Дата" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "तिथिः" + } } } }, @@ -986,6 +1094,12 @@ "state" : "translated", "value" : "День" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "दिनम्" + } } } }, @@ -1038,6 +1152,12 @@ "state" : "translated", "value" : "Дни" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "दिनानि" + } } } }, @@ -1090,6 +1210,12 @@ "state" : "translated", "value" : "По умолчанию — полночь." } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "पूर्वनिर्धारितम्: मध्यरात्रिः।" + } } } }, @@ -1142,6 +1268,12 @@ "state" : "translated", "value" : "Деванагари" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "देवनागरी" + } } } }, @@ -1194,6 +1326,12 @@ "state" : "translated", "value" : "Цифры" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "अङ्काः" + } } } }, @@ -1246,6 +1384,12 @@ "state" : "translated", "value" : "Эффект" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "प्रभावः" + } } } }, @@ -1298,6 +1442,12 @@ "state" : "translated", "value" : "Цвет эффекта" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "प्रभाववर्णः" + } } } }, @@ -1350,6 +1500,12 @@ "state" : "translated", "value" : "Свечение" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "प्रभाः" + } } } }, @@ -1402,6 +1558,12 @@ "state" : "translated", "value" : "Зелёный" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "हरितः" + } } } }, @@ -1454,6 +1616,12 @@ "state" : "translated", "value" : "Скрыть подписи" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "लेबलानि गोपय" + } } } }, @@ -1506,6 +1674,12 @@ "state" : "translated", "value" : "Скрыть заголовок" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "शीर्षकं गोपय" + } } } }, @@ -1558,6 +1732,12 @@ "state" : "translated", "value" : "Скрывает заголовок, даже если он не пустой." } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "शीर्षकं गोपयति यद्यपि तत् रिक्तं नास्ति।" + } } } }, @@ -1610,6 +1790,12 @@ "state" : "translated", "value" : "Высокая" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "उच्चम्" + } } } }, @@ -1662,6 +1848,12 @@ "state" : "translated", "value" : "Часы" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "घण्टाः" + } } } }, @@ -1714,6 +1906,12 @@ "state" : "translated", "value" : "Индиго" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "इन्दिगो" + } } } }, @@ -1766,6 +1964,12 @@ "state" : "translated", "value" : "Внутреннее свечение" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "आन्तरिकप्रभाः" + } } } }, @@ -1818,6 +2022,12 @@ "state" : "translated", "value" : "Это может быть любая будущая дата для режима таймера или любая прошедшая — для режима секундомера." } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "टाइमर-मोडस्य कृते भविष्यतिथिः वा स्टॉपवॉच-मोडस्य कृते अतीततिथिः भवितुं शक्यते।" + } } } }, @@ -1870,6 +2080,12 @@ "state" : "translated", "value" : "Латинские" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "लैटिन्" + } } } }, @@ -1922,6 +2138,12 @@ "state" : "translated", "value" : "Низкая" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "अल्पम्" + } } } }, @@ -1974,6 +2196,12 @@ "state" : "translated", "value" : "Средняя" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "मध्यम्" + } } } }, @@ -2026,6 +2254,12 @@ "state" : "translated", "value" : "Мятный" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "पुदीना" + } } } }, @@ -2078,6 +2312,12 @@ "state" : "translated", "value" : "Минуты" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "निमेषाः" + } } } }, @@ -2130,6 +2370,12 @@ "state" : "translated", "value" : "Нет" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "न किमपि" + } } } }, @@ -2182,6 +2428,12 @@ "state" : "translated", "value" : "Числа" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "अङ्कप्रणाली" + } } } }, @@ -2234,6 +2486,12 @@ "state" : "translated", "value" : "Оранжевый" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "नारङ्गः" + } } } }, @@ -2286,6 +2544,12 @@ "state" : "translated", "value" : "Персидские" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "फारसी" + } } } }, @@ -2338,6 +2602,12 @@ "state" : "translated", "value" : "Розовый" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "गुलाबी" + } } } }, @@ -2390,6 +2660,12 @@ "state" : "translated", "value" : "Фиолетовый" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "नीललोहितः" + } } } }, @@ -2442,6 +2718,12 @@ "state" : "translated", "value" : "Красный" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "रक्तः" + } } } }, @@ -2494,6 +2776,12 @@ "state" : "translated", "value" : "Отображает цифры со скруглённым начертанием." } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "अङ्कान् वृत्ताकार-डिज़ाइन-रूपेण दर्शयति।" + } } } }, @@ -2546,6 +2834,12 @@ "state" : "translated", "value" : "Скруглять цифры" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "अङ्कानां वृत्ताकारः" + } } } }, @@ -2598,6 +2892,12 @@ "state" : "translated", "value" : "Секунды" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "क्षणाः" + } } } }, @@ -2650,6 +2950,12 @@ "state" : "translated", "value" : "Задаёт толщину цифр от сверхтонкой до чёрной." } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "अत्यन्तं सूक्ष्मतः कृष्णपर्यन्तं अङ्कानां स्थूलतां निर्धारयति।" + } } } }, @@ -2702,6 +3008,12 @@ "state" : "translated", "value" : "Задаёт систему счисления для цифр. Автоматически следует региону Mac." } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "अङ्कानां कृते प्रयुक्तां अङ्कप्रणालीं निर्धारयति। स्वचालितं भवतः Mac-क्षेत्रस्य अनुसरणं करोति।" + } } } }, @@ -2754,6 +3066,12 @@ "state" : "translated", "value" : "Показывать только цифры, без подписей под ними." } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "केवलम् अङ्कान् दर्शय, अधः किमपि लेबलं नास्ति।" + } } } }, @@ -2806,6 +3124,12 @@ "state" : "translated", "value" : "Доступный диапазон — один год до и после текущей даты." } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "उपलब्धः परिसरः वर्तमानतिथेः एकवर्षपूर्वं च एकवर्षोत्तरं च अस्ति।" + } } } }, @@ -2858,6 +3182,12 @@ "state" : "translated", "value" : "Тема" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "विषयः" + } } } }, @@ -2910,6 +3240,12 @@ "state" : "translated", "value" : "Придумайте классный заголовок для заставки и напишите его здесь" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "स्क्रीनसेवर-शीर्षकस्य कृते उत्तमं विचारं चिन्तय तत्र लिख।" + } } } }, @@ -2962,6 +3298,12 @@ "state" : "translated", "value" : "Время" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "कालः" + } } } }, @@ -3014,6 +3356,12 @@ "state" : "translated", "value" : "Заголовок" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "शीर्षकम्" + } } } }, @@ -3066,6 +3414,12 @@ "state" : "translated", "value" : "Толщина цифр" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "स्थौल्यम्" + } } } }, @@ -3125,6 +3479,12 @@ "state" : "translated", "value" : "Чёрная" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "कृष्णः" + } } } }, @@ -3184,6 +3544,12 @@ "state" : "translated", "value" : "Жирная" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "स्थूलः" + } } } }, @@ -3243,6 +3609,12 @@ "state" : "translated", "value" : "Сверхжирная" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "गुरुः" + } } } }, @@ -3302,6 +3674,12 @@ "state" : "translated", "value" : "Светлая" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "लघुः" + } } } }, @@ -3361,6 +3739,12 @@ "state" : "translated", "value" : "Средняя" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "मध्यमः" + } } } }, @@ -3420,6 +3804,12 @@ "state" : "translated", "value" : "Обычная" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "सामान्यः" + } } } }, @@ -3479,6 +3869,12 @@ "state" : "translated", "value" : "Полужирная" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "अर्धस्थूलः" + } } } }, @@ -3538,6 +3934,12 @@ "state" : "translated", "value" : "Тонкая" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "सूक्ष्मः" + } } } }, @@ -3597,6 +3999,12 @@ "state" : "translated", "value" : "Сверхтонкая" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "अतिसूक्ष्मः" + } } } }, @@ -3649,6 +4057,12 @@ "state" : "translated", "value" : "Когда отсчёт достигает нуля, автоматически включается режим секундомера и он начинает идти вперёд." } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "यदा गणना शून्यं प्राप्नोति, तदा स्वयमेव स्टॉपवॉच-मोडं प्राप्नोति ऊर्ध्वं गणयितुं च आरभते।" + } } } }, @@ -3701,6 +4115,12 @@ "state" : "translated", "value" : "Белый" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "श्वेतः" + } } } }, @@ -3753,6 +4173,12 @@ "state" : "translated", "value" : "Жёлтый" } + }, + "sa" : { + "stringUnit" : { + "state" : "translated", + "value" : "पीतः" + } } } }