Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2022 Accessibility & InclusionSwiftUI & UI Frameworks

WWDC22 · 22 min · Accessibility & Inclusion / SwiftUI & UI Frameworks

Build global apps: Localization by example

Learn how you can run your apps on devices around the world and help everyone have a great experience — regardless of the language they speak. We’ll explore how Apple APIs can provide a solid foundation when creating apps for diverse audiences, and we’ll share examples, challenges, and best practices from our own experiences.

Watch at developer.apple.com ↗

Transcript all transcripts

Code shown on screen · 15 snippets

Declare strings using String(localized) swift · at 1:59 ↗
let windPerceptionLabelText = String(
    localized: "Wind is making it feel cooler", 
    comment: "Explains the wind is lowering the apparent temperature"
)
Translation example 1 swift · at 2:46 ↗
let filter = String(localized: "Archive.label",
                 defaultValue: "Archive", 
                      comment: "Name of the Archive folder in the sidebar")

let filter = String(localized: "Archive.menuItem",
                 defaultValue: "Archive", 
                      comment: "Menu item title for moving the email into the Archive folder")
Translation example 2 swift · at 3:40 ↗
String(localized: "Show weather in \(locationName)", 
       comment: "Title for a user activity to show weather at a specific city")

String(localized: "Show weather in My Location",
       comment: "Title for a user activity to show weather at the user's current location")
Comment example swift · at 4:58 ↗
String(localized: "Show weather in \(locationName)",
         comment: "Title for a user activity to show weather at a specific city")
Localized remote content example swift · at 6:40 ↗
let allServerLanguages = ["bg", "de", "en", "es", "kk", "uk"]
let language = Bundle.preferredLocalizations(from: allServerLanguages).first
Numbers in a string example 1 swift · at 7:56 ↗
String(localized: "\(amountOfRain) in last \(numberOfHours) hour",
         comment: "Label showing how much rain has fallen in the last number of hours")

String(localized: "\(amountOfRain) in last ^[\(numberOfHours) hour](inflect: true)",
         comment: "Label showing how much rain has fallen in the last number of hours")
Numbers in a string example 2 swift · at 8:40 ↗
if selectedCount == 1 {
    return String(localized: "Remove this city 
                              from your favorites")
} else {
    return String(localized: "Remove these cities 
                              from your favorites")
}
Numbers in a string example 3 swift · at 9:00 ↗
String(localized: "\(amountOfRain) in last ^[\(numberOfHours) hour](inflect: true).",
         comment: "Label showing how much rain has fallen in the last number of hours")
Formatter example swift · at 9:29 ↗
let humidity = 54

// In a SwiftUI view
Text(humidity, format: .percent)

// In Swift code
humidity.formatted(.percent)
Formatter example 2 swift · at 10:03 ↗
date.formatted(
    .dateTime.year()
    .month()   
) // Jun 2022

whatToExpect.formatted()
// New features, exciting API, and advanced tips

amountOfRain.formatted(
    .measurement(
        width: .narrow,
        usage: .rainfall)) // 12mm

(date...<later).formatted(
    .components(
        style: .wide
    )
) // 24 minutes, 18 Seconds

date.formatted(
    .relative(
        presentation: 
            .numeric
    )
) // 2 minutes ago

let components = PersonNameComponents()

nameComponentsFormatter
    .string(from: components)
// Andreas Neusüß or 田中陽子

excitementLevel.formatted(
    .number
    .precision(
        .fractionLength(2)
    )
) // 1,001.42

price.formatted(
    .currency(
        code: "EUR"
    )
) // $20.99

distance.formatted(
    .measurement(
        width: .wide,
        usage: .road)
) // 500 feet

bytesCopied.formatted(
    .byteCount(
        style: .file
)) // 42.23 MB
Combine a formatter with text swift · at 11:10 ↗
func expectedPrecipitationIn24Hours(for valueInMillimeters: Measurement<UnitLength>) -> String {
    // Use user's preferred measures
    let preferredUnit = UnitLength(forLocale: .current, usage: .rainfall)

    let valueInPreferredSystem = valueInMillimeters.converted(to: preferredUnit)

    // Format the amount of rainfall
    let formattedValue = valueInPreferredSystem
        .formatted(.measurement(width: .narrow, usage: .asProvided))

    let integerValue = Int(valueInPreferredSystem.value.rounded())

    // Load and use formatting string
    return String(localized: "EXPECTED_RAINFALL", 
               defaultValue: "\(integerValue) \(formattedValue) expected in next \(24)h.", 
                    comment: "Label - How much precipitation (2nd formatted value, in mm or Inches) is expected in the next 24 hours (3rd, always 24).")
}
Stringsdict examples in English and Spanish xml · at 12:22 ↗
Localizable.stringsdict English:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>EXPECTED_RAINFALL</key>
    <dict>
        <key>NSStringLocalizedFormatKey</key>
        <string>%#@next_expected_precipitation_amount_24h@</string>
        <key>next_expected_precipitation_amount_24h</key>
        <dict>
            <key>NSStringFormatSpecTypeKey</key>
            <string>NSStringPluralRuleType</string>
            <key>NSStringFormatValueTypeKey</key>
            <string>d</string>
            <key>other</key>
            <string>%2$@ expected in next %3$dh.</string>
        </dict>
    </dict>
</dict>
</plist>

Localizable.stringsdict Spanish:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>EXPECTED_RAINFALL</key>
    <dict>
        <key>NSStringLocalizedFormatKey</key>
        <string>%#@next_expected_precipitation_amount_24h@</string>
        <key>next_expected_precipitation_amount_24h</key>
        <dict>
            <key>NSStringFormatSpecTypeKey</key>
            <string>NSStringPluralRuleType</string>
            <key>NSStringFormatValueTypeKey</key>
            <string>d</string>
            <key>one</key>
            <string>Se prevé %2$@ en las próximas %3$d h.</string>
            <key>other</key>
            <string>Se prevén %2$@ en las próximas %3$d h.</string>
        </dict>
    </dict>
</dict>
</plist>
Swift Package localization example swift · at 13:40 ↗
let package = Package(
    name: "FoodTruckKit",

    defaultLocalization: "en",

    products: [
       .library(
            name: "FoodTruckKit",
            targets: ["FoodTruckKit"]),
    ],
    
)
Loading a string in a Swift Package swift · at 14:41 ↗
let title = String(localized: "Wind",
                      bundle: .module, 
                     comment: "Title for section that
                               shows data about wind.")
Grid example swift · at 18:19 ↗
// Requires data types "Row" and "row" to be defined

struct WeatherTestView: View {
    var rows: [Row]
    var body: some View {
        Grid(alignment: .leading) {
            ForEach(rows) { row in
                GridRow {
                    Text(row.dayOfWeek)
                    
                    Image(systemName: row.weatherCondition)
                        .symbolRenderingMode(.multicolor)
                    
                    Text(row.minimumTemperature)
                        .gridColumnAlignment(.trailing)
                    
                    Capsule().fill(Color.orange).frame(height: 4)
                    
                    Text(row.maximumTemperature)
                }
                .foregroundColor(.white)
            }
        }
    }
}

Resources