Linux за българи: Форуми

Програмиране => Web development => Темата е започната от: nov_chovek в Feb 11, 2011, 15:19



Титла: обръщане на масив в PHP
Публикувано от: nov_chovek в Feb 11, 2011, 15:19
Здравейте, още едно тъпо нещо, което ми вгорчава живота.

Принципно имам масив на ПХП, който играе ролята за транслитериращ масив:
Код
GeSHi (PHP):
  1. function cyr2lat ($string) {
  2. $table = array(
  3. 'а'=>'a', 'б'=>'b', 'в'=>'v', 'г'=>'g', 'д'=>'d',
  4. 'е'=>'e', 'ж'=>'j', 'з'=>'z', 'и'=>'i', 'й'=>'y',
  5. 'к'=>'k', 'л'=>'l', 'м'=>'m', 'н'=>'n', 'о'=>'o',
  6. 'п'=>'p', 'р'=>'r', 'с'=>'s', 'т'=>'t', 'у'=>'u',
  7. 'ф'=>'f', 'х'=>'h', 'ц'=>'c', 'ч'=>'ch', 'ш'=>'sh',
  8. 'щ'=>'sht', 'ъ'=>'a', 'ь'=>'', 'ю'=>'yu', 'я'=>'ya',
  9. 'А'=>'A', 'Б'=>'B', 'В'=>'V', 'Г'=>'G', 'Д'=>'D',
  10. 'Е'=>'E', 'Ж'=>'J', 'З'=>'Z', 'И'=>'I', 'Й'=>'Y',
  11. 'К'=>'K', 'Л'=>'L', 'М'=>'M', 'Н'=>'N', 'О'=>'O',
  12. 'П'=>'P', 'Р'=>'R', 'С'=>'S', 'Т'=>'T', 'У'=>'U',
  13. 'Ф'=>'F', 'Х'=>'H', 'Ц'=>'C', 'Ч'=>'Ch', 'Ш'=>'Sh',
  14. 'Щ'=>'Sht', 'Ъ'=>'A', 'ь'=>'', 'Ю'=>'Yu', 'Я'=>'Ya',
  15. );
  16.  
  17. return strtr($string, $table);
  18. }
  19.  
понеже не ми се играе да преписвам пак цялата азбука исках да ползвам функцията array_flip(), която сменя местата на ключа и стойността на всеки елемент т.е. по този начим ще имам с едно писане транслитерация в двете посоки.

Функцията наистина общъща местата, обаче през strtr($string, $table); не минават правилно utf-8 кирилските букви. Някакви идеи как да го направя така че да работи?



Титла: Re: обръщане на масив в PHP
Публикувано от: ivanatora в Feb 11, 2011, 15:58
http://bg.php.net/mb_strstr
Подобни Multibyte функции има алтернативи на повечето функции за работа със низове.


Титла: Re: обръщане на масив в PHP
Публикувано от: VladSun в Feb 11, 2011, 16:10
Нещо не ми харесва това :)

Как ще се транслитерира право и обратно "схващане" при условие, че
Х => H
С => S

но

SH => Ш


Титла: Re: обръщане на масив в PHP
Публикувано от: ivo3d в Feb 11, 2011, 18:58
VladSun, ти отрепа всичко детско в мене... Никога не бях се замислял за тия думи... По принцип като я правя тая простотия с масивите слагам тия букви "ш", "щ" и т.н. в началото, така че да хване първо тях, обаче за тоя случай не ми го побира акълът... Освен с някакви предварително въведени думи, ама това пак си е рисковано...

nov_chovek, ти защо реши да използваш strstr? Аз тия функция я използвам да намеря дали в някой низ се съдържа друг низ, и в частни случаи за да ми върне къде точно се намира тоя низ... Да нямаш предвид str_replace?


Титла: Re: обръщане на масив в PHP
Публикувано от: ivo3d в Feb 11, 2011, 19:03
Сега изпробвах всичките преводачи от латиница към кирилица, които намерих в нета - ни един не работи както трябва... Явно наистина това освен с предварително зададени думи няма как да се реши.

А на теб защо точно ти трябва, ако точно искаш да правиш транслитерация ще имаш проблеми, обаче ако превеждаш думи за да търсиш после по тях е една съвсем различна история.


Титла: Re: обръщане на масив в PHP
Публикувано от: VladSun в Feb 12, 2011, 00:00
VladSun, ти отрепа всичко детско в мене... Никога не бях се замислял за тия думи... По принцип като я правя тая простотия с масивите слагам тия букви "ш", "щ" и т.н. в началото, така че да хване първо тях, обаче за тоя случай не ми го побира акълът... Освен с някакви предварително въведени думи, ама това пак си е рисковано...
:P Няма просто решение за този проблем според мен.


nov_chovek, ти защо реши да използваш strstr? Аз тия функция я използвам да намеря дали в някой низ се съдържа друг низ, и в частни случаи за да ми върне къде точно се намира тоя низ... Да нямаш предвид str_replace?

Не  е strstr, a strtr - http://php.net/manual/en/function.strtr.php


Титла: Re: обръщане на масив в PHP
Публикувано от: ivo3d в Feb 12, 2011, 15:31
А, вярно... Между другото, на abv транслатора е написан както трябва... Дори ако примерно напишеш нещо от сорта на "Vie ste ste tam" първото "ste" става "ще", а второто "сте"... Не е като да не са си поиграли...


Титла: Re: обръщане на масив в PHP
Публикувано от: nov_chovek в Feb 14, 2011, 11:59
окей, направих го, но както каза VladSun не се случват нещата поради комбинацията на букви в думите.

Мислите ли, че може да се направи някакъв php клас, който да подава читава транслитерация от кирилица на латиница?

Ако има навити съм готов да дам някой лев (в разумни граници), като след това кода може да се пусне GPL или там както прецени кодера. Ако има мераклии нека пишат лично съобщение.


Титла: Re: обръщане на масив в PHP
Публикувано от: Naka в Feb 14, 2011, 13:33
Проблема е сериозен.
Транслитерация обратно от Lat->Cyr както беше казано е невъзможна, понеже латиницита има много по малко символи и при правата транслитерация  Cyr -> Lat се губи информация.

тук са много хубаво описани изискванията:
http://bg.wikisource.org/wiki/Закон_за_транслитерацията ($2)

Обаче не става с просто заместване на стрингове щото според закона има изключения:

ИЯ в края на думата става ia а не ya
Например София -> Sofia а НЕ Sofiya

другото изключение е етнонима БЪЛГ, който трябва да се транслитерира BULG а не BALG

България -> Bulgaria а не Balgariya  ;D

Има и още подробности:
Ако трябва да се запазят Малките и големите букви, така както е в оригиналният кирилски стринг - става още по сложно например:
ЖРЕБЧЕВО->ZhREBChEVO
в този случай просто заместване на Ж с Zh и Ч с Ch не изглежда хубаво щото имаме мешаница на главни и малки букви в превода.
Дали ще бъде главна или малка буква зависи от това каква е следваща буква в кирилският стринг.

А и освен това този закон явно по подразбиране приема че това е транслитерация към Английски. Ако преведените стрингове на латиница трябва да се четат от немец изобщо няма да изглежда правилно.
на немски е:
Ж -> Sch
Х -> Ch
Ц -> Z
Ч -> Tsch
Ш -> Sch
Щ -> Scht

Т.е. за другите езици са необходими и различни таблици.



 



Титла: Re: обръщане на масив в PHP
Публикувано от: nov_chovek в Feb 14, 2011, 14:08
принципно искам да транслитерирам съществителни собствени имена (вкл. градове, улици и т.н.), които не се превеждат, а се транслитерират. Значи с кофти задача съм се хванал :)


Титла: Re: обръщане на масив в PHP
Публикувано от: Naka в Feb 14, 2011, 14:19
Имам такова работещо решение и точно за такова го правих. Даже мислех да го пускам публично, но се замотах.......

Обаче изисква pcre-то да е компилирано (заради кирилцата) с
./configure --enable-utf8 --enable-unicode-properties

в fedora/RH --enable-unicode-properties липсва.

например без това $str=preg_replace('/(бълг)/ui', 'bulg', $str);
модификатора /u няма да работи :'( и разни други работи с кирилицата и preg_replace не работеха. Не открих и никакво друго алтернативно решение освен пркомпилирането на pcre.

Ако искаш ще го пусна тук, но трябва да го вадя от код и може да пропусна някоя зависмост. 3-4 функции са




Титла: Re: обръщане на масив в PHP
Публикувано от: nov_chovek в Feb 14, 2011, 14:28
Naka, много ще съм ти благодарен ако го направиш! Ако трябва ще прекомпилирам.


Титла: Re: обръщане на масив в PHP
Публикувано от: Naka в Feb 14, 2011, 14:45
Добре де ще вадя.

transliteration.php

Код
GeSHi (PHP):
  1. <?php
  2. // този файл и всички локализиращи файлове са кодирани в utf-8
  3.  
  4. // в този файл се описват масивите за транслитерация от $cyr към различните езици
  5.  
  6. $bg =  array('А', 'а',
  7. 'Б', 'б',
  8. 'В', 'в',
  9. 'Г', 'г',
  10. 'Д', 'д',
  11. 'Е', 'е',
  12. 'Ж', 'ж',
  13. 'З', 'з',
  14. 'И', 'и',
  15. 'Й', 'й',
  16. 'К', 'к',
  17. 'Л', 'л',
  18. 'М', 'м',
  19. 'Н', 'н',
  20. 'О', 'о',
  21. 'П', 'п',
  22. 'Р', 'р',
  23. 'С', 'с',
  24. 'Т', 'т',
  25. 'У', 'у',
  26. 'Ф', 'ф',
  27. 'Х', 'х',
  28. 'Ц', 'ц',
  29. 'Ч', 'ч',
  30. 'Ш', 'ш',
  31. 'Щ', 'щ',
  32. 'Ъ', 'ъ',
  33. 'Ь', 'ь',
  34. 'Ю', 'ю',
  35. 'Я', 'я');
  36. // АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯ
  37. // ABCDEFGHIJKLMNOPQRSTUVWXYZ
  38. // abcdefghijklmnopqrstuvwxyz
  39.  
  40.  
  41. // http://bg.wikisource.org/wiki/Закон_за_транслитерацията
  42. // правилата са за превод към латиница, но се подразбира English
  43. // за другите езици (например Немски) важат други правила, които не са описани в закона.
  44. //
  45. // (2) Буквеното съчетание „ия“, когато е в края на думата, се изписва и предава чрез „ia“. Sofia
  46. // Чл. 6. Името на българската държава се изписва и предава на латиница в съответствие с установената // традиция: България — Bulgaria
  47. // Bulgaria Bulgarska, Bulgarski
  48.  
  49. // $table_ia/bulg изключения.
  50. // Тези 2 таблици се използват за транслитерация само след цялостен match на стринга 'ия' или 'бълг'
  51. // как точно се мачва (например накрая на думата за 'ия') се определя от самият preg_replace()
  52. // идеята на използването им е, че така може да се запази Case-а на оригиналните букви.
  53. $table_ia=array('и'=>'i',
  54. 'я'=>'a',
  55. 'И'=>'I',
  56. 'Я'=>'A');
  57.  
  58. $table_bulg=array('б'=>'b',
  59. 'ъ'=>'u',
  60. 'л'=>'l',
  61. 'г'=>'g',
  62. 'Б'=>'B',
  63. 'Ъ'=>'U',
  64. 'Л'=>'L',
  65. 'Г'=>'G');
  66.  
  67. $en =  array('A', 'a',
  68. 'B', 'b',
  69. 'V', 'v',
  70. 'G', 'g',
  71. 'D', 'd',
  72. 'E', 'e',
  73. 'Zh','zh',
  74. 'Z', 'z',
  75. 'I', 'i',
  76. 'Y', 'y',
  77. 'K', 'k',
  78. 'L', 'l',
  79. 'M', 'm',
  80. 'N', 'n',
  81. 'O', 'o',
  82. 'P', 'p',
  83. 'R', 'r',
  84. 'S', 's',
  85. 'T', 't',
  86. 'U', 'u',
  87. 'F', 'f',
  88. 'H', 'h',
  89. 'Ts','ts',
  90. 'Ch','ch',
  91. 'Sh','sh',
  92. 'Sht','sht',
  93. 'A', 'a',
  94. 'Y', 'y',
  95. 'Yu','yu',
  96. 'Ya','ya');
  97.  
  98.  
  99. // http://de.wikipedia.org/wiki/Kyrillisches_Alphabet#Bulgarisch
  100. // но: България — Bulgaria
  101. // правилото за ия (ia) се запазва в края на думата
  102. $de =  array('A', 'a',
  103. 'B', 'b',
  104. 'W', 'w',
  105. 'G', 'g',
  106. 'D', 'd',
  107. 'E', 'e',
  108. 'Sch','sch',
  109. 'S', 's',
  110. 'I', 'i',
  111. 'J', 'j',
  112. 'K', 'k',
  113. 'L', 'l',
  114. 'M', 'm',
  115. 'N', 'n',
  116. 'O', 'o',
  117. 'P', 'p',
  118. 'R', 'r',
  119. 'S', 's',
  120. 'T', 't',
  121. 'U', 'u',
  122. 'F', 'f',
  123. 'Ch', 'ch',
  124. 'Z','z',
  125. 'Tsch','tsch',
  126. 'Sch','sch',
  127. 'Scht','scht',
  128. 'A', 'a',
  129. 'J', 'j',
  130. 'Ju','ju',
  131. 'Ja','ja');
  132. ?>


Титла: Re: обръщане на масив в PHP
Публикувано от: Naka в Feb 14, 2011, 14:50
Код
GeSHi (PHP):
  1. require "transliteration.php";
  2. // твърди параметри за експорт;
  3. $GLOBALS['bg']=$bg;
  4. $GLOBALS['table_ia']=$table_ia;
  5. $GLOBALS['table_bulg']= $table_bulg;
  6.  
  7. function mb_is_upper($str)
  8. {
  9. // препинателните знаци, шпация, '', и край на реда
  10. // се третират като главни букви и за тях тази функция връща 'true'
  11. $upper = mb_strtoupper($str,'UTF-8');
  12.  
  13. return $str === $upper;
  14. }
  15.  
  16. /*
  17. function ia_function($matches)
  18. {
  19. // as usual: $matches[0] is the complete match
  20. // $matches[1] the match for the first subpattern
  21. //
  22. // за достъп към елемент от стринга не може да се използва формата $str[1] - работи само за ASCII
  23. // не може да се използва и substr() - работи само за ASCII
  24.  
  25. $str=$matches[0];
  26. // print '|'.mb_substr($str,0,1,'UTF-8').mb_is_upper(mb_substr($str,0,1,'UTF-8')).'|';
  27.  
  28. if (mb_is_upper(mb_substr($str,0,1,'UTF-8'))) $ret='I'; else  $ret='i';
  29. if (mb_is_upper(mb_substr($str,1,1,'UTF-8'))) $ret.='A'; else  $ret.='a';
  30.  
  31. return $ret;
  32. }
  33.  
  34. function bulg_function($matches)
  35. {
  36. // Тази функция предполага че всички замествания на 'бълг' се състоят от по 1-ин символ
  37. // например за всички езици Ъ->1символ(А); Следствие на това е,
  38. // че не нужна проверка за следващият символ за запазване на 'casе'-а, както се прави в replace_function()
  39. // global $bg, $target;
  40.  
  41. $S1=$matches[1]; // 'бълг'
  42.  
  43. // print $S1;
  44.  
  45. if (mb_is_upper(mb_substr($S1,0,1,'UTF-8'))) $ret='B'; else  $ret='b';
  46. if (mb_is_upper(mb_substr($S1,1,1,'UTF-8'))) $ret.='U'; else  $ret.='u';
  47. if (mb_is_upper(mb_substr($S1,2,1,'UTF-8'))) $ret.='L'; else  $ret.='l';
  48. if (mb_is_upper(mb_substr($S1,3,1,'UTF-8'))) $ret.='G'; else  $ret.='g';
  49.  
  50. return $ret;
  51. }
  52. */
  53.  
  54. function ia_function($matches)
  55. {
  56. // as usual: $matches[0] is the complete match
  57. // $matches[1] the match for the first subpattern
  58. //
  59. // за достъп към елемент от стринга не може да се използва формата $str[1] - работи само за ASCII
  60. // не може да се използва и substr() - работи само за ASCII
  61. global $table_ia;
  62.  
  63. $S1=$matches[1];
  64.  
  65. $ST=strtr($S1,$table_ia);
  66.  
  67. return $ST;
  68. }
  69.  
  70. function bulg_function($matches)
  71. {
  72. // Тази функция предполага че всички замествания на 'бълг' се състоят от по 1-ин символ
  73. // например за всички езици Ъ->1символ(А); Следствие на това е,
  74. // че не нужна проверка за следващият символ за запазване на 'casе'-а, както се прави в replace_function()
  75. global $table_bulg;
  76.  
  77. $S1=$matches[1]; // 'бълг'
  78.  
  79. // print '|'.$S1;
  80. // 0.43 сек. (10000 цикъла) strtr($S1,$table);
  81. // 0.70 сек. (10000 цикъла) str_replace()
  82. // 1.42 сек. (10000 цикъла) 8 броя $str=preg_replace('/б/u', 'b', $S1);
  83. // 2.62 сек. (10000 цикъла) 4 броя проверки (mb_is_upper(mb_substr($S1,0,1,'UTF-8'))) $ret='B'; else  $ret='b';
  84. // 5 сек.    (10000 цикъла) най-бавно чрез цикъл и търсене в масива $bg, $target
  85.  
  86. $ST=strtr($S1,$table_bulg);
  87.  
  88. return $ST;
  89. }
  90.  
  91.  
  92. function replace_function($matches)
  93. {
  94. global $bg, $target;
  95.  
  96. $S1=$matches[1];
  97. $S2=$matches[2];
  98. //print '|'.$S1.$S2.'|';
  99.  
  100. // ако не е намерен символа в бг таблицата връща самият символ например:ы
  101. if ( ($key = array_search($S1, $bg)) === FALSE ) return $S1;
  102.  
  103. $ST=$target[$key];
  104.  
  105. // print '['.$S1.']'.($key & 1);
  106. // print '['.$S1.']'.mb_strlen($ST,'UTF-8');
  107.  
  108. // бърза проверка за главна буква: $key(четно 0,2,4)-главна;   $key(нечетно 1,3,5)-малка;
  109. // проверка за четност
  110. // ($key & 1) - 1 нечетно; 0 четно;
  111.  
  112. // ЖРЕБЧЕВО->ZhREBChEVO
  113. //         ->ZH...CH...
  114. // Ако текущият заместван символ е главна буква (и заместващият я стринг е с повече от 2 букви)
  115. // И следващият символ е главна буква то целият заместващ я стринг се капитализира Zh->ZH
  116. // проверката за mb_strlen($ST,'UTF-8')>1 се предодврати ненужното извикване на mb_is_upper($S2)
  117. if ( (!($key & 1) AND mb_strlen($ST,'UTF-8')>1) AND mb_is_upper($S2)) return mb_strtoupper($ST,'UTF-8');
  118.  
  119. return $ST;
  120. }
  121.  
  122.  
  123. function transliterate($cyrstr, $lang, $STRICT_CASE=true)
  124. {
  125. // връща транслителиран стринг към съответният език
  126. // транслитерационните масиви трябва да се заредени предварително.
  127.  
  128. // STRICT_CASE задава дали да се запазват case-а на буквите както е при оригиналния текст
  129. // STRICT_CASE = true Запазва се case-а
  130. // STRICT_CASE = false Не се запазва case-а. Всичко се конвертира към малки букви
  131. // и накрая се капитализира първата буква на всяка дума.
  132.  
  133. // STRICT_CASE == true е 6 пъти по-бавен от без STRICT_CASE
  134. // 6.4 сек. (10000 цикъла) transliterate('жжжжжж', 'en', false);
  135. // 35  сек. (10000 цикъла) transliterate('жжжжжж', 'en', true);
  136.  
  137. $target=$GLOBALS[$lang];
  138. // това е нужно за _callback функциите
  139. $GLOBALS['target']=$target;
  140.  
  141. // pcretest -C
  142. //
  143. // https://bugzilla.redhat.com/show_bug.cgi?id=457064
  144. // http://gaarai.com/2009/01/31/unicode-support-on-centos-52-with-php-and-pcre/
  145. // http://bugs.centos.org/view.php?id=3252
  146. //
  147. // Compilation failed: PCRE does not support \L, \l, \N, \U, or \u
  148. // трябва пакета да се прекомпилира със %configure --enable-utf8 --enable-unicode-properties
  149. //  --enable-utf8 е зададено в src.rpm но --enable-unicode-properties не е
  150.  
  151. setlocale(LC_CTYPE,'bg_BG.utf8');
  152.  
  153. // документация
  154. // http://www.pcre.org/pcre.txt
  155. // \b matches a word boundary (only ASCII letters recognized - all with values less than 256 )
  156. // \p{Cyrillic} -- match Cyrillic letter
  157. // \P{Cyrillic} -- match NON Cyrillic letter
  158. // \p{L} letter
  159. // \p{Ll} Lower case letter
  160. // \p{Lu} Upper case letter
  161.  
  162.  
  163. if ($STRICT_CASE)
  164. {
  165. // !!! за да работи правилно case-insensitive трябва да има задължително u за модификатор /xxx/ui
  166. // [^a-zA-Zа-яА-Я0-9]|$ маркира край на думата - всеки не буквен знак или край на стринга $
  167. //$str=preg_replace('/ия(?=[^a-zA-Zа-яА-Я0-9]|$)/ui', 'ia', $cyrstr);
  168.  
  169. // Заменя ия->ia в края на думите като запазва малките и големите букви в оригиналния текст
  170. $str=preg_replace_callback('/(ия)(?=[^a-zA-Zа-яА-Я0-9]|$)/ui', 'ia_function', $cyrstr);
  171.  
  172. // етнонима 'бълг' - незвисимо къде е се транслителира като 'bulg', частен случай е България-Bulgaria
  173. $str=preg_replace_callback('/(бълг)/ui', 'bulg_function', $str);
  174.  
  175. // ВАЖНО! (?=.?) е Lookahead assertion за всякакъв символ .? 0 или 1 път.
  176. // Въпреки че целият израз е в скоби той не се захваща и не може да се използва като $2
  177. // Но когато патъна вътре в Lookahead израза е обграден в скоби (?=(.?)) той се захваща като $2
  178. // Като при това целият израз си остава Lookahead, без да оказва влияние на целият патън
  179. // това е захващане на 1 пореден Кирилски символ $1 + инфо за следващият символ в $2 (какъвто и да е той)
  180. // /(\p{Cyrillic})(.?)/ - това по същият начин захваща $1 и $2 но скача на +2 знака при следващият цикъл
  181. // докато комбинацията с Lookahead скача на +1 - т.е. обхожда всеки пореден знак
  182. $str=preg_replace_callback('/(\p{Cyrillic})(?=(.?))/u', 'replace_function', $str);
  183.  
  184. }
  185. else
  186. {
  187. $str=preg_replace('/(ия)(?=[^a-zA-Zа-яА-Я0-9]|$)/ui', 'ia', $cyrstr);
  188. $str=preg_replace('/(бълг)/ui', 'bulg', $str);
  189. $str=str_replace($GLOBALS['bg'], $target, $str);
  190. $str=mb_convert_case($str, MB_CASE_TITLE, "UTF-8");
  191. }
  192.  
  193. return $str;
  194. }

Мисля че това е всичко.
първо трябва да заредиш масивите. transliterate.php

и след това:
transliterate('Това е само пример, София, България', 'en', false);

ако $STRICT_CASE==false игнорира спазването на всички малки и големи букви и работи много бързо. Ако обаче $STRICT_CASE==true работи много бавно щото гледа малките и големите букви да съвпадат точно и в транслителираният стринг.
Например: въведен стринг тип хакерско писане:
transliterate('ЖрЕбЧеВо', 'en', true);
ще го транслителира правилно така
ZhRеBchEvO ;D

общо взето транслитерацията (при не спазване на CASE-a) се извършва само от това:

Код
GeSHi (PHP):
  1. {
  2. $str=preg_replace('/(ия)(?=[^a-zA-Zа-яА-Я0-9]|$)/ui', 'ia', $cyrstr);
  3. $str=preg_replace('/(бълг)/ui', 'bulg', $str);
  4. $str=str_replace($GLOBALS['bg'], $target, $str);
  5. $str=mb_convert_case($str, MB_CASE_TITLE, "UTF-8");
  6. }

ако успееш да оправиш кодировките и locale-тата всичко би трябвало да работи. Не мога да се сетя входящият стринг transliterate($cyrstr  ..... дали беше в cp1251 или в utf-8





Титла: Re: обръщане на масив в PHP
Публикувано от: ivo3d в Feb 14, 2011, 15:30
А това не е ли само от кирилица към латиница?

Аз едно време бях правил един клас, който транслитерира кирилски низ към всичките възможни изписвания на латиница (примерно "живея" - zhiveq, jiveq, zhiweq, jiveq, zhiveya, jiveya и .т.н. да не ги изреждам всичките). Върши работа при търсене, ама за твоя случай мисля че няма да може да помогне. Общо взето от кирилица към латиница е лесно, но обратното няма да стане без някакви предварително въведени граматически правила.


Титла: Re: обръщане на масив в PHP
Публикувано от: VladSun в Feb 14, 2011, 15:32
обратното няма да стане без някакви предварително въведени граматически правила.

То да беше само граматика - "лесно" :) Ама е и лексика.

Горе-долу - правим търсене в правописния речник за всички думи съдържащи "проблемни" конфигурации на буквите, прилагаме граматиката към тях и получаваме речник на думите с различно транслитериране от това в алгоритъма. Би трябвало да се огледаме и за "транслитераторни омоними" - прим. "схат" и "шат" (имагинерни)


Титла: Re: обръщане на масив в PHP
Публикувано от: Naka в Feb 14, 2011, 15:37
Общо взето от кирилица към латиница е лесно, но обратното няма да стане без някакви предварително въведени граматически правила.

Обратното няма каk да стане без изкуствен интелект и разпознаване на реч --- щото се губи информация още при правото преобразуване Cyr->Lat



Титла: Re: обръщане на масив в PHP
Публикувано от: nov_chovek в Feb 14, 2011, 16:40
Окей, значи заключението е, че транслитерация от латиница към кирилица е много трудно да стане. Така ли излиза?


Титла: Re: обръщане на масив в PHP
Публикувано от: edmon в Feb 14, 2011, 19:53
Не може ли просто по правилата да се изготви алгоритъм!
Самата транслитерация е правило щом пише Zhrebchevo,  е ясно че в българския само първата буква е главна но няма думи с такива съгласни една до друг т.е. "зх" и явно става въпрос за "ж".
Май ... не е така както си мисля!Но не може да няма начин.
Имам предвид, че те правилата са измислени трябва само да се напише код с алгоритъм който да ги спазва!


Титла: Re: обръщане на масив в PHP
Публикувано от: nov_chovek в Feb 14, 2011, 22:59
има резон в думите ти edmon. Ако стринга се парсва първо по двойки и тройки букви и се търсят "zh", "sh", "sht" ...е ще има грешки но няма да е болка за умиране...

Едит: от друга страна пък как ще се познава "ъ" ? :)


Титла: Re: обръщане на масив в PHP
Публикувано от: neter в Feb 15, 2011, 02:32
но няма думи с такива съгласни една до друг т.е. "зх" и явно става въпрос за "ж".
иЗХод, беЗХарактерен... Т.е., всички думи, започващи с "х" и с представка "из" или "без", а те са достатъчно много. Със сигурност има и други случаи, за които не се сещам в момента.

Съвършена транслитерация от чужда азбука към основната азбука на даден език се постига само по един начин - речник с всички думи. Важи за всички езици. Описване на всички правила на даден език в кода също не е достатъчно за постигане на съвършена транслитерация - във всеки език има и изключения. Имаме късмета да ползваме азбука и език, предоставящи изписване на думите по същия начин, по който се четат, което ни позволява без речник да имаме добра транслитерация от кирилица към други азбуки. Повечето народи нямат и това :)
Така че, ако някой има желанието да създаде съвършена транслитерация, трябва да се заеме с изписването на речник. Не си губете времето в излишни главоблъсканици - ако имате нужда от транслитерация, но нямате възможност да изпишете речник, опишете основните транслитериращи символи и комбинации от символи и не се занимавайте повече - без речник транслитерацията от чужд език към български винаги ще е далеч от съвършенството ;)


Титла: Re: обръщане на масив в PHP
Публикувано от: morbid_viper в Feb 15, 2011, 11:05
Код
GeSHi (Perl):
  1. # преобразуване на латиницата в кирилица - дава добри резултати за лични имена
  2. sub lat2cyr(){
  3.        my $inStr = shift;
  4.  
  5.        $inStr =~ tr/[A-Z]/[a-z]/;
  6.        $inStr =~ s/([a-zA-Z]+)/\u$1/g;
  7.  
  8.        $inStr =~ s/mitar/митър/g;  $inStr =~ s/r[au]st/ръст/g;
  9.        $inStr =~ s/etar/етър/g;      $inStr =~ s/Kanch/Кънч/g;
  10.        $inStr =~ s/nd[ae]r/ндър/g;
  11.        $inStr =~ s/Dian/Диян/g;    $inStr =~ s/dian/диян/g;
  12.        $inStr =~ s/aria/ария/g;     $inStr =~ s/l[iy]a/лия/g;
  13.        $inStr =~ s/or[iy]a/ория/g;
  14.        $inStr =~ s/Lub/Люб/g;      $inStr =~ s/Lud/Люд/g;
  15.        $inStr =~ s/diyal/дял/g;        $inStr =~ s/sica/сица/g;
  16.        $inStr =~ s/Sia/Сия/g;
  17.        $inStr =~ s/nguel/нгел/g;       $inStr =~ s/[CZ][wv]et/Цвет/g;  
  18.        $inStr =~ s/ueorg/еорг/g;       $inStr =~ s/Can/Цан/g;
  19.        $inStr =~ s/Con/Цон/g;         $inStr =~ s/Lyd[iy]a/Лидия/g;
  20.        $inStr =~ s/S[yi]lv[yi]a/Силвия/g;      $inStr =~ s/Theo/Тео/g;
  21.        $inStr =~ s/Chris/Хрис/g;
  22.  
  23.        $inStr =~ s/[YJ]o?u/Ю/g;    $inStr =~ s/[yj]o?u/ю/g;
  24.        $inStr =~ s/[YJ]o/Йо/g;     $inStr =~ s/([iaoue])[yj]o/$1йо/g;
  25.        $inStr =~ s/[yj]o/ьо/g;
  26.        $inStr =~ s/[YI]a/Я/g;      $inStr =~ s/[yi]a/я/g;
  27.        $inStr =~ s/Sht/Щ/g;        $inStr =~ s/sht/щ/g;
  28.        $inStr =~ s/Sh/Ш/g;         $inStr =~ s/sh/ш/g;
  29.        $inStr =~ s/Ch/Ч/g;         $inStr =~ s/[Tt]?ch/ч/g;
  30.        $inStr =~ s/T[sz]/Ц/g;      $inStr =~ s/t[sz]/ц/g;
  31.        $inStr =~ s/Zh|J/Ж/g;       $inStr =~ s/zh|j/ж/g;
  32.        $inStr =~ s/Ou/У/g;         $inStr =~ s/ou/у/g;
  33.        $inStr =~ s/ss/с/g;         $inStr =~ s/off/ов/g;
  34.        $inStr =~ s/x/кс/g;
  35.  
  36. # след като сме пообработили доста изключения да обърнем по-голямото
  37. # количество буквил
  38. # долната команда това очевидно трябва да е на един ред!!!!
  39.        $inStr =~ tr/[ABVGDEZIKLMNOPRSTUFHabvgdeziklmnoprstufhQqWwCcy]
  40. /[АБВГДЕЗИКЛМНОПРСТУФХабвгдезиклмнопрстуфхЯяВвКкй]/;
  41.  
  42.        return $inStr;
  43. };
  44. sub cyr2lat(){
  45.        my $inStr = shift;
  46.  
  47.        # правим всички главни букви малки
  48.        $inStr =~ tr/[А-ЯA-Z]/[а-яa-z]/;
  49.        # правим голяма първата буква на всяка дума
  50.        $inStr =~ s/([a-zA-Z]+)/\u$1/g;
  51.  
  52.        $inStr =~ s/ългария/ulgaria/g;
  53.        $inStr =~ s/ия([^а-я])/ia$1/g;
  54.  
  55.        $inStr =~ s/Ю/Yu/g;    $inStr =~ s/ю/yu/g;
  56.        $inStr =~ s/Йо/Yo/g;   $inStr =~ s/[йь]о/yo/g;
  57.        $inStr =~ s/Я/Ya/g;    $inStr =~ s/я/ya/g;
  58.        $inStr =~ s/Щ/Sht/g;   $inStr =~ s/щ/sht/g;
  59.        $inStr =~ s/Ш/Sh/g;    $inStr =~ s/ш/sh/g;
  60.        $inStr =~ s/Ч/Ch/g;    $inStr =~ s/ч/ch/g;
  61.        $inStr =~ s/Ц/Ts/g;    $inStr =~ s/ц/ts/g;
  62.        $inStr =~ s/Ж/Zh/g;    $inStr =~ s/ж/zh/g;
  63.        $inStr =~ s/[Ьь]//g;
  64.  
  65.        $inStr =~ tr/[абвгдезийклмнопрстуфхъ]/[abvgdeziyklmnoprstufha]/;
  66.  
  67.        return $inStr;
  68. };
  69.  

ето и моят принос към делото… това съм го писал за една системка, която се обръщат главно лични имена
кодът е на Perl, но ако на някой му трябва лесно ще може да го обърне в РНР
изключенията съм ги правил на прилично голям корпус, но разбира се, не може да се разчита, че на 100% ще е коректно… все пак точността, която съм постигнал съм счел за достатъчна


Титла: Re: обръщане на масив в PHP
Публикувано от: morbid_viper в Feb 15, 2011, 11:32
Съвършена транслитерация от чужда азбука към основната азбука на даден език се постига само по един начин - речник с всички думи. Важи за всички езици. Описване на всички правила на даден език в кода също не е достатъчно за постигане на съвършена транслитерация - във всеки език има и изключения.
съвършена транслитерация няма! речниковото обработване има доста недостатъци и дори не решава проблема, който ти си мислиш. така например за една дума може да има няколко транлитерации и трябва да се вкарва отделно логика да се решава коя дума е по-най-вярна. да не говорим, че речникът трябва да се поддържа актуален и чист от боклуци. също така заема значително повече памет и за големи езикови множества си е тегавиня…
умните хора са измислили и други инструменти, като речник също се използва, но в една нехомогенна система и по-скоро за обслужване на изключенията.

Не си губете времето в излишни главоблъсканици - ако имате нужда от транслитерация, но нямате възможност да изпишете речник, опишете основните транслитериращи символи и комбинации от символи и не се занимавайте повече - без речник транслитерацията от чужд език към български винаги ще е далеч от съвършенството ;)
винаги ще е далеч, но поне могат да се направят няколко крачки напред. така или иначе драскачите на шльокавица си списват както им дойде наум всичко, за което ги мразя, мразя… мразя-я-я-я-я-я…


Титла: Re: обръщане на масив в PHP
Публикувано от: Naka в Feb 15, 2011, 12:02
Има още изключения:
4 -> Ч
6 -> Ш  ;D ;D ;D

За какво изобщо ви е небходима обратната транслитерация?

Айде правата има смисъл за да се предостави текст (не превод - а само имена) на чужденец който той ще може да го прочете.

Ами обратната? Да не е за търсене? Ако е за търсачки предполагам, че се изготвя някакъв междинен звуков образ на думите и по този звуков образ се сравняват. Mysql-а имаше нещо подобно.. SpellCheck -овете работят по подобен начин (gnu aspell).

Google-a предполагам също работи по подобен 'звуков' начин, но това не оправя проблемите - по скоро съдейства за налагането на световна Шльоковизация.





Титла: Re: обръщане на масив в PHP
Публикувано от: edmon в Feb 15, 2011, 14:37
но няма думи с такива съгласни една до друг т.е. "зх" и явно става въпрос за "ж".
иЗХод, беЗХарактерен... Т.е., всички думи, започващи с "х" и с представка "из" или "без", а те са достатъчно много. Със сигурност има и други случаи, за които не се сещам в момента.

без речник транслитерацията от чужд език към български винаги ще е далеч от съвършенството ;)

Преди 7-8 години като млад ентусиаст бях сканирал и ОCR-ирал правописния речник до буква 'Й' обаче ми писна! А в последствие загубих файловте :(

П.П. Има ли ентусиасти да си разделим някое пълно издание на правописен речник на по няколко букви и да ги из-по-на-сканираме! :)


Титла: Re: обръщане на масив в PHP
Публикувано от: Naka в Feb 15, 2011, 17:07
П.П. Има ли ентусиасти да си разделим някое пълно издание на правописен речник на по няколко букви и да ги из-по-на-сканираме!

Категорично НЕ!!! Освен ако не плащат по 1 € на дума  [_]3 [_]3 [_]3


Титла: Re: обръщане на масив в PHP
Публикувано от: remotex в Feb 15, 2011, 18:26

Преди 7-8 години като млад ентусиаст бях сканирал и ОCR-ирал правописния речник до буква 'Й' обаче ми писна! А в последствие загубих файловте :(

П.П. Има ли ентусиасти да си разделим някое пълно издание на правописен речник на по няколко букви и да ги из-по-на-сканираме! :)
Може, създай нов проект за правописен речник (мисля вече имаше един.. бгофис) и съм вътре и аз.

Забележка: След бърза проверка се оказа че нямам правописен речник - имам само Правоговорен (Пашов, Първев) София 1975 г.
т.е. ..кога им изтичат  авторските права .. или някой ако ги познава тези да ги пита за разрешение. Аз лично като незапознат даже не знам кой трябва да се пита Пашов и Първев или Издателство Наука и изкуство бул. руски 6 (ако още го има)