Pro Yearly is on sale from $80 to $50! »

Felix Bartz: Successful App Localization

1fa9cb8c7997c8c4d3d251fb5e41f749?s=47 Realm
June 05, 2017

Felix Bartz: Successful App Localization

1fa9cb8c7997c8c4d3d251fb5e41f749?s=128

Realm

June 05, 2017
Tweet

Transcript

  1. Successful App Localisation Or: Safely navigating the pitfalls https://www.wordcrafts.de Felix

    Bartz, Linguist, Co-founder, CTO
  2. • Is localizing worth the effort? • Fundamentals, such as:

    work with volunteers or professionals? • How do I internationalize my app? What I am not going to talk about
  3. • Pitfall 1: Concepts • Pitfall 2: Time constraints •

    Pitfall 3: Organizational skills • Pitfall 4: Tools & Platforms What I am going to talk about
  4. Concepts Or: how can I provide the basis for good

    localization?
  5. The User Interface Concepts > User Interface

  6. The User Interface Concepts > User Interface Tabs DON’T DO

    THIS
  7. The User Interface Concepts > User Interface Buttons Calendar App

    #1 Calendar App #2
  8. The User Interface Concepts > User Interface Buttons Calendar App

    #1 In German
  9. The User Interface Concepts > User Interface Buttons Calendar App

    #2 In German
  10. The User Interface Concepts > User Interface • Provide sufficient

    space: other languages are up to 20% longer • Look for ways to shorten space-constrained strings • Custom font? Does it do special characters? What did we learn?
  11. String Design Concepts > String Design Placeholders and their pains

  12. String Design Concepts > String Design Placeholders and their pains

    /* No comment provided by engineer. */ "server_down" = "We are working on it and expect to restore service by %s."; Day of the week? am Dienstag Date? am 24.12.2014 Time? um 23:00 Uhr What could %s be?
  13. String Design Concepts > String Design Placeholders and their pains

    /* %s will be replaced by local time, e.g. 3:00 AM. */ "server_down" = "We are working on it and expect to restore service by %s."; What could %s be? ✓ /* %s e.g. 3:00 AM. */ "server_down" = "We are working on it and expect to restore service by %s."; or
  14. String Design Concepts > String Design Placeholders and their pains

    Articles in front of placeholders… "notification" = "%1$@ sent you a %2$@"; "text_message" = "text message"; "video" = "video";
  15. String Design Concepts > String Design Placeholders and their pains

    Yes, it works in English…
  16. String Design Concepts > String Design Placeholders and their pains

    But not in German, for example…
  17. String Design Concepts > String Design Placeholders and their pains

    Solution? "notification" = "%1$@ sent you a %2$@"; "text_message" = "text message"; "video" = "video"; "notification" = "%1$@ sent you %2$@"; "text_message" = "a text message"; "video" = "a video"; Add articles and prepositions to the placeholder content.
  18. String Design Concepts > String Design Placeholders and their pains

    - what did we learn? • Use the comment for vital information • Communicate what type of data the placeholder represents • Just because something works in English, this does not necessarily apply to other languages
  19. String Design Concepts > String Design Multiple Use of Strings

  20. String Design Concepts > String Design Multiple Use of Strings

    /* No comment provided by engineer. */ "me" = "Me"; In this chat group: Me Chat group created by: Me Gruppenteilnehmer: Ich Gruppe erstellt von: Mir
  21. String Design Concepts > String Design Use of Generic Terms

    and Phrases (to make them re-usable)
  22. String Design Concepts > String Design Use of Generic Terms

    and Phrases /* No comment provided by engineer. */ "success" = "Success"; YouTube copy link: Geschafft
  23. String Design Concepts > String Design Use of Generic Terms

    and Phrases Copy link: Geschafft?
  24. String Design Concepts > String Design Use of Generic Terms

    and Phrases DON’T DO THIS /* No comment provided by engineer. */ "success" = "Success"; AT LEAST ADD A COMMENT
  25. String Design Concepts > String Design Concatenated Strings

  26. String Design Concepts > String Design Concatenated Strings "desc_backup_everything" =

    "BBB will clone <sourceWhole> to <destWhole>."; "desc_local_vol" = "the volume %@"; "desc_network_vol" = "the network volume %@"; "desc_folder_network_vol" = "the folder %1$@ on the network volume %2$@"; "desc_folder_local" = "the folder %1$@ on the volume %2$@"; "desc_local_vol" = "the volume %@";
  27. String Design Concepts > String Design Concatenated Strings "desc_backup_everything" =

    "BBB will clone <sourceWhole> to <destWhole>."; "desc_local_vol" = "the volume %@"; In German?
  28. String Design Concepts > String Design Concatenated Strings "desc_backup_everything" =

    "BBB will clone <sourceWhole> to <destWhole>."; "desc_local_vol" = "the volume %@"; "desc_backup_everything" = ""; "desc_local_vol" = ""; "desc_local_vol" = "das Volume %@"; "desc_backup_everything" = "BBB kopiert <sourceWhole> auf <destWhole>.";
  29. BBB kopiert das Volume X auf das Volume Y. String

    Design Concatenated Strings Concepts > String Design
  30. String Design Concepts > String Design Concatenated Strings "desc_backup_everything" =

    "BBB will clone <sourceWhole> to <destWhole>."; "desc_network_vol" = "the network volume %@"; "desc_folder_network_vol" = "the folder %1$@ on the network volume %2$@"; "desc_folder_local" = "the folder %1$@ on the volume %2$@"; "desc_local_vol" = "the volume %@"; ✓ "desc_network_vol" = "the network volume %@"; ✓ "desc_folder_local" = "the folder %1$@ on the volume %2$@"; ?
  31. String Design Concepts > String Design Concatenated Strings "desc_backup_everything" =

    "BBB will clone <sourceWhole> to <destWhole>."; "desc_folder_local" = "the folder %1$@ on the volume %2$@"; "desc_backup_everything" = "BBB kopiert <sourceWhole> auf <destWhole>."; "desc_local_vol" = "the volume %@"; "desc_local_vol" = ""; "desc_local_vol" = "das Volume %@"; "desc_folder_local" = ""; "desc_folder_local" = „den Ordner %1$@ auf dem Volume %2$@";
  32. String Design Concepts > String Design Concatenated Strings BBB kopiert

    das Volume A auf den Ordner B auf dem Volume C.
  33. BBB kopiert das Volume A in den Ordner B auf

    dem Volume C. String Design Concepts > String Design Concatenated Strings String Design
  34. String Design Concepts > String Design Concatenated Strings "desc_backup_everything" =

    "BBB will clone <sourceWhole> to <destWhole>."; "desc_folder_network_vol" = "the folder %1$@ on the network volume %2$@"; "desc_local_vol" = "the volume %@"; ✓ "desc_network_vol" = "the network volume %@"; ✓ "desc_folder_local" = "the folder %1$@ on the volume %2$@"; ✗ ✗ "desc_folder_network_vol" = "the folder %1$@ on the network volume %2$@";
  35. String Design Concepts > String Design Concatenated Strings "desc_backup_everything" =

    "BBB will clone <sourceWhole> to <destWhole>."; "desc_backup_everything" = "BBB will clone <sourceWhole> to <destWhole>."; "desc_backup_everything" = "BBB will clone <sourceWhole> to <destWhole>."; Why do we fail here? "desc_local_vol" = "the volume %@"; "desc_network_vol" = "the network volume %@"; "desc_folder_local" = "the folder %1$@ on the volume %2$@"; "desc_folder_network_vol" = "the folder %1$@ on the network volume %2$@";
  36. String Design Concepts > String Design Concatenated Strings BBB will

    clone <sourceWhole> to the folder %1$@ on network volume %2$@. CCC clonerà <sourceWhole> sulla cartella %1$@ sul volume di rete %2$@. BBB will clone <sourceWhole> to the network volume %@. CCC clonerà <sourceWhole> sul volume di rete %@.
  37. String Design Concepts > String Design Concatenated Strings "desc_backup_everything" =

    "BBB will clone <sourceWhole> to <destWhole>."; "desc_folder_local" = "the folder %1$@ on the volume %2$@"; How do we succeed? "desc_backup_everything" = "BBB will clone <sourceWhole> to <destWhole>."; "desc_folder_local" = "the folder %1$@ on the volume %2$@"; <sourceWhole> & <destWhole> use the same pool of strings
  38. String Design Concepts > String Design Concatenated Strings Solution -

    Step 1 "desc_backup_everything" = "BBB will clone <sourceWhole> to <destWhole>."; "source_desc_folder_local" = "the folder %1$@ on the volume %2$@"; "source_desc_folder_local" = "the folder %1$@ on the volume %2$@"; "dest_desc_folder_local" = "the folder %1$@ on the volume %2$@"; "desc_backup_everything" = "BBB will clone <sourceWhole> to <destWhole>."; Separate strings pools for <sourceWhole> & <destWhole>
  39. String Design Concepts > String Design Concatenated Strings "desc_backup_everything" =

    "BBB will clone <sourceWhole> to <destWhole>."; Solution - Step 2 "desc_backup_everything" = "BBB will clone <sourceWhole> <destWhole>."; Move the preposition “to” into the ‘Destination’ string. "source_desc_folder_local" = "the folder %1$@ on the volume %2$@"; "dest_desc_folder_local" = "the folder %1$@ on the volume %2$@"; "source_desc_folder_local" = "the folder %1$@ on the volume %2$@"; "dest_desc_folder_local" = "to the folder %1$@ on the volume %2$@";
  40. String Design Concepts > String Design Concatenated Strings In German

    "desc_backup_everything" = "BBB kopiert <sourceWhole> <destWhole>."; "source_desc_folder_local" = "den Ordner %1$@ auf dem Volume %2$@"; "dest_desc_folder_local" = "in den Ordner %1$@ auf dem Volume %2$@";
  41. BBB kopiert den Ordner A auf dem Volume B in

    den Ordner C auf dem Volume D.
  42. String Design Concepts > String Design Concatenated Strings In German

    "desc_backup_everything" = "BBB kopiert <sourceWhole> <destWhole>."; "source_desc_local_vol" = "das Volume %@"; "dest_desc_local_vol" = "auf das Volume %@";
  43. BBB kopiert das Volume A auf das Volume B.

  44. String Design Concepts > String Design Concatenated Strings – what

    did we learn? • Works in one language ≠ works in other languages • Move mean little fellas such as prepositions or articles into the placeholder strings • Provide for order changes by using %1$@
  45. String Design Concepts > String Design The Plural - often

    underestimated
  46. String Design Concepts > String Design "%tu matches found" =

    "%tu matches found"; The Plural - enemy of the state Most languages only have one plural.
  47. String Design Concepts > String Design "%tu matches found" =

    "%tu matches found"; The Plural - enemy of the state "%tu matches found" = "%tu Treffer"; "%tu matches found" = "%tu resultados"; "%tu matches found" = "%tu risultati";
  48. String Design Concepts > String Design The Plural - enemy

    of the state Unfortunately, not all languages have only one plural …
  49. String Design Concepts > String Design The Plural - enemy

    of the state Russian
  50. String Design Concepts > String Design The Plural - enemy

    of the state Plurals in “western” languages 1 = Singular 2 – ∞ = Plural
  51. String Design Concepts > String Design The Plural - enemy

    of the state Plurals in most Asian languages 1 – ∞ = One consistent form
  52. String Design Concepts > String Design The Plural - enemy

    of the state 1 = Singular 0, 5-20, 25-30, … = Plural Form 2 1, 21, 31, 41, 51, 61, … = Singular 2, 3, 4, 22-24, … = Plural Form 1 Plurals in Russian
  53. String Design Concepts > String Design The Plural - enemy

    of the state Solution? A .stringsdict file
  54. String Design Concepts > String Design The Plural - enemy

    of the state <dict> <key>NSStringFormatSpecTypeKey</key> <string>NSStringPluralRuleType</string> <key>NSStringFormatValueTypeKey</key> <string>tu</string> <key>zero</key> <string>No matches found</string> <key>one</key> <string>%tu match found</string> <key>other</key> <string>%tu matches found</string> </dict> <dict> <key>NSStringFormatSpecTypeKey</key> <string>NSStringPluralRuleType</string> <key>NSStringFormatValueTypeKey</key> <string>tu</string> <key>zero</key> <string>Совпадений не обнаружено</string> <key>one</key> <string>%tu совпадение обнаружено</string> <key>many</key> <string>%tu совпадений обнаружено</string> <key>other</key> <string>%tu совпадения обнаружено</string> </dict> English Russian
  55. String Design Concepts > String Design The Plural – what

    did we learn? • Not every language has just one plural form • Apple offers a simple solution • Expect the unexpected!
  56. String Design Concepts > String Design Conclusion • Be aware:

    there are languages that use a different syntax • You do not need to know the syntax of every single language • If in doubt: ask someone who is good at this stuff • Important: You don’t have to be an expert. 
 But expect this to need time during the translation.
  57. Time Constraints Or: Good things are worth waiting for…

  58. Time Constraints The main question is: How long will it

    take?
  59. Time Constraints General answer: it depends …

  60. Time Constraints Depends on what? • Word count of the

    resources • Possible specialization in a certain topic • Customization level and complexity of the UI • Your internationalization efforts • Thoroughness of the translators
  61. Time Constraints Depends on what? • Thoroughness of the translators

  62. Time Constraints Depends on what? Typically, an Initial localization requires

    *2-3 reviews.
  63. Time Constraints Depends on what? *2-3 reviews • (Typos) •

    Length constraints • Context correctness • Undiscovered issues of all sorts (gender, plurals, prepositions, order)
  64. Time Constraints Standard iPhone App: 1500 words in resources 350

    words in App Store Translation Data exchange Review Initial Localization Month M T W T F S S Do you see the issue?
  65. Time Constraints Standard Update: 200 words in resources 70 words

    release notes Translation Data exchange Review Update Localization Month M T W T F S S
  66. Time Constraints Ecosystem biorhythm Value Axis 0 12.5 25 37.5

    50 Category Axis Jan Feb Mar Apr May June Juy Aug Sep Oct Nov Dec Calendar year Workload Pre-WWDC Pre-iTC Xmas shutdown OS releases
  67. Time Constraints Conclusion • Very often the main effort is

    not the translation, but the Review • Plan for sufficient time – also consider time zone related losses • Inform your translators ahead of time • Ecosystem biorhythm: WWDC, Xmas, OS releases, iTC downtimes, …
  68. Or: how can I make it comfy for my translators?

    Organizational Skills
  69. Organizational Skills As much info material as possible, such as

    video tutorials, support documents, review guides, etc. The Learning Curve
  70. Organizational Skills Always provide the app itself. It is the

    best context source. Ever! Context2
  71. Organizational Skills Stick to your deadlines. Because you expect that

    as well. Reliability
  72. Organizational Skills Agree on one single contact. Ideally: a lead

    developer! Agree on Q&A methods and schedule sessions Communication
  73. Organizational Skills Don’t lack words. Become “The Explainer”. Comments /*

    */
  74. File Formats & Tools File Formats Or: Avoiding almost physical

    pain.
  75. File Formats & Tools File Formats Native resources Exchange file

    formats • xibs, plist, strings, stringsdict, … • json, … • xliff, … • xlsx, docx, … The bigger / complex your project is, the better it is to use native files.
  76. File Formats & Tools File Formats Native resources Exchange file

    formats • Can be versioned easily • Contain ALL context • Are context themselves • Versioning difficult • Prone to loosing context • Error source Include translators in the decision
  77. File Formats & Tools Tools / Platforms Self-services on the

    web Full services on the web • No file format hassle • Easy and quick • Anonymous translators • Status tracking and statistics • Q&A handling • No file format hassle • Easy and quick • You bring your own translators • Status tracking and statistics • Q&A handling Made for your comfort, typically inefficient for translators
  78. File Formats & Tools Conclusion • Either work with files

    or online platforms - include translators • Most online platforms are very inefficient for translators • Choose wisely and be aware of dependencies and error sources
  79. News from WWDC17 New Pséùdôlängùágès (incl. RTL) New Autolayout constraints

    checks and warnings Stringsdicts can now be exported into Xliff (meh) Watch WWDC17 Session 401 (Localizing with Xcode 9)
  80. That’s what I have for you today.

  81. Thanks a lot! Any questions?