SlideShare ist ein Scribd-Unternehmen logo
1 von 77
Downloaden Sie, um offline zu lesen
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) 👨

Weitere ähnliche Inhalte

Ähnlich wie This talk lasts 三十分钟

Search-Driven Programming
Search-Driven ProgrammingSearch-Driven Programming
Search-Driven ProgrammingEthan Herdrick
 
An introduction to go programming language
An introduction to go programming languageAn introduction to go programming language
An introduction to go programming languageTechnology Parser
 
Exploring Natural Language Processing in Ruby
Exploring Natural Language Processing in RubyExploring Natural Language Processing in Ruby
Exploring Natural Language Processing in RubyKevin Dias
 
Number of Computer Languages = 3
Number of Computer Languages = 3Number of Computer Languages = 3
Number of Computer Languages = 3Ram Sekhar
 
[GAMENEXT] Five mantras for l10 (LatisGlboal)
[GAMENEXT] Five mantras for l10 (LatisGlboal)[GAMENEXT] Five mantras for l10 (LatisGlboal)
[GAMENEXT] Five mantras for l10 (LatisGlboal)GAMENEXT Works
 
Go language presentation
Go language presentationGo language presentation
Go language presentationparamisoft
 
Lesson 301 26 nov13-1500-ay
Lesson 301 26 nov13-1500-ayLesson 301 26 nov13-1500-ay
Lesson 301 26 nov13-1500-ayCodecademy Ren
 
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 HumanitiesXiang Li
 
Multilingual Fine-grained Entity Typing
Multilingual Fine-grained Entity Typing Multilingual Fine-grained Entity Typing
Multilingual Fine-grained Entity Typing Marieke van Erp
 
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 scriptGil Fink
 
Programming Languages #devcon2013
Programming Languages #devcon2013Programming Languages #devcon2013
Programming Languages #devcon2013Iván Montes
 
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 196Mahmoud Samir Fayed
 
difference between c c++ c#
difference between c c++ c#difference between c c++ c#
difference between c c++ c#Sireesh K
 
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
 
LocJam 2014 Barcelona Workshop - Carme Mangiron
LocJam 2014 Barcelona Workshop - Carme MangironLocJam 2014 Barcelona Workshop - Carme Mangiron
LocJam 2014 Barcelona Workshop - Carme MangironCarme Mangiron Hevia
 

Ähnlich wie 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
 

Kürzlich hochgeladen

%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 Bahrainmasabamasaba
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareJim McKeeth
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastPapp Krisztián
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationShrmpro
 
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.pdfkalichargn70th171
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
%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 midrandmasabamasaba
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
 
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...masabamasaba
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...masabamasaba
 
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 🔝✔️✔️Delhi Call girls
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durbanmasabamasaba
 
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 🔝✔️✔️Delhi Call girls
 
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburgmasabamasaba
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 

Kürzlich hochgeladen (20)

%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
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions Presentation
 
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
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
%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
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
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 Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban
 
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 Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 

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) 👨