В эксплуатацию вводятся кириллические. Что это, зачем и как — поразмыслю в этом посте.
Инструмент для декодирования доменов в кириллицу. Введите закодированный домен, получите раскодированный.
Изначально идея делать домены не только на английском языке появилась потому что в некоторых странах английский совсем не употребляется. Поэтому чтобы набрать адрес в сети, нужно прибегать к шаманствам вроде копипаста символов и использования нетипичных раскладок. Ну еще были соображения по поводу того что "интернет же глобальный, международный, а говорят там все по-английски. Не хорошо."
Результат — нелатинские домены.
По сути же, они представляют собой те же латинские имена, только добавляется еще одна ступень перекодирования. Браузер отображает кириллические домены, но запрашивает все равно домен, записанный латиницей. Перевод кириллического имени в латиницу производится при помощи алгоритма кодирования Punycode.
Если посмотреть заголовки, которые посылает браузер серверу при заходе на "правительство.рф", можно увидеть что запрашивается на самом деле не кошерный юникодный адрес, а непонятное "xn--80aealotwbjpid2k.xn--p1ai". В принципе, если набрать ЭТО в адресной строке, то откроется сайт "правительство.рф".
Вот этот набор символов — и есть настоящее доменное имя. А "правительство.рф" — это лишь видимость. Но за эту видимость нужно неплохо заплатить. Стоимость кириллических доменов очень высока на данный момент.
Курьезности добавляет еще и то, что называть документы и передавать данные на русском языке в адресной строке не получится. Они, в соответствии со стандартами, будут кодироваться в URL-encode как и раньше. То есть, "правительство.рф" работает. А вот "правительство.рф/Ресурс.html" — уже нет. Получится вот что: "xn--80aealotwbjpid2k.xn--p1ai/%D0%A0%D0%B5%D1%81%D1%83%D1%80%D1%81.html". Выглядит не очень, да? И самое интересное, что даже если набрать "Ресурс.html", избежать переключения раскладки на английский все равно не удастся (html).
Еще смешнее что прежде чем давать регистрировать кириллические домены, выпустили специальный стоп-лист, который состоит из названий доменов, которые регистрировать не получится. Сам по себе этот стоп-лист интересен как справочник нецензурной брани. Можно нехило обогатить свой культурный багаж. Я даже не удержался и сделал небольшой простой поисковичок по этому словарю.
Конечно, встает несколько вопросов, связанных с разработкой. Особенно, если разрабатываемый продукт должен работать с доменами, включая кириллические. Как сохранять оригинальные имена в Punycode и их более пристойные варианты в базе, рассчитанной на одно имя?
Я бы сохранял все в Punycode. В конце концов, это и есть настоящий адрес. А чтобы получить человекочитаемый домен, я бы перекодировал используя готовые модули.
Кодирование, как я сказал, осуществляется при помощи алгоритма Punycode. Адрес разрезается по точке, отрезается часть "xn--" и остатки декодируются.
На Perl это можно легко реализовать при помощи кучи модулей, которые уже есть на CPAN. Лично я пользуюсь URI::UTF8::Punycode. Он имеет небольшой бонус — можно не отрезать "xn--".
Приведу пример и дам пару функций, написав которые, я смог быстренько сделать поддержку кириллических доменов в панели управления доменами.
use URI::UTF8::Punycode; #сама библиотека, перекодирующая по стандарту
use Encode; #нужно для перекодирования из юникода в нужную кодировку
#главная рабочая функция.
sub domain_normalize {
my $domain = shift;
if($domain =~ /^xn--/) { #если переданное похоже на домен
my $other='';
if($domain =~ /\s/) { #возможно, это строка, начинающаяся с домена, но содержащая не только его
($domain, $other) = $domain =~ /^(.*?)\s(.*)$/; #отделяем домен от остального
}
$domain = puny_domain_decode($domain); #перекодируем
$domain .= ($other)? " $other" : ''; #склеиваем обратно
}
return $domain;
}
#эта функция разрезает домен на составные, перекодирует их и склеивает обратно
sub puny_domain_decode {
my $domain = shift;
my ($dom2, $dom1) = split /\./, $domain;
return puny_decode($dom2).'.'.puny_decode($dom1);
}
#эта функция перекодирует строку из Punycode в koi8-r
sub puny_decode {
my $str = shift;
$str = puny_dec($str); #функция puny_dec возвращает строку в utf-8, что не всегда нужно
Encode::from_to($str, 'utf-8','koi8-r'); #перекодируем в нужную нам кодировку
return $str;
}
Таким вот образом проблема решается. Теперь осталось везде, где мы выводим имя домена вызывать функцию domain_normalize и если домен в punycode, он будет декодирован, а если нет — останется в прежнем виде.
А как декодировать кириллический домен на php? На самом деле,тоже не сложно. Для этого можно воспользоваться классом Net_IDNA из библиотеки PEAR. Дальше все становится совсем просто.
<?php
require "IDNA.php";
$text = 'xn--80aealotwbjpid2k.xn--p1ai';
$idna = new Net_IDNA;
$decoded = $idna->decode($text);
print $decoded;
?>
Код выведет декодированный домен "правительство.рф".