Skip to content

Commit

Permalink
Fix period abbreviated when multiple days/weeks/months/years
Browse files Browse the repository at this point in the history
  • Loading branch information
joshdholtz committed Feb 6, 2025
1 parent 0b4b047 commit 449f936
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 7 deletions.
62 changes: 56 additions & 6 deletions RevenueCatUI/Templates/V2/Variables/VariableHandlerV2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ private enum VariableLocalizationKey: String {
case numYearFew = "num_year_few"
case numYearMany = "num_year_many"
case numYearOther = "num_year_other"
case numDaysShort = "num_days_short"
case numWeeksShort = "num_weeks_short"
case numMonthsShort = "num_months_short"
case numYearsShort = "num_years_short"
}

@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
Expand Down Expand Up @@ -336,6 +340,11 @@ extension VariablesV2 {
return ""
}

// Ex: "3 months" will return as "3 months"
if period.value > 1 {
return self.productPeriodWithUnit(package: package, localizations: localizations)
}

let value: String
switch period.unit {
case .day:
Expand Down Expand Up @@ -372,15 +381,15 @@ extension VariablesV2 {
return ""
}

return localizations[period.periodLocalizationKey] ?? ""
if period.value > 1 {
return self.productPeriodWithUnit(package: package, localizations: localizations)
} else {
return localizations[period.periodLocalizationKey] ?? ""
}
}

func productPeriodAbbreviated(package: Package, localizations: [String: String]) -> String {
guard let period = package.storeProduct.subscriptionPeriod else {
return ""
}

return localizations[period.periodAbbreviatedLocalizationKey] ?? ""
return self.productPeriodAbbreviatedWithUnit(package: package, localizations: localizations)
}

func productPeriodInDays(package: Package) -> String {
Expand Down Expand Up @@ -427,6 +436,47 @@ extension VariablesV2 {
return String(format: localizedFormat, period.value)
}

func productPeriodAbbreviatedWithUnit(package: Package, localizations: [String: String]) -> String {
guard let period = package.storeProduct.subscriptionPeriod else {
return ""
}

guard let abbreviation = localizations[period.periodAbbreviatedLocalizationKey] else {
return ""
}

if period.value > 1 {
let localizedFormatKey: String
switch period.unit {
case .day:
localizedFormatKey = VariableLocalizationKey.numDaysShort.rawValue
case .week:
localizedFormatKey = VariableLocalizationKey.numWeeksShort.rawValue
case .month:
localizedFormatKey = VariableLocalizationKey.numMonthsShort.rawValue
case .year:
localizedFormatKey = VariableLocalizationKey.numYearsShort.rawValue
}

guard let localizedFormat = localizations[localizedFormatKey] else {
return ""
}

guard let cStringAbbreviation = (abbreviation as NSString).utf8String else {
return ""
}
guard let cStringPeriod = ("\(period.value)" as NSString).utf8String else {
return ""
}

// Number first, abbreviated string second
return String(format: localizedFormat, cStringPeriod, cStringAbbreviation)

} else {
return abbreviation
}
}

func productOfferPrice(package: Package, localizations: [String: String]) -> String {
guard let discount = package.storeProduct.introductoryDiscount else {
return ""
Expand Down
113 changes: 112 additions & 1 deletion Tests/RevenueCatUITests/PaywallsV2/VariableHandlerV2Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,58 @@ class VariableHandlerV2Test: TestCase {
"num_year_two": "%d years",
"num_year_few": "%d years",
"num_year_many": "%d years",
"num_year_other": "%d years"
"num_year_other": "%d years",
"num_days_short": "%1$s%2$s",
"num_weeks_short": "%1$s%2$s",
"num_months_short": "%1$s%2$s",
"num_years_short": "%1$s%2$s"
],
"ar": [
"day": "day",
"daily": "daily",
"day_short": "day",
"week": "week",
"weekly": "weekly",
"week_short": "wk",
"month": "month",
"monthly": "monthly",
"month_short": "mo",
"year": "year",
"yearly": "yearly",
"year_short": "yr",
"annual": "annual",
"annually": "annually",
"annual_short": "yr",
"free_price": "free",
"percent": "%d%%",
"num_day_zero": "%d day",
"num_day_one": "%d day",
"num_day_two": "%d days",
"num_day_few": "%d days",
"num_day_many": "%d days",
"num_day_other": "%d days",
"num_week_zero": "%d week",
"num_week_one": "%d week",
"num_week_two": "%d weeks",
"num_week_few": "%d weeks",
"num_week_many": "%d weeks",
"num_week_other": "%d weeks",
"num_month_zero": "%d month",
"num_month_one": "%d month",
"num_month_two": "%d months",
"num_month_few": "%d months",
"num_month_many": "%d months",
"num_month_other": "%d months",
"num_year_zero": "%d year",
"num_year_one": "%d year",
"num_year_two": "%d years",
"num_year_few": "%d years",
"num_year_many": "%d years",
"num_year_other": "%d years",
"num_days_short": "%2$s%1$s",
"num_weeks_short": "%2$s%1$s",
"num_months_short": "%2$s%1$s",
"num_years_short": "%2$s%1$s"
]
]

Expand Down Expand Up @@ -116,6 +167,16 @@ class VariableHandlerV2Test: TestCase {
expect(result).to(equal("monthly"))
}

func testProductPeriodlyMultipleMonths() {
let result = variableHandler.processVariables(
in: "{{ product.periodly }}",
with: TestData.threeMonthPackage,
locale: locale,
localizations: localizations["en_US"]!
)
expect(result).to(equal("3 months"))
}

func testProductPrice() {
let result = variableHandler.processVariables(
in: "{{ product.price }}",
Expand All @@ -136,6 +197,16 @@ class VariableHandlerV2Test: TestCase {
expect(result).to(equal("$6.99/month"))
}

func testProductPricePerPeriodMultipleMonths() {
let result = variableHandler.processVariables(
in: "{{ product.price_per_period }}",
with: TestData.threeMonthPackage,
locale: locale,
localizations: localizations["en_US"]!
)
expect(result).to(equal("$4.99/3 months"))
}

func testProductPricePerPeriodAbbreviated() {
let result = variableHandler.processVariables(
in: "{{ product.price_per_period_abbreviated }}",
Expand All @@ -146,6 +217,16 @@ class VariableHandlerV2Test: TestCase {
expect(result).to(equal("$6.99/mo"))
}

func testProductPricePerPeriodAbbreviatedMultipleMonths() {
let result = variableHandler.processVariables(
in: "{{ product.price_per_period_abbreviated }}",
with: TestData.threeMonthPackage,
locale: locale,
localizations: localizations["en_US"]!
)
expect(result).to(equal("$4.99/3mo"))
}

func testProductPricePerDay() {
let result = variableHandler.processVariables(
in: "{{ product.price_per_day }}",
Expand Down Expand Up @@ -196,6 +277,16 @@ class VariableHandlerV2Test: TestCase {
expect(result).to(equal("month"))
}

func testProductPeriodMultipleMonths() {
let result = variableHandler.processVariables(
in: "{{ product.period }}",
with: TestData.threeMonthPackage,
locale: locale,
localizations: localizations["en_US"]!
)
expect(result).to(equal("3 months"))
}

func testProductPeriodAbbreviated() {
let result = variableHandler.processVariables(
in: "{{ product.period_abbreviated }}",
Expand All @@ -206,6 +297,26 @@ class VariableHandlerV2Test: TestCase {
expect(result).to(equal("mo"))
}

func testProductPeriodAbbreviatedMultipleMonths() {
let result = variableHandler.processVariables(
in: "{{ product.period_abbreviated }}",
with: TestData.threeMonthPackage,
locale: locale,
localizations: localizations["en_US"]!
)
expect(result).to(equal("3mo"))
}

func testProductPeriodAbbreviatedMultipleMonthsRTL() {
let result = variableHandler.processVariables(
in: "{{ product.period_abbreviated }}",
with: TestData.threeMonthPackage,
locale: locale,
localizations: localizations["ar"]!
)
expect(result).to(equal("mo3"))
}

func testProductPeriodInDays() {
let result = variableHandler.processVariables(
in: "{{ product.period_in_days }}",
Expand Down

0 comments on commit 449f936

Please sign in to comment.