Punycode – это специальная кодировка, используется для преобразования символов Unicode в ASCII для кодирования интернационализированных доменных имен (IDN).
В PHP есть функции для преобразования:
echo idn_to_ascii('домен.рф'); // xn--d1acufc.xn--p1ai
echo idn_to_utf8('xn--d1acufc.xn--p1ai'); // домен.рф
Но с ними есть одна проблема – они неправильно работает с полными URL, например:
Чтобы перекодировать домен в ссылке, нужно разбирать URL с помощью parse_url, сделать преобразование и собрать обратно.
function punycode_encode($url)
{
$parts = parse_url($url);
$out = '';
if (!empty($parts['scheme'])) $out .= $parts['scheme'] . ':';
if (!empty($parts['host'])) $out .= '//';
if (!empty($parts['user'])) $out .= $parts['user'];
if (!empty($parts['pass'])) $out .= ':' . $parts['pass'];
if (!empty($parts['user'])) $out .= '@';
if (!empty($parts['host'])) $out .= idn_to_ascii($parts['host']);
if (!empty($parts['port'])) $out .= ':' . $parts['port'];
if (!empty($parts['path'])) $out .= $parts['path'];
if (!empty($parts['query'])) $out .= '?' . $parts['query'];
if (!empty($parts['fragment'])) $out .= '#' . $parts['fragment'];
return $out;
}
echo punycode_encode('http://домен.рф/category'); // http://xn--d1acufc.xn--p1ai/category
Обратный перевод
function punycode_decode($url)
{
$parts = parse_url($url);
$out = '';
if (!empty($parts['scheme'])) $out .= $parts['scheme'] . ':';
if (!empty($parts['host'])) $out .= '//';
if (!empty($parts['user'])) $out .= $parts['user'];
if (!empty($parts['pass'])) $out .= ':' . $parts['pass'];
if (!empty($parts['user'])) $out .= '@';
if (!empty($parts['host'])) $out .= idn_to_utf8($parts['host']);
if (!empty($parts['port'])) $out .= ':' . $parts['port'];
if (!empty($parts['path'])) $out .= $parts['path'];
if (!empty($parts['query'])) $out .= '?' . $parts['query'];
if (!empty($parts['fragment'])) $out .= '#' . $parts['fragment'];
return $out;
}
echo punycode_decode('http://xn--d1acufc.xn--p1ai/category'); // http://домен.рф/category