language, country and any special variant preferences that the user wants to see in their user interface" Wikipedia AKA: rules for a specific region ‣ Current code standard: RFC 4646 ‣ Language in lowercase (ISO 639-1), hyphen, region in uppercase (ISO 3166-1 alpha-2) 7
list of languages ‣ \Locale::getDisplayRegion() Display the country where the locale is used ‣ \Locale::acceptFromHttp() Parse browser Accept header ‣ \Locale::setDefault() Set the default localization to use
ago: ‣ nl_NL: (Original text) "Kom genieten van het uitzicht bij de Reeuwijkse plassen!" ‣ en_US: (Google Translate) "Come and enjoy the view at the Reeuwijkse pee!"
Jabłek 1 Apple Jabłko 2 .. 4 Apples Jabłka 5 .. 21 Apples Jabłek 22 .. 24 Apples Jabłka 25 .. 31 Apples Jabłek More complex cases do exist! ‣ Slovenian: 4 plural forms There are also cases with 1 plural form ‣ Japanese ‣ Vietnamese
‣ Can do pretty amazing stuff ‣ I personally don't have experience with it 30 $fmt = new MessageFormatter( 'en_GB', 'Peter has {0, plural, =0{no cat} =1{a cat} other{# cats}}' ); echo $fmt->format(array(0)); $fmt = new MessageFormatter( 'nl_NL', 'Peter heeft {0, plural, =0{geen kat} =1{een kat} other{# katten}}' ); echo $fmt->format(array(0)); // Outputs: // Peter has no cat // Peter heeft geen kat
different types of annotations ‣ Corollary: nobody really knows well how a number should be formatted 31 Interactive question! How do you format the following negative number, in Euros, here in the Netherlands? 1234,57
'ps-AR',]; foreach ($locales as $myLocale) { $numberFormatter = new \NumberFormatter($myLocale, \NumberFormatter::DECIMAL); $percentFormatter = new \NumberFormatter($myLocale, \NumberFormatter::PERCENT); $currencyFormatter = new \NumberFormatter($myLocale, \NumberFormatter::CURRENCY); printf('Locale: %s'.PHP_EOL, $myLocale); printf('[DEC]-1.234,57: "%s" :: ', $numberFormatter->format(-1234.57)); printf('[PER]25%%: "%s" :: ', $percentFormatter->format(0.25)); printf('[CUR]1.234,57-: "%s"'.PHP_EOL, $currencyFormatter->formatCurrency(-1234.57, 'EUR')); // Last argument can also be \NumberFormatter::CURRENCY to print in CURRENCY of loaded locale }
'ps-AR',]; foreach ($locales as $myLocale) { $numberFormatter = new \NumberFormatter($myLocale, \NumberFormatter::DECIMAL); $percentFormatter = new \NumberFormatter($myLocale, \NumberFormatter::PERCENT); $currencyFormatter = new \NumberFormatter($myLocale, \NumberFormatter::CURRENCY); printf('Locale: %s'.PHP_EOL, $myLocale); printf('[DEC]-1.234,57: "%s" :: ', $numberFormatter->format(-1234.57)); printf('[PER]25%%: "%s" :: ', $percentFormatter->format(0.25)); printf('[CUR]1.234,57-: "%s"'.PHP_EOL, $currencyFormatter->formatCurrency(-1234.57, 'EUR')); // Last argument can also be \NumberFormatter::CURRENCY to print in CURRENCY of loaded locale }
[PER]25%: "25%" :: [CUR]1.234,57-: "€ 1.234,57-" All this in Dutch AKA Nederlands -------------------------------------------------------------------------------- Locale: fr-FR [DEC]-1.234,57: "-1 234,57" :: [PER]25%: "25 %" :: [CUR]1.234,57-: "-1 234,57 €" All this in French AKA français -------------------------------------------------------------------------------- Locale: pt-BR [DEC]-1.234,57: "-1.234,57" :: [PER]25%: "25%" :: [CUR]1.234,57-: "(€1.234,57)" All this in Portuguese AKA português -------------------------------------------------------------------------------- Locale: hi-IN [DEC]-1.234,57: "-१,२३४.५७" :: [PER]25%: "२५%" :: [CUR]1.234,57-: "-€ १,२३४.५७" All this in Hindi AKA िहन्दी -------------------------------------------------------------------------------- Locale: ps-AR [DEC]-1.234,57: "-١،٢٣۴٫۵٧" :: [PER]25%: "٢۵٪" :: [CUR]1.234,57-: "-١،٢٣۴٫۵٧ €" All this in Pashto AKA ﻮﺘ,ﭘ
‣ echo $fmt->format(12345) -> 3 hours, 25 minutes, 45 seconds ‣ "Easy" to implement using getPattern() and setPattern() ‣ Documentation exists, but is not optimal 36
different annotations ‣ YYYY-MM-DD (1.660M) ‣ DD-MM-YYYY (4.810M) ‣ MM-DD-YYYY (320M) ‣ "It's complicated" (457M) ‣ Contrary to numbers, everybody knows how a date is formatted 37 Interactive question! What is the value of the following date in The Netherlands? 05-03-13
classes, like ALWAYS! ‣ Incredibly versatile yet powerful functions ‣ Specially in combination with locales ‣ Always work in UTC, let the \*Date* classes do the rest 39
Short "23-05-15" "23/05/15" "२३-५-१५" "۲۰۱۵/۵/۲۳" Medium "23 mei 2015" "23 mai 2015" "२३-०५-२०१५" "۲۳ ۲۰۱۵ یم" With time "23 mei 2015 01:34:09" "23 mai 2015 01:34:09" "२३-०५-२०१५ १:३४:०९ पूवार्ह्न" "۲۳ ۱:۳۴:۰۹ ۲۰۱۵ یم"
‣ Automatic in i18n and L10n is better ‣ Operating system plays an important role ‣ Why reinvent a very very very complicated wheel if it already exists? 42
expensive! ‣ With a known locale, get all timezones ‣ If there's only one, instantiate \DateTimeZone ‣ More than 1? Get precise timezoneId and DST settings (cache them!) ‣ Now calculate the offset of a timezone for the view 47
is defined as \Locale::getRegion($currentLocale) */ private function _setTimezoneCandidates($region='') { if (!empty($region)) { $this->_timezoneCandidates = \DateTimeZone::listIdentifiers( \DateTimeZone::PER_COUNTRY, $region ); if (!empty($this->_timezoneCandidates) && count($this->_timezoneCandidates) == 1) { $this->setTimezone($this->_timezoneCandidates[0]); } } }
‣ Include some basic stuff so that PHP also knows that it has to work in UTF-8 ‣ Don't forget to send the browser information as well 54 mb_internal_encoding('UTF-8'); header('Content-type: %s; charset=UTF-8'); ‣ Lots of small things to consider, but can vary on each case
some problems with UTF-7 Always encode "To" (BC, BCC) and "Subject" fields 55 Code Output "=?utf-8?B?5L2p5ae/?= <[email protected]>" ֫ "=?iso-8859-1?Q?B=F8lla?=, med =?iso-8859-1?Q?=F8l?= i baggen <[email protected]>" Bølla , med øl i baggen "=?utf-7?Q?Petra_M+APw-ller?=" Petra Müller
It helps the db engine to predict better its memory assignment) 61 Interactive question! What charset should be used to save the following string? f5d39e997c5d7e4e2a3ef49973f61fb2
be indirectly and negatively impacted ‣ Too big (and complex) of a topic for now ‣ Use EXPLAIN to understand underlying decisions of MySQL (in some cases) ‣ Don't bother in micro-optimization either 64
with utf8_general_ci and utf8_unicode_ci! ➡ utf8_general_ci has some problems with Hebrew and some cyrillic characters ➡ It's generally faster (7~12%) ➡ But utf8_unicode_ci is more compatible 66
‣ Best way to save information is to save it in binary format: 69 CREATE TABLE `thaPeople` ( `name` MEDIUMBLOB NULL DEFAULT NULL, `address` MEDIUMBLOB NULL DEFAULT NULL ); ‣ However this is a very extreme case ‣ More info? Check www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/
metric or imperial system (either British or American)? ‣ What type of rounding is used in that locale? ‣ Optional: custom number and currency pattern to overwrite any default rules ‣ The preferred timezone (user based, not L10n based) ‣ Direction of text 70
are generally safe to use ‣ Don't forget to test multibyte characters ‣ 2 bytes: ñÖÑú - ӬģĽ ‣ 3 bytes: 佸ਁ - —၍₶ ‣ 4+bytes: 韴韵韶 - ‣ Example: Mamá vive en Föllinge en el bosque del Ñañdú.¿Enredado? ¡Deberías! (SimSun-ExtB) 71