6 Stimmen

Nummeriert in akzentuiertes Pinyin umwandeln?

Bei einem Ausgangstext wie

nin2 hao3 ma

(dies ist eine typische Art, ASCII-Pinyin zu schreiben, ohne richtige akzentuierte Zeichen) und eine (UTF8) Konvertierungstabelle wie

a1;a
e1;e
i1;i
o1;o
u1;u
ü1;u
A1;A
E1;E
...

wie kann ich den Ausgangstext in

nín hao ma

?

Für was es wert ist, ich bin mit PHP, und dies könnte ein Regex ich bin in der Suche sein?

11voto

Bouke Versteegh Punkte 3240

Ollies Algorithmus war ein guter Anfang, aber er wendete die Markierungen nicht korrekt an. Zum Beispiel wurde qiao1 zu qiao. Dieses Beispiel ist korrekt und vollständig. Sie können leicht erkennen, wie die Ersetzungsregeln definiert sind.

Es macht das Ganze auch für Ton 5, obwohl es keinen Einfluss auf die Ausgabe hat, außer dem Löschen der Nummer. Ich habe es drin gelassen, für den Fall, dass Sie etwas mit Ton 5 machen wollen.

Der Algorithmus funktioniert wie folgt:

  • Das Wort und der Ton werden in $match[1] und [2] angegeben.
  • Hinter dem Buchstaben, der das Akzentzeichen erhalten soll, wird ein Stern hinzugefügt
  • Ein Buchstabe mit einem Stern wird durch den Buchstaben mit der richtigen Tonmarke ersetzt.

Beispiel:

qiao => (iao becomes ia\*o) => qia\*o => qiao

Diese Strategie und der Einsatz von strtr (das längeren Ersetzungen Vorrang einräumt), sorgt dafür, dass dies nicht passiert:

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('a','e','i','o','u','u','A','E','I','O','U','U'),
        2 => Array('á','é','í','ó','ú','u','Á','É','Í','Ó','Ú','U'),
        3 => Array('a','e','i','o','u','u','A','E','I','O','U','U'),
        4 => Array('à','è','ì','ò','ù','u','À','È','Ì','Ò','Ù','U'),
        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;
}

1voto

Ollie Saunders Punkte 7237
<?php
$in = 'nin2 hao3 ma';
$out = 'nín hao ma';

function replacer($match) {
  static $trTable = array(
    1 => array(
      'a' => 'a',
      'e' => 'e',
      'i' => 'i',
      'o' => 'o',
      'u' => 'u',
      'ü' => 'u',
      'A' => 'A',
      'E' => 'E'),
    2 => array('i' => 'í'),
    3 => array('a' => '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);

1voto

Dale Punkte 12715

Für eine .NET-Lösung versuchen Sie Pinyin4j.NET

Eigenschaften Konvertieren Sie Chinesisch (sowohl vereinfacht als auch traditionell) in die gängigsten Pinyin-Systeme. Die unterstützten Pinyin-Systeme sind unten aufgeführt.

  • Hanyu Pinyin
  • Tongyong Pinyin
  • Wade-Giles
  • MPS2 (Phonetische Symbole für Mandarin II)
  • Yale-Romanisierung
  • Gwoyeu Romatzyh

1voto

tike Punkte 2164

Um eine Javascript-Lösung hinzuzufügen:

Dieser Code platziert Tonemarks nach dem offiziellen Algorithmus für die Platzierung von Tonemarks, siehe wikipedia .

Ich hoffe, das hilft einigen von Ihnen, Vorschläge und Verbesserungen sind willkommen!

    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'));

0voto

Francois Punkte 31

VB Makro (Libre)Office : Umwandlung von Pinyin-Tonzahlen in Akzente

Hoffentlich ist der Algorithmus entsprechend den Pinyin-Regeln korrekt, insbesondere für i und u.

    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

Hoffentlich hilft das jemandem

François

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X