В очередной раз написав "поиск" для проекта задумался о его удобстве. Очень малое число людей владеет слепым методом печати, поэтому вводят не глядя на экран. В результате появляются такие вещи типа «Bpvtytybt hfcrkflrb cnhjrb d ЗРЗ bkb Згтещ Ыцшесрук yf зрз» (Изменение раскладки строки в PHP или Punto Switcher на php). Заставлять юзера вводить текст заново, как-то не гуманно. Яша и Гугл автоматически подбирают верный вариант. Чем мы хуже.

Чтобы поиск был более-менее адекватный, надо переводить раскладку во все возможные варианты написания, к примеру: «hfcrkflrf ЗРЗ» нужно перевести в «раскладка ЗРЗ»  и  «раскладка PHP» и проверить все три варианта. По хорошему надо делать 3 разных запроса и выводить данные по тому, который вернул больше всего данных, либо выводить все варианты, но тот что находит больше всего выводить выше.

 Поиск в гугле по запросу зрз раскладка, выдал мне эту статейку. В ней дается такая функция



<?php
function textswitch ($text) 
{
   $str_search = array(
   "й","ц","у","к","е","н","г","ш","щ","з","х","ъ",
   "ф","ы","в","а","п","р","о","л","д","ж","э",
   "я","ч","с","м","и","т","ь","б","ю"
   );
   $str_replace = array(
   "q","w","e","r","t","y","u","i","o","p","[","]",
   "a","s","d","f","g","h","j","k","l",";","'",
   "z","x","c","v","b","n","m",",","."
   );
   return str_replace($str_search, $str_replace, $text);
}
?>

смысл, понятен. Надо заменять одну букву на другую.

Проблема в том, что пример чувствителен к регистру . На помощь придут регулярные выражения, но для этого надо модифицировать $str_search, обрамляя его элементы в #й#ui, где ui - это модификатор означающий, что выражение не чувствительно к регистру и работает в кодировке utf-8.  Для этого будем в цикле, в зависимости от нужной раскладки менять один из массивов



function switcher ($text,$reverse=false) {
	$str[0] = array(
		"й","ц","у","к","е","н","г","ш","щ","з","х","ъ",
		"ф","ы","в","а","п","р","о","л","д","ж","э",
		"я","ч","с","м","и","т","ь","б","ю"
	);
	$str[1]= array(
		"q","w","e","r","t","y","u","i","o","p","[","]",
		"a","s","d","f","g","h","j","k","l",";","'",
		"z","x","c","v","b","n","m",",","."
	);
	$out = array();
	foreach($str[0] as $i=>$key){
		$out[0][$i] =  '#'.str_replace(array('.',']','['),array('\.','\]','\['),  $str[ $reverse ? 0:1][$i]).'#ui';
		$out[1][$i] =  $str[$reverse ? 1:0][$i] ; 
	};
	return preg_replace($out[0], $out[1], $text);
}

в результате код



echo switcher ('hfcrkflrf ЗРЗ');//раскладка ЗРЗ
echo switcher ('hfcrkflrf ЗРЗ',1);//hfcrkflrf php

два варианта написания получены, однако они оба бесполезны, потому, как запрос по ним ничего не даст. Нужен  третий - комбинированный. Чтобы на выходе давал из  hfcrkflrf ЗРЗ = раскладка PHP. Вроде бы все просто, объединить оба массива и пропустить через preg_replace. Однако, тут, как в анекдоте - есть нюанс. Его очень просто продемонстрировать



echo preg_replace(array('#a#','#b#'),array('b','c'),'aaabbbccc');// на выходе дает ccccccccc

т.е. preg_replace заменяет первое вхождение, а затем использует уже полученную строку для второго вхождения. Нам же нужно, чтобы пример выше вывел bbbcccccc.

Из строковых функция php, такое получилось только у strtr



echo strtr('aaabbbccc',array('a'=>'b','b'=>'c'));//bbbcccccc

значит нужен новый массив



$a = array ( 'й' => 'q', 'ц' => 'w', 'у' => 'e', 'к' => 'r', 'е' => 't', 'н' => 'y', 'г' => 'u', 'ш' => 'i', 'щ' => 'o', 'з' => 'p', 'х' => '[', 'ъ' => ']', 'ф' => 'a', 'ы' => 's', 'в' => 'd', 'а' => 'f', 'п' => 'g', 'р' => 'h', 'о' => 'j', 'л' => 'k', 'д' => 'l', 'ж' => ';', 'э' => '\'', 'я' => 'z', 'ч' => 'x', 'с' => 'c', 'м' => 'v', 'и' => 'b', 'т' => 'n', 'ь' => 'm', 'б' => ',', 'ю' => '.', 'q' => 'й', 'w' => 'ц', 'e' => 'у', 'r' => 'к', 't' => 'е', 'y' => 'н', 'u' => 'г', 'i' => 'ш', 'o' => 'щ', 'p' => 'з', '[' => 'х', ']' => 'ъ', 'a' => 'ф', 's' => 'ы', 'd' => 'в', 'f' => 'а', 'g' => 'п', 'h' => 'р', 'j' => 'о', 'k' => 'л', 'l' => 'д', ';' => 'ж', '\'' => 'э', 'z' => 'я', 'x' => 'ч', 'c' => 'с', 'v' => 'м', 'b' => 'и', 'n' => 'т', 'm' => 'ь', ',' => 'б', '.' => 'ю',
'Й' => 'Q', 'Ц' => 'W', 'У' => 'E', 'К' => 'R', 'Е' => 'T', 'Н' => 'Y', 'Г' => 'U', 'Ш' => 'I', 'Щ' => 'O', 'З' => 'P', 'Х' => '[', 'Ъ' => ']', 'Ф' => 'A', 'Ы' => 'S', 'В' => 'D', 'А' => 'F', 'П' => 'G', 'Р' => 'H', 'О' => 'J', 'Л' => 'K', 'Д' => 'L', 'Ж' => ';', 'Э' => '\'', '?' => 'Z', 'ч' => 'X', 'С' => 'C', 'М' => 'V', 'И' => 'B', 'Т' => 'N', 'Ь' => 'M', 'Б' => ',', 'Ю' => '.', 'Q' => 'Й', 'W' => 'Ц', 'E' => 'У', 'R' => 'К', 'T' => 'Е', 'Y' => 'Н', 'U' => 'Г', 'I' => 'Ш', 'O' => 'Щ', 'P' => 'З', '[' => 'Х', ']' => 'Ъ', 'A' => 'Ф', 'S' => 'Ы', 'D' => 'В', 'F' => 'А', 'G' => 'П', 'H' => 'Р', 'J' => 'О', 'K' => 'Л', 'L' => 'Д', ';' => 'Ж', '\'' => 'Э', 'Z' => '?', 'X' => 'ч', 'C' => 'С', 'V' => 'М', 'B' => 'И', 'N' => 'Т', 'M' => 'Ь', ',' => 'Б', '.' => 'Ю', );
echo strtr('hfcКkflrf зрз',$a);// расКладка php

этот вариант помимо всего прочего сохраняет регистр букв. Однако он не дает первых двух вариантов. Итоговый вариант будет выглядеть так



function switcher($text,$arrow=0){
	$str[0] = array('й' => 'q', 'ц' => 'w', 'у' => 'e', 'к' => 'r', 'е' => 't', 'н' => 'y', 'г' => 'u', 'ш' => 'i', 'щ' => 'o', 'з' => 'p', 'х' => '[', 'ъ' => ']', 'ф' => 'a', 'ы' => 's', 'в' => 'd', 'а' => 'f', 'п' => 'g', 'р' => 'h', 'о' => 'j', 'л' => 'k', 'д' => 'l', 'ж' => ';', 'э' => '\'', 'я' => 'z', 'ч' => 'x', 'с' => 'c', 'м' => 'v', 'и' => 'b', 'т' => 'n', 'ь' => 'm', 'б' => ',', 'ю' => '.','Й' => 'Q', 'Ц' => 'W', 'У' => 'E', 'К' => 'R', 'Е' => 'T', 'Н' => 'Y', 'Г' => 'U', 'Ш' => 'I', 'Щ' => 'O', 'З' => 'P', 'Х' => '[', 'Ъ' => ']', 'Ф' => 'A', 'Ы' => 'S', 'В' => 'D', 'А' => 'F', 'П' => 'G', 'Р' => 'H', 'О' => 'J', 'Л' => 'K', 'Д' => 'L', 'Ж' => ';', 'Э' => '\'', '?' => 'Z', 'ч' => 'X', 'С' => 'C', 'М' => 'V', 'И' => 'B', 'Т' => 'N', 'Ь' => 'M', 'Б' => ',', 'Ю' => '.',);
	$str[1] = array (  'q' => 'й', 'w' => 'ц', 'e' => 'у', 'r' => 'к', 't' => 'е', 'y' => 'н', 'u' => 'г', 'i' => 'ш', 'o' => 'щ', 'p' => 'з', '[' => 'х', ']' => 'ъ', 'a' => 'ф', 's' => 'ы', 'd' => 'в', 'f' => 'а', 'g' => 'п', 'h' => 'р', 'j' => 'о', 'k' => 'л', 'l' => 'д', ';' => 'ж', '\'' => 'э', 'z' => 'я', 'x' => 'ч', 'c' => 'с', 'v' => 'м', 'b' => 'и', 'n' => 'т', 'm' => 'ь', ',' => 'б', '.' => 'ю','Q' => 'Й', 'W' => 'Ц', 'E' => 'У', 'R' => 'К', 'T' => 'Е', 'Y' => 'Н', 'U' => 'Г', 'I' => 'Ш', 'O' => 'Щ', 'P' => 'З', '[' => 'Х', ']' => 'Ъ', 'A' => 'Ф', 'S' => 'Ы', 'D' => 'В', 'F' => 'А', 'G' => 'П', 'H' => 'Р', 'J' => 'О', 'K' => 'Л', 'L' => 'Д', ';' => 'Ж', '\'' => 'Э', 'Z' => '?', 'X' => 'ч', 'C' => 'С', 'V' => 'М', 'B' => 'И', 'N' => 'Т', 'M' => 'Ь', ',' => 'Б', '.' => 'Ю', );
	return strtr($text,isset( $str[$arrow] )? $str[$arrow] :array_merge($str[0],$str[1]));
}

которая на выходе дает 



echo switcher('hfcrkflrf зрз',0);//hfcrkflrf php
echo switcher('hfcrkflrf зрз',1);//раскладка зрз
echo switcher('hfcrkflrf зрз',2);//раскладка php

вариантов немного прибавилось, но в целом неплохо =)

для интересующихся приведу еще пример с javascript

var switcher = function(text,arrow){
  var str = [], newstr = []; 
  str[0] = {'й' : 'q', 'ц' : 'w', 'у' : 'e', 'к' : 'r', 'е' : 't', 'н' : 'y', 'г' : 'u', 'ш' : 'i', 'щ' : 'o', 'з' : 'p', 'х' : '[', 'ъ' : ']', 'ф' : 'a', 'ы' : 's', 'в' : 'd', 'а' : 'f', 'п' : 'g', 'р' : 'h', 'о' : 'j', 'л' : 'k', 'д' : 'l', 'ж' : ';', 'э' : '\'', 'я' : 'z', 'ч' : 'x', 'с' : 'c', 'м' : 'v', 'и' : 'b', 'т' : 'n', 'ь' : 'm', 'б' : ',', 'ю' : '.','Й' : 'Q', 'Ц' : 'W', 'У' : 'E', 'К' : 'R', 'Е' : 'T', 'Н' : 'Y', 'Г' : 'U', 'Ш' : 'I', 'Щ' : 'O', 'З' : 'P', 'Х' : '[', 'Ъ' : ']', 'Ф' : 'A', 'Ы' : 'S', 'В' : 'D', 'А' : 'F', 'П' : 'G', 'Р' : 'H', 'О' : 'J', 'Л' : 'K', 'Д' : 'L', 'Ж' : ';', 'Э' : '\'', '?' : 'Z', 'ч' : 'X', 'С' : 'C', 'М' : 'V', 'И' : 'B', 'Т' : 'N', 'Ь' : 'M', 'Б' : ',', 'Ю' : '.',};
  str[1] = {  'q' : 'й', 'w' : 'ц', 'e' : 'у', 'r' : 'к', 't' : 'е', 'y' : 'н', 'u' : 'г', 'i' : 'ш', 'o' : 'щ', 'p' : 'з', '[' : 'х', ']' : 'ъ', 'a' : 'ф', 's' : 'ы', 'd' : 'в', 'f' : 'а', 'g' : 'п', 'h' : 'р', 'j' : 'о', 'k' : 'л', 'l' : 'д', ';' : 'ж', '\'' : 'э', 'z' : 'я', 'x' : 'ч', 'c' : 'с', 'v' : 'м', 'b' : 'и', 'n' : 'т', 'm' : 'ь', ',' : 'б', '.' : 'ю','Q' : 'Й', 'W' : 'Ц', 'E' : 'У', 'R' : 'К', 'T' : 'Е', 'Y' : 'Н', 'U' : 'Г', 'I' : 'Ш', 'O' : 'Щ', 'P' : 'З', '[' : 'Х', ']' : 'Ъ', 'A' : 'Ф', 'S' : 'Ы', 'D' : 'В', 'F' : 'А', 'G' : 'П', 'H' : 'Р', 'J' : 'О', 'K' : 'Л', 'L' : 'Д', ';' : 'Ж', '\'' : 'Э', 'Z' : '?', 'X' : 'ч', 'C' : 'С', 'V' : 'М', 'B' : 'И', 'N' : 'Т', 'M' : 'Ь', ',' : 'Б', '.' : 'Ю',};
  for(var j=0;j<=1;j++)
  if( arrow==undefined||arrow==j )
    for(var i=0;i<text.length;i++)
      if(str[j][text[i]])
        newstr[i]=str[j][text[i]];
  for(var i=0;i<text.length;i++)
      if( !newstr[i] )
        newstr[i]= text[i];
  return newstr.join('');
};

использовать почти также

alert(switcher('hfcrkflrf зрз',0));//hfcrkflrf php
alert(switcher('hfcrkflrf зрз',1));//раскладка зрз
alert(switcher('hfcrkflrf зрз'));//раскладка php

 

Оставлять комментарии могут только зарегистрированные пользователи

Комментарии  

mops1k
# mops1k 29.10.2013 18:04
Как увидел Ваш скрипт, сделал себе расширение для хрома, теперь браузер стал еще удобнее)
Leroy
# Leroy 29.10.2013 19:36
так может в паблик?)
alukard696
# alukard696 12.06.2014 16:15
Ошибочка с буквой ч у Вас она большую букву Х делает
moldavian
# moldavian 12.06.2014 18:20
Еще косяк с буквой Ж ибо : = Ж а ; = ж, поправьте

ЗЫЖ Система комментариев на этом сайте это отдельный баг :-)
moldavian
# moldavian 12.06.2014 18:29
Аналогичная тема с буквой Б, только она перепутана и в обратном порядке. В общем не буду заваливать комментариями, просто внимательно просмотрите массив, если будете юзать этот скрипт :-) Лично мне понравился, спасибо автору, поправлю и буду юзать :-)
Leroy
# Leroy 14.06.2014 03:27
спасибо
Mark
# Mark 15.04.2016 18:17
Спасибо. Взял за основу, и собрал функцию для поиска по битркису в обоих раскладках и по оригинальному запросу, может кому пригодится.
Кстати большие буквы заменяю без регулярок - просто продублировал параметры с большими буквами.
---

/**
* Меняет раскладку текста с русской на латинскую
* */
function switchTextToEnglish ($text)
{
$str_search = array(
"й","ц","у","к","е","н","г","ш","щ","з","х","ъ",
"ф","ы","в","а","п","р","о","л","д","ж","э",
"я","ч","с","м","и","т","ь","б","ю",

"Й","Ц","У","К","Е","Н","Г","Ш","Щ","З","Х","Ъ",
"Ф","Ы","В","А","П","Р","О","Л","Д","Ж","Э",
"Я","Ч","С","М","И","Т","Ь","Б","Ю"
);

$str_replace = array(
"q","w","e","r","t","y","u","i","o","p","[","]",
"a","s","d","f","g","h","j","k","l",";","'",
"z","x","c","v","b","n","m",",",".",

"Q","W","E","R","T","Y","U","I","O","P","[","]",
"A","S","D","F","G","H","J","K","L",";","'",
"Z","X","C","V","B","N","M",",","."
);

return str_replace($str_search, $str_replace, $text);
}


/**
* Меняет раскладку текста с латинской на русскую
* */
function switchTextToRussian ($text)
{
$str_search = array(
"q","w","e","r","t","y","u","i","o","p","[","]",
"a","s","d","f","g","h","j","k","l",";","'",
"z","x","c","v","b","n","m",",",".",

"Q","W","E","R","T","Y","U","I","O","P","[","]",
"A","S","D","F","G","H","J","K","L",";","'",
"Z","X","C","V","B","N","M",",","."
);

$str_replace = array(
"й","ц","у","к","е","н","г","ш","щ","з","х","ъ",
"ф","ы","в","а","п","р","о","л","д","ж","э",
"я","ч","с","м","и","т","ь","б","ю",

"Й","Ц","У","К","Е","Н","Г","Ш","Щ","З","Х","Ъ",
"Ф","Ы","В","А","П","Р","О","Л","Д","Ж","Э",
"Я","Ч","С","М","И","Т","Ь","Б","Ю"
);

return str_replace($str_search, $str_replace, $text);
}

/**
* Формирует множественный фильтр по строке с логикой "ИЛИ", содержит
* - оригинальный запрос
* - запрос в русской раскладке
* - запрос в латинской раскладке
*
* Usage example:
*
* $arFilter = array(
* ...
* );
*
* $arFilter[] = prepareTextQueryMultiLangFilter($arParams["QUERY"] );
* */
function prepareTextQueryMultiLangFilter($query)
{
$result = array(
"LOGIC" => "OR",
"SEARCHABLE_CONTENT" => array(
"%" . $query . "%",
"%" . switchTextToEnglish($query) . "%",
"%" . switchTextToRussian($query) . "%",
),
);

return $result;
}
Mark
# Mark 15.04.2016 18:18
потерялся сайт, проверка
krut1
# krut1 29.05.2019 22:20
Заюзал для сайта. Лови в отформатированном виде для PHP 7.3 ;)

/**
* Punto switcher (0: rus -> eng, 1: eng -> rus, false -> eng & rus -> rus & eng)
*
* @param string $text
* @param int|bool $arrow
* @return string
*/
private function stringSwitcher($text, $arrow = 0): string
{
$str[0] = array(
'й' => 'q', 'ц' => 'w', 'у' => 'e', 'к' => 'r', 'е' => 't', 'н' => 'y', 'г' => 'u', 'ш' => 'i', 'щ' => 'o', 'з' => 'p', 'х' => '[', 'ъ' => ']', 'ф' => 'a', 'ы' => 's', 'в' => 'd',
'а' => 'f', 'п' => 'g', 'р' => 'h', 'о' => 'j', 'л' => 'k', 'д' => 'l', 'ж' => ';', 'э' => '\'', 'я' => 'z', 'ч' => 'x', 'с' => 'c', 'м' => 'v', 'и' => 'b', 'т' => 'n', 'ь' => 'm',
'б' => ',', 'ю' => '.', 'Й' => 'Q', 'Ц' => 'W', 'У' => 'E', 'К' => 'R', 'Е' => 'T', 'Н' => 'Y', 'Г' => 'U', 'Ш' => 'I', 'Щ' => 'O', 'З' => 'P', 'Х' => '[', 'Ъ' => ']', 'Ф' => 'A',
'Ы' => 'S', 'В' => 'D', 'А' => 'F', 'П' => 'G', 'Р' => 'H', 'О' => 'J', 'Л' => 'K', 'Д' => 'L', 'Ж' => ';', 'Э' => '\'', '?' => 'Z', 'ч' => 'X', 'С' => 'C', 'М' => 'V', 'И' => 'B',
'Т' => 'N', 'Ь' => 'M', 'Б' => ',', 'Ю' => '.',
);
$str[1] = array(
'q' => 'й', 'w' => 'ц', 'e' => 'у', 'r' => 'к', 't' => 'е', 'y' => 'н', 'u' => 'г', 'i' => 'ш', 'o' => 'щ', 'p' => 'з', '[' => 'х', ']' => 'ъ', 'a' => 'ф', 's' => 'ы', 'd' => 'в',
'f' => 'а', 'g' => 'п', 'h' => 'р', 'j' => 'о', 'k' => 'л', 'l' => 'д', ';' => 'ж', '\'' => 'э', 'z' => 'я', 'x' => 'ч', 'c' => 'с', 'v' => 'м', 'b' => 'и', 'n' => 'т', 'm' => 'ь',
',' => 'б', '.' => 'ю', 'Q' => 'Й', 'W' => 'Ц', 'E' => 'У', 'R' => 'К', 'T' => 'Е', 'Y' => 'Н', 'U' => 'Г', 'I' => 'Ш', 'O' => 'Щ', 'P' => 'З', '[' => 'Х', ']' => 'Ъ', 'A' => 'Ф',
'S' => 'Ы', 'D' => 'В', 'F' => 'А', 'G' => 'П', 'H' => 'Р', 'J' => 'О', 'K' => 'Л', 'L' => 'Д', ';' => 'Ж', '\'' => 'Э', 'Z' => '?', 'X' => 'ч', 'C' => 'С', 'V' => 'М', 'B' => 'И',
'N' => 'Т', 'M' => 'Ь', ',' => 'Б', '.' => 'Ю',
);

return strtr($text, $str[$arrow] ?? \array_merge($str[0], $str[1]));
}