Internationali[sz]ation: 
It's easy in Ember!

Internationali[sz]ation: 
It's easy in Ember!

Ab97201abd62673ed21bb286e1b20345?s=128

Tobias Bieniek

September 21, 2018
Tweet

Transcript

  1. Internationali[sz]ation
 It's easy in Ember!

  2. Turbo87 TobiasBieniek

  3. simplabs based in Munich consulting all over ! * Stickers

    available after the talk
  4. Internationali[sz]ation
 It's easy in Ember!

  5. " Internationalization # Internationalisation $ Internationalisierung % Internationalisering & 国際化

  6. Plurals 0 apples 1 apple 2 apples 10 apples "

  7. Plurals 0 fish 1 fish 2 fish 10 fish "

  8. Plurals 0 apel 1 apel 2 apel 10 apel )

  9. Plurals zero 0 one 1 two 2 few 3-10, 103-110,

    ... many 11-99, 111-199, ... other 100-102, 200-202, ... * http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html
  10. Numbers 1,545.12 1 545,12 1'545,12 1.545,12 " # + ,

    - . $
  11. Numbers 123,456,789 123 456 789 12,34,56,789 " # + ,

    - /
  12. Currencies $123,456.78 123.456,78 € 123 456,78 ₽ " # $

    -
  13. Date and Time 2018-09-21T13:45:30 2018/9/21 13:45:30 21/09/2018 13:45:30 09/21/2018 1:45:30

    PM ISO8601 + 0 "
  14. Units 1 league = 3 miles 1 mile = 5,280

    feet 1 yard = 3 feet 1 foot = 12 inches 1 inch = 1
  15. Terminology (words)

  16. ... is the design and development of a product that

    
 enables easy localization for target audiences that 
 vary in culture, region, or language. I18n: Internationalization https://blog.mozilla.org/l10n/2011/12/14/i18n-vs-l10n-whats-the-diff/
  17. ... refers to the adaptation of a product to
 meet

    the language, cultural and other
 requirements of a specific target market. L10n: Localization https://blog.mozilla.org/l10n/2011/12/14/i18n-vs-l10n-whats-the-diff/
  18. Internationalization: what developers work on Localization: what translators work on

    Internationalization enables Localization tl;dr https://blog.mozilla.org/l10n/2011/12/14/i18n-vs-l10n-whats-the-diff/
  19. a set of parameters that defines the user's language, region

    and any special variant preferences that the user wants to see in their user interface. Locale https://en.wikipedia.org/wiki/Locale_(computer_software)
  20. pt-BR Brazilian Portuguese BCP 47 Language Region

  21. pt-BR Brazilian Portuguese en English BCP 47 Language

  22. pt-BR Brazilian Portuguese en English zh-Hans-HK Hong Kong Chinese in

    simplified script BCP 47 Language Script Region
  23. Locale Defaults de $ de-Latn-DE es 0 es-Latn-ES en "

    en-Latn-US pt 3 pt-Latn-BR zh + zh-Hans-CN https://github.com/unicode-cldr/cldr-core/blob/33.0.0/supplemental/likelySubtags.json
  24. window.Intl

  25. window.Intl

  26. let numberFormat = new Intl.NumberFormat('en-IN'); let formattedNumber = numberFormat.format(123456.789); //

    1,23,456.789 Intl.NumberFormat
  27. let numberFormat = new Intl.NumberFormat('en-IN', { style: 'currency', currency: 'EUR',

    }); let formattedNumber = numberFormat.format(123456.789); // 123.456,79 € Intl.NumberFormat
  28. let date = new Date(2018, 8, 21, 12, 0, 0);

    new Intl.DateTimeFormat('en-US').format(date); // 09/21/2018 new Intl.DateTimeFormat('de-DE').format(date); // 21.09.2018 Intl.DateFormat
  29. Common Locale Data Repository http://cldr.unicode.org/ CLDR

  30. let cldr = require(
 'cldr-localenames-modern/main/pt/territories'
 ); console.log(cldr.main.pt.localeDisplayNames.territories.US); // Estados Unidos

    CLDR
  31. None
  32. ප"ව$තන 5

  33. translations/fr.po: #: src/myapp.js:12 msgid "My name is %s.\n" msgstr "Je

    m'appelle %s.\n" gettext
  34. config/locales/fr.yml: fr: my-name-is: 'My name is %{name}.' Ruby on Rails

  35. config/locales/en.yml: apples: zero: 'no apples' one: 'one apple' other: '%{count}

    apples' Ruby on Rails
  36. He has 5 apples and one tomato. dynamic static

  37. He has 5 apples and one tomato. She has one

    apple and no tomatoes. They have no apples and 101 tomatoes. dynamic static
  38. {GENDER, select, male {He has} female {She has} other {They

    have} } {APPLES, plural, =0 {no apples} one {one apple} other {# apples} } and {TOMATOES, plural, =0 {no tomatoes} one {one tomato} other {# tomatoes} }. ICU
  39. {GENDER, select, male {He has} female {She has} other {They

    have} } {APPLES, plural, =0 {no apples} one {one apple} other {# apples} } and {TOMATOES, plural, =0 {no tomatoes} one {one tomato} other {# tomatoes} }. ICU t('apple-and-tomatoes', { GENDER: 'male', APPLES: 5, TOMATOES: 0, }); // He has 5 apples // and no tomatoes
  40. ember-intl Thank you @jasonmit ! It's easy in Ember !

  41. Basic Setup app/route/application.js: intl: service(), beforeModel() { let locale =

    figureOutLocale(); // e.g. 'en' this.intl.set('locale', locale); }
  42. Service API this.intl.formatNumber(1234.456); // 1.234,567 this.intl.formatDate(Date.parse('2018-09-21')); // 21.9.2018

  43. Template Helpers {{format-number 1234.456}} <!-- 1.234,567 --> {{format-date date}} <!--

    21.9.2018 -->
  44. Translations translations/en.yml: my-name-is: 'My name is {name}.' translations/de.yml: my-name-is: 'Ich

    heiße {name}.'
  45. Translations this.intl.t('my-name-is', { name: 'Robert Jackson' }); // Ich heiße

    Robert Jackson {{t "my-name-is" name="Robert Jackson"}} <!-- Ich heiße Robert Jackson -->
  46. Tips and Tricks

  47. Async Loading $ ls translations/ total 4864 -rw-r --r --

    1 tbieniek staff 129K 12 Sep 11:28 cs.yml -rw-r --r -- 1 tbieniek staff 123K 12 Sep 11:28 da.yml -rw-r --r -- 1 tbieniek staff 127K 12 Sep 11:28 de-at.yml -rw-r --r -- 1 tbieniek staff 129K 12 Sep 11:28 de-ch.yml -rw-r --r -- 1 tbieniek staff 128K 12 Sep 11:28 de.yml -rw-r --r -- 1 tbieniek staff 122K 12 Sep 11:28 en-at.yml -rw-r --r -- 1 tbieniek staff 123K 12 Sep 11:28 en.yml -rw-r --r -- 1 tbieniek staff 124K 12 Sep 11:28 es.yml -rw-r --r -- 1 tbieniek staff 129K 12 Sep 11:28 fr-ch.yml -rw-r --r -- 1 tbieniek staff 130K 12 Sep 11:28 fr.yml ...
  48. Async Loading async beforeModel() { let locale = figureOutLocale(); let

    translations = await loadTranslations(locale); this.intl.addTranslations(locale, translations); this.intl.set('locale', locale); }
  49. Async Loading config/ember-intl.js: publicOnly: true $ ls dist/assets/translations/ total 6488

    -rw-r --r -- 1 tbieniek staff 174K 11 Sep 15:49 cs.json -rw-r --r -- 1 tbieniek staff 166K 11 Sep 15:49 da.json -rw-r --r -- 1 tbieniek staff 170K 11 Sep 15:49 de-at.json -rw-r --r -- 1 tbieniek staff 171K 11 Sep 15:49 de-ch.json -rw-r --r -- 1 tbieniek staff 169K 11 Sep 15:49 de.json -rw-r --r -- 1 tbieniek staff 163K 11 Sep 15:49 en-at.json
  50. Async Loading async loadTranslations(locale) { let response = await fetch(

    `/assets/translations/${locale}.json` ); let translations = await response.json(); return translations; }
  51. Async Polyfill Loading https: //simplabs.com
 /blog/2018/06/18/intl-polyfill-loading.html

  52. Links

  53. <a href={{pilotHref}}>{{pilotName}} </a> uploaded a {{distance}} flight on {{date}}.

  54. <a href={{pilotHref}}>{{pilotName}} </a> uploaded a {{distance}} flight on {{date}}. {{t

    "event.flight-upload" pilotName=flight.pilot.name pilotHref=flight.pilot.url distance=(format-distance flight.distance) date=(format-date flight.date) htmlSafe=true }}
  55. ember-href-to pilotHref=(href-to "user.details" flight.pilot.id)

  56. Internationali[sz]ation
 It's easy in Ember! Turbo87 TobiasBieniek