Skip to content

Commit

Permalink
Merge pull request #17630 from wordpress-mobile/tooling/l10n-step2/io…
Browse files Browse the repository at this point in the history
…s13-widgets

[Tooling] Migrate iOS13 Widgets to use App strings
  • Loading branch information
AliSoftware authored Dec 8, 2021
2 parents c295466 + ef8b4b4 commit 82d6fd1
Show file tree
Hide file tree
Showing 45 changed files with 130 additions and 160 deletions.
69 changes: 69 additions & 0 deletions WordPress/Classes/Utility/AppLocalizedString.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import SwiftUI


extension Bundle {
/// Returns the `Bundle` for the host `.app`.
///
/// - If this is called from code already located in the main app's bundle or from a Pod/Framework,
/// this will return the same as `Bundle.main`, aka the bundle of the app itself.
/// - If this is called from an App Extension (Widget, ShareExtension, etc), this will return the bundle of the
/// main app hosting said App Extension (while `Bundle.main` would return the App Extension itself)
///
/// This is particularly useful to reference a resource or string bundled inside the app from an App Extension / Widget.
///
/// - Note:
/// In the context of Unit Tests this will return the Test Harness (aka Test Host) app, since that is the app running said tests.
///
static let app: Bundle = {
var url = Bundle.main.bundleURL
while url.pathExtension != "app" && url.lastPathComponent != "/" {
url.deleteLastPathComponent()
}
guard let appBundle = Bundle(url: url) else { fatalError("Unable to find the parent app bundle") }
return appBundle
}()
}

/// Use this to express *intent* on your API that the string you are manipulating / returning is intended to already be localized
/// and its value to have been provided via a call to `NSLocalizedString` or `AppLocalizedString`.
///
/// Semantically speaking, a method taking or returning a `LocalizedString` is signaling that you can display said UI string
/// to the end user, without the need to be treated as a key to be localized. The string is expected to already have been localized
/// at that point of the code, via a call to `NSLocalizedString`, `AppLocalizedString` or similar upstream in the code.
///
/// - Note: Remember though that, as a `typealias`, this won't provide any compile-time guarantee.
typealias LocalizedString = String

/// Use this function instead of `NSLocalizedString` to reference localized strings **from the app bundle** – especially
/// when using localized strings from the code of an app extension.
///
/// You should use this `AppLocalizedString` method in place of `NSLocalizedString` especially when calling it
/// from App Extensions and Widgets, in order to reference strings whose localization live in the app bundle's `.strings` file
/// (rather than the AppExtension's own bundle).
///
/// In order to avoid duplicating our strings accross targets, and make our localization process & tooling easier, we keep all
/// localized `.strings` in the app's bundle (and don't have a `.strings` file in the App Extension targets themselves);
/// then we make those App Extensions & Widgets reference the strings from the `Localizable.strings` files
/// hosted in the app bundle itself – which is when this helper method is helpful.
///
/// - Note:
/// Tooling: Be sure to pass this function's name as a custom routine when parsing the code to generate the main `.strings` file,
/// using `genstrings -s AppLocalizedString`, so that this helper method is recognized. You will also have to
/// exclude this very file from being parsed by `genstrings`, so that it won't accidentally misinterpret that routine/function definition
/// below as a call site and generate an error because of it.
///
/// - Parameters:
/// - key: An identifying value used to reference a localized string.
/// - tableName: The basename of the `.strings` file **in the app bundle** containing
/// the localized values. If `tableName` is `nil`, the `Localizable` table is used.
/// - value: The English/default copy for the string. This is the user-visible string that the
/// translators will use as original to translate, and also the string returned when the localized string for
/// `key` cannot be found in the table. If `value` is `nil` or empty, `key` would be returned instead.
/// - comment: A note to the translator describing the context where the localized string is presented to the user.
///
/// - Returns: A localized version of the string designated by `key` in the table identified by `tableName`.
/// If the localized string for `key` cannot be found within the table, `value` is returned.
/// (However, `key` is returned instead when `value` is `nil` or the empty string).
func AppLocalizedString(_ key: String, tableName: String? = nil, value: String? = nil, comment: String) -> LocalizedString {
Bundle.app.localizedString(forKey: key, value: value, table: nil)
}
45 changes: 33 additions & 12 deletions WordPress/Classes/ViewRelated/Stats/Extensions/Double+Stats.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,39 @@ extension Double {
struct Cache {
static let units: [Unit] = {
var units: [Unit] = []

units.append(Unit(abbreviationFormat: NSLocalizedString("%@K", comment: "Label displaying value in thousands. Ex: 66.6K."), accessibilityLabelFormat: NSLocalizedString("%@ thousand", comment: "Accessibility label for value in thousands. Ex: 66.6 thousand.")))

units.append(Unit(abbreviationFormat: NSLocalizedString("%@M", comment: "Label displaying value in millions. Ex: 66.6M."), accessibilityLabelFormat: NSLocalizedString("%@ million", comment: "Accessibility label for value in millions. Ex: 66.6 million.")))

units.append(Unit(abbreviationFormat: NSLocalizedString("%@B", comment: "Label displaying value in billions. Ex: 66.6B."), accessibilityLabelFormat: NSLocalizedString("%@ billion", comment: "Accessibility label for value in billions. Ex: 66.6 billion.")))

units.append(Unit(abbreviationFormat: NSLocalizedString("%@T", comment: "Label displaying value in trillions. Ex: 66.6T."), accessibilityLabelFormat: NSLocalizedString("%@ trillion", comment: "Accessibility label for value in trillions. Ex: 66.6 trillion.")))

units.append(Unit(abbreviationFormat: NSLocalizedString("%@P", comment: "Label displaying value in quadrillions. Ex: 66.6P."), accessibilityLabelFormat: NSLocalizedString("%@ quadrillion", comment: "Accessibility label for value in quadrillion. Ex: 66.6 quadrillion.")))

units.append(Unit(abbreviationFormat: NSLocalizedString("%@E", comment: "Label displaying value in quintillions. Ex: 66.6E."), accessibilityLabelFormat: NSLocalizedString("%@ quintillion", comment: "Accessibility label for value in quintillions. Ex: 66.6 quintillion.")))
// Note: using `AppLocalizedString` here (instead of `NSLocalizedString`) to ensure that strings
// will be looked up from the app's _own_ `Localizable.strings` file, even when this file is used
// as part of an _App Extension_ (especially our various stats Widgets which also use this file)

units.append(Unit(
abbreviationFormat: AppLocalizedString("%@K", comment: "Label displaying value in thousands. Ex: 66.6K."),
accessibilityLabelFormat: AppLocalizedString("%@ thousand", comment: "Accessibility label for value in thousands. Ex: 66.6 thousand.")
))

units.append(Unit(
abbreviationFormat: AppLocalizedString("%@M", comment: "Label displaying value in millions. Ex: 66.6M."),
accessibilityLabelFormat: AppLocalizedString("%@ million", comment: "Accessibility label for value in millions. Ex: 66.6 million.")
))

units.append(Unit(
abbreviationFormat: AppLocalizedString("%@B", comment: "Label displaying value in billions. Ex: 66.6B."),
accessibilityLabelFormat: AppLocalizedString("%@ billion", comment: "Accessibility label for value in billions. Ex: 66.6 billion.")
))

units.append(Unit(
abbreviationFormat: AppLocalizedString("%@T", comment: "Label displaying value in trillions. Ex: 66.6T."),
accessibilityLabelFormat: AppLocalizedString("%@ trillion", comment: "Accessibility label for value in trillions. Ex: 66.6 trillion.")
))

units.append(Unit(
abbreviationFormat: AppLocalizedString("%@P", comment: "Label displaying value in quadrillions. Ex: 66.6P."),
accessibilityLabelFormat: AppLocalizedString("%@ quadrillion", comment: "Accessibility label for value in quadrillion. Ex: 66.6 quadrillion.")
))

units.append(Unit(
abbreviationFormat: AppLocalizedString("%@E", comment: "Label displaying value in quintillions. Ex: 66.6E."),
accessibilityLabelFormat: AppLocalizedString("%@ quintillion", comment: "Accessibility label for value in quintillions. Ex: 66.6 quintillion.")
))

return units
}()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ private extension WidgetDifferenceCell {
enum Constants {
static let noDataLabel = "-"
static let cornerRadius: CGFloat = 4.0
static let today = NSLocalizedString("Today", comment: "Label for most recent stat row.")
static let today = AppLocalizedString("Today", comment: "Label for most recent stat row.")
static let positiveColor: UIColor = .success
static let negativeColor: UIColor = .error
static let neutralColor: UIColor = .neutral(.shade40)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ private extension WidgetNoConnectionCell {
}

enum LocalizedText {
static let title = NSLocalizedString("No network available", comment: "Displayed in the Stats widgets when there is no network")
static let message = NSLocalizedString("Stats will be updated next time you're online", comment: "Displayed in the Stats widgets when there is no network")
static let title = AppLocalizedString("No network available", comment: "Displayed in the Stats widgets when there is no network")
static let message = AppLocalizedString("Stats will be updated next time you're online", comment: "Displayed in the Stats widgets when there is no network")
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ private extension WidgetUnconfiguredCell {
}

enum LocalizedText {
static let configureToday = NSLocalizedString("Display your site stats for today here. Configure in the WordPress app in your site stats.", comment: "Unconfigured stats today widget helper text")
static let configureAllTime = NSLocalizedString("Display your all-time site stats here. Configure in the WordPress app in your site stats.", comment: "Unconfigured stats all-time widget helper text")
static let configureThisWeek = NSLocalizedString("Display your site stats for this week here. Configure in the WordPress app in your site stats.", comment: "Unconfigured stats this week widget helper text")
static let openWordPress = NSLocalizedString("Open WordPress", comment: "Today widget label to launch WP app")
static let loadingFailed = NSLocalizedString("Couldn't load data", comment: "Message displayed when a Stats widget failed to load data.")
static let retry = NSLocalizedString("Retry", comment: "Stats widgets label to reload the widget.")
static let configureToday = AppLocalizedString("Display your site stats for today here. Configure in the WordPress app in your site stats.", comment: "Unconfigured stats today widget helper text")
static let configureAllTime = AppLocalizedString("Display your all-time site stats here. Configure in the WordPress app in your site stats.", comment: "Unconfigured stats all-time widget helper text")
static let configureThisWeek = AppLocalizedString("Display your site stats for this week here. Configure in the WordPress app in your site stats.", comment: "Unconfigured stats this week widget helper text")
static let openWordPress = AppLocalizedString("Open WordPress", comment: "Today widget label to launch WP app")
static let loadingFailed = AppLocalizedString("Couldn't load data", comment: "Message displayed when a Stats widget failed to load data.")
static let retry = AppLocalizedString("Retry", comment: "Stats widgets label to reload the widget.")
}

}
Loading

0 comments on commit 82d6fd1

Please sign in to comment.