PHP中的西里尔字母转写

37

如何将 Cyrillic 字符转换为拉丁字母?

E.g. Главная страница -> Glavnaja stranica

这个Transliteration PHP Extension可以非常好地解决这个问题,但我无法在我的服务器上安装它。

最好有一个相同的PHP实现。

15个回答

74

尝试以下代码:

$textcyr="Тествам с кирилица";
        $textlat="I pone dotuk raboti!";
        $cyr = ['Љ', 'Њ', 'Џ', 'џ', 'ш', 'ђ', 'ч', 'ћ', 'ж', 'љ', 'њ', 'Ш', 'Ђ', 'Ч', 'Ћ', 'Ж','Ц','ц', 'а','б','в','г','д','е','ё','ж','з','и','й','к','л','м','н','о','п', 'р','с','т','у','ф','х','ц','ч','ш','щ','ъ','ы','ь','э','ю','я', 'А','Б','В','Г','Д','Е','Ё','Ж','З','И','Й','К','Л','М','Н','О','П', 'Р','С','Т','У','Ф','Х','Ц','Ч','Ш','Щ','Ъ','Ы','Ь','Э','Ю','Я'
        ];
        $lat = ['Lj', 'Nj', 'Dž', 'dž', 'š', 'đ', 'č', 'ć', 'ž', 'lj', 'nj', 'Š', 'Đ', 'Č', 'Ć', 'Ž','C','c', 'a','b','v','g','d','e','io','zh','z','i','y','k','l','m','n','o','p', 'r','s','t','u','f','h','ts','ch','sh','sht','a','i','y','e','yu','ya', 'A','B','V','G','D','E','Io','Zh','Z','I','Y','K','L','M','N','O','P', 'R','S','T','U','F','H','Ts','Ch','Sh','Sht','A','I','Y','e','Yu','Ya'
        ];
        $textcyr = str_replace($cyr, $lat, $textcyr);
        $textlat = str_replace($lat, $cyr, $textlat);
        echo("$textcyr $textlat");

1
$lat 中的 "е" 是 Cyrillic 字母,与 "e" 不同,即使它们在视觉上相同。 - Timo Huovinen
5
顺便提一下,这个数组中没有'ё'、'ы'和'э'这些字母。 - Victor Rudkov
运行得很好,你有最新版本和注释的网站或Github吗? - d.raev
$cyr数组中有一个错别字:'$cyr'数组中的'e'实际上是拉丁字母'e'。它们看起来相同,但这会在进一步的转换中造成问题。 - d.raev
@TuralAliyev 谢谢,但是我在4年前已经评论了这篇文章。而且它已经被编辑过了。 - Victor Rudkov
@TuralAliyev 当你将拉丁字母转换为西里尔字母时,跳过HTML标记怎么样? - Nuriddin Rashidov

46
您好!这段文本是英语,以下是翻译:

@Tural Teyyuboglu

你的代码有问题:如果你尝试把“щеки”转换成拉丁字符,然后再转回到西里尔字符,它会产生类似于“схтеки”的结果。多字节字符必须首先出现在数组中,像这样:

function transliterate($textcyr = null, $textlat = null) {
    $cyr = array(
    'ж',  'ч',  'щ',   'ш',  'ю',  'а', 'б', 'в', 'г', 'д', 'е', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ъ', 'ь', 'я',
    'Ж',  'Ч',  'Щ',   'Ш',  'Ю',  'А', 'Б', 'В', 'Г', 'Д', 'Е', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ъ', 'Ь', 'Я');
    $lat = array(
    'zh', 'ch', 'sht', 'sh', 'yu', 'a', 'b', 'v', 'g', 'd', 'e', 'z', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'f', 'h', 'c', 'y', 'x', 'q',
    'Zh', 'Ch', 'Sht', 'Sh', 'Yu', 'A', 'B', 'V', 'G', 'D', 'E', 'Z', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F', 'H', 'c', 'Y', 'X', 'Q');
    if($textcyr) return str_replace($cyr, $lat, $textcyr);
    else if($textlat) return str_replace($lat, $cyr, $textlat);
    else return null;
}

echo transliterate(null, transliterate("щеки")) == "щеки";


这段代码的意思是:使用转换函数将"щеки"翻译成另一种字符集,然后再将其转换回原始字符集,最后比较两者是否相等。

我使用字典中的4万个单词测试了我的代码,但在“безизходен” -> “bezizhoden” -> “безижоден”这样的情况下存在缺陷。如果我能找到既保持人类可读性且不失真的解决方案,我会在我的网站上发布该解决方案。 - bobef
是的。我发现没有无损解决方案。一个字母大约有30个字符,而另一个字母大约有26个字符。 - bobef
2
$cyr数组中有一个错别字:'$cyr'数组中的'e'实际上是拉丁字母'e'。它们看起来相同,但这会在进一步的转换中造成问题。 - d.raev
1
你缺少了Ы和Ё。 - Yaroslav
非常有用,谢谢!然而,这个转换表使用所谓的“聊天拼写”来表示字母“ц”,“ъ”,“ь”和“я”。如果您想使其符合音译规则,您需要将“ц”更改为“ts”,“ъ”更改为“a”,“ь”更改为“y”,并将“я”更改为“ya”。 - cheeseus
"多字节字符必须首先出现",但你搞砸了... 你的大型多字节字符应该在小型多字节字符之后,所以类似于['ж','ч','щ','ш','ю','Ж','Ч','Щ','Ш','Ю',<小写字母>,<大写字母>]。 - Enis P. Aginić

23

最佳选择是使用PHP Intl扩展。您可能需要先安装它

这将解决问题:

$transliteratedString = transliterator_transliterate('Russian-Latin/BGN', $cyrillicString);

我选择了“俄语-拉丁字母/BGN”翻译选项,因为提问者在问题中使用了俄语。但是,还有其他用西里尔字母书写的语言的选项。要查看它们所有的选项,请执行以下操作:

print_r(transliterator_list_ids());

2
在CentOS 7和PHP 7.1下,您可以使用yum install php71w-intl - devugur

7
你应该使用带有 //TRANSLIT 选项的 iconv() 函数。
$trstr = iconv(<your encoding here>, "ISO-8859-1//TRANSLIT", $src_str)

3
我本以为这是正确的答案,但iconv()似乎不支持对西里尔字符进行音译。 - Álvaro González
5
我明白了,iconv() 并没有那个转换方案。但是 ICU 有,所以如果你的 PHP 安装了 ICU,你可以使用 transliterate。 (在基于 Debian 的机器上,可能需要执行 aptitude install php5-intl。) - Kerrek SB

6
这里是我用于清理波斯尼亚语、克罗地亚语、塞尔维亚语的拉丁字符的函数。
 function cleanUTF($name){
        $name = str_replace(array('š','č','đ','č','ć','ž','ñ'),array('s','c','d','c','c','z','n'), $name);
        $name = str_replace(array('Š','Č','Đ','Č','Ć', 'Ž','Ñ'),array('S','C','D','C','C','Z','N'), $name);
        $name = str_replace(array('а','б','в','г','д','е','ё','ж','з','и','й','к','л','љ','м','н','њ','о','п','р','с','т','у','ф','х','ц','ч','џ','ш','щ','ъ','ы','ь','э','ю','я','А','Б','В','Г','Д','Е','Ё','Ж','З','И','Й','К','Л','Љ','М','Н','Њ','О','П','Р','С','Т','У','Ф','Х','Ц','Ч','Џ','Ш','Щ','Ъ','Ы','Ь','Э','Ю','Я'),
                            array('a','b','v','g','d','e','e','z','z','i','j','k','l','lj','m','n','nj','o','p','r','s','t','u','f','h','c','c','dz','s','s','i','j','j','e','ju','ja','A','B','V','G','D','E','E','Z','Z','I','J','K','L','Lj','M','N','Nj','O','P','R','S','T','U','F','H','C','C','Dz','S','S','I','J','J','E','Ju','Ja'), $name);
        return $name;
    }

6
$textcyr="Тест на кирилице";
$textlat="Test na kirilitse!";
$cyr  = array('а','б','в','г','д','е','ё','ж','з','и','й','к','л','м','н','о','п','р','с','т','у', 
            'ф','х','ц','ч','ш','щ','ъ', 'ы','ь', 'э', 'ю','я','А','Б','В','Г','Д','Е','Ж','З','И','Й','К','Л','М','Н','О','П','Р','С','Т','У',
            'Ф','Х','Ц','Ч','Ш','Щ','Ъ', 'Ы','Ь', 'Э', 'Ю','Я' );
$lat = array( 'a','b','v','g','d','e','io','zh','z','i','y','k','l','m','n','o','p','r','s','t','u',
            'f' ,'h' ,'ts' ,'ch','sh' ,'sht' ,'a', 'i', 'y', 'e' ,'yu' ,'ya','A','B','V','G','D','E','Zh',
            'Z','I','Y','K','L','M','N','O','P','R','S','T','U',
            'F' ,'H' ,'Ts' ,'Ch','Sh' ,'Sht' ,'A' ,'Y' ,'Yu' ,'Ya' );

$textcyr = str_replace($cyr, $lat, $textcyr);
$textlat = str_replace($lat, $cyr, $textlat);
echo("$textcyr $textlat");

缺失 ё, э, ы (Э, Ы, Ё) 字母


4
大写字母Ё仍然缺失。在3个答案中,没有一个人能够写出完整的字母表。 - Gherman

4

对我来说,这个是最好的选择。 代码来自这个页面

function ru2lat($str)
{
    $tr = array(
    "А"=>"a", "Б"=>"b", "В"=>"v", "Г"=>"g", "Д"=>"d",
    "Е"=>"e", "Ё"=>"yo", "Ж"=>"zh", "З"=>"z", "И"=>"i", 
    "Й"=>"j", "К"=>"k", "Л"=>"l", "М"=>"m", "Н"=>"n", 
    "О"=>"o", "П"=>"p", "Р"=>"r", "С"=>"s", "Т"=>"t", 
    "У"=>"u", "Ф"=>"f", "Х"=>"kh", "Ц"=>"ts", "Ч"=>"ch", 
    "Ш"=>"sh", "Щ"=>"sch", "Ъ"=>"", "Ы"=>"y", "Ь"=>"", 
    "Э"=>"e", "Ю"=>"yu", "Я"=>"ya", "а"=>"a", "б"=>"b", 
    "в"=>"v", "г"=>"g", "д"=>"d", "е"=>"e", "ё"=>"yo", 
    "ж"=>"zh", "з"=>"z", "и"=>"i", "й"=>"j", "к"=>"k", 
    "л"=>"l", "м"=>"m", "н"=>"n", "о"=>"o", "п"=>"p", 
    "р"=>"r", "с"=>"s", "т"=>"t", "у"=>"u", "ф"=>"f", 
    "х"=>"kh", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh", "щ"=>"sch", 
    "ъ"=>"", "ы"=>"y", "ь"=>"", "э"=>"e", "ю"=>"yu", 
    "я"=>"ya", " "=>"-", "."=>"", ","=>"", "/"=>"-",  
    ":"=>"", ";"=>"","—"=>"", "–"=>"-"
    );
return strtr($str,$tr);
}

希望这能帮到某些人。

我偶然发现了这条评论,但我无法理解它应该如何工作。当我尝试执行strstr时,它显示了一个错误信息“needle不是字符串或整数”。 - Moseleyi
@Moseleyi 这个函数只是简单地替换子字符串,http://php.net/manual/en/function.strtr.php - pc_

4

这是我对俄语字母的音译表版本。虽然不是官方版,但基于技术标准GOST 7.79-2000和GOST 16876-71。多字符排在前面。

public static function transliterate($textcyr = null, $textlat = null) {
    $cyr = array(
        'ё',  'ж',  'х',  'ц',  'ч',  'щ',   'ш',  'ъ',  'э',  'ю',  'я',  'а', 'б', 'в', 'г', 'д', 'е', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'ь',
        'Ё',  'Ж',  'Х',  'Ц',  'Ч',  'Щ',   'Ш',  'Ъ',  'Э',  'Ю',  'Я',  'А', 'Б', 'В', 'Г', 'Д', 'Е', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Ь');
    $lat = array(
        'yo', 'zh', 'kh', 'ts', 'ch', 'shh', 'sh', '``', 'eh', 'yu', 'ya', 'a', 'b', 'v', 'g', 'd', 'e', 'z', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'f', '`',
        'Yo', 'Zh', 'Kh', 'Ts', 'Ch', 'Shh', 'Sh', '``', 'Eh', 'Yu', 'Ya', 'A', 'B', 'V', 'G', 'D', 'E', 'Z', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F', '`');
    if($textcyr)
        return str_replace($cyr, $lat, $textcyr);
    else if($textlat)
        return str_replace($lat, $cyr, $textlat);
    else
        return null;
}

4
如果您想要每个字母的精确双重转换,需要稍微改进方法。我已经有用于URL的翻译,URL参数通过数据库进行搜索。这就是为什么对于我来说保持精确字符而不替换一个字符非常重要。!!! 支持乌克兰符号。
/**
 * @param $string
 *
 * @return string only cyrillic letter
 */
function to_cyrillic($string):string
{
    $gost = [
        "a" => "а", "b" => "б", "v" => "в", "g" => "г", "d" => "д", "e" => "е", "yo" => "ё",
        "j" => "ж", "z" => "з", "ii" => "и", "ji" => "й", "k" => "к",
        "l" => "л", "m" => "м", "n" => "н", "o" => "о", "p" => "п", "r" => "р", "s" => "с", "t" => "т",
        "y" => "у", "f" => "ф", "h" => "х", "c" => "ц",
        "ch" => "ч", "sh" => "ш", "sch" => "щ", "ie" => "ы", "u" => "у", "ya" => "я", "A" => "А", "B" => "Б",
        "V" => "В", "G" => "Г", "D" => "Д", "E" => "Е", "Yo" => "Ё", "J" => "Ж", "Z" => "З", "I" => "И", "Ji" => "Й",
        "K" => "К", "L" => "Л", "M" => "М",
        "N" => "Н", "O" => "О", "P" => "П",
        "R" => "Р", "S" => "С", "T" => "Т", "Y" => "Ю", "F" => "Ф", "H" => "Х", "C" => "Ц", "Ch" => "Ч", "Sh" => "Ш",
        "Sch" => "Щ", "Ie" => "Ы", "U" => "У", "Ya" => "Я", "'" => "ь", "_'" => "Ь", "''" => "ъ", "_''" => "Ъ",
        "yi" => "ї", "ge" => "ґ",
        "ye" => "є",
        "Yi" => "Ї",
        "II" => "І",
        "Ge" => "Ґ",
        "YE" => "Є",
    ];
    return strtr($string, $gost);
}

/**
 * @param $string
 *
 * @return string only latin letter
 */
function to_latin($string):string
{
    $gost = [
        "а" => "a", "б" => "b", "в" => "v", "г" => "g", "д" => "d",
        "е" => "e", "ё" => "yo", "ж" => "j", "з" => "z", "и" => "ii",
        "й" => "ji", "к" => "k", "л" => "l", "м" => "m", "н" => "n",
        "о" => "o", "п" => "p", "р" => "r", "с" => "s", "т" => "t",
        "у" => "y", "ф" => "f", "х" => "h", "ц" => "c", "ч" => "ch",
        "ш" => "sh", "щ" => "sch", "ы" => "ie", "э" => "e", "ю" => "u",
        "я" => "ya",
        "А" => "A", "Б" => "B", "В" => "V", "Г" => "G", "Д" => "D",
        "Е" => "E", "Ё" => "Yo", "Ж" => "J", "З" => "Z", "И" => "I",
        "Й" => "Ji", "К" => "K", "Л" => "L", "М" => "M", "Н" => "N",
        "О" => "O", "П" => "P", "Р" => "R", "С" => "S", "Т" => "T",
        "У" => "Y", "Ф" => "F", "Х" => "H", "Ц" => "C", "Ч" => "Ch",
        "Ш" => "Sh", "Щ" => "Sch", "Ы" => "Ie", "Э" => "E", "Ю" => "U",
        "Я" => "Ya",
        "ь" => "'", "Ь" => "_'", "ъ" => "''", "Ъ" => "_''",
        "ї" => "yi",
        "і" => "ii",
        "ґ" => "ge",
        "є" => "ye",
        "Ї" => "Yi",
        "І" => "II",
        "Ґ" => "Ge",
        "Є" => "YE",
    ];
    return strtr($string, $gost);
}

3
我为utf-8编写了一个涵盖所有欧洲语言的全拼音转换类。可能会有所帮助(注释是波兰语,但不多,下面是一些提示:
  1. 常量中存储的数字是本地数据库中的idCountry - 您可以根据需要更改它们。
  2. "Rób transliterację dla "意思是"对进行转换" - 您可以通过常量名称确定国家。
  3. "Słownik tłumaczący rosyjską cyrylicę wg standardu "意思是"按标准进行转换的字典"
  4. "Tablica wycinająca akcenty z różnych znaków narodowych pobrana z http://stuffofinterest.com/misc/utf8-about.html"意思是“从不同语言中去掉重音的数组”(如果您发现iconv中的某些错误或无法使用它,则可能会有所帮助)。
  5. 方法utf2ascii和cyr2lat非常明显。
希望它能帮助一些人,因为实现它是一场噩梦 :)

编辑:我刚刚注意到代码的一部分丢失了,所以我已经将完整的类放在Pastie上:class


我担心有人会删除或编辑它,如果你知道一个更安全的分享地方,请告诉我。 - Tomasz Kapłoński
看起来非常有前途。我会尝试一下,谢谢。Github是分享这样代码的绝佳地方。 - Sfisioza
1
谢谢你分享这个,到目前为止这是我找到的最好的代码片段。 - Kohjah Breese
@TomaszKapłoński,不再起作用了:( 你在GitHub上有那段代码吗? - ptyskju
1
@ptyskju 这里:https://github.com/moby04/Transliteration/blob/master/translit.php - Tomasz Kapłoński
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接