SlideShare una empresa de Scribd logo
1 de 77
Descargar para leer sin conexión
This talk lasts
Localisation is easy
Administrative Notes
• @pilif on twitter
• pilif on github
• working at Sensational AG
• @pilif on twitter
• pilif on github
• working at Sensational AG
• warming up to shirts
Thanks Richard for the
Recording
About that 💩
Maybe ES6…?
My host name is a horrible spoiler if you're into JRPGs. Disregard
however…
close enough.
Back to the topic at
hand
Let’s talk terms
• Language is a language as it is spoken or
written
• Locale is the name given to a set of parameters
that define how things should be done for users
speaking a certain language in a certain place
• There are many more locales than countries
Locale
• Locales consist of a language…
• … and a country
• … and sometimes specific variants
Specifying locales
• IETF BCP-47 document
• See RFC 5646 and RFC 4647
• Use language-script-territory@modifier
• POSIX uses
language_territory.encoding@modifier
fr-Latn-CH
fr-CH
fr_CH.utf-8
The Locale affects
many things
Number formatting
• Probably the most obvious of the bunch.
• Decimal separator
• Thousands separator
• Sign
• Also: Currency information
Some Samples
de-CH de-DE en-US
decimal
separator
. , .
thousands
separator
' . ,
12,435
en-US twelve thousand four hundred and thirty five
de-DE twelve comma four three five
de-CH error
Date Formatting
• Obviously names of months and weekdays
• Order of distinct parts
• Separator character
• Commonly used formats in different contexts
Date Formatting
• Libraries usually provide a generic short/
medium/long format
• Libraries also provide templates
• If your library’s template language has any
characters that are not for replacement, they are
doing it wrong
• Apple does it right since 10.11 and iOS9
2015-07-18 17:47
Long Medium Short
en-US
July 18, 2015 at
4:58:00 PM CEST
Jul 18, 2015,
4:58:00 PM
7/18/15, 4:58 PM
fr-CA
18 juillet 2015
16:58:00 UTC+2
18 juil. 2015
16:58:00
15-07-18 16:58
fr-CH
18 juillet 2015
16:58:00 UTC+2
18 juil. 2015
16:58:00
18.07.15 16:58
fr-FR
18 juillet 2015
16:58:00 UTC+2
18 juil. 2015
16:58:00
18/07/2015 16:58
Choice of calendar
• Most of the world is using the Gregorian
calendar
• The Julian calendar uses the same month names
but is off by 13 days (they have July 5th right
now)
• Other calendars use different month names
• Might affect holiday calculations
Collation order
• How to compare to strings. Which one is first?
• Where to put the characters with pesky
accents?
• How to deal with case differences?
• What about non-latin scripts?
Collation fun*
• Phonebook german vs. ordinary german, vs.
Austrian german (dealing with umlauts)
• Contractions (Spanish ch counts as one letter,
ch in Czech sorts after h, but c after b, etc)
• Handling of accents is language-dependent
• Case insensitive is a mess
Case folding
• Some languages don’t differentiate between upper- and
lowercase
• Inconsistent mapping between upper- and lowercase (ß
=> SS, the reverse is not always true)
• Uppercasing accented characters is language (and
sometimes locale) dependent. French characters often
loose accents when uppercasing
• Inconsistent uppercasing for some languages (uppercase
turkish i is İ. Lowercase turkish I is ı)
Double the fun
• Collation and Case-Folding provide an interesting
team
• Depending on locale, upper- and lowercase should be
sorted together or apart
• In some locales, case doesn’t matter at all when sorting
• In some locales, case always matters when sorting
• Depends on the use-case
Collation strength
• icu created the concept of “collation strength”
• strength 1 is the most lenient
• strength 5 is the most exact
• Example: Strength 2 removes accents unless
the language is Danish
‘nough said
RTL
Perspectives matter
Context matters
• “This slide lasts one minute”
• “This talk lasts 30 minutes”
• “Lunch lasted 1:30 hours”
• “Tomorrow I’ll sleep in”
• “August, 1th is a national holiday”
Let’s get practical
Locale handling is like escaping
• Always store raw unformatted data
• Format near the end of the chain
• Just before you escape
• Parse user input as early as possible
• Use native data types
UI Language is not locale
• Users might prefer to use the os in a different
language than what’s inferred by their locale
• Just because I’m in de_CH it doesn’t mean I
want your software to speak german to me
• UI language is completely different from the
users locale
Avoid this mess
Avoid this mess
Avoid this mess
Mixing Locales
• Forming sentences in UI language with locale formatted
data is… challenging
• Be mindful that language might influence some locale
formatting.
• “This talk lasts ”
• or rather “This talk lasts 30 minutes”
• It depends. Does the locale also use hours and minutes?
Never be helpful* and
translate units
1kg in de_CH is not
1lbs in en_US
Btw: Apple’s APIs are
really good at this
What about web sites?
• Never, ever infer UI language by IP Geolocation.
People from Google: This slide is for you!
What about web sites?
• Never, ever infer UI language by IP Geolocation.
• Ever. Ever. EVER.
People from Google: This slide is for you!
What about web sites?
• Never, ever infer UI language by IP Geolocation.
• Ever. Ever. EVER.
• Promise!
People from Google: This slide is for you!
What about web sites?
• Never, ever infer UI language by IP Geolocation.
• Ever. Ever. EVER.
• Promise!
• You may infer Locale from IP Geolocation
though
People from Google: This slide is for you!
Rely on HTTP
• Trust Accept-Language - by now browser set
it correctly
• Use the header to determine UI language
• Use the header to determine default locale
• But ask the user
• Same goes for time zones
SHOW ME SOME
CODE ALREADY!!!
The past
• There has always been date formatting
(Date.toLocaleString). Mostly useless
• People were self-nebling (search youtube for “ich
neble selber”) for example in date pickers and
libraries
• hint: applying substr() to Date.toDateString() is not a
correct solution.
• same goes for using replace(‘.’, ‘,’) on a number
The present
• Microsoft has donated a huge chunk of localisation code to the
jQuery project.
• It’s not integrated into jQuery, but maintained by the jQuery project
• Check out https://github.com/jquery/globalize
• Doesn’t support collation
• The library is big
• But most of it is data and this problem can only be solved with a
huge database of special cases
Globalize.locale("fr-CH");



console.log(Globalize.formatDate(

new Date(), {datetime: "medium" }

));



console.log(Globalize.formatDate(

new Date(), {skeleton: "yMMMM" }

));



console.log(Globalize.formatNumber(12345.6789));



console.log(Globalize.formatCurrency(1956.3334, "EUR"));



console.log(Globalize.formatRelativeTime(-35, "second"));
Globalize.locale("fr-CH");



console.log(Globalize.formatDate(

new Date(), {datetime: "medium" }

));



console.log(Globalize.formatDate(

new Date(), {skeleton: "yMMMM" }

));



console.log(Globalize.formatNumber(12345.6789));



console.log(Globalize.formatCurrency(1956.3334, "EUR"));



console.log(Globalize.formatRelativeTime(-35, "second"));
Globalize.locale("fr-CH");



console.log(Globalize.formatDate(

new Date(), {datetime: "medium" }

));



console.log(Globalize.formatDate(

new Date(), {skeleton: "yMMMM" }

));



console.log(Globalize.formatNumber(12345.6789));



console.log(Globalize.formatCurrency(1956.3334, "EUR"));



console.log(Globalize.formatRelativeTime(-35, "second"));
Globalize.locale("fr-CH");



console.log(Globalize.formatDate(

new Date(), {datetime: "medium" }

));



console.log(Globalize.formatDate(

new Date(), {skeleton: "yMMMM" }

));



console.log(Globalize.formatNumber(12345.6789));



console.log(Globalize.formatCurrency(1956.3334, "EUR"));



console.log(Globalize.formatRelativeTime(-35, "second"));
Globalize.locale("fr-CH");



console.log(Globalize.formatDate(

new Date(), {datetime: "medium" }

));



console.log(Globalize.formatDate(

new Date(), {skeleton: "yMMMM" }

));



console.log(Globalize.formatNumber(12345.6789));



console.log(Globalize.formatCurrency(1956.3334, "EUR"));



console.log(Globalize.formatRelativeTime(-35, "second"));
Globalize.locale("fr-CH");



console.log(Globalize.formatDate(

new Date(), {datetime: "medium" }

));



console.log(Globalize.formatDate(

new Date(), {skeleton: "yMMMM" }

));



console.log(Globalize.formatNumber(12345.6789));



console.log(Globalize.formatCurrency(1956.3334, "EUR"));



console.log(Globalize.formatRelativeTime(-35, "second"));
Globalize.locale("fr-CH");



console.log(Globalize.formatDate(

new Date(), {datetime: "medium" }

));



console.log(Globalize.formatDate(

new Date(), {skeleton: "yMMMM" }

));



console.log(Globalize.formatNumber(12345.6789));



console.log(Globalize.formatCurrency(1956.3334, "EUR"));



console.log(Globalize.formatRelativeTime(-35, "second"));
The future
• ECMA-402 from 2012
• Yes. Specs from 2012 are “the future” in JS land
• Provides the global Intl object
• Date, Number formatting and Collation
• see: http://www.ecma-international.org/
ecma-402/1.0/
Could be worse
node.js is still
bikeshedding because icu
var f = new Intl.DateTimeFormat('de-CH', {

weekday: 'long', year: 'numeric',

month: 'long', day: 'numeric'

});

console.log(f.format(new Date()));



var n = new Intl.NumberFormat('de-CH', {

style: "decimal",

minimumFractionDigits: 2

});

console.log(n.format(1234.5));



var currency = new Intl.NumberFormat('de-CH', {

style: "currency",

currency: 'EUR'

});

console.log(currency.format(1234.5));



var comp = new Intl.Collator('de-CH');

var words = [

"Swissjs", "swissjs", "is",

"loads", "of", "fun"

];

console.log(words.sort(comp));
var f = new Intl.DateTimeFormat('de-CH', {

weekday: 'long', year: 'numeric',

month: 'long', day: 'numeric'

});

console.log(f.format(new Date()));



var n = new Intl.NumberFormat('de-CH', {

style: "decimal",

minimumFractionDigits: 2

});

console.log(n.format(1234.5));



var currency = new Intl.NumberFormat('de-CH', {

style: "currency",

currency: 'EUR'

});

console.log(currency.format(1234.5));



var comp = new Intl.Collator('de-CH');

var words = [

"Swissjs", "swissjs", "is",

"loads", "of", "fun"

];

console.log(words.sort(comp));
var f = new Intl.DateTimeFormat('de-CH', {

weekday: 'long', year: 'numeric',

month: 'long', day: 'numeric'

});

console.log(f.format(new Date()));



var n = new Intl.NumberFormat('de-CH', {

style: "decimal",

minimumFractionDigits: 2

});

console.log(n.format(1234.5));



var currency = new Intl.NumberFormat('de-CH', {

style: "currency",

currency: 'EUR'

});

console.log(currency.format(1234.5));



var comp = new Intl.Collator('de-CH');

var words = [

"Swissjs", "swissjs", "is",

"loads", "of", "fun"

];

console.log(words.sort(comp));
var f = new Intl.DateTimeFormat('de-CH', {

weekday: 'long', year: 'numeric',

month: 'long', day: 'numeric'

});

console.log(f.format(new Date()));



var n = new Intl.NumberFormat('de-CH', {

style: "decimal",

minimumFractionDigits: 2

});

console.log(n.format(1234.5));



var currency = new Intl.NumberFormat('de-CH', {

style: "currency",

currency: 'EUR'

});

console.log(currency.format(1234.5));



var comp = new Intl.Collator('de-CH');

var words = [

"Swissjs", "swissjs", "is",

"loads", "of", "fun"

];

console.log(words.sort(comp));
var f = new Intl.DateTimeFormat('de-CH', {

weekday: 'long', year: 'numeric',

month: 'long', day: 'numeric'

});

console.log(f.format(new Date()));



var n = new Intl.NumberFormat('de-CH', {

style: "decimal",

minimumFractionDigits: 2

});

console.log(n.format(1234.5));



var currency = new Intl.NumberFormat('de-CH', {

style: "currency",

currency: 'EUR'

});

console.log(currency.format(1234.5));



var comp = new Intl.Collator('de-CH');

var words = [

"Swissjs", "swissjs", "is",

"loads", "of", "fun"

];

console.log(words.sort(comp));
var f = new Intl.DateTimeFormat('de-CH', {

weekday: 'long', year: 'numeric',

month: 'long', day: 'numeric'

});

console.log(f.format(new Date()));



var n = new Intl.NumberFormat('de-CH', {

style: "decimal",

minimumFractionDigits: 2

});

console.log(n.format(1234.5));



var currency = new Intl.NumberFormat('de-CH', {

style: "currency",

currency: 'EUR'

});

console.log(currency.format(1234.5));



var comp = new Intl.Collator('de-CH');

var words = [

"Swissjs", "swissjs", "is",

"loads", "of", "fun"

];

console.log(words.sort(comp));
var f = new Intl.DateTimeFormat('de-CH', {

weekday: 'long', year: 'numeric',

month: 'long', day: 'numeric'

});

console.log(f.format(new Date()));



var n = new Intl.NumberFormat('de-CH', {

style: "decimal",

minimumFractionDigits: 2

});

console.log(n.format(1234.5));



var currency = new Intl.NumberFormat('de-CH', {

style: "currency",

currency: 'EUR'

});

console.log(currency.format(1234.5));



var comp = new Intl.Collator('de-CH');

var words = [

"Swissjs", "swissjs", "is",

"loads", "of", "fun"

];

console.log(words.sort(comp));
var f = new Intl.DateTimeFormat('de-CH', {

weekday: 'long', year: 'numeric',

month: 'long', day: 'numeric'

});

console.log(f.format(new Date()));



var n = new Intl.NumberFormat('de-CH', {

style: "decimal",

minimumFractionDigits: 2

});

console.log(n.format(1234.5));



var currency = new Intl.NumberFormat('de-CH', {

style: "currency",

currency: 'EUR'

});

console.log(currency.format(1234.5));



var comp = new Intl.Collator('de-CH');

var words = [

"Swissjs", "swissjs", "is",

"loads", "of", "fun"

];

console.log(words.sort(comp));
Conclusion
• Proper localisation is part of our job to make the web useful for
everybody
• Use the libraries provided
• Whenever you think you know better than the library: No. You
don’t.
• Remember that UI language and Locale are not always connected
• Don’t do IP geolocation for language choice
• When in doubt: Ask the user. She’ll know for sure.
Before I leave
""".length
[…"""].length
In case you answered
11 and 8, I salute you
Thanks everyone and
enjoy your evening
• U+1F468 (MAN) 👨
• U+200D (ZERO WIDTH JOINER)
• U+2764 (HEAVY BLACK HEART) ❤
• U+FE0F (VARIATION SELECTOR-16)
• U+200D (ZERO WIDTH JOINER)
• U+1F48B (KISS MARK) 💋
• U+200D (ZERO WIDTH JOINER)
• U+1F468 (MAN) 👨

Más contenido relacionado

Similar a This talk lasts 三十分钟

Search-Driven Programming
Search-Driven ProgrammingSearch-Driven Programming
Search-Driven Programming
Ethan Herdrick
 
PCEP Module 1.pptx
PCEP Module 1.pptxPCEP Module 1.pptx
PCEP Module 1.pptx
zakariaHujale
 
Lesson 301 26 nov13-1500-ay
Lesson 301 26 nov13-1500-ayLesson 301 26 nov13-1500-ay
Lesson 301 26 nov13-1500-ay
Codecademy Ren
 
Programming Languages #devcon2013
Programming Languages #devcon2013Programming Languages #devcon2013
Programming Languages #devcon2013
Iván Montes
 
How to create/improve OSS product and its community (revised)
How to create/improve OSS product and its community (revised)How to create/improve OSS product and its community (revised)
How to create/improve OSS product and its community (revised)
SATOSHI TAGOMORI
 

Similar a This talk lasts 三十分钟 (20)

Search-Driven Programming
Search-Driven ProgrammingSearch-Driven Programming
Search-Driven Programming
 
An introduction to go programming language
An introduction to go programming languageAn introduction to go programming language
An introduction to go programming language
 
Exploring Natural Language Processing in Ruby
Exploring Natural Language Processing in RubyExploring Natural Language Processing in Ruby
Exploring Natural Language Processing in Ruby
 
Number of Computer Languages = 3
Number of Computer Languages = 3Number of Computer Languages = 3
Number of Computer Languages = 3
 
PCEP Module 1.pptx
PCEP Module 1.pptxPCEP Module 1.pptx
PCEP Module 1.pptx
 
[GAMENEXT] Five mantras for l10 (LatisGlboal)
[GAMENEXT] Five mantras for l10 (LatisGlboal)[GAMENEXT] Five mantras for l10 (LatisGlboal)
[GAMENEXT] Five mantras for l10 (LatisGlboal)
 
Using unicode with php
Using unicode with phpUsing unicode with php
Using unicode with php
 
Go language presentation
Go language presentationGo language presentation
Go language presentation
 
Lesson 301 26 nov13-1500-ay
Lesson 301 26 nov13-1500-ayLesson 301 26 nov13-1500-ay
Lesson 301 26 nov13-1500-ay
 
Natural Language Processing Tools for the Digital Humanities
Natural Language Processing Tools for the Digital HumanitiesNatural Language Processing Tools for the Digital Humanities
Natural Language Processing Tools for the Digital Humanities
 
Multilingual Fine-grained Entity Typing
Multilingual Fine-grained Entity Typing Multilingual Fine-grained Entity Typing
Multilingual Fine-grained Entity Typing
 
One language to rule them all type script
One language to rule them all type scriptOne language to rule them all type script
One language to rule them all type script
 
Programming Languages #devcon2013
Programming Languages #devcon2013Programming Languages #devcon2013
Programming Languages #devcon2013
 
Using unicode with php
Using unicode with phpUsing unicode with php
Using unicode with php
 
The Ring programming language version 1.7 book - Part 4 of 196
The Ring programming language version 1.7 book - Part 4 of 196The Ring programming language version 1.7 book - Part 4 of 196
The Ring programming language version 1.7 book - Part 4 of 196
 
Craft of coding
Craft of codingCraft of coding
Craft of coding
 
difference between c c++ c#
difference between c c++ c#difference between c c++ c#
difference between c c++ c#
 
About programming languages
About programming languagesAbout programming languages
About programming languages
 
How to create/improve OSS product and its community (revised)
How to create/improve OSS product and its community (revised)How to create/improve OSS product and its community (revised)
How to create/improve OSS product and its community (revised)
 
LocJam 2014 Barcelona Workshop - Carme Mangiron
LocJam 2014 Barcelona Workshop - Carme MangironLocJam 2014 Barcelona Workshop - Carme Mangiron
LocJam 2014 Barcelona Workshop - Carme Mangiron
 

Último

AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 

Último (20)

AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
Generic or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisionsGeneric or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisions
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions Presentation
 

This talk lasts 三十分钟

  • 3. • @pilif on twitter • pilif on github • working at Sensational AG
  • 4. • @pilif on twitter • pilif on github • working at Sensational AG • warming up to shirts
  • 5. Thanks Richard for the Recording
  • 8. My host name is a horrible spoiler if you're into JRPGs. Disregard
  • 10.
  • 11.
  • 13. Back to the topic at hand
  • 14. Let’s talk terms • Language is a language as it is spoken or written • Locale is the name given to a set of parameters that define how things should be done for users speaking a certain language in a certain place • There are many more locales than countries
  • 15. Locale • Locales consist of a language… • … and a country • … and sometimes specific variants
  • 16. Specifying locales • IETF BCP-47 document • See RFC 5646 and RFC 4647 • Use language-script-territory@modifier • POSIX uses language_territory.encoding@modifier
  • 18. fr-CH
  • 21. Number formatting • Probably the most obvious of the bunch. • Decimal separator • Thousands separator • Sign • Also: Currency information
  • 22. Some Samples de-CH de-DE en-US decimal separator . , . thousands separator ' . ,
  • 23. 12,435 en-US twelve thousand four hundred and thirty five de-DE twelve comma four three five de-CH error
  • 24. Date Formatting • Obviously names of months and weekdays • Order of distinct parts • Separator character • Commonly used formats in different contexts
  • 25. Date Formatting • Libraries usually provide a generic short/ medium/long format • Libraries also provide templates • If your library’s template language has any characters that are not for replacement, they are doing it wrong • Apple does it right since 10.11 and iOS9
  • 26. 2015-07-18 17:47 Long Medium Short en-US July 18, 2015 at 4:58:00 PM CEST Jul 18, 2015, 4:58:00 PM 7/18/15, 4:58 PM fr-CA 18 juillet 2015 16:58:00 UTC+2 18 juil. 2015 16:58:00 15-07-18 16:58 fr-CH 18 juillet 2015 16:58:00 UTC+2 18 juil. 2015 16:58:00 18.07.15 16:58 fr-FR 18 juillet 2015 16:58:00 UTC+2 18 juil. 2015 16:58:00 18/07/2015 16:58
  • 27. Choice of calendar • Most of the world is using the Gregorian calendar • The Julian calendar uses the same month names but is off by 13 days (they have July 5th right now) • Other calendars use different month names • Might affect holiday calculations
  • 28. Collation order • How to compare to strings. Which one is first? • Where to put the characters with pesky accents? • How to deal with case differences? • What about non-latin scripts?
  • 29. Collation fun* • Phonebook german vs. ordinary german, vs. Austrian german (dealing with umlauts) • Contractions (Spanish ch counts as one letter, ch in Czech sorts after h, but c after b, etc) • Handling of accents is language-dependent • Case insensitive is a mess
  • 30. Case folding • Some languages don’t differentiate between upper- and lowercase • Inconsistent mapping between upper- and lowercase (ß => SS, the reverse is not always true) • Uppercasing accented characters is language (and sometimes locale) dependent. French characters often loose accents when uppercasing • Inconsistent uppercasing for some languages (uppercase turkish i is İ. Lowercase turkish I is ı)
  • 31. Double the fun • Collation and Case-Folding provide an interesting team • Depending on locale, upper- and lowercase should be sorted together or apart • In some locales, case doesn’t matter at all when sorting • In some locales, case always matters when sorting • Depends on the use-case
  • 32. Collation strength • icu created the concept of “collation strength” • strength 1 is the most lenient • strength 5 is the most exact • Example: Strength 2 removes accents unless the language is Danish
  • 35. Context matters • “This slide lasts one minute” • “This talk lasts 30 minutes” • “Lunch lasted 1:30 hours” • “Tomorrow I’ll sleep in” • “August, 1th is a national holiday”
  • 37. Locale handling is like escaping • Always store raw unformatted data • Format near the end of the chain • Just before you escape • Parse user input as early as possible • Use native data types
  • 38. UI Language is not locale • Users might prefer to use the os in a different language than what’s inferred by their locale • Just because I’m in de_CH it doesn’t mean I want your software to speak german to me • UI language is completely different from the users locale
  • 42. Mixing Locales • Forming sentences in UI language with locale formatted data is… challenging • Be mindful that language might influence some locale formatting. • “This talk lasts ” • or rather “This talk lasts 30 minutes” • It depends. Does the locale also use hours and minutes?
  • 43. Never be helpful* and translate units
  • 44. 1kg in de_CH is not 1lbs in en_US
  • 45. Btw: Apple’s APIs are really good at this
  • 46. What about web sites? • Never, ever infer UI language by IP Geolocation. People from Google: This slide is for you!
  • 47. What about web sites? • Never, ever infer UI language by IP Geolocation. • Ever. Ever. EVER. People from Google: This slide is for you!
  • 48. What about web sites? • Never, ever infer UI language by IP Geolocation. • Ever. Ever. EVER. • Promise! People from Google: This slide is for you!
  • 49. What about web sites? • Never, ever infer UI language by IP Geolocation. • Ever. Ever. EVER. • Promise! • You may infer Locale from IP Geolocation though People from Google: This slide is for you!
  • 50. Rely on HTTP • Trust Accept-Language - by now browser set it correctly • Use the header to determine UI language • Use the header to determine default locale • But ask the user • Same goes for time zones
  • 51. SHOW ME SOME CODE ALREADY!!!
  • 52. The past • There has always been date formatting (Date.toLocaleString). Mostly useless • People were self-nebling (search youtube for “ich neble selber”) for example in date pickers and libraries • hint: applying substr() to Date.toDateString() is not a correct solution. • same goes for using replace(‘.’, ‘,’) on a number
  • 53. The present • Microsoft has donated a huge chunk of localisation code to the jQuery project. • It’s not integrated into jQuery, but maintained by the jQuery project • Check out https://github.com/jquery/globalize • Doesn’t support collation • The library is big • But most of it is data and this problem can only be solved with a huge database of special cases
  • 54. Globalize.locale("fr-CH");
 
 console.log(Globalize.formatDate(
 new Date(), {datetime: "medium" }
 ));
 
 console.log(Globalize.formatDate(
 new Date(), {skeleton: "yMMMM" }
 ));
 
 console.log(Globalize.formatNumber(12345.6789));
 
 console.log(Globalize.formatCurrency(1956.3334, "EUR"));
 
 console.log(Globalize.formatRelativeTime(-35, "second"));
  • 55. Globalize.locale("fr-CH");
 
 console.log(Globalize.formatDate(
 new Date(), {datetime: "medium" }
 ));
 
 console.log(Globalize.formatDate(
 new Date(), {skeleton: "yMMMM" }
 ));
 
 console.log(Globalize.formatNumber(12345.6789));
 
 console.log(Globalize.formatCurrency(1956.3334, "EUR"));
 
 console.log(Globalize.formatRelativeTime(-35, "second"));
  • 56. Globalize.locale("fr-CH");
 
 console.log(Globalize.formatDate(
 new Date(), {datetime: "medium" }
 ));
 
 console.log(Globalize.formatDate(
 new Date(), {skeleton: "yMMMM" }
 ));
 
 console.log(Globalize.formatNumber(12345.6789));
 
 console.log(Globalize.formatCurrency(1956.3334, "EUR"));
 
 console.log(Globalize.formatRelativeTime(-35, "second"));
  • 57. Globalize.locale("fr-CH");
 
 console.log(Globalize.formatDate(
 new Date(), {datetime: "medium" }
 ));
 
 console.log(Globalize.formatDate(
 new Date(), {skeleton: "yMMMM" }
 ));
 
 console.log(Globalize.formatNumber(12345.6789));
 
 console.log(Globalize.formatCurrency(1956.3334, "EUR"));
 
 console.log(Globalize.formatRelativeTime(-35, "second"));
  • 58. Globalize.locale("fr-CH");
 
 console.log(Globalize.formatDate(
 new Date(), {datetime: "medium" }
 ));
 
 console.log(Globalize.formatDate(
 new Date(), {skeleton: "yMMMM" }
 ));
 
 console.log(Globalize.formatNumber(12345.6789));
 
 console.log(Globalize.formatCurrency(1956.3334, "EUR"));
 
 console.log(Globalize.formatRelativeTime(-35, "second"));
  • 59. Globalize.locale("fr-CH");
 
 console.log(Globalize.formatDate(
 new Date(), {datetime: "medium" }
 ));
 
 console.log(Globalize.formatDate(
 new Date(), {skeleton: "yMMMM" }
 ));
 
 console.log(Globalize.formatNumber(12345.6789));
 
 console.log(Globalize.formatCurrency(1956.3334, "EUR"));
 
 console.log(Globalize.formatRelativeTime(-35, "second"));
  • 60. Globalize.locale("fr-CH");
 
 console.log(Globalize.formatDate(
 new Date(), {datetime: "medium" }
 ));
 
 console.log(Globalize.formatDate(
 new Date(), {skeleton: "yMMMM" }
 ));
 
 console.log(Globalize.formatNumber(12345.6789));
 
 console.log(Globalize.formatCurrency(1956.3334, "EUR"));
 
 console.log(Globalize.formatRelativeTime(-35, "second"));
  • 61. The future • ECMA-402 from 2012 • Yes. Specs from 2012 are “the future” in JS land • Provides the global Intl object • Date, Number formatting and Collation • see: http://www.ecma-international.org/ ecma-402/1.0/
  • 64. var f = new Intl.DateTimeFormat('de-CH', {
 weekday: 'long', year: 'numeric',
 month: 'long', day: 'numeric'
 });
 console.log(f.format(new Date()));
 
 var n = new Intl.NumberFormat('de-CH', {
 style: "decimal",
 minimumFractionDigits: 2
 });
 console.log(n.format(1234.5));
 
 var currency = new Intl.NumberFormat('de-CH', {
 style: "currency",
 currency: 'EUR'
 });
 console.log(currency.format(1234.5));
 
 var comp = new Intl.Collator('de-CH');
 var words = [
 "Swissjs", "swissjs", "is",
 "loads", "of", "fun"
 ];
 console.log(words.sort(comp));
  • 65. var f = new Intl.DateTimeFormat('de-CH', {
 weekday: 'long', year: 'numeric',
 month: 'long', day: 'numeric'
 });
 console.log(f.format(new Date()));
 
 var n = new Intl.NumberFormat('de-CH', {
 style: "decimal",
 minimumFractionDigits: 2
 });
 console.log(n.format(1234.5));
 
 var currency = new Intl.NumberFormat('de-CH', {
 style: "currency",
 currency: 'EUR'
 });
 console.log(currency.format(1234.5));
 
 var comp = new Intl.Collator('de-CH');
 var words = [
 "Swissjs", "swissjs", "is",
 "loads", "of", "fun"
 ];
 console.log(words.sort(comp));
  • 66. var f = new Intl.DateTimeFormat('de-CH', {
 weekday: 'long', year: 'numeric',
 month: 'long', day: 'numeric'
 });
 console.log(f.format(new Date()));
 
 var n = new Intl.NumberFormat('de-CH', {
 style: "decimal",
 minimumFractionDigits: 2
 });
 console.log(n.format(1234.5));
 
 var currency = new Intl.NumberFormat('de-CH', {
 style: "currency",
 currency: 'EUR'
 });
 console.log(currency.format(1234.5));
 
 var comp = new Intl.Collator('de-CH');
 var words = [
 "Swissjs", "swissjs", "is",
 "loads", "of", "fun"
 ];
 console.log(words.sort(comp));
  • 67. var f = new Intl.DateTimeFormat('de-CH', {
 weekday: 'long', year: 'numeric',
 month: 'long', day: 'numeric'
 });
 console.log(f.format(new Date()));
 
 var n = new Intl.NumberFormat('de-CH', {
 style: "decimal",
 minimumFractionDigits: 2
 });
 console.log(n.format(1234.5));
 
 var currency = new Intl.NumberFormat('de-CH', {
 style: "currency",
 currency: 'EUR'
 });
 console.log(currency.format(1234.5));
 
 var comp = new Intl.Collator('de-CH');
 var words = [
 "Swissjs", "swissjs", "is",
 "loads", "of", "fun"
 ];
 console.log(words.sort(comp));
  • 68. var f = new Intl.DateTimeFormat('de-CH', {
 weekday: 'long', year: 'numeric',
 month: 'long', day: 'numeric'
 });
 console.log(f.format(new Date()));
 
 var n = new Intl.NumberFormat('de-CH', {
 style: "decimal",
 minimumFractionDigits: 2
 });
 console.log(n.format(1234.5));
 
 var currency = new Intl.NumberFormat('de-CH', {
 style: "currency",
 currency: 'EUR'
 });
 console.log(currency.format(1234.5));
 
 var comp = new Intl.Collator('de-CH');
 var words = [
 "Swissjs", "swissjs", "is",
 "loads", "of", "fun"
 ];
 console.log(words.sort(comp));
  • 69. var f = new Intl.DateTimeFormat('de-CH', {
 weekday: 'long', year: 'numeric',
 month: 'long', day: 'numeric'
 });
 console.log(f.format(new Date()));
 
 var n = new Intl.NumberFormat('de-CH', {
 style: "decimal",
 minimumFractionDigits: 2
 });
 console.log(n.format(1234.5));
 
 var currency = new Intl.NumberFormat('de-CH', {
 style: "currency",
 currency: 'EUR'
 });
 console.log(currency.format(1234.5));
 
 var comp = new Intl.Collator('de-CH');
 var words = [
 "Swissjs", "swissjs", "is",
 "loads", "of", "fun"
 ];
 console.log(words.sort(comp));
  • 70. var f = new Intl.DateTimeFormat('de-CH', {
 weekday: 'long', year: 'numeric',
 month: 'long', day: 'numeric'
 });
 console.log(f.format(new Date()));
 
 var n = new Intl.NumberFormat('de-CH', {
 style: "decimal",
 minimumFractionDigits: 2
 });
 console.log(n.format(1234.5));
 
 var currency = new Intl.NumberFormat('de-CH', {
 style: "currency",
 currency: 'EUR'
 });
 console.log(currency.format(1234.5));
 
 var comp = new Intl.Collator('de-CH');
 var words = [
 "Swissjs", "swissjs", "is",
 "loads", "of", "fun"
 ];
 console.log(words.sort(comp));
  • 71. var f = new Intl.DateTimeFormat('de-CH', {
 weekday: 'long', year: 'numeric',
 month: 'long', day: 'numeric'
 });
 console.log(f.format(new Date()));
 
 var n = new Intl.NumberFormat('de-CH', {
 style: "decimal",
 minimumFractionDigits: 2
 });
 console.log(n.format(1234.5));
 
 var currency = new Intl.NumberFormat('de-CH', {
 style: "currency",
 currency: 'EUR'
 });
 console.log(currency.format(1234.5));
 
 var comp = new Intl.Collator('de-CH');
 var words = [
 "Swissjs", "swissjs", "is",
 "loads", "of", "fun"
 ];
 console.log(words.sort(comp));
  • 72. Conclusion • Proper localisation is part of our job to make the web useful for everybody • Use the libraries provided • Whenever you think you know better than the library: No. You don’t. • Remember that UI language and Locale are not always connected • Don’t do IP geolocation for language choice • When in doubt: Ask the user. She’ll know for sure.
  • 75. In case you answered 11 and 8, I salute you
  • 77. • U+1F468 (MAN) 👨 • U+200D (ZERO WIDTH JOINER) • U+2764 (HEAVY BLACK HEART) ❤ • U+FE0F (VARIATION SELECTOR-16) • U+200D (ZERO WIDTH JOINER) • U+1F48B (KISS MARK) 💋 • U+200D (ZERO WIDTH JOINER) • U+1F468 (MAN) 👨