Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift Scripting Redux: Localization

Swift Scripting Redux: Localization

Talk given 14 June 2016 at AltConf in San Francisco

The first ever conference talk I gave was about [scripting in Swift](https://realm.io/news/swift-scripting/) in early 2015, pretty soon after Swift was released in mid 2014. Since then, I’ve been using Swift for even more scripting and automation tasks. Most recently, we’ve been working on internationalization and localization for the Workflow app. In this talk we’ll go over the steps that went into this localization process, how Swift makes things much more fun and easier, and how to get up and running with Swift scripting so you can start writing even more Swift!

Ayaka Nonaka

June 14, 2016
Tweet

More Decks by Ayaka Nonaka

Other Decks in Programming

Transcript

  1. MYCLASS.SWIFT let okButtonTitle = NSLocalizedString("OK", comment: "Alert button confirmation title")

    let cancelButtonTitle = NSLocalizedstring("Cancel", comment: "Alert button cancel title")
  2. BASE.LPROJ/LOCALIZABLE.STRINGS /* Alert button confirmation title */ "OK" = "OK";

    /* Alert button cancel title */ "Cancel" = "Cancel";
  3. NL.LPROJ/LOCALIZABLE.STRINGS /* Alert button confirmation title */ "OK" = "OK";

    /* Alert button cancel title */ "Cancel" = "Annuleer";
  4. JP.LPROJ/LOCALIZABLE.STRINGS /* Alert button confirmation title */ "OK" = "OK";

    /* Alert button cancel title */ "Cancel" = "Ωϟϯηϧ";
  5. let runWorkflowTitle = NSLocalizedString("Run", comment: "Run workflow title") let goOnARunTitle

    = NSLocalizedString("Run", comment: "Go on a run title") /* Run workflow title */ "Run" = "Run"; /* Go on a run title */ "Run" = "Run";
  6. /* Run workflow title */ "run-workflow.button.title" = "Run"; /* Go

    on a run title */ "go-on-a-run.button.title" = "Run";
  7. /* Run workflow title */ "RUN_WORKFLOW_BUTTON_TITLE" = "Run"; /* Go

    on a run title */ "GO_ON_A_RUN_BUTTON_TITLE" = "Run";
  8. /* Run workflow title */ "RUN_WORKFLOW_BUTTON_TITLE" = "࣮ߦ"; /* Go

    on a run title */ "GO_ON_A_RUN_BUTTON_TITLE" = "૸Δ";
  9. /* Run workflow title */ "Run" = "Run"; /* Go

    on a run title */ "Run" = "Run";
  10. /* Run workflow title */ "run-run_workflow_title" = "Run"; /* Go

    on a run title */ "run-go_on_a_run_title" = "Run";
  11. NSLocalizedString("Run", comment: "Run workflow title") NSLocalizedString("Run", comment: "Go on a

    run title") /* Run workflow title */ "run-run_workflow_title" = "Run"; /* Go on a run title */ "run-go_on_a_run_title" = "Run";
  12. GOALS 1. Effortless NSLocalizedString-ing via autogenerating localization keys from comments

    2. Continuous localization via loading strings from the ‘
  13. WHY SWIFT? 1. Familiar 2. Or new! 3. Fewer language

    dependencies 4. Type-safe 5. But still feels light-weight & script friendly 6. Fun!
  14. THE PLAN 1. Get all the .swift, .m, .mm files

    2. Parse out all of the WFLocalizedStrings from each file 3. Write them all out to Localizable.strings
  15. func getMatches(in line: String) throws -> [TextCheckingResult] { let pattern

    = "WFLocalizedString\\(@\"([^\"]*)\"\\)" let regex = try RegularExpression(pattern: pattern, options: []) let matches = regex.matches(in: line, options: [], range: NSRange(location: 0, length: line.utf16.count)) if matches.count > 0 { return matches } let descriptivePattern = "WFLocalizedStringWithDescription\\(@\"([^\"]*)\", @\"([^\"]*)\"\\)" let descriptiveRegex = try RegularExpression(pattern: descriptivePattern, options: []) return descriptiveRegex.matches(in: line, options: [], range: NSRange(location: 0, length: line.utf16.count)) }
  16. struct LocalizedString { let string: String let description: String? }

    func getLocalizedStrings(in line: String) throws -> [LocalizedString] { let matches = try getMatches(in: line) return matches.map { let line = line as NSString let string = line.substring(with: $0.range(at: 1)) var description: String? = nil if $0.numberOfRanges > 2 { description = line.substring(with: $0.range(at: 2)) } return LocalizedString(string: string, description: description) } }
  17. TIPS ▸ Make all user facing strings an NSLocalizedString even

    if you don’t have plans to localize the app in the nearest future. ▸ Avoid using spaces for layout padding like @" OK" ▸ Avoid concatenating strings to make sentences.
  18. MORE READING ▸ Apple’s iOS Developer Library: Localizing Your App

    ▸ objc.io Issue 9: String Localization ▸ My Swift Summit London talk