Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Punycode
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
==Description== {{technical|section|date=September 2024}} As stated in RFC 3492, "Punycode is an instance of a more general algorithm called ''Bootstring'', which allows strings composed from a small set of 'basic' code points to uniquely represent any string of code points drawn from a larger set." Punycode defines parameters for the general Bootstring algorithm to match the characteristics of Unicode text. This section demonstrates the procedure for Punycode encoding, using as an example the [[German language|German]] string "bücher" ([[English language|English]]: ''books''), which is translated into the label "bcher-kva". To make the encoding and decoding algorithms simple, no attempt has been made to prevent some encoded values from encoding inadmissible Unicode values: however, these should be checked for and detected during decoding. Punycode is designed to work across all scripts, and to be self-optimizing by attempting to adapt to the character set ranges within the string as it operates. It is optimized for the case where the string is composed of zero or more ASCII characters and in addition characters from only one other script system, but will cope with any arbitrary Unicode string. Note that for DNS use, the domain name string is assumed to have been normalized using [[nameprep]] and (for [[top-level domain]]s) filtered against an officially registered language table before being punycoded, and that the DNS protocol sets limits on the acceptable lengths of the output Punycode string. ===Separation of ASCII characters=== First, all [[ASCII]] characters in the string are copied from input to output, skipping over any other characters. For example, "bücher" is copied to "bcher". If any characters were copied, i.e. if there was at least one ASCII character in the input,<!-- This is correct according to RFC. If there are no ASCII characters then there is no leading dash! This is dealt with by the "xn--" prefix, described later, which is not part of Punycode.--> an ASCII hyphen is appended to the output (e.g., "bücher" → "bcher-", but "ü" → ""). Note that hyphens are themselves ASCII characters. Thus, they can be present in the input and, if so, they will be copied to the output. This causes no ambiguity: if the output contains hyphens, the one that got added is always the last one. It marks the end of the ASCII characters. ===Encoding the non-ASCII characters=== The non-ASCII characters are sorted by Unicode value, lowest first (if a character occurs more than once, they are sorted by position). Each is then encoded as a single number. This single number defines both the location to insert the character at and which character to insert. * An {{mvar|index}} into the result to insert the code at, starting at 0 (for insertion at the start).{{cn|date=March 2024}} * The number of {{mvar|insertionPoints}} (current length of the result plus one). * The {{mvar|reducedCodepoint}} is the Unicode code point to insert minus 127.{{cn|date=March 2024}} The encoded number is {{math|''insertionPoints'' × ''reducedCodepoint'' + ''index''}}. By dividing by {{mvar|insertionPoints}} and also getting the remainder, a decoder can determine {{mvar|reducedCodepoint}} and {{mvar|index}}. There are 6 possible insertion points for a character in the string "bcher" (including before the first character and after the last one). {{char|ü}} is Unicode code point {{tt|0xFC}} or 252 (see [[Latin-1_Supplement_(Unicode_block)|Latin-1 Supplement]]), and the reduced code point is {{math|252 − 127}}, or {{math|124}}. The {{char|ü}} is inserted at position 1, after the {{char|b}}. Thus the encoder will add the number {{math|1=6 × 124 + 1 = 745}}, and the decoder can retrieve these by {{math|1=⌊745 / 6⌋ = 124}} and {{math|1=745 mod 6 = 1}}. These numbers are strictly increasing. For the second and subsequent inserted characters, the difference between the number and the previous one is written. ===Variable-length number encoding=== The number is encoded using the letters {{char|a}} through {{char|z}} and the digits {{char|0}} through {{char|9}}. It is not base-36 but a more complex scheme, [[Numeral system#Generalized variable-length integers|generalized variable-length integers]], which allows the numbers to be concatenated with nothing separating them. This is how "kva" is used to represent the code number 745: <blockquote> A number system with [[Endianness#Detailed description|little-endian ordering]] is used which allows variable-length codes without separate delimiters: a digit lower than a threshold value marks that it is the most-significant digit, hence the end of the number. The threshold value depends on the position in the number and also on previous insertions, to increase efficiency. Correspondingly the weights of the digits vary. In this case a number system with 36 symbols is used, with the [[case sensitivity|case-insensitive]] 'a' through 'z' equal to the decimal numbers 0 through 25, and '0' through '9' equal to the decimal numbers 26 through 35. Thus "kva", corresponds to the decimal number string "10 21 0". </blockquote> To decode this string of symbols, a sequence of thresholds will be needed, in this case it's (1, 1, 26, 26, ...).<ref>This is true for the first encoded character (or, in terms of RFC 3492, the first "delta"): see RFC 3492, Sec. 6.</ref> The weight (or [[place value]]) of the least-significant digit is always 1: 'k' (=10) with a weight of 1 equals 10. After this, the weight of the next digit depends on the first threshold: generally, for any ''n'', the weight of the (''n''+1)-th digit is ''w'' × (36 − ''t''), where ''w'' is the previous weight and ''t'' is the threshold of the ''n''-th digit. So in this case, the second symbol has a place value of 36 minus the previous threshold value of 1, which equals 35. Therefore, the sum of the first two symbols 'k' (=10) and 'v' (=21) is 10 × 1 + 21 × 35. Since the second symbol is not less than its threshold value of 1, there is more to come. However, since the third symbol in this example is 'a' (=0), we may ignore calculating its weight. Therefore, "kva" represents the decimal number (10 × 1) + (21 × 35) = 745. Number 745 will be encoded as 10 + 21 × 35 + 0 (base 35 used for second digit, the most significant digit 0 needed as terminator), 10 → 'k', 21 → 'v', 0 → 'a', so "bücher" → "bcher-kva". The thresholds themselves are determined for each successive encoded character by an algorithm keeping them between 1 and 26 inclusive.<ref>RFC 3492, Secs. 3.4, 5.</ref> The case can then be used to provide information about the original case of the string.<ref>RFC 3492, App. A.</ref> Because special characters are sorted by their code points by encoding algorithm, for the insertion of a second special character in "bücher", the first possibility is "büücher" with code "bcher-kvaa", the second "bücüher" with code "bcher-kvab", etc. After "bücherü" with code "bcher-kvae" comes codes representing insertion of ý, the Unicode character following ü, starting with "ýbücher" with code "bcher-kvaf" (different from "übücher" coded "bcher-jvab"), etc. ===ACE prefix for internationalized domain names=== {{main|Internationalized domain name}} To prevent hyphens in non-international domain names from triggering a Punycode decoding, the string <code>xn--</code> is prepended to Punycode sequences in internationalized domain names. This is called ACE (ASCII Compatible Encoding).<ref>{{cite web |url=http://www.atm.tut.fi/list-archive/ietf-announce/msg13572.html |title=Completion of IANA Selection of IDNA Prefix |author=Internet Assigned Numbers Authority |author-link=Internet Assigned Numbers Authority |website=www.atm.tut.fi |date=2003-02-14 |access-date=2017-09-22 |archive-url=https://web.archive.org/web/20100427154004/http://www.atm.tut.fi/list-archive/ietf-announce/msg13572.html |archive-date=2010-04-27 |url-status=dead }}</ref> Thus the domain name "bücher.tld" would be represented in a URL as "xn--bcher-kva.tld".
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)