2009-10-21 10 views
5

dado un texto de origen comoConvertir numerado a Pinyin acentuado?

nin2 hao3 ma 

(que es una forma típica de escribir ASCII Pinyin, sin caracteres acentuados adecuados) y dado un (UTF8) tabla de conversión como

a1;ā 
e1;ē 
i1;ī 
o1;ō 
u1;ū 
ü1;ǖ 
A1;Ā 
E1;Ē 
... 

¿Cómo me convertir el texto fuente en

nín hǎo ma 

?

Por lo que vale, estoy usando PHP, y esta podría ser una expresión regular que estoy buscando.

+0

información adicional para aquellos que buscan en este :! (del artículo de Wikipedia http://en.wikipedia.org/wiki/Pinyin) un algoritmo para encontrar la letra vocal correcta (cuando hay más de uno) es la siguiente: 1. Si hay una "a" o un " e "que se llevará a la marca del tono. 2. Si hay un" ou "entonces el" o "la toma tono de marca. 3. De lo contrario, la segunda vocal lleva la marca del tono. –

Respuesta

1
<?php 
$in = 'nin2 hao3 ma'; 
$out = 'nín hǎo ma'; 

function replacer($match) { 
    static $trTable = array(
    1 => array(
     'a' => 'ā', 
     'e' => 'ē', 
     'i' => 'ī', 
     'o' => 'ō', 
     'u' => 'ū', 
     'ü' => 'ǖ', 
     'A' => 'Ā', 
     'E' => 'Ē'), 
    2 => array('i' => 'í'), 
    3 => array('a' => 'ǎ') 
); 
    list(, $word, $i) = $match; 
    return str_replace(
    array_keys($trTable[$i]), 
    array_values($trTable[$i]), 
    $word); } 

// Outputs: bool(true) 
var_dump(preg_replace_callback('~(\w+)(\d+)~', 'replacer', $in) === $out); 
+0

impresionante. Gracias! –

+1

significa esto realmente toma en cuenta todos los casos? ¿qué pasa con cuarto de tono? ¿qué pasa con 'a' en segundo tono? no está allí ? algo especial con 'ou' o usted acaba de tratar de proporcionar una pieza de código que necesita ser ampliado – philfreo

+0

¿qué pasa con diptongos Ej liao3 -. ??> liǎo ¿Cómo funciona este cifra a cabo los –

9

El algoritmo de Ollie fue un buen comienzo, pero no aplicó las marcas correctamente. Por ejemplo, qiao1 se convirtió en qīāō. Este es correcto y completo. Puede ver fácilmente cómo se definen las reglas de reemplazo.

Hace todo para el tono 5 también, aunque no afecta la salida, excepto para eliminar el número. Lo dejé en, en caso de que quiera hacer algo con tono 5.

El algoritmo funciona de la siguiente manera:

  • La palabra y el tono están dentro de $ partido [1] y [2]
  • Se agrega una estrella detrás de la letra que debe obtener la marca de acento
  • Una letra con una estrella se reemplaza por esa letra con la marca de tono correcta.

Ejemplo:

qiao => (iao becomes ia*o) => qia*o => qiǎo

Esta estrategia, y el uso de strtr (que da prioridad a los reemplazos más largos), se asegura de que esto no sucederá:

qiao1 => Qiao


function pinyin_addaccents($string) { 
    # Find words with a number behind them, and replace with callback fn. 
    return preg_replace_callback(
     '~([a-zA-ZüÜ]+)(\d)~', 
     'pinyin_addaccents_cb', 
     $string); 
} 

# Helper callback 
function pinyin_addaccents_cb($match) { 
    static $accentmap = null; 

    if($accentmap === null) { 
     # Where to place the accent marks 
     $stars = 
      'a* e* i* o* u* ü* '. 
      'A* E* I* O* U* Ü* '. 
      'a*i a*o e*i ia* ia*o ie* io* iu* '. 
      'A*I A*O E*I IA* IA*O IE* IO* IU* '. 
      'o*u ua* ua*i ue* ui* uo* üe* '. 
      'O*U UA* UA*I UE* UI* UO* ÜE*'; 
     $nostars = str_replace('*', '', $stars); 

     # Build an array like Array('a' => 'a*') and store statically 
     $accentmap = array_combine(explode(' ',$nostars), explode(' ', $stars)); 
     unset($stars, $nostars); 
    } 

    static $vowels = 
     Array('a*','e*','i*','o*','u*','ü*','A*','E*','I*','O*','U*','Ü*'); 

    static $pinyin = Array(
     1 => Array('ā','ē','ī','ō','ū','ǖ','Ā','Ē','Ī','Ō','Ū','Ǖ'), 
     2 => Array('á','é','í','ó','ú','ǘ','Á','É','Í','Ó','Ú','Ǘ'), 
     3 => Array('ǎ','ě','ǐ','ǒ','ǔ','ǚ','Ǎ','Ě','Ǐ','Ǒ','Ǔ','Ǚ'), 
     4 => Array('à','è','ì','ò','ù','ǜ','À','È','Ì','Ò','Ù','Ǜ'), 
     5 => Array('a','e','i','o','u','ü','A','E','I','O','U','Ü') 
    ); 

    list(,$word,$tone) = $match; 
    # Add star to vowelcluster 
    $word = strtr($word, $accentmap); 
    # Replace starred letter with accented 
    $word = str_replace($vowels, $pinyin[$tone], $word); 
    return $word; 
} 
+0

que funciona muy bien ?! ! gracias tanto tengo el siguiente problema sin embargo: el 'ǖ' están escritos como este en mis datos: 'lu: 4'? ¿Cómo puedo integrar que aquí – uncovery

+0

me ayudó a mí ahora por addind '$ string = str_replace (array ('u:', 'T:'), array ('U', 'U'), $ cadena); 'before' volver preg_replace_callback ( ! ' – uncovery

+0

Esto es muy bueno, gracias – Jen

1

Para una solución .NET prueba Pinyin4j.NET

Características Convierte chino (tanto simplificado como tradicional) a los sistemas de pinyin más populares. El sistema de soporte de pinyin se enumera a continuación.

  • Hanyu Pinyin Pinyin
  • Tongyong Pinyin TongYongPinYin
  • Wade-Giles Pinyin Wade
  • MPS2 (símbolos fonéticos del mandarín II) Símbolos fonéticos del mandarín II
  • Yale Romanization Yale Roma de Pinyin
  • Gwoyeu Romatzyh mandarín mandarín Pinyin romanización
0

VB Macro Oficina (Libre) :. Convert pinyin tone numbers to accents

Esperamos que el algoritmo es correcto de acuerdo a las reglas pinyin especialmente para iyu

sub replaceNumberByTones 

    call PinyinTonesNumber("a([a-z]*[a-z]*)0", "a$1") 
    call PinyinTonesNumber("a([a-z]*[a-z]*)1", "a$1") 
    call PinyinTonesNumber("a([a-z]*[a-z]*)2", "á$1") 
    call PinyinTonesNumber("a([a-z]*[a-z]*)3", "a$1") 
    call PinyinTonesNumber("a([a-z]*[a-z]*)4", "à$1") 

    call PinyinTonesNumber("o([a-z]*[a-z]*)0", "o$1") 
    call PinyinTonesNumber("o([a-z]*[a-z]*)1", "o$1") 
    call PinyinTonesNumber("o([a-z]*[a-z]*)2", "ó$1") 
    call PinyinTonesNumber("o([a-z]*[a-z]*)3", "o$1") 
    call PinyinTonesNumber("o([a-z]*[a-z]*)4", "ò$1") 

    call PinyinTonesNumber("e([a-z]*[a-z]*)0", "e$1") 
    call PinyinTonesNumber("e([a-z]*[a-z]*)1", "e$1") 
    call PinyinTonesNumber("e([a-z]*[a-z]*)2", "é$1") 
    call PinyinTonesNumber("e([a-z]*[a-z]*)3", "e$1") 
    call PinyinTonesNumber("e([a-z]*[a-z]*)4", "è$1") 

    call PinyinTonesNumber("u([a-hj-z]*[a-hj-z]*)0", "u$1") 
    call PinyinTonesNumber("u([a-hj-z]*[a-hj-z]*)1", "u$1") 
    call PinyinTonesNumber("u([a-hj-z]*[a-hj-z]*)2", "ú$1") 
    call PinyinTonesNumber("u([a-hj-z]*[a-hj-z]*)3", "u$1") 
    call PinyinTonesNumber("u([a-hj-z]*[a-hj-z]*)4", "ù$1") 

    call PinyinTonesNumber("i([a-z]*[a-z]*)0", "i$1") 
    call PinyinTonesNumber("i([a-z]*[a-z]*)1", "i$1") 
    call PinyinTonesNumber("i([a-z]*[a-z]*)2", "í$1") 
    call PinyinTonesNumber("i([a-z]*[a-z]*)3", "i$1") 
    call PinyinTonesNumber("i([a-z]*[a-z]*)4", "ì$1") 

    End sub 

    sub PinyinTonesNumber(expression, replacement) 
    rem ---------------------------------------------------------------------- 
    rem define variables 
    dim document as object 
    dim dispatcher as object 
    rem ---------------------------------------------------------------------- 
    rem get access to the document 
    document = ThisComponent.CurrentController.Frame 
    dispatcher = createUnoService("com.sun.star.frame.DispatchHelper") 

    rem ---------------------------------------------------------------------- 
    dim args1(18) as new com.sun.star.beans.PropertyValue 
    args1(0).Name = "SearchItem.StyleFamily" 
    args1(0).Value = 2 
    args1(1).Name = "SearchItem.CellType" 
    args1(1).Value = 0 
    args1(2).Name = "SearchItem.RowDirection" 
    args1(2).Value = true 
    args1(3).Name = "SearchItem.AllTables" 
    args1(3).Value = false 
    args1(4).Name = "SearchItem.Backward" 
    args1(4).Value = false 
    args1(5).Name = "SearchItem.Pattern" 
    args1(5).Value = false 
    args1(6).Name = "SearchItem.Content" 
    args1(6).Value = false 
    args1(7).Name = "SearchItem.AsianOptions" 
    args1(7).Value = false 
    args1(8).Name = "SearchItem.AlgorithmType" 
    args1(8).Value = 1 
    args1(9).Name = "SearchItem.SearchFlags" 
    args1(9).Value = 65536 
    args1(10).Name = "SearchItem.SearchString" 
    args1(10).Value = expression 
    args1(11).Name = "SearchItem.ReplaceString" 
    args1(11).Value = replacement 
    args1(12).Name = "SearchItem.Locale" 
    args1(12).Value = 255 
    args1(13).Name = "SearchItem.ChangedChars" 
    args1(13).Value = 2 
    args1(14).Name = "SearchItem.DeletedChars" 
    args1(14).Value = 2 
    args1(15).Name = "SearchItem.InsertedChars" 
    args1(15).Value = 2 
    args1(16).Name = "SearchItem.TransliterateFlags" 
    args1(16).Value = 1280 
    args1(17).Name = "SearchItem.Command" 
    args1(17).Value = 3 
    args1(18).Name = "Quiet" 
    args1(18).Value = true 

    dispatcher.executeDispatch(document, ".uno:ExecuteSearch", "", 0, args1()) 


    end sub 

Espero que esto ayude a alguien

François

1

para añadir una solución javascript:

Este código coloca Ton . EMarks acuerdo con el algoritmo oficial para colocar uno, ver wikipedia

la esperanza de que ayude a algunos de ustedes, sugerencias y mejoras Wellcome

var ACCENTED = { 
      '1': {'a': '\u0101', 'e': '\u0113', 'i': '\u012B', 'o': '\u014D', 'u': '\u016B', 'ü': '\u01D6'}, 
      '2': {'a': '\u00E1', 'e': '\u00E9', 'i': '\u00ED', 'o': '\u00F3', 'u': '\u00FA', 'ü': '\u01D8'}, 
      '3': {'a': '\u01CE', 'e': '\u011B', 'i': '\u01D0', 'o': '\u01D2', 'u': '\u01D4', 'ü': '\u01DA'}, 
      '4': {'a': '\u00E0', 'e': '\u00E8', 'i': '\u00EC', 'o': '\u00F2', 'u': '\u00F9', 'ü': '\u01DC'}, 
      '5': {'a': 'a', 'e': 'e', 'i': 'i', 'o': 'o', 'u': 'u', 'ü': 'ü'} 
    }; 

    function getPos (token) { 
      if (token.length === 1){ 
       // only one letter, nothing to differentiate 
       return 0; 
      } 
      var precedence = ['a', 'e', 'o']; 
      for (i=0; i<precedence.length; i += 1){ 
       var pos = token.indexOf(precedence[i]); 
       // checking a before o, will take care of ao automatically 
       if (pos >= 0){ 
        return pos; 
       } 
      } 
      var u = token.indexOf('u'); 
      var i = token.indexOf('i'); 
      if (i < u){ 
       // -iu OR u-only case, accent goes to u 
       return u; 
      } else { 
       // -ui OR i-only case, accent goes to i 
       return i; 
      } 
      // the only vowel left is ü 
      var ü = token.indexOf('ü'); 
      if (ü >= 0){ 
       return ü; 
      } 
     } 

    //and finally: 
    // we asume the input to be valid PinYin, therefore no security checks.... 
    function placeTone(numbered_PinYin){ 
       var ToneIndex = numbered_PinYin.charAt(numbered_PinYin.length -1); 
       var accentpos = getPos(numbered_PinYin); 
       var accented_Char = ACCENTED[ToneIndex][numbered_PinYin.charAt(accentpos)]; 

       var accented_PinYin = ""; 
       if (accentpos === 0){ 
        // minus one to trimm the number off 
        accented_PinYin = accented_Char + numbered_PinYin.substr(1, numbered_PinYin.length-1); 
       } else { 
        var before = numbered_PinYin.substr(0, accentpos); 
        var after = numbered_PinYin.substring(accentpos+1, numbered_PinYin.length-1); 
        accented_PinYin = before + accented_Char + after; 
       } 
       return accented_PinYin; 
    } 

    console.log(placeTone('han4 zi4'));