-
Notifications
You must be signed in to change notification settings - Fork 333
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This also expands `Localization` support to be able to format this in any language.
- Loading branch information
Showing
7 changed files
with
271 additions
and
103 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
// | ||
// Localization.swift | ||
// | ||
// | ||
// Created by Nacho Soto on 7/20/23. | ||
// | ||
|
||
import Foundation | ||
import RevenueCat | ||
|
||
enum Localization { | ||
|
||
/// - Returns: an appropriately short abbreviation for the given `unit`. | ||
static func abbreviatedUnitLocalizedString( | ||
for unit: NSCalendar.Unit, | ||
locale: Locale = .current | ||
) -> String { | ||
let (full, abbreviated) = self.unitLocalizedString(for: unit, locale: locale) | ||
|
||
if full.count <= Self.unitAbbreviationMaximumLength { | ||
return full | ||
} else { | ||
return abbreviated | ||
} | ||
} | ||
|
||
static func localizedDuration( | ||
for subscriptionPeriod: SubscriptionPeriod, | ||
locale: Locale = .current | ||
) -> String { | ||
let formatter = DateComponentsFormatter() | ||
formatter.calendar?.locale = locale | ||
formatter.allowedUnits = [subscriptionPeriod.unit.calendarUnit] | ||
formatter.unitsStyle = .full | ||
formatter.includesApproximationPhrase = false | ||
formatter.includesTimeRemainingPhrase = false | ||
formatter.maximumUnitCount = 1 | ||
|
||
return formatter.string(from: subscriptionPeriod.components) ?? "" | ||
} | ||
|
||
} | ||
|
||
// MARK: - Private | ||
|
||
private extension Localization { | ||
|
||
static func unitLocalizedString( | ||
for unit: NSCalendar.Unit, | ||
locale: Locale = .current | ||
) -> (full: String, abbreviated: String) { | ||
var calendar: Calendar = .current | ||
calendar.locale = locale | ||
|
||
let date = Date() | ||
let value = 1 | ||
let component = unit.component | ||
|
||
guard let sinceUnits = calendar.date(byAdding: component, | ||
value: value, | ||
to: date) else { return ("", "") } | ||
|
||
let formatter = DateComponentsFormatter() | ||
formatter.calendar = calendar | ||
formatter.allowedUnits = [unit] | ||
|
||
func result(for style: DateComponentsFormatter.UnitsStyle) -> String { | ||
formatter.unitsStyle = style | ||
guard let string = formatter.string(from: date, to: sinceUnits) else { return "" } | ||
|
||
return string | ||
.replacingOccurrences(of: String(value), with: "") | ||
.trimmingCharacters(in: .whitespaces) | ||
} | ||
|
||
return (full: result(for: .full), | ||
abbreviated: result(for: .abbreviated)) | ||
} | ||
|
||
static let unitAbbreviationMaximumLength = 3 | ||
|
||
} | ||
|
||
// MARK: - Extensions | ||
|
||
private extension NSCalendar.Unit { | ||
|
||
var component: Calendar.Component { | ||
switch self { | ||
case .era: return .era | ||
case .year: return .year | ||
case .month: return .month | ||
case .day: return .day | ||
case .hour: return .hour | ||
case .minute: return .minute | ||
case .second: return .second | ||
case .weekday: return .weekday | ||
case .weekdayOrdinal: return .weekdayOrdinal | ||
case .quarter: return .quarter | ||
case .weekOfMonth: return .weekOfMonth | ||
case .weekOfYear: return .weekOfYear | ||
case .yearForWeekOfYear: return .yearForWeekOfYear | ||
case .nanosecond: return .nanosecond | ||
case .calendar: return .calendar | ||
case .timeZone: return .timeZone | ||
default: return .calendar | ||
} | ||
} | ||
} | ||
|
||
private extension SubscriptionPeriod.Unit { | ||
|
||
var calendarUnit: NSCalendar.Unit { | ||
switch self { | ||
case .day: return .day | ||
case .week: return .weekOfMonth | ||
case .month: return .month | ||
case .year: return .year | ||
} | ||
} | ||
|
||
} | ||
|
||
private extension SubscriptionPeriod { | ||
|
||
var components: DateComponents { | ||
switch self.unit { | ||
case .day: | ||
return DateComponents(day: self.value) | ||
case .week: | ||
return DateComponents(weekOfMonth: self.value) | ||
case .month: | ||
return DateComponents(month: self.value) | ||
case .year: | ||
return DateComponents(year: self.value) | ||
@unknown default: | ||
return .init() | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 0 additions & 67 deletions
67
RevenueCatUI/Helpers/StoreProductDiscount+Localization.swift
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.