Internationalisation

is a piece of cake

 

Eli schutze

ui developer

@elibelly

👋

  👶🏽    ❤️    🤓     📝     🏡

🇲🇽🇳🇮🇺🇸🇨🇳🇬🇧

united kingdom

nicaragua

Internationalisation

is a piece of cake*

 

*not really**

**actually not at all

react-intl

i18n? wtf?

🤔

@elibelly

Numeronym

A number-based word

  • K9, l8r
  • 411, 007
  • i18n, l10n, a11y
  • ... n7m, a16z

@elibelly

i18n? wtf?

🤔

@elibelly

the internet ™

@elibelly

Estimated percentages of the top 10 million websites using various content languages as of October 2017

 estimates of the number of Internet users by language as of June 2017

https://w3techs.com/technologies/overview/content_language/all

http://www.internetworldstats.com/stats7.htm​

@elibelly

Internationalisation

If you internationalise, you design or develop your content, application, specification, and so on, in a way that ensures it will work well for, or can be easily adapted for, users from any culture, region, or language.

W3C Standards

@elibelly

think about..

  • Writing System - é, โลก, 世界 
  • Language
  • Formatting: Date, Time, Currency - 01/09/17
  • Writing Direction
  • Ordering, Pluralisation
  • Grammar
  • Relative time 
  • Locale * 

*LOCALEs ≠ language

@elibelly

i18n cake

Unicode

BCP47

CLDR

ICU

ECMAScript Intl API

Format JS Core

library integration

🕯🕯🕯🕯🕯

i18n cake

Unicode

BCP47

CLDR

ICU

ECMAScript Intl API

Format JS Core

react-intl

🕯🕯🕯🕯🕯

Unicode

BCP47

CLDR

ICU

ECMAScript Intl API

Format JS Core

React Intl

🕯🕯🕯🕯🕯

unicode

A standard for consistent encoding, representation, and handling of text expressed in most of the world's writing systems. 

This includes all world languages and emoji! 🙌

Includes various encodings, most used is UTF-8, the most widely used by websites. 1-4 bytes.

 

Solves the writing system consideration!

@elibelly

☕️

咖啡

قهوة

coffee

Unicode

BCP47

CLDR

ICU

ECMAScript Intl API

Format JS Core

React Intl

🕯🕯🕯🕯🕯

BCP47

LOCALEs ≠ language !

Internet Engineering Task Force - best common practice

Tags for Identifying Languages

[Language Tag]-[Subtags]*

  • en-US, en-GB
  • mn-Cyrl-MN, zh-Hant-HK
  • es-419

@elibelly

@elibelly

  👶🏽    ❤️    🤓     📝     🏡

🇲🇽🇳🇮🇺🇸🇨🇳🇬🇧

es_MX      es_NI     en_US  zh_Hans_CN    en_UK 

es_419

My Locales

what will you show me?

Unicode

BCP47

CLDR

ICU

ECMAScript Intl API

Format JS Core

React Intl

🕯🕯🕯🕯🕯

CLDR

Unicode - Common Locale Data Repository

Provides key building blocks for software to support the world's languages, with the largest and most extensive standard repository of locale data available.

  • XML Repository
  • Written in a standard - Locale Data Markup Language (LDML)
  • Includes:
    • Locale specific formatting paterns
    • Translations of names of things
    • Language/script details
  • Most devs will use CLDR indirectly, via  libraries, such as ICU, Closure, or TwitterCLDR

@elibelly

<days>
  <dayContext type="format">
	<dayWidth type="abbreviated">
		<day type="sun">dom.</day>
		<day type="mon">lun.</day>
		<day type="tue">mar.</day>
		<day type="wed">mié.</day>
		<day type="thu">jue.</day>
		<day type="fri">vie.</day>
		<day type="sat">sáb.</day>
	</dayWidth>
	<dayWidth type="short">
		<day type="sun">DO</day>
		<day type="mon">LU</day>
		<day type="tue">MA</day>
		<day type="wed">MI</day>
		<day type="thu">JU</day>
		<day type="fri">VI</day>
		<day type="sat">SA</day>
	</dayWidth>
	<dayWidth type="wide">
        	<day type="sun">domingo</day>
		<day type="mon">lunes</day>
		<day type="tue">martes</day>
		<day type="wed">miércoles</day>
		<day type="thu">jueves</day>
		<day type="fri">viernes</day>
		<day type="sat">sábado</day>
	</dayWidth>
  </dayContext>
</days>

CLDR 'Days' Section for Spanish Language

Unicode

BCP47

CLDR

ICU

ECMAScript Intl API

Format JS Core

React Intl

🕯🕯🕯🕯🕯

ICU

set of C/C++ and Java libraries providing Unicode and Globalization support for software applications

international components for unicode

defines message format  

Stores variable data between { curly braces }

@elibelly

  • Welcome, { name } ! 
  • There were { count, number } people there - 1,000 vs 1.000
  • My birthday is { birthday, date, short } - 01/02/2017 vs 02/01/2017
  • { gender, select,
    ​   male { He likes trains },
       female { She likes trains },
       other { They like trains }
  • { count , plural ,
       =0 {No more seats available }
      one {Just a single seat left!}
    other {# seats left}} - *some languages have few and many !

@elibelly

🚨 Javascript Alert 🚨

Unicode

BCP47

CLDR

ICU

ECMAScript Intl API

Format JS Core

React Intl

🕯🕯🕯🕯🕯

ECMAScript INTL API

@elibelly

ECMA 402

  • Intl.NumberFormat
  • Intl.DateTimeFormat
  • Intl.Collator
  • Constructor takes locale and formatting options
  • Exposes main method (compare() or format())
  • Currently being worked on TC39

@elibelly

var myNumber = 123456.789;

// the Japanese yen doesn't use a minor unit
console.log(
  new Intl.NumberFormat('ja-JP', 
    { style: 'currency', 
      currency: 'JPY' })
    .format(myNumber)
)
// → ¥123,457


// request a weekday along with a long date
var options = { 
  weekday: 'long', 
  year: 'numeric', 
  month: 'long', 
  day: 'numeric' };
console.log(
  new Intl.DateTimeFormat('de-DE', options).format(date)
);
// → "Donnerstag, 20. Dezember 2012"

@elibelly

  • Not supported in older browsers 
  • Expensive (esp. in React)

Unicode

BCP47

CLDR

ICU

ECMAScript Intl API

Format JS Core

React Intl

🕯🕯🕯🕯🕯

FORMAT JS

  • Open sourced by Yahoo
  • Modular collection of I18n javascript libraries 
  • Has core libs built on standards 
  • Provides integration modules 
  • Robust - works down to ES3 & IE 6 as well as Node

@elibelly

Unicode

BCP47

CLDR

ICU

ECMAScript Intl API

Format JS Core

React Intl

🕯🕯🕯🕯🕯

FORMAT JS - CORE

  • Exports Javascript API with more functionality than ECMA
  • Polyfills where needed 

@elibelly

Unicode

BCP47

CLDR

ICU

ECMAScript Intl API

Format JS Core

React Intl

🕯🕯🕯🕯🕯

REACT INTL

  • Config

    • addLocaleData
    • intlShape
    • injectIntl
    • defineMessages
  • Wrapper: IntlProvider

  • Components:
    • FormattedDate
    • FormattedTime
    • FormattedRelative
    • FormattedNumber
    • FormattedPlural
    • FormattedMessage

https://github.com/yahoo/react-intl

@elibelly

Setup

  1. Load Locale Data
  2. Add i18n context to React App
  3. Provide app specific messages (strings)
  4. Use Components! 

@elibelly

Load Locale Data

import { IntlProvider, addLocaleData } from 'react-intl';

import en from 'react-intl/locale-data/en';
import ru from 'react-intl/locale-data/ru';
import es from 'react-intl/locale-data/es';
import fr from 'react-intl/locale-data/fr';

addLocaleData([...en, ...fr, ...es, ...ru]);

If on the client side, each extra locale (usually language) is loaded in as a separate bundle

 

On the node all locales are loaded into memory server-side

@elibelly

ADD CONTEXT

import { IntlProvider, addLocaleData } from 'react-intl';
...

// This should be the only place where you update the locale
const locale = 'es-419';

const messages = require(`./locales/${locale}.json`);

ReactDOM.render(
  <IntlProvider locale={locale} messages={messages}>
    <App />
  </IntlProvider>,
  document.getElementById('root')
);

@elibelly

Provide messages 

// es-419.json

{
  "nameInput.placeholder": "Por favor introduzca su nombre...",
  "app.header": "Ejemplos de React Intl",
  "app.welcome_message":
    "{gender, select, 
      female {Bienvenida} 
      male {Bienvenido} 
      other {Bienvenidx}} {name}, {unreadCount, plural, 
            =0 {no tienes messages} 
            one {tienes {formattedUnreadCount} mensaje nuevo} 
            other {tienes {formattedUnreadCount} mensajes nuevos}} desde {formattedLastLoginTime}.",
  "app.currentTime": "Hora actual: ",
  "app.you": "tú"
}

@elibelly

USE COMPONENTS - (examples)

<FormattedNumber value={unreadCount} /> // 1,234 vs 1.234

<FormattedMessage id="app.login_screen.header" defaultMessage="This is a Header" />

<FormattedTime value={Date.now()} timeZoneName="long" />
<FormattedMessage
          id="app.welcome_message"
          defaultMessage={`
            Welcome {name}, you have received {unreadCount, plural,
                =0 {no new messages}
                one {{formattedUnreadCount} new message}
                other {{formattedUnreadCount} new messages}
            } since {formattedLastLoginTime}.
        `}
          values={{
            name: (
              <b>
                {this.state.name || (
                  <FormattedMessage id="app.you" defaultMessage="you" />
                )}
              </b>
            ),
            unreadCount: unreadCount,
            formattedUnreadCount,
            formattedLastLoginTime,
            gender,
          }}
        />

🎉

Unicode

BCP47

CLDR

ICU

ECMAScript Intl API

Format JS Core

react-intl

🕯🕯🕯

what about the candles

other challenges 

🕯 Locale Detection 

🕯 Performance

🕯 Continuous Localisation

import { 
    IntlProvider, 
    addLocaleData 
} from 'react-intl';
...

// This should be the only place 
// where you update the locale
const locale = 'es-419';

Locale detection

 

  • accept headers vs geo/IP ?
  • UI - good practice to let the user choose!
  • browser? cookies? app storage?
  • UX & Auth - are they a recognised user? a guest?
  • meaningful fallbacks

Content negotiation

Performance

  • locales and bundle size
  • polyfills
  • caching 

Continuous Localisation

  • ease
  • price
  • services & features

It is a way of automatically, seamlessly gathering new source material, publishing it for translation, acquiring translations and integrating them back into the product.

i18l has a logistics problem

internationalisation

is part of accessibility

 

 

💡

Unicode

BCP47

CLDR

ICU

ECMAScript Intl API

Format JS Core

react-intl

🕯🕯🕯

Thank you

👋

@elibelly

Internationalisation is a Piece of Cake

By Eli Schütze Ramírez

Internationalisation is a Piece of Cake

While about 51% of the world’s websites are in English, only about 25% of web users are English speakers. With half of the world’s population online, internationalisation is as relevant as ever! Let’s explore how i18n gets made on the web.

  • 2,283