Unicode et graphèmes clusters pour PHP
Unicode et graphèmes clusters pour PHP
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Unicode : bases et concepts
Unicode : état de lřart
Patchwork\Utf8
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Peace
和平 ☮
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
P U+0050LATIN CAPITAL LETTER P
U+0633ARABIC LETTER SEEN
和 U+548CCJK UNIFIED IDEOGRAPH-548C ☮ U+262E
PEACE SYMBOL
A chaque caractère son numéro, un nom et des propriétés (catégorie, script, etc.)
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Représentations binaires
Majuscules, minuscules, folding
Compositions, ligatures
Comparaison : normalisations et collations
Segmentation : caractères, mots, phrases et césures
Locales : conventions culturelles, translittérations
Identifiants et sécurité, confusables
Affichage : direction, largeur
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
De point de codeà séquence dřoctets◦ UTF-8 : 1, 2, 3 ou 4 octets
◦ UTF-16 : 2 ou 4 octets
◦ UTF-32 : 4 octets
BOM U+FEFFByte Order Mark
UTF-32BE 00 00 FE FF
UTF-32LE FF FE 00 00
UTF-16BE FE FF
UTF-16LE FF FE
UTF-8 EF BB BF ()
á U+00E1LATIN SMALL LETTER A WITH ACUTE
UTF-16BE 00 E1
UTF-8 C3 A1
あ U+3042HIRAGANA LETTER A
UTF-16BE 30 42
UTF-8 E3 81 82
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Sur-ensemble dřASCII
Auto-synchronisé
Caractéristique
Octet 1 Octet 2 Octet 3 Octet 4
0xxxxxxx
110xxxxx 10xxxxxx
1110xxxx 10xxxxxx 10xxxxxx
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Concerne un peu plus de 1000 caractères
Folding Ŕ comparaison insensible à la casse◦ Comparer les chaînes en minuscules
◦ Une majuscule, deux minuscules : Σ ⇔ σ/ς
◦ Exception turque : I ⇔ i vs İ ⇔ i et I ⇔ ı
◦ Full folding : ß ⇔ ss
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
ÅÅ U+00C5
LATIN CAPITAL LETTER A WITH RING ABOVE
A+◌̊ 0041, 030ALATIN CAPITAL LETTER A, COMBINING RING ABOVE
fif+i U+0066, U+0069
LATIN SMALL LETTER F, LATIN SMALL LETTER I
fi FB01LATIN SMALL LIGATURE FI
둑ᄃ+ᅮ+ᆨ
U+1103, U+116E, U+11A8HANGUL CHOSEONG TIKEUT, HANGUL JUNGSEONG U, HANGUL JONGSEONG KIYEOK
둑 U+B451HANGUL SYLLABE DUG
Comment tester lřégalité ? (=, ≠)
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Forme Composée, Décomposée, de Kompatiblité
ḋ+◌U+1E0B, U+0323LATIN SMALL LETTER D WITH DOT ABOVE,COMBINING DOT BELOW
d+◌+◌̇U+0064, U+0323, U+0307LATIN SMALL LETTER D,COMBINING DOT BELOW, COMBINING DOT ABOVE
ḍ+◌̇U+1E0D, U+0307LATIN SMALL LETTER D WITH DOT BELOW,COMBINING DOT ABOVE
fif+i U+0066, U+0069
LATIN SMALL LETTER F, LATIN SMALL LETTER I
fi U+FB01LATIN SMALL LIGATURE FI
NFD
NFC
NFKD, NFKC
NFD, NFC
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
NFC
D é j à U+0044 U+00E9 U+006A U+00E0
NFD
D e ◌ j a ◌U+0044 U+0065 U+0301 U+006A U+0061 U+0300
Quel est le 2e caractère ? le 3e ?
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
ICU : Java et C/C++◦ Licence X-like, soutenu par IBM, utilisé comme
implémentation de référence pour Unicode et +
Perl 6 Parrot : NFG◦ NFC + Graphèmes Clusters
JavaScript : Unicode (NFC)
Python : chaînes typées
PHP : iconv, mbstring, pcre, intl
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
iconv_set_encoding('UTF-8')
◦ iconv($in_charset , $out_charset , $str)
◦ iconv_strlen($str)
◦ iconv_substr($str, $start, $length)
◦ iconv_strpos($haystack, $needle, $offset = 0)
◦ iconv_strrpos($haystack, $needle)
Manipulation de chaînes UTF-8 : fait !
NFC : DéjàNFD : De◌ ◌
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
mb_internal_encoding('UTF-8')
◦ Équivalents dřiconv
◦ mb_strtolower/upper (), pas de folding
◦ mb_stripos(), folding simple
Manipulation de chaînes UTF-8 : fait ! (bis)
Manipulation de la casse : fait ! % folding
NFC : DéjàNFD : De◌ ja◌
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Avec le modificateur u : /./u
Donne accès aux propriétés Unicode◦ \x{00E9} ou simplement é ssi source UTF-8◦ \p{Greek}◦ \p{Mn}◦ \X ⇔ (?>\PM\pM*) pour PCRE < 8.32
Vérifier la validité UTF-8 de $str :
preg_match('//u', $str)
Manipulation de chaînes UTF-8 : fait ! (ter) Manipulation des propriétés Unicode : fait !
NFC : DéjàNFD : De◌ ◌
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Normalizer
Gestion des graphèmes clusters
Collator, NumberFormatter, Locale, MessageFormatter, IntlDateFormatter, Spoofchecker, Transliterator, Fonctions IDN, Uconverter (PHP5.5)
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
use Normalizer as n;
n::isNormalized($str, $form = n::NFC)
n::normalize($str, $form = n::NFC)
n::NFC, n::NFD, n::NFKC, n::NFKC, n::NONE
Tester lřégalité de chaînes : fait !
NFC : DéjàNFD : De◌ ◌
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
grapheme_extract ŕ Extrait un groupe de graphèmes d'une chaîne UTF-8
grapheme_stripos grapheme_stristr grapheme_strlen grapheme_strpos grapheme_strripos grapheme_strrpos grapheme_strstr grapheme_substr
Manipulation par graphème cluster : fait !◦ Encore un peu jeune, attention aux bugs◦ https://bugs.php.net/55562, 61860 et 62759
NFC : DéjàNFD : De◌ ◌
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Chaînes UTF-8 : iconv, mbstring, pcre Casse : mbstring Normalisation : intl Graphèmes : intl et pcre
function toAscii($s){
if (preg_match("/[\x80-\xFF]/", $s)){
$s = Normalizer::normalize($s, Normalizer::NFKD);$s = preg_replace('/\p{Mn}+/u', '', $s);
$s = iconv('UTF-8', 'ASCII//TRANSLIT', $s);}
return $s;}
Quid :◦ Case folding ? Complexité ? Disponibilité ?
Unicode et graphèmes clusters pour PHP
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Portabilité PHP, optimisé pour UTF-8
◦ Iconv : 99%
◦ Mbstring : les 45% nécessaires
◦ Intl : Normalizer et grapheme_*()
◦ utf8_en/decode() - Windows-1252 enhanced
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF
0x NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI
1x DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
2x SP ! " # $ % & ' ( ) * + , - . /
3x 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
4x @ A B C D E F G H I J K L M N O
5x P Q R S T U V W X Y Z [ \ ] ^ _
6x ` a b c d e f g h i j k l m n o
7x p q r s t u v w x y z { | } ~ DEL
8x € ‚ ƒ „ … † ※ ˆ ‰ Š ‹ Œ Ţ
9x Ř ř Ŗ ŗ • Ŕ ŕ ˜ ™ š › œ ţ Ÿ
AxNBS
P¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ® ¯
Bx ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿
Cx À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï
Dx Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß
Ex à á â ã ä å æ ç è é ê ë ì í î ï
Fx ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
HTML5 : se substitue à ISO-8859-1
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Patchwork\Utf8
mbstring
iconv
grapheme_*
Normalizer
pcre
xml
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Les fonctions PHP, version UTF-8
◦ Limité au sous-ensemble qui le nécessite
◦ Préfixe u:: pour déclarer lřintention dans le code
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
strlen - chr - ord
substr - str_split
strpos - strrpos - strstr - strrchr - stripos - strripos - stristr - strrichr
strtolower - strtoupper - ucfirst - lcfirst - ucwords
trim - ltrim - rtrim
strtr - str_ireplace - substr_replace - str_replace déjà compatible
strcmp - strnatcmp - strcasecmp - strnatcasecmp - strncasecmp - strncmp
strspn - strcspn - strpbrk - substr_compare - substr_count - str_word_count -count_chars
number_format - wordwrap - str_pad - strrev - str_shuffle
utf8_encode - utf8_decode Ŕ Windows-1252 enhanced
Manque la famille printf
Ajoute isUtf8 - toAscii - strtocasefold - strtonatfold et nombreux workaround
NFC : DéjàNFD : De◌ ja◌
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Quelques extras, workarounds et bootstrapping
Couvert par de nombreux tests unitaires
Licences Apache-2.0 et GPL-2.0
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
https://github.com/FSX/php-utf8
Mediawiki, PhpBB, Drupal, etc.
Différences majeures◦ Gestion des graphème clusters
◦ API déjà documentée : cf. documentation PHP
◦ Bootstrapping via autoload possible
◦ Testable et comparable en même temps
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Editeur de code en mode UTF-8 sans BOM
Vérifiez la validité UTF-8 de vos entrées
Mais ne supprimez pas les caractères erronés◦ java\xFFscript:alert("XSS")◦ preg_match('//u', $v) or $v = u::utf8_encode($v);
Normalisez vos entrées UTF-8 : NFC on demand
require 'bootup.utf8.php';
use Patchwork\Utf8 as u;
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
NFC repousse les graphèmes clusters
Pour manipuler des données (cf. MySQL),pas les identifiants.
A utiliser avec discernement
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
Questions ?
https://github.com/nicolas-grekas/Patchwork-UTF8
composer : {"require": {"patchwork/utf8": "1.0.*"}}
Unicode.org
Wikipédia
« PHP et UTF-8 »http://julp.lescigales.org/php/utf8/
« Handling UTF-8 with PHP » http://www.phpwact.org/php/i18n/utf-8
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
PHP Tour Ŕ Nantes 2012https://github.com/nicolas-grekas/Patchwork-UTF8
14Mo4Mo2Mo
-