Как пометить весь текст CJK в документе?

У меня есть файл, file1.txt, содержащий текст на английском, китайском, японском и корейском языках. Для использования в ConTeXt мне нужно отметить каждую область текста в файле в соответствии с языком, кроме английского, и вывести новый файл, например, вот пример строки:

The 恐龙 ate 鱼.

Поскольку он содержит текст китайскими иероглифами, он будет помечен следующим образом:

The \language[cn]{恐龙} ate \language[cn]{鱼}.
  • Документ сохраняется как UTF-8.
  • Текст на китайском должен быть помечен \language[cn]{*},
  • Текст на японском языке должен быть отмечен \language[ja]{*},
  • Текст на корейском языке должен быть отмечен \language[ko]{*},
  • Контент никогда не продолжается с одной строки на другую.
  • Если код когда-либо сомневается в том, является ли что-то китайским, японским или корейским, лучше всего по умолчанию использовать китайский.

Как я могу пометить текст в соответствии с языком присутствующего?

3 ответа

Грубый алгоритм:

use 5.014;
use utf8;
while (<DATA>) {
    s
        {(\p{Hangul}+)}
        {\\language[ko]{$1}}g;
    s
        {(\p{Hani}+)}
        {\\language[zh]{$1}}g;
    s
        {(\p{Hiragana}+|\p{Katakana}+)}
        {\\language[ja]{$1}}g;
    say;
}

__DATA__
The 恐龙 ate 鱼.
The 恐竜 ate 魚.
The キョウリュウ ate うお.
The 공룡 ate 물고기.

(Также см. Обнаружение китайских символов с помощью Perl?)

Есть проблемы с этим. Daenyth комментирует, что, например, 恐竜 ошибочно идентифицируется как китайский. Я считаю маловероятным, что вы действительно работаете со смешанным английским-CJK и просто даете пример плохого текста. Сначала проведите лексический анализ, чтобы отличить китайский от японского.

Я хотел бы предоставить решение Python. Независимо от того, какой язык, он основан на информации сценария Unicode (из базы данных Unicode, также известный как UCD). У Perl довольно подробный UCD по сравнению с Python.
У Python нет информации о скриптах, открытых в его модуле "unicodedata". Но кто-то добавил его здесь https://gist.github.com/2204527 (крошечный и полезный). Моя реализация основана на этом. Кстати, он не чувствителен к пространству (нет необходимости в каком-либо лексическом анализе).

    # coding=utf8
    import unicodedata2
    text=u"""The恐龙ate鱼.
    The 恐竜ate 魚.
    Theキョウリュウ ate うお.
    The공룡 ate 물고기. """

    langs = {
    'Han':'cn',
    'Katakana':'ja',
    'Hiragana':'ja',
    'Hangul':'ko'
    }

    alist = [(x,unicodedata2.script_cat(x)[0]) for x in text]
    # Add Last
    alist.append(("",""))
    newlist = []
    langlist = []
    prevlang = ""
    for raw, lang in alist:
        if prevlang in langs and prevlang != lang:
            newlist.append("\language[%s]{" % langs[prevlang] +"".join(langlist) + "}")
            langlist = []

        if lang not in langs:
            newlist.append(raw)
        else:                      
            langlist.append(raw)
        prevlang = lang

    newtext = "".join(newlist)
    print newtext

Выход:

    $ python test.py 
    The\language[cn]{恐龙}ate\language[cn]{鱼}.
    The \language[cn]{恐竜}ate \language[cn]{魚}.
    The\language[ja]{キョウリュウ} ate \language[ja]{うお}.
    The\language[ko]{공룡} ate \language[ko]{물고기}.

В то время как корейский язык больше не использует много синограмм [an / кандзи], они иногда всплывают. Некоторые японские синограммы являются исключительно японскими, например 竜, но многие идентичны либо упрощенному китайскому, либо традиционному. Так что вы застряли. Так что вам нужно посмотреть на полное предложение, если у вас есть несколько символов "Хан". Если у этого есть немного хирагана / катакана + кандзи, вероятность очень высока, это японский язык. Кроме того, несколько слогов хангыль и пара синограмм скажут вам, что предложение на корейском языке.

Затем, если это все символы Han, то есть китайский, вы можете посмотреть, являются ли некоторые символы упрощенными: kZVariant обозначает упрощенный китайский символ. Да, и kSpecializedSemanticVariant очень часто используется для специфичных для Японии упрощенных символов. 内 и 內 могут выглядеть одинаково для вас, но первый - это японский, второй - традиционный китайский и корейский (корейский использует традиционный китайский в качестве стандарта).

У меня где-то есть код, который возвращает для одной кодовой точки имя скрипта. Это могло бы помочь. Вы проходите через предложение и видите, что осталось в конце. Я поставлю код где-нибудь.

РЕДАКТИРОВАТЬ: код

http://pastebin.com/e276zn6y

В ответ на комментарий ниже:

Приведенная выше функция построена на основе данных, предоставленных Unicode.org... Хотя я не являлся экспертом как таковой, я внес немалый вклад в базу данных Unihan - и мне случается говорить на CJK. Да, все 3. У меня есть некоторый код, который использует преимущества kXXX свойства в базе данных Unihan, но A/ I не знал, что мы должны были написать код для OP, и B/ это потребовало бы логистики, которая могла бы выходить за рамки того, что OP готов реализовать. Мой совет стоит. С помощью функции выше, переберите одно полное предложение. Если все кодовые точки "Хан"(или "Хан"+"латиница"), высоки шансы, что это китайский. Если, с другой стороны, результатом является сочетание "Хан"+"Хангул"(возможно, "латинский"), вы не ошибетесь с корейским. Аналогично, смесь "Хан" и "Катакана"/"Хирагана" у вас есть японская.

БЫСТРЫЙ ТЕСТ

Некоторый код, который будет использоваться с функцией, с которой я связан ранее.

function guessLanguage(x) {
  var results={};
  var s='';
  var i,j=x.length;
  for(i=0;i<j;i++) {
    s=scriptName(x.substr(i,1));
    if(results.hasOwnProperty(s)) {
      results[s]+=1;
    } else {
      results[s]=1;
    }
  }
  console.log(results);
  mostCount=0;
  mostName='';
  for(x in results) {
    if (results.hasOwnProperty(x)) {
      if(results[x]>mostCount) {
        mostCount=results[x];
        mostName=x;
      }
    }
  }
  return mostName;
}

Некоторые тесты:

r=guessLanguage("外人だけど、日本語をペラペラしゃべるよ!");
Object
  Common: 2
  Han: 5
  Hiragana: 9
  Katakana: 4
  __proto__: Object
"Hiragana"

r Объект содержит количество вхождений каждого скрипта. Хирагана является наиболее частым, а Хирагана + катакана -> 2/3 предложения.

r=guessLanguage("我唔知道,佢講乜話.")
Object
  Common: 2
  Han: 8
  __proto__: Object
"Han"

Очевидный случай китайцев (кантонский в данном случае).

r=guessLanguage("中國이 韓國보다 훨씬 크지만, 꼭 아름다운 나라가 아니다...");
Object
  Common: 11
  Han: 4
  Hangul: 19
  __proto__: Object
"Hangul"

Несколько ханьских персонажей и много хангул. Корейское предложение, конечно.

Другие вопросы по тегам