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

i18n in Elm - Treat localized text as constants

i18n in Elm - Treat localized text as constants

A presentation explaining the concept and techniques used in https://github.com/iosphere/elm-i18n. This also includes a brief look at other techniques for translations and internationalizations in Elm.

B7cc642a21d4fa77d0ad5096f353fa66?s=128

Felix Lamouroux

June 10, 2017
Tweet

Transcript

  1. i18n in Elm Treat localized text as constants Felix Lamouroux,

    iosphere GmbH © Felix Lamouroux, iosphere GmbH, 2017 1
  2. Two approaches to internationalization (i18n) Switching languages at 1. Runtime

    2. Compile time © Felix Lamouroux, iosphere GmbH, 2017 2
  3. Switching languages at runtime © Felix Lamouroux, iosphere GmbH, 2017

    3
  4. Basic Setup Elm App Model Keep user's language in model

    Rose!a Stone Translation function Pass through Provide the language to any function requiring localized text Monolithic build One build for all languages: all.js © Felix Lamouroux, iosphere GmbH, 2017 4
  5. Example 1 type Language = English | Norwegian type TranslationId

    = Login | WelcomeBack {name : String} {-| Get a translated string for the given language. -} translate : Language -> TranslationId -> String {-| ... provide user's language to view functions. -} view : Language -> Html Msg 1 See Elm i18n and Type Safety By Amitai Burstein gizra.com/content/elm-i18n-type-safety © Felix Lamouroux, iosphere GmbH, 2017 5
  6. Main drawback: monolithic versions Monolithic builds ➜ Monolithic versions Lockstep

    Each version must fully support all languages. Larger builds All supported languages are downloaded on clients. © Felix Lamouroux, iosphere GmbH, 2017 6
  7. Translation.json: elm-taco Load translations dynamically via JSON 1. Not type-safe

    2. No guarantee that all translations are complete © Felix Lamouroux, iosphere GmbH, 2017 7
  8. Switching languages at compile time © Felix Lamouroux, iosphere GmbH,

    2017 8
  9. Setup using iosphere/elm-i18n 1. One build per language: en.js and

    no.js2 2. Use functions & constants for localized strings 3. Serve localized builds 2 Issue #2 © Felix Lamouroux, iosphere GmbH, 2017 9
  10. Organizing localized strings /src/ ├─ Main.elm # (e.g. imports Translation.Main)

    └─ View.elm # (e.g. imports Translation.View) /Translation/ ├─ En/ │ ├─ Main.elm # (module Translation.Main) │ └─ View.elm # (module Translation.View) └─ No/ ├─ Main.elm # (module Translation.Main) └─ View.elm # (module Translation.View) © Felix Lamouroux, iosphere GmbH, 2017 10
  11. Organizing localized strings /src/ ├─ Main.elm # (e.g. imports Translation.Main)

    ├─ View.elm # (e.g. imports Translation.View) └─>Translation # (linked to e.g. /Translation/No/) /Translation/ ├─ En/ │ ├─ Main.elm # (module Translation.Main) │ └─ View.elm # (module Translation.View) └─ No/ ├─ Main.elm # (module Translation.Main) └─ View.elm # (module Translation.View) © Felix Lamouroux, iosphere GmbH, 2017 11
  12. Organizing localized strings /src/ ├─ Main.elm # (e.g. imports Translation.Main)

    ├─ View.elm # (e.g. imports Translation.View) └─>Translation # (linked to e.g. /Translation/En/) /Translation/ ├─ En/ │ ├─ Main.elm # (module Translation.Main) │ └─ View.elm # (module Translation.View) └─ No/ ├─ Main.elm # (module Translation.Main) └─ View.elm # (module Translation.View) © Felix Lamouroux, iosphere GmbH, 2017 12
  13. Example: Translation/No/Main.elm module Translation.Main exposing ( ..) {-| A short

    greeting. -} greeting : String greeting = "Hei!" {-| A personalized greeting. Use placeholder `name`. -} greetingWithName : String -> String greetingWithName name = "God dag, " ++ name © Felix Lamouroux, iosphere GmbH, 2017 13
  14. Example: Translation/En/Main.elm module Translation.Main exposing ( ..) {-| A short

    greeting. -} greeting : String greeting = "Hello" {-| A personalized greeting. Use placeholder `name`. -} greetingWithName : String -> String greetingWithName name = "Welcome back, " ++ name © Felix Lamouroux, iosphere GmbH, 2017 14
  15. Switching languages — Switch working copy of your app to

    English: elm-i18n-switch -l En — Compile Norwegian and English versions to dist/no.js and dist/en.js: elm-i18n-switch -l No --output dist elm-i18n-switch -l En --output dist — Serve appropriate build on your website (e.g. en.html). © Felix Lamouroux, iosphere GmbH, 2017 15
  16. Tooling CSV ⁶ Elm ⁶ PO © Felix Lamouroux, iosphere

    GmbH, 2017 16
  17. Export Elm code to CSV Extract strings from your Elm

    code to a CSV file. elm-i18n-generator --format CSV --root example/Translation --language No --export © Felix Lamouroux, iosphere GmbH, 2017 17
  18. Example: CSV export — All modules are exported into one

    long CSV file. — CSV can be converted back to Elm code. Module Key Comment Supported Placeholders Translation Translation.Main greeting A short greeting. -/- Hei! Translation.Main greetingWithNa me A personalized greeting. Use placeholder name. name God dag, {{name}} © Felix Lamouroux, iosphere GmbH, 2017 18
  19. Example: PO export3 — All modules are exported into one

    long PO string file. — PO file can be converted back to Elm code. #. A short greeting. msgid "Translation.Main.greeting" msgstr "Hei!" #. A personalized greeting. Use placeholder `name`. #. i18n: placeholders: name msgid "Translation.Main.greetingWithName" msgstr "God dag, %(name)s" 3 The Format of PO Files © Felix Lamouroux, iosphere GmbH, 2017 19
  20. Import Elm string constants and functions from PO — Create

    Elm modules from PO/CSV exports: elm-i18n-generator --format PO --language De --import export.po © Felix Lamouroux, iosphere GmbH, 2017 20
  21. Main drawback: no runtime language switching — Reload to switch

    language — Restore state of app/session But: You are doing it wrong if many users switch language ➜ Make an educated guess about the user's preferred language © Felix Lamouroux, iosphere GmbH, 2017 21
  22. Advantages © Felix Lamouroux, iosphere GmbH, 2017 22

  23. Simple view functions and code — Full type safety —

    Auto-completion by the IDE — Your Elm app can be language agnostic import Translation.Main as Translation view : Html Msg view = div [] [ text (Translation.greeting "Richard") ] © Felix Lamouroux, iosphere GmbH, 2017 23
  24. Phased rollout Quick Develop new features in your own language

    Phased Rollout new features to some languages first Safe Incomplete translations do not compile © Felix Lamouroux, iosphere GmbH, 2017 24
  25. Be!er testing Create a pseudo language for testing Avoid changing

    tests when wording changes Setup: Translation/Test/Main.elm elm-i18n-switch -l Test elm-test © Felix Lamouroux, iosphere GmbH, 2017 25
  26. Work with professional translators Be!er collaboration Work with translators in

    a known convenient formats Add new languages Setup new languages without changes to existing files © Felix Lamouroux, iosphere GmbH, 2017 26
  27. Contributions welcome — Add support for JSON/XLIFF/... import & export

    — Add support for plurals4 — Alternative build option: runtime language switching5 5 Issue #2 4 Issue #1 © Felix Lamouroux, iosphere GmbH, 2017 27
  28. Demo © Felix Lamouroux, iosphere GmbH, 2017 28

  29. None
  30. Contact me — Elm Slack: felix — Twitter: @felixlamouroux —

    Website: iosphere.de — Repository: github.com/iosphere/elm-i18n © Felix Lamouroux, iosphere GmbH, 2017 30