To convert IDN Domains with the IDNA2008 definition use following command.
idn_to_ascii('teßt.com',IDNA_NONTRANSITIONAL_TO_ASCII,INTL_IDNA_VARIANT_UTS46)
The result is then as expected
xn--tet-6ka.com
(PHP 5 >= 5.3.0, PHP 7, PHP 8, PECL intl >= 1.0.2, PECL idn >= 0.1)
idn_to_ascii — Alan adını IDNA ASCII biçimine dönüştürür
Yordamsal kullanım
$alan
,$seçenekler
= IDNA_DEFAULT
,$varyant
= INTL_IDNA_VARIANT_UTS46
,&$idna_info
= null
Unicode alan adını IDNA ASCII kodlu alan adına dönüştürür.
alan
Dönüştürülecek alan adı. UTF-8 kodlu olmalıdır.
seçenekler
IDNA_* sabitlerinden oluşan dönüşüm seçenekleri. (IDNA_ERROR_* sabitleri hariç)
varyant
Ya IDNA 2003 için INTL_IDNA_VARIANT_2003
(kullanımı
PHP 7.2.0 itibariyle önerilmiyor) ya da UTS #46 için
INTL_IDNA_VARIANT_UTS46
(sadece ICU 4.6 ve üstü ile
kullanılabilir).
idna_info
Bu bağımsız değişken sadece varyant
için
INTL_IDNA_VARIANT_UTS46
kullanılmışsa
kullanılabilir. Bu durumda, muhtemelen meşru olmayan bir dönüşümün
sonucu olarak 'result'
, sonucu değiştirmiş ya da
değiştirecek olan UTS #46'nın geçiş mekanizmalarının kullanımının
değişip değişmediğini gösteren bir mantıksal değer olarak
'isTransitionalDifferent'
ve IDNA_ERROR_* hata
sabitlerinin bir bit kümesini temsil eden birer tamsayı olarak
'errors'
anahtarlı bir dizi ile doldurulur.
ASCII uyumlu kodlanmış alan adı, başarısızlık durumunda false
döner.
Sürüm: | Açıklama |
---|---|
7.4.0 |
varyant bağımsız değişkeninin öntanımlısı artık
INTL_IDNA_VARIANT_UTS46 oldu; evvelce
INTL_IDNA_VARIANT_2003 idi ve kulllanımı
önerilmiyordu.
|
7.2.0 |
INTL_IDNA_VARIANT_2003 sabitinin kulllanımı
artık önerilmiyor; yerine INTL_IDNA_VARIANT_UTS46
kullanılmalıdır.
|
Örnek 1 - idn_to_ascii() örneği
<?php
echo idn_to_ascii('täst.de');
?>
Yukarıdaki örneğin çıktısı:
xn--tst-qla.de
To convert IDN Domains with the IDNA2008 definition use following command.
idn_to_ascii('teßt.com',IDNA_NONTRANSITIONAL_TO_ASCII,INTL_IDNA_VARIANT_UTS46)
The result is then as expected
xn--tet-6ka.com
The notes on this function are not very clear and a little misleading.
Firstly, <=5.3, you will need to make use of one of several scripts or classes available on the internet which might, or might not, require the installation of of the intl and idn PECL extensions ...and you will need to have !<4.0 in order to be able to install both.
Secondly, if you have >=5.4 you will not require the PECL extensions.
Third, use of utf8_encode() is not necessary. In fact, it will potentially prevent idn_to_ascii() from working at all.
On my setup it was necessary to change the charset in the script meta tags to UTF-8:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
...and to change charset_default in the php.ini file (/usr/local/lib/php.ini, whereis php.ini, find / -name php.ini):
default_charset = "UTF-8"
The above changes mean that idn_to_ascii() can now be used with that syntax (no need for utf8_encode()). Previously, the function worked to convert some IDNs, but failed to convert Japanese and Cyrillic IDNs. Further, no additional locales were enabled or added, and Apache's charset file was left unmodified.
It is also important to remember only to apply the function where required, eg:
idn_to_ascii(cåsino.com) // is wrong
...whereas...
iden_to_ascii(cåsino) // is right
...and also be aware of text editors that don't support UTF-8 encoding, or the $domain = 'cåsino' value will end up as $domain = '??????' ...and the function will fail.
I have found that Notepad++ easily and reliably handles UTF-8 encoding that works for this function using UTF-8 as the encoding option, not UTF-8 without BOM.
idn_to_ascii and idn_to_utf8 functions don't properly handle full URLs (i.e. with schema and paths), so here's the helper functions which handles all URLs, including ones with path but without a scheme
<?php
/**
* Converts URLS to punycode
* It doesn't url-encodes other parts
* The initial code from snipp dor ru website, here is modified version that handles urls without scheme
*/
function punycode_encode($url)
{
$no_scheme = false;
if (!preg_match('/^.+?:\/\//', $url) && substr($url, 0, 2) !== '//') {
$url = '//' . $url;
$no_scheme = true;
}
$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'];
if ($no_scheme) {
$out = substr($out, 2);
}
return $out;
}
function punycode_decode($url)
{
$no_scheme = false;
if (!preg_match('/^.+?:\/\//', $url) && substr($url, 0, 2) !== '//') {
$url = '//' . $url;
$no_scheme = true;
}
$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'];
if ($no_scheme) {
$out = substr($out, 2);
}
return $out;
}
The documentation ist not clear what failure in the return section means. This should be substituted to something like this:
"Returns failure if the given string could not be converted".