Translated Strings and Foreign Language Support in JavaScript Web Apps - OSCON 2013

1,606 views

Published on

Most apps of a significant viral popularity, or even modest ones providing value in the enterprise, need to implement foreign languages. Why? Supporting the largest possible audience in today’s connected world lets programmers create an opportunity for expanding the business. Find supporting demo app and GitHub repo here: bit.ly/KenOscon13

Published in: Technology, Education
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,606
On SlideShare
0
From Embeds
0
Number of Embeds
12
Actions
Shares
0
Downloads
12
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Translated Strings and Foreign Language Support in JavaScript Web Apps - OSCON 2013

  1. 1. Translated Strings and Foreign Language Support in JavaScript Web Apps Ken Tabor Twitter: @KenTabor
  2. 2. Shared bit.ly/KenOscon13
  3. 3. Translating What? Any and all blocks of text
  4. 4. Translating What? Date/time formatters
  5. 5. Translating Where? Single page app
  6. 6. Translating Myth #1 We don’t need translated text, we’re only shipping to North America
  7. 7. Translating Myth #2 No need - it’s just an internal tool
  8. 8. Translating Myth #3 We’re a start-up ... let’s just submit
  9. 9. Translating OMG #1 Just before code freeze marketing asks:
  10. 10. Translating OMG #1 Just before code freeze marketing asks: Hey, will you send over all the text please? We want to do a polish pass for voice and message before ship.
  11. 11. Translating OMG #1 Just before code freeze marketing asks: Hey, will you send over all the text please? We want to do a polish pass for voice and message before ship. Don’t worry we’ll return it by end of day.
  12. 12. Translating OMG #2 CoderSean and PM build create() feature “Connection error, notifying the admin.”
  13. 13. Translating OMG #2 CoderBurin and BA build add() feature “Network problem. Notifying the admin.”
  14. 14. Why Work Smarter? Programmers: Don’t RepeatYourself Business: Include More Customers Marketing: Craft Consistent Message
  15. 15. Solution? String Tables
  16. 16. Typical String Table TS.tstring = { appTitle: 'TString.JS', programListing: 'Program Listing', english: 'English', spanish: 'Spanish', german: 'German', title: 'Title', date: 'Date', synopsis: 'Synopsis', programDate: 'MMM Do YYYY, h:mm a' };
  17. 17. Architectural Rule #1 Never hard-code text strings
  18. 18. Architectural Rule #2 String-tables must be easily accessed throughout the application
  19. 19. Architectural Rule #3 Language string-tables must be demand- loadable resources
  20. 20. Is this Difficult? Couldn’t Google my way out of this task JavaScript is popular lacks formal support We’re all rushed after all
  21. 21. Who Am I to Do This? I’m a front-end product engineer Working at Sabre Holdings Building TripCase
  22. 22. Our Dev Strategy Mobile web browser (webkit)
  23. 23. Our Dev Strategy iOS and Android native apps (PhoneGap)
  24. 24. Our Dev Strategy Coders get smart and stay smart
  25. 25. Core Languages App Structure Presentation Layer Utility Libs Code Analysis/Build Native Wrapper
  26. 26. JavaScript + CSS + HTML Backbone + Underscore + RequireJS jQuery + SASS + Compass Handlebars + Moment + Modernizr Jasmine + jsHint + Plato + Grunt PhoneGap
  27. 27. Demo Show the people some running code
  28. 28. String Table TS.tstring = { appTitle: 'TString.JS', programListing: 'Program Listing', english: 'English', spanish: 'Spanish', german: 'German', title: 'Title', date: 'Date', synopsis: 'Synopsis', programDate: 'MMM Do YYYY, h:mm a' };
  29. 29. Global Resource // encapsulate all code modules into a global namespace var TS = TS || {}; TS.model = TS.model || {}; TS.view = TS.view || {}; TS.collection = TS.collection || {}; TS.app = null; TS.tstring = null;
  30. 30. Template User TS.view.Application = Backbone.View.extend({ template: '<h1>TStringJS</h1>' + '<h2>Example of translated strings and foreign language</h2>' + '<select id="lang-list">' + '<option value="english">English</option>' + '<option value="spanish">Spanish</option>' + '<option value="french">French</option>' + '<option value="italian">Italian</option>' + '</select>' + '<button id="lang-load">Select'
  31. 31. Template User TS.view.Application = Backbone.View.extend({ template: '<h1><%= TS.tstring.appTitle %></h1>' + '<h2><%= TS.tstring.appSubTitle %></h2>' + '<select id="lang-list">' + '<option value="english"><%= TS.tstring.english %></option>' + '<option value="spanish"><%= TS.tstring.spanish %></option>' + '<option value="french"><%= TS.tstring.french %></option>' + '<option value="italian"><%= TS.tstring.italian %></option>' + '</select>' + '<button id="lang-load"><%= TS.tstring.select %>'
  32. 32. JavaScript User function onSelectChoice(id) { var userModel; userModel = this.collection.get(id); alert(TS.tstring.selectedProgram + ': ' + userModel.getDisplayTitle()); }
  33. 33. Resource Loader function LanguageLoad(lang) { var langFn; if (lang === 'english') langFn = 'en-US.js'; else if (lang === 'spanish') langFn = 'es.js'; else if (lang === 'klingon') langFn = 'tlh.js'; $.ajax({ url: 'code/strings/' + langFn, dataType: 'script', success: function(data, textStatus) { TS.app.onRender(); } }); }
  34. 34. Making the Case Combine duplicating strings Stop nearly duplicated strings Easier word-smithing Setup for translation services Abstract away date/time formatting
  35. 35. Handlebars User Write a “helper” function Wraps the global resource Param indexes into the string table
  36. 36. Handlebars Helper Handlebars.registerHelper('tstring', function(key) { var tstring = TS.tstring[key]; if (tstring === undefined) console.log('Missing string[' + key + ']'); return tstring; }); <h1>{{tstring “appTitle”}}</h1> <h2>{{tstring “appSubTitle”}}</h2>
  37. 37. RequireJS RequireJS has “i18n” plugin Auto-loads based on navigator.language At the cost of user control
  38. 38. Native App All string files are packaged together TS.tstring.en = {...}; TS.tstring.fr = {...}; TS.tstring.es = {...}; TS.tstring.tlh = {...}; TS.tstrings = TS.tstring.es;
  39. 39. Testing Test entire app in English Native speaker confirms translations Wait on bug reports
  40. 40. Testing Automated testing: Jasmine and Selenium Manual debug: English with “SP-” prefix
  41. 41. The “Ken Bug” Don’t accidentally ship your debug files
  42. 42. Think About It Start from the start Retrofitting costed a 50hr week Plus 20hr regression testing
  43. 43. Think About It Server-side error conditions happen Map return codes rather than text
  44. 44. Keep Thinking Pluralization functions
  45. 45. Keep Thinking Coordinate with plugins & libraries
  46. 46. Keep Thinking Designers must brain-sweat composition
  47. 47. Questions?
  48. 48. Thank-You bit.ly/KenOscon13 Ken Tabor (@KenTabor)

×