|
1 | 1 |
|
2 |
| -# Unicode, String internals |
| 2 | +# Unicode, vnitřní reprezentace řetězce |
3 | 3 |
|
4 |
| -```warn header="Advanced knowledge" |
5 |
| -The section goes deeper into string internals. This knowledge will be useful for you if you plan to deal with emoji, rare mathematical or hieroglyphic characters, or other rare symbols. |
| 4 | +```warn header="Pokročilá znalost" |
| 5 | +Tato kapitola se hlouběji zabývá vnitřní reprezentací řetězců. Tato znalost vám bude užitečná, jestliže plánujete pracovat s emoji, vzácnými matematickými nebo hieroglyfickými znaky nebo jinými vzácnými symboly. |
6 | 6 | ```
|
7 | 7 |
|
8 |
| -As we already know, JavaScript strings are based on [Unicode](https://en.wikipedia.org/wiki/Unicode): each character is represented by a byte sequence of 1-4 bytes. |
| 8 | +Jak už víme, řetězce v JavaScriptu jsou založeny na [Unicode](https://cs.wikipedia.org/wiki/Unicode): každý znak je reprezentován posloupností 1 až 4 bytů. |
9 | 9 |
|
10 |
| -JavaScript allows us to insert a character into a string by specifying its hexadecimal Unicode code with one of these three notations: |
| 10 | +JavaScript nám umožňuje vložit znak do řetězce specifikací jeho hexadecimálního kódu v Unicode pomocí jednoho z následujících tří zápisů: |
11 | 11 |
|
12 | 12 | - `\xXX`
|
13 | 13 |
|
14 |
| - `XX` must be two hexadecimal digits with a value between `00` and `FF`, then `\xXX` is the character whose Unicode code is `XX`. |
| 14 | + `XX` musí být dvě hexadecimální číslice s hodnotou mezi `00` a `FF`, pak `\xXX` je znak, jehož kód v Unicode je `XX`. |
15 | 15 |
|
16 |
| - Because the `\xXX` notation supports only two hexadecimal digits, it can be used only for the first 256 Unicode characters. |
| 16 | + Protože zápis `\xXX` podporuje jen dvě hexadecimální číslice, může být použit jen pro prvních 256 znaků Unicode. |
17 | 17 |
|
18 |
| - These first 256 characters include the Latin alphabet, most basic syntax characters, and some others. For example, `"\x7A"` is the same as `"z"` (Unicode `U+007A`). |
| 18 | + Těchto prvních 256 znaků obsahuje latinskou abecedu, většinu základních syntaktických znaků a některé další. Například `"\x7A"` je totéž jako `"z"` (Unicode `U+007A`). |
19 | 19 |
|
20 | 20 | ```js run
|
21 | 21 | alert( "\x7A" ); // z
|
22 |
| - alert( "\xA9" ); // ©, the copyright symbol |
| 22 | + alert( "\xA9" ); // ©, symbol copyrightu |
23 | 23 | ```
|
24 | 24 |
|
25 | 25 | - `\uXXXX`
|
26 |
| - `XXXX` must be exactly 4 hex digits with the value between `0000` and `FFFF`, then `\uXXXX` is the character whose Unicode code is `XXXX`. |
27 | 26 |
|
28 |
| - Characters with Unicode values greater than `U+FFFF` can also be represented with this notation, but in this case, we will need to use a so called surrogate pair (we will talk about surrogate pairs later in this chapter). |
| 27 | + `XXXX` musí být přesně 4 hexadecimální číslice s hodnotou mezi `0000` a `FFFF`, pak `\uXXXX` je znak, jehož kód v Unicode je `XXXX`. |
| 28 | +
|
| 29 | + Tímto zápisem mohou být reprezentovány i znaky, jejichž hodnoty v Unicode jsou větší než `U+FFFF`, ale v takovém případě musíme použít takzvaný zástupný pár (o zástupných párech pohovoříme později v této kapitole). |
29 | 30 |
|
30 | 31 | ```js run
|
31 |
| - alert( "\u00A9" ); // ©, the same as \xA9, using the 4-digit hex notation |
32 |
| - alert( "\u044F" ); // я, the Cyrillic alphabet letter |
33 |
| - alert( "\u2191" ); // ↑, the arrow up symbol |
| 32 | + alert( "\u00A9" ); // ©, totéž jako \xA9 s použitím 4-ciferného hexadecimálního zápisu |
| 33 | + alert( "\u044F" ); // я, písmeno z kyrilice (azbuky) |
| 34 | + alert( "\u2191" ); // ↑, symbol šipky nahoru |
34 | 35 | ```
|
35 | 36 |
|
36 | 37 | - `\u{X…XXXXXX}`
|
37 | 38 |
|
38 |
| - `X…XXXXXX` must be a hexadecimal value of 1 to 6 bytes between `0` and `10FFFF` (the highest code point defined by Unicode). This notation allows us to easily represent all existing Unicode characters. |
| 39 | + `X…XXXXXX` musí být hexadecimální hodnota 1 až 6 bytů mezi `0` a `10FFFF` (nejvyšší kódová hodnota definovaná v Unicode). Tento zápis nám umožňuje snadno reprezentovat všechny existující znaky v Unicode. |
39 | 40 |
|
40 | 41 | ```js run
|
41 |
| - alert( "\u{20331}" ); // 佫, a rare Chinese character (long Unicode) |
42 |
| - alert( "\u{1F60D}" ); // 😍, a smiling face symbol (another long Unicode) |
| 42 | + alert( "\u{20331}" ); // 佫, vzácný čínský znak (dlouhý Unicode) |
| 43 | + alert( "\u{1F60D}" ); // 😍, symbol usmívající se tváře (další dlouhý Unicode) |
43 | 44 | ```
|
44 | 45 |
|
45 |
| -## Surrogate pairs |
| 46 | +## Zástupné páry |
46 | 47 |
|
47 |
| -All frequently used characters have 2-byte codes (4 hex digits). Letters in most European languages, numbers, and the basic unified CJK ideographic sets (CJK -- from Chinese, Japanese, and Korean writing systems), have a 2-byte representation. |
| 48 | +Všechny často používané znaky mají 2-bytové kódy (4 hexadecimální číslice). Písmena ve většině evropských jazyků, číslice a základní sjednocené ideografické sady CJK (CJK -- pro čínské, japonské a korejské písemné soustavy) mají 2-bytovou reprezentaci. |
48 | 49 |
|
49 |
| -Initially, JavaScript was based on UTF-16 encoding that only allowed 2 bytes per character. But 2 bytes only allow 65536 combinations and that's not enough for every possible symbol of Unicode. |
| 50 | +JavaScript byl původně založen na kódování UTF-16, které umožňovalo jen 2 byty na znak. Avšak 2 byty umožňují jen 65536 kombinací, a to pro každý možný symbol v Unicode nestačí. |
50 | 51 |
|
51 |
| -So rare symbols that require more than 2 bytes are encoded with a pair of 2-byte characters called "a surrogate pair". |
| 52 | +Vzácné symboly, které vyžadují více než 2 byty, jsou tedy zakódovány dvojicí 2-bytových znaků nazývanou „zástupný pár“ („surrogate pair“). |
52 | 53 |
|
53 |
| -As a side effect, the length of such symbols is `2`: |
| 54 | +Vedlejším efektem je, že délka takových symbolů je `2`: |
54 | 55 |
|
55 | 56 | ```js run
|
56 |
| -alert( '𝒳'.length ); // 2, MATHEMATICAL SCRIPT CAPITAL X |
57 |
| -alert( '😂'.length ); // 2, FACE WITH TEARS OF JOY |
58 |
| -alert( '𩷶'.length ); // 2, a rare Chinese character |
| 57 | +alert( '𝒳'.length ); // 2, VELKÉ X V MATEMATICKÉM PÍSMU |
| 58 | +alert( '😂'.length ); // 2, TVÁŘ SE SLZAMI RADOSTI |
| 59 | +alert( '𩷶'.length ); // 2, vzácný čínský znak |
59 | 60 | ```
|
60 | 61 |
|
61 |
| -That's because surrogate pairs did not exist at the time when JavaScript was created, and thus are not correctly processed by the language! |
| 62 | +Je to proto, že v době, kdy JavaScript vznikl, ještě zástupné páry neexistovaly, a proto nejsou jazykem správně zpracovávány! |
62 | 63 |
|
63 |
| -We actually have a single symbol in each of the strings above, but the `length` property shows a length of `2`. |
| 64 | +Ve skutečnosti máme v každém z uvedených řetězců jediný symbol, ale vlastnost `length` ukazuje délku `2`. |
64 | 65 |
|
65 |
| -Getting a symbol can also be tricky, because most language features treat surrogate pairs as two characters. |
| 66 | +Rovněž získání symbolu může být problematické, jelikož většina prvků jazyka zachází se zástupnými páry jako se dvěma znaky. |
66 | 67 |
|
67 |
| -For example, here we can see two odd characters in the output: |
| 68 | +Například zde vidíme na výstupu dva podivné znaky: |
68 | 69 |
|
69 | 70 | ```js run
|
70 |
| -alert( '𝒳'[0] ); // shows strange symbols... |
71 |
| -alert( '𝒳'[1] ); // ...pieces of the surrogate pair |
| 71 | +alert( '𝒳'[0] ); // zobrazuje zvláštní symboly... |
| 72 | +alert( '𝒳'[1] ); // ...části zástupného páru |
72 | 73 | ```
|
73 | 74 |
|
74 |
| -Pieces of a surrogate pair have no meaning without each other. So the alerts in the example above actually display garbage. |
| 75 | +Části zástupného páru nemají jedna bez druhé žádný význam. V uvedeném příkladu se tedy ve skutečnosti zobrazí nesmysly. |
75 | 76 |
|
76 |
| -Technically, surrogate pairs are also detectable by their codes: if a character has the code in the interval of `0xd800..0xdbff`, then it is the first part of the surrogate pair. The next character (second part) must have the code in interval `0xdc00..0xdfff`. These intervals are reserved exclusively for surrogate pairs by the standard. |
| 77 | +Technicky lze zástupné páry detekovat podle jejich kódu: jestliže znak má kód v intervalu `0xd800..0xdbff`, pak je to první část zástupného páru. Další znak (druhá část) musí mít kód v intervalu `0xdc00..0xdfff`. Tyto intervaly jsou ve standardu exkluzívně rezervovány pro zástupné páry. |
77 | 78 |
|
78 |
| -So the methods [String.fromCodePoint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint) and [str.codePointAt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt) were added in JavaScript to deal with surrogate pairs. |
| 79 | +Proto byly do JavaScriptu přidány metody [String.fromCodePoint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint) a [řetězec.codePointAt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt), které si dokáží se zástupnými páry poradit. |
79 | 80 |
|
80 |
| -They are essentially the same as [String.fromCharCode](mdn:js/String/fromCharCode) and [str.charCodeAt](mdn:js/String/charCodeAt), but they treat surrogate pairs correctly. |
| 81 | +Jsou v zásadě stejné jako [String.fromCharCode](mdn:js/String/fromCharCode) a [řetězec.charCodeAt](mdn:js/String/charCodeAt), ale se zástupnými páry zacházejí správně. |
81 | 82 |
|
82 |
| -One can see the difference here: |
| 83 | +Zde vidíme rozdíl: |
83 | 84 |
|
84 | 85 | ```js run
|
85 |
| -// charCodeAt is not surrogate-pair aware, so it gives codes for the 1st part of 𝒳: |
86 |
| -
|
| 86 | +// charCodeAt nezná zástupné páry, takže vydá kód pro 1. část: |
87 | 87 | alert( '𝒳'.charCodeAt(0).toString(16) ); // d835
|
88 | 88 |
|
89 |
| -// codePointAt is surrogate-pair aware |
90 |
| -alert( '𝒳'.codePointAt(0).toString(16) ); // 1d4b3, reads both parts of the surrogate pair |
| 89 | +// codePointAt zná zástupné páry |
| 90 | +alert( '𝒳'.codePointAt(0).toString(16) ); // 1d4b3, přečte obě části zástupného páru |
91 | 91 | ```
|
92 | 92 |
|
93 |
| -That said, if we take from position 1 (and that's rather incorrect here), then they both return only the 2nd part of the pair: |
| 93 | +Ovšem načítáme-li od pozice 1 (a to je zde dosti nekorektní), pak obě vrátí jen druhou část páru: |
94 | 94 |
|
95 | 95 | ```js run
|
96 | 96 | alert( '𝒳'.charCodeAt(1).toString(16) ); // dcb3
|
97 | 97 | alert( '𝒳'.codePointAt(1).toString(16) ); // dcb3
|
98 |
| -// meaningless 2nd half of the pair |
| 98 | +// nesmyslná 2. část páru |
99 | 99 | ```
|
100 | 100 |
|
101 |
| -You will find more ways to deal with surrogate pairs later in the chapter <info:iterable>. There are probably special libraries for that too, but nothing famous enough to suggest here. |
| 101 | +Další způsoby, jak si se zástupnými páry poradit, naleznete v kapitole <info:iterable>. Pravděpodobně pro to existují i speciální knihovny, ale žádná není dostatečně známá na to, abychom ji tady doporučili. |
102 | 102 |
|
103 |
| -````warn header="Takeaway: splitting strings at an arbitrary point is dangerous" |
104 |
| -We can't just split a string at an arbitrary position, e.g. take `str.slice(0, 4)` and expect it to be a valid string, e.g.: |
| 103 | +````warn header="Zásadní zjištění: dělení řetězců na libovolném místě je nebezpečné" |
| 104 | +Nemůžeme jen tak rozdělit řetězec na libovolné pozici, např. volat `řetězec.slice(0, 6)` a očekávat, že to bude platný řetězec, např.: |
105 | 105 |
|
106 | 106 | ```js run
|
107 |
| -alert( 'hi 😂'.slice(0, 4) ); // hi [?] |
| 107 | +alert( 'ahoj 😂'.slice(0, 6) ); // ahoj [?] |
108 | 108 | ```
|
109 | 109 |
|
110 |
| -Here we can see a garbage character (first half of the smile surrogate pair) in the output. |
| 110 | +Zde vidíme na výstupu nesmyslný znak (první polovinu zástupného páru úsměvu). |
111 | 111 |
|
112 |
| -Just be aware of it if you intend to reliably work with surrogate pairs. May not be a big problem, but at least you should understand what happens. |
| 112 | +Mějte to na paměti, jestliže zamýšlíte zodpovědně pracovat se zástupnými páry. Nemusí to být velký problém, ale aspoň byste měli rozumět tomu, co se děje. |
113 | 113 | ````
|
114 | 114 |
|
115 |
| -## Diacritical marks and normalization |
| 115 | +## Diakritická znaménka a normalizace |
116 | 116 |
|
117 |
| -In many languages, there are symbols that are composed of the base character with a mark above/under it. |
| 117 | +Mnoho jazyků obsahuje symboly, které se skládají ze základního znaku a znaménka nad nebo pod ním. |
118 | 118 |
|
119 |
| -For instance, the letter `a` can be the base character for these characters: `àáâäãåā`. |
| 119 | +Například písmeno `a` může být základním znakem pro tyto znaky: `àáâäãåā`. |
120 | 120 |
|
121 |
| -Most common "composite" characters have their own code in the Unicode table. But not all of them, because there are too many possible combinations. |
| 121 | +Většina běžných „složených“ znaků má v tabulce Unicode svůj vlastní kód. Ne však všechny, protože možných kombinací je příliš mnoho. |
122 | 122 |
|
123 |
| -To support arbitrary compositions, the Unicode standard allows us to use several Unicode characters: the base character followed by one or many "mark" characters that "decorate" it. |
| 123 | +Abychom mohli používat libovolné složeniny, standard Unicode nám umožňuje použít několik znaků Unicode za sebou: základní znak následovaný jedním nebo více znaky „znamének“, která jej „ozdobí“. |
124 | 124 |
|
125 |
| -For instance, if we have `S` followed by the special "dot above" character (code `\u0307`), it is shown as Ṡ. |
| 125 | +Například máme-li `S` následované speciálním znakem „tečka nahoře“ (kód `\u0307`), zobrazí se jako Ṡ. |
126 | 126 |
|
127 | 127 | ```js run
|
128 | 128 | alert( 'S\u0307' ); // Ṡ
|
129 | 129 | ```
|
130 | 130 |
|
131 |
| -If we need an additional mark above the letter (or below it) -- no problem, just add the necessary mark character. |
| 131 | +Potřebujeme-li další znaménko nad písmenem (nebo pod ním) -- žádný problém, jednoduše přidáme potřebný znak znaménka. |
132 | 132 |
|
133 |
| -For instance, if we append a character "dot below" (code `\u0323`), then we'll have "S with dots above and below": `Ṩ`. |
| 133 | +Například připojíme-li znak „tečka dole“ (kód `\u0323`), budeme mít „S s tečkami nahoře a dole“: `Ṩ`. |
134 | 134 |
|
135 |
| -For example: |
| 135 | +Příklad: |
136 | 136 |
|
137 | 137 | ```js run
|
138 | 138 | alert( 'S\u0307\u0323' ); // Ṩ
|
139 | 139 | ```
|
140 | 140 |
|
141 |
| -This provides great flexibility, but also an interesting problem: two characters may visually look the same, but be represented with different Unicode compositions. |
| 141 | +To nám poskytuje velkou flexibilitu, ale také zajímavý problém: dva znaky mohou vizuálně vypadat stejně, ale být reprezentovány různými složeninami z Unicode. |
142 | 142 |
|
143 |
| -For instance: |
| 143 | +Příklad: |
144 | 144 |
|
145 | 145 | ```js run
|
146 |
| -let s1 = 'S\u0307\u0323'; // Ṩ, S + dot above + dot below |
147 |
| -let s2 = 'S\u0323\u0307'; // Ṩ, S + dot below + dot above |
| 146 | +let s1 = 'S\u0307\u0323'; // Ṩ, S + tečka nahoře + tečka dole |
| 147 | +let s2 = 'S\u0323\u0307'; // Ṩ, S + tečka dole + tečka nahoře |
148 | 148 |
|
149 | 149 | alert( `s1: ${s1}, s2: ${s2}` );
|
150 | 150 |
|
151 |
| -alert( s1 == s2 ); // false though the characters look identical (?!) |
| 151 | +alert( s1 == s2 ); // false, třebaže znaky vypadají stejně (?!) |
152 | 152 | ```
|
153 | 153 |
|
154 |
| -To solve this, there exists a "Unicode normalization" algorithm that brings each string to the single "normal" form. |
| 154 | +Řešení nám poskytuje algoritmus „normalizace Unicode“, který převádí každý řetězec do jednoduché „normální“ formy. |
155 | 155 |
|
156 |
| -It is implemented by [str.normalize()](mdn:js/String/normalize). |
| 156 | +Je implementován metodou [řetězec.normalize()](mdn:js/String/normalize). |
157 | 157 |
|
158 | 158 | ```js run
|
159 | 159 | alert( "S\u0307\u0323".normalize() == "S\u0323\u0307".normalize() ); // true
|
160 | 160 | ```
|
161 | 161 |
|
162 |
| -It's funny that in our situation `normalize()` actually brings together a sequence of 3 characters to one: `\u1e68` (S with two dots). |
| 162 | +Je humorné, že v naší situaci `normalize()` ve skutečnosti spojí posloupnost tří znaků do jednoho: `\u1e68` (S se dvěma tečkami). |
163 | 163 |
|
164 | 164 | ```js run
|
165 | 165 | alert( "S\u0307\u0323".normalize().length ); // 1
|
166 | 166 |
|
167 | 167 | alert( "S\u0307\u0323".normalize() == "\u1e68" ); // true
|
168 | 168 | ```
|
169 | 169 |
|
170 |
| -In reality, this is not always the case. The reason is that the symbol `Ṩ` is "common enough", so Unicode creators included it in the main table and gave it the code. |
| 170 | +V realitě však tomu tak není vždy. Důvodem je, že symbol `Ṩ` je „dostatečně běžný“, takže jej tvůrci Unicode zahrnuli do hlavní tabulky a přiřadili mu kód. |
171 | 171 |
|
172 |
| -If you want to learn more about normalization rules and variants -- they are described in the appendix of the Unicode standard: [Unicode Normalization Forms](https://www.unicode.org/reports/tr15/), but for most practical purposes the information from this section is enough. |
| 172 | +Pokud se chcete o pravidlech a variantách normalizace dozvědět víc, jsou popsána v příloze standardu Unicode: [Normalizační formy Unicode](https://www.unicode.org/reports/tr15/), ale pro většinu praktických účelů je informace z tohoto článku dostačující. |
0 commit comments