Difference between revisions of "Руководство по созданию новой языковой пары"

From Apertium
Jump to navigation Jump to search
 
(48 intermediate revisions by 9 users not shown)
Line 1: Line 1:
{{TOCD}}
{{TOCD}}
Руководство по созданию новой языковой пары

В этом руководстве описывается порядок создания новой языковой пары для системы машинного перевода Apertium.
В этом руководстве описывается порядок создания новой языковой пары для системы машинного перевода Apertium.
От Вас не требуются какие-либо лингвистические знания или знания по машинному переводу, кроме как способности различать части речи (отличать существительные от глаголов, например).
От вас не требуются какие-либо лингвистические знания или знания по машинному переводу, кроме как способности различать части речи (отличать существительные от глаголов, например).


==Введение==
==Введение==


Как Вы только что узнали, Apertium является системой машинного перевода. Но если быть более точным, то Apertium следует назвать не системой, а платформой машинного перевода. Он обеспечивает Вас "движком" машинного перевода (англ. "engine". Можно также перевести как "ядро", "механизм" и т.п.) и набором инструментов, с помощью которых Вы можете строить свои собственные системы машинного перевода. Единственное, что Вы должны сделать, это написать данные. На базовом уровне эти данные состоят из трёх словарей и некоторого набора правил (обеспечивающих перестановку слов и другие грамматические трансформации).
Как вы только что узнали, Apertium является системой машинного перевода. Но если быть более точным, то Apertium следует назвать не системой, а платформой машинного перевода. Он обеспечивает вас "движком" машинного перевода (англ. "engine". Можно также перевести как "ядро", "механизм" и т. п.) и набором инструментов, с помощью которых вы можете строить свои собственные системы машинного перевода. Единственное, что вы должны сделать, это написать исходные данные. На базовом уровне эти данные состоят из трёх словарей и некоторого набора правил (обеспечивающих перестановку слов и другие грамматические трансформации).


За более подробной информацией, как всё это работает, обращайтесь к веб-сайту проекта [http://apertium.sourceforge.net apertium.sourceforge.net].
За более подробной информацией, как всё это работает, обращайтесь к веб-сайту проекта [http://apertium.sourceforge.net apertium.sourceforge.net].


==Что Вам потребуется==
==Что вам потребуется==


* [[lttoolbox]] (>= 3.0.0)
* [[lttoolbox]] (>= 3.0.0)
* libxml utils (xmllint и др.)
* libxml utils (xmllint и др.)
* apertium (>= 3.0.0)
* apertium (>= 3.0.0)
* текстовый редактор (или специализированный XML-редактор, если таковой Вам больше по душе)
* текстовый редактор (или специализированный XML-редактор, если таковой вам больше по душе)


Это руководство не описывает порядок установки этих пакетов, за подробной информацией обращайтесь к разделу документации веб-сайта Apertium.
Это руководство не описывает порядок установки этих пакетов, за подробной информацией обращайтесь к разделу документации веб-сайта Apertium.
Line 22: Line 20:
==Из чего состоит языковая пара?==
==Из чего состоит языковая пара?==


Apertium представляет собой систему машинного перевода поверхностно-трансферного типа. Следовательно, в основном он имеет дело со словарями и правилами поверхностного трансфера. На практике поверхностный трансфер отличается от глубокого тем, что при нём не выполняется полный синтаксический разбор предложений, а правила, в отличии от операций на дереве синтаксического разбора, представляют собой операции с группами лексических единиц. На базовом уровне имеются три словаря:
Apertium представляет собой систему машинного перевода поверхностно-трансферного типа. Следовательно, в основном он имеет дело со словарями и правилами поверхностного трансфера. На практике поверхностный трансфер отличается от глубокого тем, что при нём не выполняется полный синтаксический разбор предложений, а правила, в отличии от операций на дереве синтаксического разбора, представляют собой операции с группами лексических единиц. Этих словарей три:
# Морфологический словарь для языка xx: он содержит информацию о словоизменении (склонении или спряжении) на языке xx. В нашем примере этот словарь будет называться так: <code>apertium-sh-en.sh.dix</code>
# Морфологический словарь для языка xx: он содержит информацию о словоизменении (склонении или спряжении) на языке xx. В нашем примере этот словарь будет называться так: <code>apertium-sh-en.sh.dix</code>
# Морфологический словарь для языка yy: он, в свою очередь, содержит информацию о словоизменении (склонении или спряжении) на языке yy. В нашем примере он имеет следующее название: <code>apertium-sh-en.en.dix</code>
# Морфологический словарь для языка yy: он, в свою очередь, содержит информацию о словоизменении (склонении или спряжении) на языке yy. В нашем примере он имеет следующее название: <code>apertium-sh-en.en.dix</code>
# Двуязычный словарь: содержит переводные соответствия слов и символов двух языков. Он будет называться так: <code>apertium-sh-en.sh-en.dix</code>
# Двуязычный словарь: содержит переводные соответствия слов и символов двух языков. Он будет называться так: <code>apertium-sh-en.sh-en.dix</code>


В языковой паре любой из языков, составляющих эту пару, может быть как входным, так и выходным языком, т.е. эти термины употребляются условно.
В языковой паре любой из языков, составляющих эту пару, может быть как входным, так и выходным языком, т.&nbsp;е. эти термины употребляются условно.


Составляющими языковую пару являются также два файла с правилами трансфера. Это правила, которые управляют перестановкой слов в предложениях, например chat noir -> cat black -> black cat. Также эти правила обеспечивают в предложении согласование рода, числа и т.д. Они же могут использоваться и для вставки или удаления лексических единиц, как это будет описано ниже. Это следующие файлы:
Составляющими языковую пару являются также два файла с правилами трансфера. Это правила, которые управляют перестановкой слов в предложениях, например chat noir -> cat black -> black cat. Также эти правила обеспечивают в предложении согласование рода, числа и т.&nbsp;д. Они же могут использоваться и для вставки или удаления лексических единиц, как это будет описано ниже. Это следующие файлы:


* правила трансфера языка xx на язык yy: эти правила описывают, каким изменениям подвергнутся предложения языка xx при переводе на язык yy. В нашем примере это следующий файл: <code>apertium-sh-en.sh-en.t1x</code>
* правила трансфера языка xx на язык yy: эти правила описывают, каким изменениям подвергнутся предложения языка xx при переводе на язык yy. В нашем примере это следующий файл: <code>apertium-sh-en.sh-en.t1x</code>
Line 38: Line 36:
==Языковая пара==
==Языковая пара==


Как уже можно было догадаться по названиям файлов, для описания порядка создания базовой системы в этом руководстве будут использоваться примеры перевода с сербско-хорватского на английский язык. Заметим, что это не идеальная пара, так как система работает лучше с родственными языками. Однако в случае простых примеров, приводимых здесь, это не должно приводить к каким-либо проблемам.
Как уже можно было догадаться по названиям файлов, для описания порядка создания базовой системы в этом руководстве будут использоваться примеры перевода с сербохорватского на английский язык. Заметим, что это не идеальная пара, так как система работает лучше с родственными языками. Однако в случае простых примеров, приводимых здесь, мы не столкнёмся с какими-либо проблемами.


==Краткое замечание о терминах==
==Краткое замечание о терминах==
Line 44: Line 42:
Перед тем как продолжить, следует пояснить значение некоторых терминов.
Перед тем как продолжить, следует пояснить значение некоторых терминов.


Первый из них это ''лемма''. Лемма — это каноническая форма слова, слово без грамматической информации. Например, леммой слова ''cats'' является ''cat''. В английском языке лемма рассматриваемого существительного как правило совпадает с его формой единственного числа. В русском и татарском языках лемма существительного имеет вид его формы именительного падежа единственного числа. Для глаголов в английском языке лемма будет иметь вид инфинитива без ''to'' (или просто инфинитива в русском и татарском языках). Например, леммой слова ''was'' будет ''be'', также как леммой слова ''был'' будет ''быть'', или леммой слова ''булды'' будет ''булырга''.
Первым из них является ''лемма''. Лемма — это каноническая форма слова, слово без грамматической информации. Например, леммой слова ''cats'' является ''cat''. В английском языке лемма рассматриваемого существительного как правило совпадает с его формой единственного числа. В русском и татарском языках лемма существительного имеет вид его формы именительного падежа единственного числа. Для глаголов в английском языке лемма будет иметь вид инфинитива без ''to'' (или просто инфинитива в русском и татарском языках). Например, леммой слова ''was'' будет ''be'', также как леммой слова ''был'' будет ''быть'', или леммой слова ''булды'' будет ''булырга''.


Вторым термином является термин ''символ''. В контексте платформы Aperium символ означает грамматический знак. Слово ''cats'' есть существительное множественного числа, следовательно, он будет иметь символ существительного и символ множественного числа. На входе и выходе модулей Apertium`а эти символы обычно заключаются в квадратные скобки, как показано ниже:
Вторым термином является термин ''символ''. В контексте Apertium`а символ означает грамматический знак. Слово ''cats'' есть существительное множественного числа, следовательно, он будет иметь символ существительного и символ множественного числа. На входе и выходе модулей Apertium`а эти символы обычно заключаются в угловые скобки, как показано ниже:


* <code><n></code>; для существительного
* <code><n></code>; для существительного
* <code><pl></code>; для множественного числа
* <code><pl></code>; для множественного числа


Другими примерами символов являются <sg> (единственное число), <p1> (первое лицо), <pri> (настоящее время изъявительное наклонение) и др. Стоит заметить, что во многих из существующих языковых пар символы имеют вид акронимов или сокращений каталанских слов. Например, ''vbhaver'' — от ''vb'' (verb, глагол) и ''haver'' ("иметь" на каталанском). Символы определяются в тэгах <sdef> и используются в тэгах <nowiki><s></nowiki>.
Другими примерами символов являются <sg> (единственное число), <p1> (первое лицо), <pri> (настоящее время изъявительное наклонение) и др. Стоит заметить, что во многих из существующих языковых пар символы имеют вид акронимов или сокращений каталанских слов. Например, ''vbhaver'' — от ''vb'' (verb, глагол) и ''haver'' ("иметь" на каталанском). Символы определяются в тегах <sdef> и используются в тегах <nowiki><s></nowiki>.


Третьим же термином является ''парадигма''. В контексте системы Apertium парадигма является примером склонения/спряжения определённой группы слов. В морфологическом словаре леммы (см. выше) ссылаются на парадигмы, что позволяет нам показать все словоформы этих лемм без необходимости записи всех возможных окончаний.
The third word is ''paradigm''. In the context of the Apertium system, paradigm refers to an example of how a particular group of words inflect. In the morphological dictionary, lemmas (see above) are linked to paradigms that allow us to describe how a given lemma inflects without having to write out all of the endings.


Примером использования парадигмы может служить следующее. Допустим, мы хотим добавить в словарь прилагательные ''happy'' и ''lazy''. Вместо записи одинаковых окончаний:
An example of the utility of this is, if we wanted to store the two adjectives ''happy'' and ''lazy'', instead of storing two lots of the same thing:


* happy, happ (y, ier, iest)
* happy, happ (y, ier, iest)
* lazy, laz (y, ier, iest)
* lazy, laz (y, ier, iest)


мы можем записать окончания форм слова ''happy'', а потом сказать "lazy изменяется как happy", или "shy изменяется как happy", "naughty изменяется как happy", "friendly изменяется как happy" и т.&nbsp;д. В этом примере ''happy'' и будет парадигмой, моделью изменения всех остальных. Точное описание определения парадигм будет дано позже. Парадигмы определяются в тегах <pardef> и используются в тегах <par>.
We can simply store one, and then say "lazy, inflects like happy", or indeed "shy inflects like happy", "naughty inflects like happy", "friendly inflects like happy", etc. In this example, happy would be the paradigm, the model for how the others inflect. The precise description of how this is defined will be explained shortly. Paradigms are defined in <pardef> tags, and used in <par> tags.


==Начало работы==
==Getting started==
<!-- Ur yezh indezeuropek eo ar brezhoneg -->
<!-- Ur yezh indezeuropek eo ar brezhoneg -->


===Одноязычные словари===
===Monolingual dictionaries===
{{see-also|List of dictionaries|Incubator}}
{{see-also|List of dictionaries|Incubator}}
Начнём с создания нашего первого словаря входного языка. Словарь является XML-файлом. Откройте ваш текстовый редактор и наберите следующее:
Let's start by making our first source language dictionary. The dictionary is an XML file. Fire up your text editor and type the following:
<pre>
<pre>
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
Line 74: Line 72:
</dictionary>
</dictionary>
</pre>
</pre>
Так, теперь файл определяет, что мы хотим начать создание словаря. Чтобы этот файл был более полезным, мы должны добавить в него ещё несколько записей, первой из которых будет алфавит. Он определяет набор букв, которые могут использоваться в словаре для сербохорватского языка. Он выглядит как показано ниже и содержит все буквы сербохорватского алфавита:
So, the file so far defines that we want to start a dictionary. In order for it to be useful, we need to add some more entries, the first is an alphabet. This defines the set of letters that may be used in the dictionary, for Serbo-Croatian. It will look something like the following, containing all the letters of the Serbo-Croatian alphabet:
<pre>
<pre>
<alphabet>ABCČĆDDžĐEFGHIJKLLjMNNjOPRSŠTUVZŽabcčćddžđefghijklljmnnjoprsštuvzž</alphabet>
<alphabet>ABCČĆDDžĐEFGHIJKLLjMNNjOPRSŠTUVZŽabcčćddžđefghijklljmnnjoprsštuvzž</alphabet>
</pre>
</pre>


Place the alphabet below the <dictionary> tag.
Добавьте алфавит после тега <dictionary>.


Далее нам необходимо определить некоторые символы. Начнём с более простых — существительное (n) в единственном (sg) и множественном (pl) числах.
Next we need to define some symbols. Let's start off with the simple stuff, noun (n) in singular (sg) and plural (pl).
<pre>
<pre>
<sdefs>
<sdefs>
Line 89: Line 87:
</sdefs>
</sdefs>
</pre>
</pre>
Имена символов не обязательно должны быть такими краткими, их можно даже писать полностью, но так как делать это придётся много раз, есть смысл в сокращении.
The symbol names do not have to be so small, in fact, they could just be written out in full, but as you'll be typing them a lot, it makes sense to abbreviate.


К сожалению, всё не так просто — существительные в сербохорватском языке имеют не только категорию числа, но и категории рода и падежа. Однако для нашего примера мы будем предполагать, что существительное является существительным мужского рода и что он в именительном падеже (пример можно найти в конце этого документа).
Unfortunately, it isn't quite so simple, nouns in Serbo-Croatian inflect for more than just number, they also inflect for gender and case. However, we'll assume for the purposes of this example that the noun is masculine and in the nominative case (a full example may be found at the end of this document).


Следующим шагом определим раздел для парадигм,
The next thing is to define a section for the paradigms,
<pre>
<pre>
<pardefs>
<pardefs>
Line 99: Line 97:
</pardefs>
</pardefs>
</pre>
</pre>
и раздел для словаря:
and a dictionary section:
<pre>
<pre>
<section id="main" type="standard">
<section id="main" type="standard">
Line 105: Line 103:
</section>
</section>
</pre>
</pre>
Есть два вида разделов. Первый — стандартный раздел, он содержит слова, энклитики и&nbsp;т.&nbsp;д. Второй — безусловный раздел, содержащий знаки препинания и т.&nbsp;п. В нашем примере нет безусловного раздела, хотя он будет показан позднее.
There are two types of sections, the first is a standard section, that contains words, enclitics, etc. The second type is an inconditional section which typically contains punctuation, and so forth. We don't have an inconditional section here, although it will be demonstrated later.


Таким образом, наш файл будет выглядеть так:
So, our file should now look something like:
<pre>
<pre>
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
Line 124: Line 122:
</dictionary>
</dictionary>
</pre>
</pre>
Теперь у нас есть скелет словаря, и мы можем перейти к добавлению существительного. Им будет слово 'gramofon'.
Now we've got the skeleton in place, we can start by adding a noun. The noun in question will be 'gramofon' (which means 'gramophone' or 'record player').


Так как ранее определённых парадигм у нас нет, первым делом нужно определить парадигму.
The first thing we need to do, as we have no prior paradigms, is to define a paradigm.


Напомним, что мы имеем ввиду мужской род и именительный падеж. Формой единственного числа является 'gramofon', формой множественного числа — 'gramofoni'. Таким образом:
Remember, we're assuming masculine gender and nominative case. The singular form of the noun is 'gramofon', and the plural is 'gramofoni'. So:
<pre>
<pre>
<pardef n="gramofon__n">
<pardef n="gramofon__n">
Line 145: Line 143:
</pardef>
</pardef>
</pre>
</pre>
Заметьте: конструкция <l/> (эквивалент <l></l>) означает, что в единственном числе к основе ничего не присоединяется.
Note: the '<l/>' (equivalent to <l></l>) denotes that there is no extra material to be added to the stem for the singular.


Всё это может показаться довольно многословным способом описания, но для такого описания есть причины и к нему быстро привыкаешь. Вы, наверное, уже задаётесь вопросом, что означают все эти <e>, <l> и <r>?
This may seem like a rather verbose way of describing it, but there are reasons for this and it quickly becomes second nature. You're probably wondering what the <e>, <p>, <l> and <r> stand for. Well,


* e означает запись (entry). Образно это можно также назвать словарной статьёй.
* e, is for entry.
* p, is for pair.
* p означает пару (pair).
* l, is for left.
* l означает влево (left).
* r, is for right.
* r означает вправо (right).


Почему влево и вправо? Морфологические словари позднее будут скомпилированы в конечные автоматы. Их компиляция слева направо создаёт анализы слов, а справа налево — слова из анализов. Например:
Why left and right? Well, the morphological dictionaries will later be compiled into finite state machines. Compiling them left to right produces analyses from words, and from right to left produces words from analyses. For example:
<pre>
<pre>
* gramofoni (left to right) gramofon<n><pl> (analysis)
* gramofoni (слева направо) gramofon<n><pl> (анализ)
* gramofon<n><pl> (right to left) gramofoni (generation)
* gramofon<n><pl> (справа налево) gramofoni (генерирование)
</pre>
</pre>
Мы определили парадигму, теперь требуется соотнести её с леммой — gramofon. Это действие выполняется в ранее определённом разделе (section).
Now we've defined a paradigm, we need to link it to its lemma, gramofon. We put this in the section that we've defined.


Записью, которую нужно добавить в &lt;section&gt;, является следующее:
The entry to put in the <section> will look like:
<pre>
<pre>
<e lm="gramofon"><i>gramofon</i><par n="gramofon__n"/></e>
<e lm="gramofon"><i>gramofon</i><par n="gramofon__n"/></e>
</pre>
</pre>
Краткое пояснение к сокращениям:
A quick run down on the abbreviations:


* lm, is for lemma.
* lm означает лемму (lemma).
* i означает идентичность (identity). Одно и то же и при генерации, и при анализе.
* i, is for identity (the left and the right are the same).
* par, is for paradigm.
* par означает парадигму (paradigm).


Эта запись определяет лемму слова, gramofon, корень слова, gramofon, и парадигму склонения этого слова gramofon_n. Разница между леммой и корнем в том, что лемма есть "цитируемая форма" слова, в то время как корень есть часть леммы, к которой присоединяются суффиксы и окончания. Эта разница станет понятной, когда мы покажем запись с разными леммой и корнем.
This entry states the lemma of the word, gramofon, the root, gramofon and the paradigm with which it inflects gramofon__n. The difference between the lemma and the root is that the lemma is the citation form of the word, while the root is the substring of the lemma to which stems are added. This will become clearer later when we show an entry where the two are different.


Теперь мы можем проверить наш словарь. Сохраните его и вернитесь к командной строке. Первым делом мы должны скомпилировать его (с помощью lt-comp), потом мы сможем его проверить (с помощью lt-proc).
We're now ready to test the dictionary. Save it, and then return to the shell. We first need to compile it (with lt-comp), then we can test it (with lt-proc).
<pre>
<pre>
$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin
$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin
</pre>
</pre>
Что должно выдать следующее:
Should produce the output:
<pre>
<pre>
main@standard 12 12
main@standard 12 12
</pre>
</pre>
Так как мы компилировали слева направо, мы создали анализатор. Давайте создадим и генератор.
As we are compiling it left to right, we're producing an analyser. Lets make a generator too.
<pre>
<pre>
$ lt-comp rl apertium-sh-en.sh.dix sh-en.autogen.bin
$ lt-comp rl apertium-sh-en.sh.dix sh-en.autogen.bin
</pre>
</pre>
Команда должна выдать тоже самое сообщение.
At this stage, the command should produce the same output.


Теперь мы можем их протестировать. Запустите lt-proc на анализаторе.
We can now test these. Run lt-proc on the analyser.
<pre>
<pre>
$ lt-proc sh-en.automorf.bin
$ lt-proc sh-en.automorf.bin
</pre>
</pre>
Теперь проверьте — введите ''gramofoni'' (граммофоны), и посмотрите результат:
Now try it out, type in gramofoni (gramophones), and see the output:
<pre>
<pre>
^gramofoni/gramofon<n><pl>$
^gramofoni/gramofon<n><pl>$
</pre>
</pre>
Теперь сделайте то же самое для английского словаря, но замените слово ''gramofon'' английским словом ''gramophone'' и поменяйте окончание множественного числа (т.&nbsp;е. ''i'' на ''s'') А что если вы захотите использовать более правильный перевод 'record player'? Однако это мы объясним позднее.
Now, for the English dictionary, do the same thing, but substitute the English word gramophone for gramofon, and change the plural inflection. What if you want to use the more correct word 'record player'? Well, we'll explain how to do that later.


Теперь в папке у вас должно быть два файла:
You should now have two files in the directory:


* apertium-sh.sh.dix, который содержит (очень) маленький сербохорватский морфологический словарь, и
* apertium-sh-en.sh.dix which contains a (very) basic Serbo-Croatian morphological dictionary, and
* apertium-en.en.dix, который содержит (ну очень) маленький английский морфологический словарь.
* apertium-sh-en.en.dix which contains a (very) basic English morphological dictionary.


===Двуязычные словари===
===Bilingual dictionary===


Таким образом, теперь у нас есть два морфологических словаря и далее мы перейдём к двуязычному словарю. Двуязычный словарь описывает соответствия слов. Все словари имеют один и тот же формат (которой описан в DTD, dix.dtd).
So we now have two morphological dictionaries, next thing to make is the bilingual dictionary. This describes mappings between words. All dictionaries use the same format (which is specified in the DTD, dix.dtd).


Create a new file, apertium-sh-en.sh-en.dix and add the basic skeleton:
Создайте новый файл с именем apertium-sh-en.sh-en.dix и вставьте следующий "скелет" словаря:
<pre>
<pre>
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
Line 222: Line 220:
</dictionary>
</dictionary>
</pre>
</pre>
Теперь мы должны добавить запись (в &lt;section&gt;) для осуществления перевода двух слов:
Now we need to add an entry to translate between the two words. Something like:
<pre>
<pre>
<e><p><l>gramofon<s n="n"/></l><r>gramophone<s n="n"/></r></p></e>
<e><p><l>gramofon<s n="n"/></l><r>gramophone<s n="n"/></r></p></e>
</pre>
</pre>
Так как в словаре таких записей очень много, для удобочитаемости их обычно пишут в одну строку. Снова вопросы о 'l' и 'r', да? Всё довольно просто — мы компилируем слева направо для создания сербохорватско → английского словаря, и справа налево для создания английско → сербохорватского словаря.
Because there are a lot of these entries, they're typically written on one line to facilitate easier reading of the file. Again with the 'l' and 'r' right? Well, we compile it left to right to produce the Serbo-Croatian → English dictionary, and right to left to produce the English → Serbo-Croatian dictionary.


Когда всё это сделано, выполните следующие команды:
So, once this is done, run the following commands:
<pre>
<pre>
$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin
$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin
Line 239: Line 237:
$ lt-comp rl apertium-sh-en.sh-en.dix en-sh.autobil.bin
$ lt-comp rl apertium-sh-en.sh-en.dix en-sh.autobil.bin
</pre>
</pre>
To generate the morphological analysers (automorf), the morphological generators (autogen) and the word lookups (autobil), the bil is for "bilingual".
для создания морфологических анализаторов (automorf), морфологических генераторов (autogen) и поисковиков слов (autobil), слово "bil" означает "bilingual", т.&nbsp;е. "двуязычный".


===Правила трансфера===
===Transfer rules===


Теперь мы имеем два морфологических словаря и один двуязычный словарь. Всё что нам ещё нужно сделать это правила трансфера для существительных. Файлы с правилами трансфера имеют свой собственный DTD (transfer.dtd), который может быть найден в пакете Apertium. Если вам нужно написать правило трансфера, то часто имеет смысл сначала обратиться к файлам с правилами для других языковых пар, так как многие правила могут быть использованы для разных языковых пар. Или же эти правила можно использовать в модифицированном виде. Например, правило, приведённое ниже, может быть использовано для всех нуль-субъектных языков.
So, now we have two morphological dictionaries, and a bilingual dictionary. All that we need now is a transfer rule for nouns. Transfer rule files have their own DTD (transfer.dtd) which can be found in the Apertium package. If you need to implement a rule it is often a good idea to look in the rule files of other language pairs first. Many rules can be recycled/reused between languages. For example the one described below would be useful for any null-subject language.


"Скелет" файла такой же:
Start out like all the others with a basic skeleton:
<pre>
<pre>
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
Line 252: Line 250:
</transfer>
</transfer>
</pre>
</pre>
Так как мы не учитываем падежи (т.&nbsp;е. возможное изменение падежей при переводе), нам необходимо создать правило, которое просто "брало" бы грамматические символы на входе и, в свою очередь, выдавало их.
At the moment, because we're ignoring case, we just need to make a rule that takes the grammatical symbols input and outputs them again.


Сначала нам следует определить категории и атрибуты. Категории и атрибуты позволяют объединять грамматические символы. С помощью категорий мы можем объединять символы для их "сведения воедино" (например, категория 'n.*' объединяет все существительные). Атрибуты позволяют нам объединять символы, из которых мы далее можем выбрать нужный нам (например, 'sg' и 'pl' могут быть объединены атрибутом 'number').
We first need to define categories and attributes. Categories and attributes both allow us to group grammatical symbols. Categories allow us to group symbols for the purposes of matching (for example 'n.*' is all nouns). Attributes allow us to group a set of symbols that can be chosen from. For example ('sg' and 'pl' may be grouped a an attribute 'number').


Добавим необходимые разделы:
Lets add the necessary sections:
<pre>
<pre>
<section-def-cats>
<section-def-cats>
Line 265: Line 263:
</section-def-attrs>
</section-def-attrs>
</pre>
</pre>
Существительные в нашем примере изменяются только по числам (что мы уже много раз повторяли), следовательно, необходимо добавить категорию для существительных и атрибут числа. Достаточно следующих записей:
As we're only inflecting, nouns in singular and plural then we need to add a category for nouns, and with an attribute of number. Something like the following will suffice:


Into section-def-cats add:
В раздел section-def-cats добавьте:
<pre>
<pre>
<def-cat n="nom">
<def-cat n="nom">
Line 273: Line 271:
</def-cat>
</def-cat>
</pre>
</pre>
Категория "покрывает" все существительные (леммы, за которыми следует <n> и за ним ещё что-нибудь) и ссылается на них как "nom" (вы увидите далее, как это применяется).
This catches all nouns (lemmas followed by <n> then anything) and refers to them as "nom" (we'll see how thats used later).


Into the section section-def-attrs, add:
В раздел section-def-attrs добавьте:
<pre>
<pre>
<def-attr n="nbr">
<def-attr n="nbr">
Line 282: Line 280:
</def-attr>
</def-attr>
</pre>
</pre>
а также
and then
<pre>
<pre>
<def-attr n="a_nom">
<def-attr n="a_nom">
Line 288: Line 286:
</def-attr>
</def-attr>
</pre>
</pre>
Первая запись определяет атрибут nbr (number=число), которое может быть либо единственным (sg), либо множественным (pl).
The first defines the attribute nbr (number), which can be either singular (sg) or plural (pl).


Вторая запись определяет атрибут a_nom (атрибут существительное).
The second defines the attribute a_nom (attribute noun).


Далее нам необходимо добавить раздел для глобальных переменных:
Next we need to add a section for global variables:
<pre>
<pre>
<section-def-vars>
<section-def-vars>
Line 298: Line 296:
</section-def-vars>
</section-def-vars>
</pre>
</pre>
Эти переменные используются для сохранения атрибутов или их передачи между несколькими правилами. Пока нам нужна только одна,
These variables are used to store or transfer attributes between rules. We need only one for now,
<pre>
<pre>
<def-var n="number"/>
<def-var n="number"/>
</pre>
</pre>
И наконец, необходимо добавить само правило, которое позволяло бы принимать существительное и затем выводить его в правильной форме. Нам нужен раздел для правил...
Finally, we need to add a rule, to take in the noun and then output it in the correct form. We'll need a rules section...
<pre>
<pre>
<section-rules>
<section-rules>
Line 308: Line 306:
</section-rules>
</section-rules>
</pre>
</pre>
На этот раз я сначала покажу правило, и только затем дам к нему пояснения.
Changing the pace from the previous examples, I'll just paste this rule, then go through it, rather than the other way round.
<pre>
<pre>
<rule>
<rule>
Line 326: Line 324:
</pre>
</pre>


Первый тег понятен — он определяет правило. Второй тег, ''pattern'', (означает следюущее: "применять это правило, если обнаружен этот шаблон". В этом примере шаблон состоит из одного существительного (определённого категорией nom). Заметьте, что шаблоны накладываются в режиме "длиннейший совпадающий". Так, если у вас есть три правила, первый из которых относится к соединениям слов, соответствующих шаблону "<prn><vblex><n>", второй — шаблону "<prn><vblex>" и третий — шаблону "<n>", накладываемым шаблоном и применяемым (в случае соответствия соединения слов этому шаблону) правилом будет первый.
The first tag is obvious, it defines a rule. The second tag, pattern basically says: "apply this rule, if this pattern is found". In this example the pattern consists of a single noun (defined by the category item nom). Note that patterns are matched in a longest-match first. So if you have three rules, the first catches "<prn><vblex><n>", the second catches "<prn><vblex>" and the third catches "<n>", the pattern matched, and rule executed will be the first.


Каждому шаблону соответствует определённое действие, которое генерирует соответствующие выводные данные. Выводными данными (выводом) является лексическая единица (lu, lexical unit).
For each pattern, there is an associated action, which produces an associated output, out. The output, is a lexical unit (lu).


Тег ''clip'' позволяет пользователю выбирать атрибуты или части лексической единицы входного (side="sl") или выходного (side="tl") языка и манипулировать ими.
The clip tag allows a user to select and manipulate attributes and parts of the source language (side="sl"), or target language (side="tl") lexical item.


Скомпилируем и проверим файл. Правила трансфера компилируются так:
Let's compile it and test it. Transfer rules are compiled with:
<pre>
<pre>
$ apertium-preprocess-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin
$ apertium-preprocess-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin
</pre>
</pre>
Which will generate a <code>sh-en.t1x.bin</code> file.
что создаст файл <code>sh-en.t1x.bin</code>.


Теперь всё готово для проверки нашей системы машинного перевода. У нас ещё нет одного важного компонента, а именно разметчика по частям речи или частеречного теггера (PoS tagger, part-of-speech tagger), однако вскоре этот вопрос будет пояснён. Пока мы можем проверить систему и без него.
Now we're ready to test our machine translation system. There is one crucial part missing, the part-of-speech (PoS) tagger, but that will be explained shortly. In the meantime we can test it as is:


Сначала проанализируем слово "gramofoni":
First, lets analyse a word, gramofoni:
<pre>
<pre>
$ echo "gramofoni" | lt-proc sh-en.automorf.bin
$ echo "gramofoni" | lt-proc sh-en.automorf.bin
^gramofon/gramofon<n><pl>$
^gramofon/gramofon<n><pl>$
</pre>
</pre>
После этого теггер по частям речи должен выбрать правильный вариант (правильную часть речи), но так как теггера пока у нас нет, мы можем использовать маленький gawk-скрипт (спасибо Sergio), который будет выдавать первый из полученных результатов (на самом деле и результат-то у нас будет всего один).
Now, normally here the POS tagger would choose the right version based on the part of speech, but we don't have a POS tagger yet, so we can use this little gawk script (thanks to Sergio) that will just output the first item retrieved.
<pre>
<pre>
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \
Line 351: Line 349:
^gramofon<n><pl>$
^gramofon<n><pl>$
</pre>
</pre>
Теперь обработаем результат с помощью правила трансфера:
Now let's process that with the transfer rule:
<pre>
<pre>
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \
Line 357: Line 355:
apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin
apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin
</pre>
</pre>
Что выдаст следующее:
It will output:
<pre>
<pre>
^gramophone<n><pl>$^@
^gramophone<n><pl>$^@
</pre>
</pre>
* 'gramophone' is the target language (side="tl") lemma (lem) at position 1 (pos="1").
* 'gramophone' есть лемма (lem) выходного языка (side="tl") в позиции 1 (pos="1").
* '<n>' есть a_nom (существительное) выходного языка в позции 1.
* '<n>' is the target language a_nom at position 1.
* '<pl>' есть атрибут числа (nbr) выходного языка в позиции 1.
* '<pl>' is the target language attribute of number (nbr) at position 1.


Попробуйте закомментировать одну из этих clip-строк, перекомпилировать файл и посмотреть, что произойдёт.
Try commenting out one of these clip statements, recompiling and seeing what happens.


Теперь у нас есть вывод трансфера, и единственное, что остаётся сделать, это сгенерировать словоформы (т.&nbsp;е. должным образом склонённые или спряжённые формы) на выходном языке. Для этого используется тот же самый lt-proc, но в другом режиме — в режиме генерирования.
So, now we have the output from the transfer, the only thing that remains is to generate the target-language inflected forms. For this, we use lt-proc, but in generation (-g), not analysis mode.
<pre>
<pre>
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \
$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \
Line 376: Line 374:
gramophones\@
gramophones\@
</pre>
</pre>
Вуаля. Теперь у вас есть система машинного перевода, которая переводит сербохорватское существительное на английский язык. Очевидно, что пользы от такой системы не так много, однако вскоре мы перейдём к более сложному материалу. Ах да, о символе '@' тоже не беспокойтесь, скоро я объясню, что это такое.
And c'est ca. You now have a machine translation system that translates a Serbo-Croatian noun into an English noun. Obviously this isn't very useful, but we'll get onto the more complex stuff soon. Oh, and don't worry about the '@' symbol, I'll explain that soon too.


Попробуйте найти/вспомнить другие слова, которые склоняются так же, как слово "gramofon". О порядке их добавления — нам нужно добавлять только записи (entries, которые мы образно назвали "словарными статьями") в главном разделе одноязычного и двуязычного словарей, а не парадигмы.
Think of a few other words that inflect the same as gramofon. How about adding those. We don't need to add any paradigms, just the entries in the main section of the monolingual and bilingual dictionaries.


==Добавим глаголы==
==Bring on the verbs==


Так, теперь наша система может переводить существительные. Однако проку от этого не много, ведь мы хотим переводить и глаголы, и даже целые предложения! Начнём с глагола "to see". В сербохорватском ему соответствует "videti". Сербохорватский язык есть т.н. нуль-субъектный язык (на сербохорватском перед личными формами глаголов личные местоимения как правило не используются). Английский же не является таковым. Так, например: английское "I see" будет переведено на сербохорватский как "vidim".
Ok, so we have a system that translates nouns, but thats pretty useless, we want to translate verbs too, and even whole sentences! How about we start with the verb to see. In Serbo-Croatian this is videti. Serbo-Croatian is a null-subject language, this means that it doesn't typically use personal pronouns before the conjugated form of the verb. English is not. So for example: I see in English would be translated as vidim in Serbo-Croatian.


* Vidim
* Vidim
Line 388: Line 386:
* I see
* I see


Note: <code><p1></code> denotes first person
Примечание: <code><p1></code> означает первое лицо


Другими примерами нуль-субъектных языков могут служить испанский, румынский и польский. Это будет важно при написании правил трансфера для глаголов.
This will be important when we come to write the transfer rule for verbs. Other examples of null-subject languages include: Spanish, Romanian and Polish. This also has the effect that while we only need to add the verb in the Serbo-Croatian morphological dictionary, we need to add both the verb, and the personal pronouns in the English morphological dictionary. We'll go through both of these.


"Нуль-субъектность" сербохорватского языка означает, что если в сербохорватский морфологический словарь мы добавим только глагол, то в английский морфологический словарь нужно будет добавить не только глагол, но и личные местоимения.
The other forms of the verb videti are: vidiš, vidi, vidimo, vidite, and vide; which correspond to: you see (singular), he sees, we see, you see (plural), and they see.


Остальными формами глагола видеть являются: vidiš, vidi, vidimo, vidite, и vide. Соответственно: you see (единственное число), he sees, we see, you see (множественное число), и they see.
There are two forms of you see, one is plural and formal singular (vidite) and the other is singular and informal (vidiš).


Мы постараемся перевести сербохорватское "Vidim gramofoni" в английское "I see gramophones". В целях экономии времени мы добавим в словарь только достаточную для перевода информацию и оставим описание парадигмы (добавление остальных личных форм глагола) как упражнение для самостоятельной работы читателя.
We're going to try and translate the sentence: "Vidim gramofoni" into "I see gramophones". In the interests of space, we'll just add enough information to do the translation and will leave filling out the paradigms (adding the other conjugations of the verb) as an exercise to the reader.


Внимательный читатель наверное заметил, что перевод "vidim gramofoni неправилен, так как это предложение грамматически некорректно. Грамматически правильным предложением является "vidim gramofone", так как существительное должно быть в винительном падеже. Да, мы добавим форму винительного падежа, однако информацию о падеже добавлять не будем (в этом нет необходимости) — нужное нам слово будет фигурировать как второй вариант множественного числа. Для этого скопируйте (другими словами "клонируйте") блок 'e' для формы множественного числа и исправьте там букву 'i' (в теге <l>) на 'e'.
The astute reader will have realised by this point that we can't just translate vidim gramofoni because it is not a grammatically correct sentence in Serbo-Croatian. The correct sentence would be vidim gramofone, as the noun takes the accusative case. We'll have to add that form too, no need to add the case information for now though, we just add it as another option for plural. So, just copy the 'e' block for 'i' and change the 'i' to 'e' there.


Прежде всего мы должны добавить несколько новых символов. Для начала символ для глагола ('verb'), который мы будем называть "vblex" (lexical verb=знаменательный глагол, в противовес модальным и другим глаголам. Наряду с числом (number) глаголы имеют категорию лица ('person') и времени ('tense'), так что добавим эти символы тоже. Напомним, что мы хотели перевести "I see" — значит, для лица мы добавим "p1", т.&nbsp;е. 'первое лицо', а для времени — "pri", т.&nbsp;е. 'present indicative'.
First thing we need to do is add some more symbols. We need to first add a symbol for 'verb', which we'll call "vblex" (this means lexical verb, as opposed to modal verbs and other types). Verbs have 'person', and 'tense' along with number, so lets add a couple of those as well. We need to translate "I see", so for person we should add "p1", or 'first person', and for tense "pri", or 'present indicative'.
<pre>
<pre>
<sdef n="vblex"/>
<sdef n="vblex"/>
Line 406: Line 404:
<sdef n="pri"/>
<sdef n="pri"/>
</pre>
</pre>
После этого (как и в случае существительных) мы добавим парадигму спряжения глагола. Первой строкой будет:
After we've done this, the same with the nouns, we add a paradigm for the verb conjugation. The first line will be:
<pre>
<pre>
<pardef n="vid/eti__vblex">
<pardef n="vid/eti__vblex">
</pre>
</pre>
Знаком '/' разграничивается основа слова, к которой присоединяются содержимые тегов <l>.
The '/' is used to demarcate where the stems (the parts between the <l> </l> tags) are added to.


Затем флексию для первого лица единственного числа:
Then the inflection for first person singular:
<pre>
<pre>
<e>
<e>
Line 421: Line 419:
</e>
</e>
</pre>
</pre>
'im' является суффиксом первого лица единственного числа (как в нашем примере 'vidim'), в теге <r> необходимо добавить 'eti', суффикс инфинитива. С остальным всё просто: 'vblex' есть , как уже выше было сказано, сокращение от "lexical verb", 'pri' — от "present indicative", 'p1' означает "first person" (первое лицо) 'sg' есть единственное число. Можно добавить словарь и форму первого лица множественного числа — в нашей статье нужно будет заменить суффикс 'im' суффиксом 'imo', а символ 'sg' символом 'pl'.
The 'im' denotes the ending (as in 'vidim'), it is necessary to add 'eti' to the <r> section, as this will be chopped off by the definition. The rest is fairly straightforward, 'vblex' is lexical verb, 'pri' is present indicative tense, 'p1' is first person and 'sg' is singular. We can also add the plural which will be the same, except 'imo' instead of 'im' and 'pl' instead of 'sg'.


Далее нам следует добавит в основной раздел лемму и соотнести её с вышеописанной парадигмой:
After this we need to add a lemma, paradigm mapping to the main section:
<pre>
<pre
<e lm="videti"><i>vid</i><par n="vid/eti__vblex"/></e>
<e lm="videti"><i>vid</i><par n="vid/eti__vblex"/></e>
</pre>
</pre>
Note: the content of <nowiki><i> </i></nowiki> is the root, not the lemma.
Заметьте: в тег <nowiki><i> </i></nowiki> пишется корень глагола, не сама лемма.


На этом завершим составление сербохорватского словаря. Скомпилируем и проверим его.
Thats the work on the Serbo-Croatian dictionary done for now. Lets compile it then test it.
<pre>
<pre>
$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin
$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin
Line 438: Line 436:
^vidimo/videti<vblex><pri><p1><pl>$
^vidimo/videti<vblex><pri><p1><pl>$
</pre>
</pre>
Теперь сделаем тоже самое для английского словаря (не забудьте добавить в английский словарь определения символов, что было сделано на предыдущем этапе для сербохорватскоо словаря).
Ok, so now we do the same for the English dictionary (remember to add the same symbol definitions here as you added to the Serbo-Croatian one).


Парадигма выглядит так:
The paradigm is:
<pre>
<pre>
<pardef n="s/ee__vblex">
<pardef n="s/ee__vblex">
</pre>
</pre>
"основой" принимается только "s", так как формой прошедшего времени является 'saw'. Теперь мы могли бы добавить формы первого и второго лица, однако они никак друг от друга не отличаются. Более того, всеми формами настоящего времени глагола "to see" (кроме формы третьего лица единственного числа) будет "see". По этой причине мы добавим в словарь только одну запись с "see" и символом "pri".
because the past tense is 'saw'. Now, we can do one of two things, we can add both first and second person, but they are the same form. In fact, all forms (except third person singular) of the verb 'to see' are 'see'. So instead we make one entry for 'see' and give it only the 'pri' symbol.
<pre>
<pre>
<e>
<e>
Line 453: Line 451:
</e>
</e>
</pre>
</pre>
и, как обычно, запись в основном разделе:
and as always, an entry in the main section:
<pre>
<pre>
<e lm="see"><i>s</i><par n="s/ee__vblex"/></e>
<e lm="see"><i>s</i><par n="s/ee__vblex"/></e>
</pre>
</pre>
Сохраним, скомпилируем и проверим:
Then lets save, recompile and test:
<pre>
<pre>
$ lt-comp lr apertium-sh-en.en.dix en-sh.automorf.bin
$ lt-comp lr apertium-sh-en.en.dix en-sh.automorf.bin
Line 465: Line 463:
^see/see<vblex><pri>$
^see/see<vblex><pri>$
</pre>
</pre>
Теперь обязательная запись в двуязычный словарь:
Now for the obligatory entry in the bilingual dictionary:
<pre>
<pre>
<e><p><l>videti<s n="vblex"/></l><r>see<s n="vblex"/></r></p></e>
<e><p><l>videti<s n="vblex"/></l><r>see<s n="vblex"/></r></p></e>
</pre>
</pre>
(не забудьте добавить sdefs из предыдущих примеров)
(again, don't forget to add the sdefs from earlier)


Перекомпилируем:
And recompile:
<pre>
<pre>
$ lt-comp lr apertium-sh-en.sh-en.dix sh-en.autobil.bin
$ lt-comp lr apertium-sh-en.sh-en.dix sh-en.autobil.bin
Line 478: Line 476:
main@standard 18 18
main@standard 18 18
</pre>
</pre>
Теперь протестируем:
Now to test:
<pre>
<pre>
$ echo "vidim" | lt-proc sh-en.automorf.bin | \
$ echo "vidim" | lt-proc sh-en.automorf.bin | \
Line 486: Line 484:
^see<vblex><pri><p1><sg>$^@
^see<vblex><pri><p1><sg>$^@
</pre>
</pre>
Анализ работает корректно, а при попытке генерации мы получаем '#', как показано ниже:
We get the analysis passed through correctly, but when we try and generate a surface form from this, we get a '#', like below:
<pre>
<pre>
$ echo "vidim" | lt-proc sh-en.automorf.bin | \
$ echo "vidim" | lt-proc sh-en.automorf.bin | \
Line 494: Line 492:
#see\@
#see\@
</pre>
</pre>
Это '#' означает, что генератор не может сгенерировать правильную лексическую форму из-за ее отсутсвия. Почему это происходит?
This '#' means that the generator cannot generate the correct lexical form because it does not contain it. Why is this?


Просто анализы не совпадают: 'see' в словаре — это 'see<vblex><pri>', а 'see' доставляемый трансфером — 'see<vblex><pri<p1><sg>'. Сербскохорватская сторона имеет больше информации, чем нужно английской стороне. Вы можете проверить это, добавив нехватающие символы в английский словарь, перекомпилировав и протестировав снова.
Basically the analyses don't match, the 'see' in the dictionary is see<vblex><pri>, but the see delivered by the transfer is see<vblex><pri><p1><sg>. The Serbo-Croatian side has more information than the English side requires. You can test this by adding the missing symbols to the English dictionary, and then recompiling, and testing again.


However, a more paradigmatic way of taking care of this is by writing a rule. So, we open up the rules file (<code>apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin</code> in case you forgot).
Но существует более парадигматический способ это сделать, суть которого заключается в написании правила. Так что, открываем файл с правилами(apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin на случай, если вы забыли).



We need to add a new category for 'verb'.
Мы должны добавить новую категорию для 'verb'(глагола).
<pre>
<pre>
<def-cat n="vrb">
<def-cat n="vrb">
Line 506: Line 505:
</def-cat>
</def-cat>
</pre>
</pre>

We also need to add attributes for tense and for person. We'll make it really simple for now, you can add p2 and p3, but I won't in order to save space.
Также мы должны добавить атрибуты для времени и лица. Сейчас мы сделаем всё проще, вы сможете добавить p2 и p3, но я не буду этого делать в целях экономии.
<pre>
<pre>
<def-attr n="temps">
<def-attr n="temps">
Line 516: Line 516:
</def-attr>
</def-attr>
</pre>
</pre>
Еще мы должны добавить атрибут для глаголов.
We should also add an attribute for verbs.
<pre>
<pre>
<def-attr n="a_verb">
<def-attr n="a_verb">
Line 522: Line 522:
</def-attr>
</def-attr>
</pre>
</pre>
Теперь к правилу:
Now onto the rule:
<pre>
<pre>
<rule>
<rule>
Line 539: Line 539:
</rule>
</rule>
</pre>
</pre>
Remember when you tried commenting out the 'clip' tags in the previous rule example and they disappeared from the transfer, well, thats pretty much what we're doing here. We take in a verb with a full analysis, but only output a partial analysis (lemma + verb tag + tense tag).


Помните, когда вы попытались закомментировать clip-строки в предыдущем примере правила, они исчезли из трансфера? Сейчас мы делаем то же самое.
So now, if we recompile that, we get:
Мы берем глагол с полным анализом, а на выходе получаем только частичный анализ (лемма + 'verb tag'(тег глагола) + 'tense tag' (тег времени)).


Теперь, если мы всё это перекомпилируем, то получим:
<pre>
<pre>
$ echo "vidim" | lt-proc sh-en.automorf.bin | \
$ echo "vidim" | lt-proc sh-en.automorf.bin | \
Line 548: Line 551:
^see<vblex><pri>$^@
^see<vblex><pri>$^@
</pre>
</pre>
and:
и:
<pre>
<pre>
$ echo "vidim" | lt-proc sh-en.automorf.bin | \
$ echo "vidim" | lt-proc sh-en.automorf.bin | \
Line 556: Line 559:
see\@
see\@
</pre>
</pre>
Try it with 'vidimo' (we see) to see if you get the correct output.


Попробуйте это со словом 'vidimo' (we see), чтобы увидеть, получили ли вы корректный вывод.
Now try it with "vidim gramofone":

А теперь с "vidim gramafone":
<pre>
<pre>
$ echo "vidim gramofoni" | lt-proc sh-en.automorf.bin | \
$ echo "vidim gramofoni" | lt-proc sh-en.automorf.bin | \
Line 567: Line 571:
</pre>
</pre>


==А что насчёт личных местоимений?==
==But what about personal pronouns?==


Всё это отлично, но у нас всё ещё нет личных местоимений, которые обязательны для английского языка. Для того, чтобы их добавить, сначала нам нужно отредактировать английский морфологический словарь.
Well, thats great, but we're still missing the personal pronoun that is necessary in English. In order to add it in, we first need to edit the English morphological dictionary.


Как и раньше, первое, что мы делаем — это добавляем необходимые символы:
As before, the first thing to do is add the necessary symbols:
<pre>
<pre>
<sdef n="prn"/>
<sdef n="prn"/>
<sdef n="subj"/>
<sdef n="subj"/>
</pre>
</pre>
Of the two symbols, prn is pronoun, and subj is subject (as in the subject of a sentence).
Всего два символа: prn pronoun (местоимение) и subj subject (подлежащее).


Поскольку у таких личных местоимений нет ни корня, ни 'леммы', то мы просто добавляем pardef:
Because there is no root, or 'lemma' for personal subject pronouns, we just add the pardef as follows:
<pre>
<pre>
<pardef n="prsubj__prn">
<pardef n="prsubj__prn">
Line 589: Line 593:
</pardef>
</pardef>
</pre>
</pre>
With 'prsubj' being 'personal subject'. The rest of them (You, We etc.) are left as an exercise to the reader.


Где 'prsubj' — 'personal subject'. С остальными местоимениями ('You','We', и т.&nbsp;д.) читатель может поупражняться сам.
We can add an entry to the main section as follows:

Можно добавить такую запись в главный раздел:
<pre>
<pre>
<e lm="personal subject pronouns"><i/><par n="prsubj__prn"/></e>
<e lm="personal subject pronouns"><i/><par n="prsubj__prn"/></e>
</pre>
</pre>
Итак, сохраним, перекомпилируем и протестируем. В результате должно получиться это:
So, save, recompile and test, and we should get something like:
<pre>
<pre>
$ echo "I" | lt-proc en-sh.automorf.bin
$ echo "I" | lt-proc en-sh.automorf.bin
Line 601: Line 606:
</pre>
</pre>


(Слово написано заглавными буквами, так как 'I' пишется с заглавной буквой).
(Note: it's in capitals because 'I' is in capitals).


Теперь нам нужно немного исправить правило 'verb', для вывода личного местоимения и правильной формы глагола.
Now we need to amend the 'verb' rule to output the subject personal pronoun along with the correct verb form.


Для начала, добавляем категорию :
First, add a category (this must be getting pretty pedestrian by now):
<pre>
<pre>
<def-cat n="prpers">
<def-cat n="prpers">
Line 611: Line 616:
</def-cat>
</def-cat>
</pre>
</pre>
Теперь добавляем типы местоимений как атрибуты, мы также можем добавить тип 'obj', но сейчас он нам не нужен:
Now add the types of pronoun as attributes, we might as well add the 'obj' type as we're at it, although we won't need to use it for now:
<pre>
<pre>
<def-attr n="tipus_prn">
<def-attr n="tipus_prn">
Line 618: Line 623:
</def-attr>
</def-attr>
</pre>
</pre>
И теперь к вводу правила:
And now to input the rule:
<pre>
<pre>
<rule>
<rule>
Line 643: Line 648:
</rule>
</rule>
</pre>
</pre>
Это почти тоже самое правило, как и раньше, за исключением нескольких маленьких изменений.
This is pretty much the same rule as before, only we made a couple of small changes.


Нам нужно было вывести:
We needed to output:
<pre>
<pre>
^prpers<prn><subj><p1><sg>$ ^see<vblex><pri>$
^prpers<prn><subj><p1><sg>$ ^see<vblex><pri>$
</pre>
</pre>
так, чтобы генератор смог правильно выбрать и местоимение, и форму глагола.
so that the generator could choose the right pronoun and the right form of the verb.


Небольшое пояснение:
So, a quick rundown:


* <code><lit></code>, prints a literal string, in this case "prpers"
* <code><lit></code>, печатает буквенную строку, в данном случае "prpers"
* <code><lit-tag></code>, prints a literal tag, because we can't get the tags from the verb, we add these ourself, "prn" for pronoun, and "subj" for subject.
* <code><lit-tag></code>, печатает буквенный тег, так как сами мы не можем получить его из глагола, то просто добавляем; "prn" значит pronoun, а "subj" subject.
* <code><b/></code>, prints a blank, a space.
* <code><b/></code>, печатает пробел.


Заметьте, что мы получаем информацию о числе и времени напрямую из глагола.
Note that we retrieved the information for number and tense directly from the verb.


Теперь перекомпилируем и протестируем снова:
So, now if we recompile and test that again:
<pre>
<pre>
$ echo "vidim gramofone" | lt-proc sh-en.automorf.bin | \
$ echo "vidim gramofone" | lt-proc sh-en.automorf.bin | \
Line 667: Line 672:
I see gramophones
I see gramophones
</pre>
</pre>
Полученный результат, может быть, и не получит приз на конкурсе (как и само это руководство), но всё равно является точным переводом.
Which, while it isn't exactly prize-winning prose (much like this HOWTO), is a fairly accurate translation.


==Расскажи же мне о проигрывателях (многословные конструкции 'Multiwords') ==
==So tell me about the record player (Multiwords)==


Несмотря на то, что gramophone (граммофон) — это английское слово, само по себе оно не является лучшим переводом. 'Gramophone' употребляется, в основном, для старых проигрывателей с иглой и без усиления. Лучшим вариантом перевода будет 'record player' (проигрыватель записей). Хотя это и не одно слово, мы можем работать с ним, как с одним, используя 'multiword' (многословные) конструкции.
While gramophone is an English word, it isn't the best translation. Gramophone is typically used for the very old kind, you know with the needle instead of the stylus, and no powered amplification. A better translation would be 'record player'. Although this is more than one word, we can treat it as if it is one word by using multiword (multipalabra) constructions.


Сербскохорватский словарь нам не понадобится, так что открываем только английский и двуязычный.
We don't need to touch the Serbo-Croatian dictionary, just the English one and the bilingual one, so open it up.


The plural of 'record player' is 'record players', so it takes the same paradigm as gramophone (gramophone__n) in that we just add 's'. All we need to do is add a new element to the main section.
Множественное число от 'record player' — это 'record players', то есть используется та же парадигма, что и для gramophone (gramophone__n)— мы просто добавляем 's'. Всё, что нам нужно сделать это добавить новый элемент в главный раздел.
<pre>
<pre>
<e lm="record player"><i>record<b/>player</i><par n="gramophone__n"/></e>
<e lm="record player"><i>record<b/>player</i><par n="gramophone__n"/></e>
</pre>
</pre>
Единственное различие — использование тега <b/>, хотя и это не ново, поскольку мы видели это в файле с правилами.
The only thing different about this is the use of the <b/> tag, although this isn't entirely new as we saw it in use in the rules file.


Перекомпилируем и тестируем:
So, recompile and test in the orthodox fashion:
<pre>
<pre>
$ echo "vidim gramofone" | lt-proc sh-en.automorf.bin | \
$ echo "vidim gramofone" | lt-proc sh-en.automorf.bin | \
Line 689: Line 694:
I see record players
I see record players
</pre>
</pre>
Perfect. A big benefit of using multiwords is that you can translate idiomatic expressions verbatim, without having to do word-by-word translation. For example the English phrase, "at the moment" would be translated into Serbo-Croatian as "trenutno" (trenutak = ''moment'', trenutno being adverb of that) &mdash; it would not be possible to translate this English phrase word-by-word into Serbo-Croatian.


==Dealing with minor variation==


Отлично. Огромная выгода использования 'multiwords' (многословные конструкции) заключается в том, что можно переводить идиоматические выражения дословно, без необходимости пословного перевода. Например, английская фраза "at the moment" (сейчас, в данный момент) будет переведена на сербскохорватский как "trenutno" (trenutak — момент, trenutno — наречие, образованное от него) — было бы невозможно перевести эту фразу на сербскохорватский пословно.
Serbo-Croatian typically has a few ways of writing each word because of dialectal variation. It has a cool phonetic writing system so you write how you speak. For example, people speaking in Ijekavian would say "rječnik", while someone speaking Ekavian would say "rečnik", which reflects the differences in pronunciation of the proto-Slavic vowel ''yat''.

==Работа с незначительными вариациями==

Сербскохорватский язык имеет несколько вариантов написания, из-за диалектических вариаций. Этот язык имеет интересную фонетическую письменную систему — как слышится, так и пишется. Например, люди, говорящие на Иекавском диалекте сказали бы "rječnik", в то же время, кто-нибудь говорящий на Экавском сказал бы "rečnik". Это отражает разницу в произношении праславянской гласной 'ят'.


===Analysis===
===Анализ===


Должен существовать легкий способ борьбы с этим, и он есть: снова использовать парадигмы. Они используются не только для добавления грамматических символов, но и для замены букв и символов. Для примера, посмотрите на парадигму для распознавания при анализе и "e" и "je". Эта парадигма, как и остальные, должна быть записана в cербохорватский словарь.
There should be a fairly easy way of dealing with this, and there is, using paradigms again. Paradigms aren't only used for adding grammatical symbols, but they can also be used to replace any character/symbol with another. For example, here is a paradigm for accepting both "e" and "je" in the analysis. The paradigm should, as with the others go into the monolingual dictionary for Serbo-Croatian.


<pre>
<pre>
Line 716: Line 723:
</pre>
</pre>


Затем в главном разделе:
Then in the "main section":


<pre>
<pre>
Line 722: Line 729:
</pre>
</pre>


Это позволяет нам только анализировать обе формы, а если мы хотим и генерировать обе формы, то нужно проделать больше работы.
This only allows us to analyse both forms however... more work is necessary if we want to generate both forms.


===Generation===
===Генерация===


==See also==
==См. также==


*[[Building dictionaries]]
*[[Building dictionaries]]
*[[Finding_errors_in_dictionaries]]
*[[Cookbook]]
*[[Cookbook]]
*[[Chunking]]
*[[Chunking]]
*[[Contributing to an existing pair]]
*[[Contributing to an existing pair]]


[[Category:Документация на русском языке]]
[[Category:Documentation]]
[[Category:Documentation]]
[[Category:HOWTO]]
[[Category:HOWTO]]
[[Category:Writing dictionaries]]
[[Category:Writing dictionaries]]
[[Category:Quickstart]]

Latest revision as of 17:48, 13 April 2019

В этом руководстве описывается порядок создания новой языковой пары для системы машинного перевода Apertium. От вас не требуются какие-либо лингвистические знания или знания по машинному переводу, кроме как способности различать части речи (отличать существительные от глаголов, например).

Введение[edit]

Как вы только что узнали, Apertium является системой машинного перевода. Но если быть более точным, то Apertium следует назвать не системой, а платформой машинного перевода. Он обеспечивает вас "движком" машинного перевода (англ. "engine". Можно также перевести как "ядро", "механизм" и т. п.) и набором инструментов, с помощью которых вы можете строить свои собственные системы машинного перевода. Единственное, что вы должны сделать, это написать исходные данные. На базовом уровне эти данные состоят из трёх словарей и некоторого набора правил (обеспечивающих перестановку слов и другие грамматические трансформации).

За более подробной информацией, как всё это работает, обращайтесь к веб-сайту проекта apertium.sourceforge.net.

Что вам потребуется[edit]

  • lttoolbox (>= 3.0.0)
  • libxml utils (xmllint и др.)
  • apertium (>= 3.0.0)
  • текстовый редактор (или специализированный XML-редактор, если таковой вам больше по душе)

Это руководство не описывает порядок установки этих пакетов, за подробной информацией обращайтесь к разделу документации веб-сайта Apertium.

Из чего состоит языковая пара?[edit]

Apertium представляет собой систему машинного перевода поверхностно-трансферного типа. Следовательно, в основном он имеет дело со словарями и правилами поверхностного трансфера. На практике поверхностный трансфер отличается от глубокого тем, что при нём не выполняется полный синтаксический разбор предложений, а правила, в отличии от операций на дереве синтаксического разбора, представляют собой операции с группами лексических единиц. Этих словарей три:

  1. Морфологический словарь для языка xx: он содержит информацию о словоизменении (склонении или спряжении) на языке xx. В нашем примере этот словарь будет называться так: apertium-sh-en.sh.dix
  2. Морфологический словарь для языка yy: он, в свою очередь, содержит информацию о словоизменении (склонении или спряжении) на языке yy. В нашем примере он имеет следующее название: apertium-sh-en.en.dix
  3. Двуязычный словарь: содержит переводные соответствия слов и символов двух языков. Он будет называться так: apertium-sh-en.sh-en.dix

В языковой паре любой из языков, составляющих эту пару, может быть как входным, так и выходным языком, т. е. эти термины употребляются условно.

Составляющими языковую пару являются также два файла с правилами трансфера. Это правила, которые управляют перестановкой слов в предложениях, например chat noir -> cat black -> black cat. Также эти правила обеспечивают в предложении согласование рода, числа и т. д. Они же могут использоваться и для вставки или удаления лексических единиц, как это будет описано ниже. Это следующие файлы:

  • правила трансфера языка xx на язык yy: эти правила описывают, каким изменениям подвергнутся предложения языка xx при переводе на язык yy. В нашем примере это следующий файл: apertium-sh-en.sh-en.t1x
  • правила трансфера языка yy на язык xx: этот файл содержит правила, описывающие преобразования, которые должны быть осуществлены при переводе с языка yy на язык xx. В нашем примере этот файл будет называться так: apertium-sh-en.en-sh.t1x

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

Языковая пара[edit]

Как уже можно было догадаться по названиям файлов, для описания порядка создания базовой системы в этом руководстве будут использоваться примеры перевода с сербохорватского на английский язык. Заметим, что это не идеальная пара, так как система работает лучше с родственными языками. Однако в случае простых примеров, приводимых здесь, мы не столкнёмся с какими-либо проблемами.

Краткое замечание о терминах[edit]

Перед тем как продолжить, следует пояснить значение некоторых терминов.

Первым из них является лемма. Лемма — это каноническая форма слова, слово без грамматической информации. Например, леммой слова cats является cat. В английском языке лемма рассматриваемого существительного как правило совпадает с его формой единственного числа. В русском и татарском языках лемма существительного имеет вид его формы именительного падежа единственного числа. Для глаголов в английском языке лемма будет иметь вид инфинитива без to (или просто инфинитива в русском и татарском языках). Например, леммой слова was будет be, также как леммой слова был будет быть, или леммой слова булды будет булырга.

Вторым термином является термин символ. В контексте Apertium`а символ означает грамматический знак. Слово cats есть существительное множественного числа, следовательно, он будет иметь символ существительного и символ множественного числа. На входе и выходе модулей Apertium`а эти символы обычно заключаются в угловые скобки, как показано ниже:

  • <n>; для существительного
  • <pl>; для множественного числа

Другими примерами символов являются <sg> (единственное число), <p1> (первое лицо), <pri> (настоящее время изъявительное наклонение) и др. Стоит заметить, что во многих из существующих языковых пар символы имеют вид акронимов или сокращений каталанских слов. Например, vbhaver — от vb (verb, глагол) и haver ("иметь" на каталанском). Символы определяются в тегах <sdef> и используются в тегах <s>.

Третьим же термином является парадигма. В контексте системы Apertium парадигма является примером склонения/спряжения определённой группы слов. В морфологическом словаре леммы (см. выше) ссылаются на парадигмы, что позволяет нам показать все словоформы этих лемм без необходимости записи всех возможных окончаний.

Примером использования парадигмы может служить следующее. Допустим, мы хотим добавить в словарь прилагательные happy и lazy. Вместо записи одинаковых окончаний:

  • happy, happ (y, ier, iest)
  • lazy, laz (y, ier, iest)

мы можем записать окончания форм слова happy, а потом сказать "lazy изменяется как happy", или "shy изменяется как happy", "naughty изменяется как happy", "friendly изменяется как happy" и т. д. В этом примере happy и будет парадигмой, моделью изменения всех остальных. Точное описание определения парадигм будет дано позже. Парадигмы определяются в тегах <pardef> и используются в тегах <par>.

Начало работы[edit]

Одноязычные словари[edit]

See also: List of dictionaries and Incubator

Начнём с создания нашего первого словаря входного языка. Словарь является XML-файлом. Откройте ваш текстовый редактор и наберите следующее:

<?xml version="1.0" encoding="UTF-8"?>
<dictionary>

</dictionary>

Так, теперь файл определяет, что мы хотим начать создание словаря. Чтобы этот файл был более полезным, мы должны добавить в него ещё несколько записей, первой из которых будет алфавит. Он определяет набор букв, которые могут использоваться в словаре для сербохорватского языка. Он выглядит как показано ниже и содержит все буквы сербохорватского алфавита:

<alphabet>ABCČĆDDžĐEFGHIJKLLjMNNjOPRSŠTUVZŽabcčćddžđefghijklljmnnjoprsštuvzž</alphabet>

Добавьте алфавит после тега <dictionary>.

Далее нам необходимо определить некоторые символы. Начнём с более простых — существительное (n) в единственном (sg) и множественном (pl) числах.

<sdefs>
   <sdef n="n"/>
   <sdef n="sg"/>
   <sdef n="pl"/>
</sdefs>

Имена символов не обязательно должны быть такими краткими, их можно даже писать полностью, но так как делать это придётся много раз, есть смысл в сокращении.

К сожалению, всё не так просто — существительные в сербохорватском языке имеют не только категорию числа, но и категории рода и падежа. Однако для нашего примера мы будем предполагать, что существительное является существительным мужского рода и что он в именительном падеже (пример можно найти в конце этого документа).

Следующим шагом определим раздел для парадигм,

<pardefs>

</pardefs>

и раздел для словаря:

<section id="main" type="standard">

</section>

Есть два вида разделов. Первый — стандартный раздел, он содержит слова, энклитики и т. д. Второй — безусловный раздел, содержащий знаки препинания и т. п. В нашем примере нет безусловного раздела, хотя он будет показан позднее.

Таким образом, наш файл будет выглядеть так:

<?xml version="1.0" encoding="UTF-8"?>
<dictionary>
   <sdefs>
     <sdef n="n"/>
     <sdef n="sg"/>
     <sdef n="pl"/>
   </sdefs>
   <pardefs>

   </pardefs>
   <section id="main" type="standard">

   </section>
</dictionary>

Теперь у нас есть скелет словаря, и мы можем перейти к добавлению существительного. Им будет слово 'gramofon'.

Так как ранее определённых парадигм у нас нет, первым делом нужно определить парадигму.

Напомним, что мы имеем ввиду мужской род и именительный падеж. Формой единственного числа является 'gramofon', формой множественного числа — 'gramofoni'. Таким образом:

<pardef n="gramofon__n">
   <e>
     <p>
       <l/>
       <r><s n="n"/><s n="sg"/></r>
     </p>
   </e>
   <e>
     <p>
       <l>i</l>
       <r><s n="n"/><s n="pl"/></r>
     </p>
   </e>
</pardef>

Заметьте: конструкция <l/> (эквивалент <l></l>) означает, что в единственном числе к основе ничего не присоединяется.

Всё это может показаться довольно многословным способом описания, но для такого описания есть причины и к нему быстро привыкаешь. Вы, наверное, уже задаётесь вопросом, что означают все эти <e>, <l> и <r>?

  • e означает запись (entry). Образно это можно также назвать словарной статьёй.
  • p означает пару (pair).
  • l означает влево (left).
  • r означает вправо (right).

Почему влево и вправо? Морфологические словари позднее будут скомпилированы в конечные автоматы. Их компиляция слева направо создаёт анализы слов, а справа налево — слова из анализов. Например:

* gramofoni (слева направо) gramofon<n><pl> (анализ)
* gramofon<n><pl> (справа налево) gramofoni (генерирование)

Мы определили парадигму, теперь требуется соотнести её с леммой — gramofon. Это действие выполняется в ранее определённом разделе (section).

Записью, которую нужно добавить в <section>, является следующее:

<e lm="gramofon"><i>gramofon</i><par n="gramofon__n"/></e>

Краткое пояснение к сокращениям:

  • lm означает лемму (lemma).
  • i означает идентичность (identity). Одно и то же и при генерации, и при анализе.
  • par означает парадигму (paradigm).

Эта запись определяет лемму слова, gramofon, корень слова, gramofon, и парадигму склонения этого слова gramofon_n. Разница между леммой и корнем в том, что лемма есть "цитируемая форма" слова, в то время как корень есть часть леммы, к которой присоединяются суффиксы и окончания. Эта разница станет понятной, когда мы покажем запись с разными леммой и корнем.

Теперь мы можем проверить наш словарь. Сохраните его и вернитесь к командной строке. Первым делом мы должны скомпилировать его (с помощью lt-comp), потом мы сможем его проверить (с помощью lt-proc).

$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin

Что должно выдать следующее:

main@standard 12 12

Так как мы компилировали слева направо, мы создали анализатор. Давайте создадим и генератор.

$ lt-comp rl apertium-sh-en.sh.dix sh-en.autogen.bin

Команда должна выдать тоже самое сообщение.

Теперь мы можем их протестировать. Запустите lt-proc на анализаторе.

$ lt-proc sh-en.automorf.bin

Теперь проверьте — введите gramofoni (граммофоны), и посмотрите результат:

^gramofoni/gramofon<n><pl>$

Теперь сделайте то же самое для английского словаря, но замените слово gramofon английским словом gramophone и поменяйте окончание множественного числа (т. е. i на s) А что если вы захотите использовать более правильный перевод 'record player'? Однако это мы объясним позднее.

Теперь в папке у вас должно быть два файла:

  • apertium-sh.sh.dix, который содержит (очень) маленький сербохорватский морфологический словарь, и
  • apertium-en.en.dix, который содержит (ну очень) маленький английский морфологический словарь.

Двуязычные словари[edit]

Таким образом, теперь у нас есть два морфологических словаря и далее мы перейдём к двуязычному словарю. Двуязычный словарь описывает соответствия слов. Все словари имеют один и тот же формат (которой описан в DTD, dix.dtd).

Создайте новый файл с именем apertium-sh-en.sh-en.dix и вставьте следующий "скелет" словаря:

<?xml version="1.0" encoding="UTF-8"?>
<dictionary>
   <alphabet/>
   <sdefs>
     <sdef n="n"/>
     <sdef n="sg"/>
     <sdef n="pl"/>
   </sdefs>

   <section id="main" type="standard">

   </section>
</dictionary>

Теперь мы должны добавить запись (в <section>) для осуществления перевода двух слов:

<e><p><l>gramofon<s n="n"/></l><r>gramophone<s n="n"/></r></p></e>

Так как в словаре таких записей очень много, для удобочитаемости их обычно пишут в одну строку. Снова вопросы о 'l' и 'r', да? Всё довольно просто — мы компилируем слева направо для создания сербохорватско → английского словаря, и справа налево для создания английско → сербохорватского словаря.

Когда всё это сделано, выполните следующие команды:

$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin
$ lt-comp rl apertium-sh-en.en.dix sh-en.autogen.bin

$ lt-comp lr apertium-sh-en.en.dix en-sh.automorf.bin
$ lt-comp rl apertium-sh-en.sh.dix en-sh.autogen.bin

$ lt-comp lr apertium-sh-en.sh-en.dix sh-en.autobil.bin
$ lt-comp rl apertium-sh-en.sh-en.dix en-sh.autobil.bin

для создания морфологических анализаторов (automorf), морфологических генераторов (autogen) и поисковиков слов (autobil), слово "bil" означает "bilingual", т. е. "двуязычный".

Правила трансфера[edit]

Теперь мы имеем два морфологических словаря и один двуязычный словарь. Всё что нам ещё нужно сделать это правила трансфера для существительных. Файлы с правилами трансфера имеют свой собственный DTD (transfer.dtd), который может быть найден в пакете Apertium. Если вам нужно написать правило трансфера, то часто имеет смысл сначала обратиться к файлам с правилами для других языковых пар, так как многие правила могут быть использованы для разных языковых пар. Или же эти правила можно использовать в модифицированном виде. Например, правило, приведённое ниже, может быть использовано для всех нуль-субъектных языков.

"Скелет" файла такой же:

<?xml version="1.0" encoding="UTF-8"?>
<transfer>

</transfer>

Так как мы не учитываем падежи (т. е. возможное изменение падежей при переводе), нам необходимо создать правило, которое просто "брало" бы грамматические символы на входе и, в свою очередь, выдавало их.

Сначала нам следует определить категории и атрибуты. Категории и атрибуты позволяют объединять грамматические символы. С помощью категорий мы можем объединять символы для их "сведения воедино" (например, категория 'n.*' объединяет все существительные). Атрибуты позволяют нам объединять символы, из которых мы далее можем выбрать нужный нам (например, 'sg' и 'pl' могут быть объединены атрибутом 'number').

Добавим необходимые разделы:

<section-def-cats>

</section-def-cats>
<section-def-attrs>

</section-def-attrs>

Существительные в нашем примере изменяются только по числам (что мы уже много раз повторяли), следовательно, необходимо добавить категорию для существительных и атрибут числа. Достаточно следующих записей:

В раздел section-def-cats добавьте:

<def-cat n="nom">
   <cat-item tags="n.*"/>
</def-cat>

Категория "покрывает" все существительные (леммы, за которыми следует <n> и за ним ещё что-нибудь) и ссылается на них как "nom" (вы увидите далее, как это применяется).

В раздел section-def-attrs добавьте:

<def-attr n="nbr">
   <attr-item tags="sg"/>
   <attr-item tags="pl"/>
</def-attr>

а также

<def-attr n="a_nom">
   <attr-item tags="n"/>
</def-attr>

Первая запись определяет атрибут nbr (number=число), которое может быть либо единственным (sg), либо множественным (pl).

Вторая запись определяет атрибут a_nom (атрибут существительное).

Далее нам необходимо добавить раздел для глобальных переменных:

<section-def-vars>

</section-def-vars>

Эти переменные используются для сохранения атрибутов или их передачи между несколькими правилами. Пока нам нужна только одна,

<def-var n="number"/>

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

<section-rules>

</section-rules>

На этот раз я сначала покажу правило, и только затем дам к нему пояснения.

<rule>
   <pattern>
     <pattern-item n="nom"/>
   </pattern>
   <action>
     <out>
       <lu>
         <clip pos="1" side="tl" part="lem"/>
         <clip pos="1" side="tl" part="a_nom"/>
         <clip pos="1" side="tl" part="nbr"/>
       </lu>
     </out>
   </action>
</rule>

Первый тег понятен — он определяет правило. Второй тег, pattern, (означает следюущее: "применять это правило, если обнаружен этот шаблон". В этом примере шаблон состоит из одного существительного (определённого категорией nom). Заметьте, что шаблоны накладываются в режиме "длиннейший совпадающий". Так, если у вас есть три правила, первый из которых относится к соединениям слов, соответствующих шаблону "<prn><vblex><n>", второй — шаблону "<prn><vblex>" и третий — шаблону "<n>", накладываемым шаблоном и применяемым (в случае соответствия соединения слов этому шаблону) правилом будет первый.

Каждому шаблону соответствует определённое действие, которое генерирует соответствующие выводные данные. Выводными данными (выводом) является лексическая единица (lu, lexical unit).

Тег clip позволяет пользователю выбирать атрибуты или части лексической единицы входного (side="sl") или выходного (side="tl") языка и манипулировать ими.

Скомпилируем и проверим файл. Правила трансфера компилируются так:

$ apertium-preprocess-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin

что создаст файл sh-en.t1x.bin.

Теперь всё готово для проверки нашей системы машинного перевода. У нас ещё нет одного важного компонента, а именно разметчика по частям речи или частеречного теггера (PoS tagger, part-of-speech tagger), однако вскоре этот вопрос будет пояснён. Пока мы можем проверить систему и без него.

Сначала проанализируем слово "gramofoni":

$ echo "gramofoni" | lt-proc sh-en.automorf.bin 
^gramofon/gramofon<n><pl>$

После этого теггер по частям речи должен выбрать правильный вариант (правильную часть речи), но так как теггера пока у нас нет, мы можем использовать маленький gawk-скрипт (спасибо Sergio), который будет выдавать первый из полученных результатов (на самом деле и результат-то у нас будет всего один).

$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \
  gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \
^gramofon<n><pl>$

Теперь обработаем результат с помощью правила трансфера:

$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \
  gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \
  apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin

Что выдаст следующее:

^gramophone<n><pl>$^@
  • 'gramophone' есть лемма (lem) выходного языка (side="tl") в позиции 1 (pos="1").
  • '<n>' есть a_nom (существительное) выходного языка в позции 1.
  • '<pl>' есть атрибут числа (nbr) выходного языка в позиции 1.

Попробуйте закомментировать одну из этих clip-строк, перекомпилировать файл и посмотреть, что произойдёт.

Теперь у нас есть вывод трансфера, и единственное, что остаётся сделать, это сгенерировать словоформы (т. е. должным образом склонённые или спряжённые формы) на выходном языке. Для этого используется тот же самый lt-proc, но в другом режиме — в режиме генерирования.

$ echo "gramofoni" | lt-proc sh-en.automorf.bin | \
  gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \
  apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin | \
  lt-proc -g sh-en.autogen.bin

gramophones\@

Вуаля. Теперь у вас есть система машинного перевода, которая переводит сербохорватское существительное на английский язык. Очевидно, что пользы от такой системы не так много, однако вскоре мы перейдём к более сложному материалу. Ах да, о символе '@' тоже не беспокойтесь, скоро я объясню, что это такое.

Попробуйте найти/вспомнить другие слова, которые склоняются так же, как слово "gramofon". О порядке их добавления — нам нужно добавлять только записи (entries, которые мы образно назвали "словарными статьями") в главном разделе одноязычного и двуязычного словарей, а не парадигмы.

Добавим глаголы[edit]

Так, теперь наша система может переводить существительные. Однако проку от этого не много, ведь мы хотим переводить и глаголы, и даже целые предложения! Начнём с глагола "to see". В сербохорватском ему соответствует "videti". Сербохорватский язык есть т.н. нуль-субъектный язык (на сербохорватском перед личными формами глаголов личные местоимения как правило не используются). Английский же не является таковым. Так, например: английское "I see" будет переведено на сербохорватский как "vidim".

  • Vidim
  • see<p1><sg>
  • I see

Примечание: <p1> означает первое лицо

Другими примерами нуль-субъектных языков могут служить испанский, румынский и польский. Это будет важно при написании правил трансфера для глаголов.

"Нуль-субъектность" сербохорватского языка означает, что если в сербохорватский морфологический словарь мы добавим только глагол, то в английский морфологический словарь нужно будет добавить не только глагол, но и личные местоимения.

Остальными формами глагола видеть являются: vidiš, vidi, vidimo, vidite, и vide. Соответственно: you see (единственное число), he sees, we see, you see (множественное число), и they see.

Мы постараемся перевести сербохорватское "Vidim gramofoni" в английское "I see gramophones". В целях экономии времени мы добавим в словарь только достаточную для перевода информацию и оставим описание парадигмы (добавление остальных личных форм глагола) как упражнение для самостоятельной работы читателя.

Внимательный читатель наверное заметил, что перевод "vidim gramofoni неправилен, так как это предложение грамматически некорректно. Грамматически правильным предложением является "vidim gramofone", так как существительное должно быть в винительном падеже. Да, мы добавим форму винительного падежа, однако информацию о падеже добавлять не будем (в этом нет необходимости) — нужное нам слово будет фигурировать как второй вариант множественного числа. Для этого скопируйте (другими словами "клонируйте") блок 'e' для формы множественного числа и исправьте там букву 'i' (в теге <l>) на 'e'.

Прежде всего мы должны добавить несколько новых символов. Для начала символ для глагола ('verb'), который мы будем называть "vblex" (lexical verb=знаменательный глагол, в противовес модальным и другим глаголам. Наряду с числом (number) глаголы имеют категорию лица ('person') и времени ('tense'), так что добавим эти символы тоже. Напомним, что мы хотели перевести "I see" — значит, для лица мы добавим "p1", т. е. 'первое лицо', а для времени — "pri", т. е. 'present indicative'.

<sdef n="vblex"/>
<sdef n="p1"/>
<sdef n="pri"/>

После этого (как и в случае существительных) мы добавим парадигму спряжения глагола. Первой строкой будет:

<pardef n="vid/eti__vblex">

Знаком '/' разграничивается основа слова, к которой присоединяются содержимые тегов <l>.

Затем флексию для первого лица единственного числа:

<e>
   <p>
     <l>im</l>
     <r>eti<s n="vblex"/><s n="pri"/><s n="p1"/><s n="sg"/></r>
   </p>
</e>

'im' является суффиксом первого лица единственного числа (как в нашем примере 'vidim'), в теге <r> необходимо добавить 'eti', суффикс инфинитива. С остальным всё просто: 'vblex' есть , как уже выше было сказано, сокращение от "lexical verb", 'pri' — от "present indicative", 'p1' означает "first person" (первое лицо) 'sg' есть единственное число. Можно добавить словарь и форму первого лица множественного числа — в нашей статье нужно будет заменить суффикс 'im' суффиксом 'imo', а символ 'sg' символом 'pl'.

Далее нам следует добавит в основной раздел лемму и соотнести её с вышеописанной парадигмой:

<i>vid</i><par n="vid/eti__vblex"/></e>

Заметьте: в тег <i> </i> пишется корень глагола, не сама лемма.

На этом завершим составление сербохорватского словаря. Скомпилируем и проверим его.

$ lt-comp lr apertium-sh-en.sh.dix sh-en.automorf.bin
main@standard 23 25
$ echo "vidim" | lt-proc sh-en.automorf.bin
^vidim/videti<vblex><pri><p1><sg>$
$ echo "vidimo" | lt-proc sh-en.automorf.bin
^vidimo/videti<vblex><pri><p1><pl>$

Теперь сделаем тоже самое для английского словаря (не забудьте добавить в английский словарь определения символов, что было сделано на предыдущем этапе для сербохорватскоо словаря).

Парадигма выглядит так:

<pardef n="s/ee__vblex">

"основой" принимается только "s", так как формой прошедшего времени является 'saw'. Теперь мы могли бы добавить формы первого и второго лица, однако они никак друг от друга не отличаются. Более того, всеми формами настоящего времени глагола "to see" (кроме формы третьего лица единственного числа) будет "see". По этой причине мы добавим в словарь только одну запись с "see" и символом "pri".

<e>
   <p>
     <l>ee</l>
     <r>ee<s n="vblex"/><s n="pri"/></r>
   </p>
</e>

и, как обычно, запись в основном разделе:

<e lm="see"><i>s</i><par n="s/ee__vblex"/></e>

Сохраним, скомпилируем и проверим:

$ lt-comp lr apertium-sh-en.en.dix en-sh.automorf.bin
main@standard 18 19

$ echo "see" | lt-proc en-sh.automorf.bin
^see/see<vblex><pri>$

Теперь обязательная запись в двуязычный словарь:

<e><p><l>videti<s n="vblex"/></l><r>see<s n="vblex"/></r></p></e>

(не забудьте добавить sdefs из предыдущих примеров)

Перекомпилируем:

$ lt-comp lr apertium-sh-en.sh-en.dix sh-en.autobil.bin
main@standard 18 18
$ lt-comp rl apertium-sh-en.sh-en.dix en-sh.autobil.bin
main@standard 18 18

Теперь протестируем:

$ echo "vidim" | lt-proc sh-en.automorf.bin | \
  gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \
  apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin

^see<vblex><pri><p1><sg>$^@

Анализ работает корректно, а при попытке генерации мы получаем '#', как показано ниже:

$ echo "vidim" | lt-proc sh-en.automorf.bin | \
  gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \
  apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin | \
  lt-proc -g sh-en.autogen.bin
#see\@

Это '#' означает, что генератор не может сгенерировать правильную лексическую форму из-за ее отсутсвия. Почему это происходит?

Просто анализы не совпадают: 'see' в словаре — это 'see<vblex><pri>', а 'see' доставляемый трансфером — 'see<vblex><pri<p1><sg>'. Сербскохорватская сторона имеет больше информации, чем нужно английской стороне. Вы можете проверить это, добавив нехватающие символы в английский словарь, перекомпилировав и протестировав снова.

Но существует более парадигматический способ это сделать, суть которого заключается в написании правила. Так что, открываем файл с правилами(apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin на случай, если вы забыли).


Мы должны добавить новую категорию для 'verb'(глагола).

<def-cat n="vrb">
   <cat-item tags="vblex.*"/>
</def-cat>

Также мы должны добавить атрибуты для времени и лица. Сейчас мы сделаем всё проще, вы сможете добавить p2 и p3, но я не буду этого делать в целях экономии.

<def-attr n="temps">
   <attr-item tags="pri"/>
</def-attr>

<def-attr n="pers">
   <attr-item tags="p1"/>
</def-attr>

Еще мы должны добавить атрибут для глаголов.

<def-attr n="a_verb">
   <attr-item tags="vblex"/>
</def-attr>

Теперь к правилу:

<rule>
   <pattern>
     <pattern-item n="vrb"/>
   </pattern>
   <action>
     <out>
       <lu>
         <clip pos="1" side="tl" part="lem"/>
         <clip pos="1" side="tl" part="a_verb"/>
         <clip pos="1" side="tl" part="temps"/>
       </lu>
     </out>
   </action>
</rule>

Помните, когда вы попытались закомментировать clip-строки в предыдущем примере правила, они исчезли из трансфера? Сейчас мы делаем то же самое. Мы берем глагол с полным анализом, а на выходе получаем только частичный анализ (лемма + 'verb tag'(тег глагола) + 'tense tag' (тег времени)).


Теперь, если мы всё это перекомпилируем, то получим:

$ echo "vidim" | lt-proc sh-en.automorf.bin | \
  gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \
  apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin
^see<vblex><pri>$^@

и:

$ echo "vidim" | lt-proc sh-en.automorf.bin  | \
  gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \
  apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin | \
  lt-proc -g sh-en.autogen.bin
see\@

Попробуйте это со словом 'vidimo' (we see), чтобы увидеть, получили ли вы корректный вывод.

А теперь с "vidim gramafone":

$ echo "vidim gramofoni" | lt-proc sh-en.automorf.bin | \
  gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \
  apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin | \
  lt-proc -g sh-en.autogen.bin
see gramophones\@

А что насчёт личных местоимений?[edit]

Всё это отлично, но у нас всё ещё нет личных местоимений, которые обязательны для английского языка. Для того, чтобы их добавить, сначала нам нужно отредактировать английский морфологический словарь.

Как и раньше, первое, что мы делаем — это добавляем необходимые символы:

<sdef n="prn"/>
<sdef n="subj"/>

Всего два символа: prn — pronoun (местоимение) и subj — subject (подлежащее).

Поскольку у таких личных местоимений нет ни корня, ни 'леммы', то мы просто добавляем pardef:

<pardef n="prsubj__prn">
   <e>
     <p>
       <l>I</l>
       <r>prpers<s n="prn"/><s n="subj"/><s n="p1"/><s n="sg"/></r>
     </p>
   </e>
</pardef>

Где 'prsubj' — 'personal subject'. С остальными местоимениями ('You','We', и т. д.) читатель может поупражняться сам.

Можно добавить такую запись в главный раздел:

<e lm="personal subject pronouns"><i/><par n="prsubj__prn"/></e>

Итак, сохраним, перекомпилируем и протестируем. В результате должно получиться это:

$ echo "I" | lt-proc en-sh.automorf.bin
^I/PRPERS<prn><subj><p1><sg>$

(Слово написано заглавными буквами, так как 'I' пишется с заглавной буквой).

Теперь нам нужно немного исправить правило 'verb', для вывода личного местоимения и правильной формы глагола.

Для начала, добавляем категорию :

<def-cat n="prpers">
   <cat-item lemma="prpers" tags="prn.*"/>
</def-cat>

Теперь добавляем типы местоимений как атрибуты, мы также можем добавить тип 'obj', но сейчас он нам не нужен:

<def-attr n="tipus_prn">
   <attr-item tags="prn.subj"/>
   <attr-item tags="prn.obj"/>
</def-attr>

И теперь к вводу правила:

<rule>
   <pattern>
     <pattern-item n="vrb"/>
   </pattern>
   <action>
     <out>
       <lu>
         <lit v="prpers"/>
         <lit-tag v="prn"/>
         <lit-tag v="subj"/>
         <clip pos="1" side="tl" part="pers"/>
         <clip pos="1" side="tl" part="nbr"/>
       </lu>
       <b/>
       <lu>
         <clip pos="1" side="tl" part="lem"/>
         <clip pos="1" side="tl" part="a_verb"/>
         <clip pos="1" side="tl" part="temps"/>
       </lu>
     </out>
   </action>
</rule>

Это почти тоже самое правило, как и раньше, за исключением нескольких маленьких изменений.

Нам нужно было вывести:

^prpers<prn><subj><p1><sg>$ ^see<vblex><pri>$

так, чтобы генератор смог правильно выбрать и местоимение, и форму глагола.

Небольшое пояснение:

  • <lit>, печатает буквенную строку, в данном случае "prpers"
  • <lit-tag>, печатает буквенный тег, так как сами мы не можем получить его из глагола, то просто добавляем; "prn" значит pronoun, а "subj" — subject.
  • , печатает пробел.

Заметьте, что мы получаем информацию о числе и времени напрямую из глагола.

Теперь перекомпилируем и протестируем снова:

$ echo "vidim gramofone" | lt-proc sh-en.automorf.bin  | \
  gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \
  apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin | \
  lt-proc -g sh-en.autogen.bin
I see gramophones

Полученный результат, может быть, и не получит приз на конкурсе (как и само это руководство), но всё равно является точным переводом.

Расскажи же мне о проигрывателях (многословные конструкции 'Multiwords')[edit]

Несмотря на то, что gramophone (граммофон) — это английское слово, само по себе оно не является лучшим переводом. 'Gramophone' употребляется, в основном, для старых проигрывателей с иглой и без усиления. Лучшим вариантом перевода будет 'record player' (проигрыватель записей). Хотя это и не одно слово, мы можем работать с ним, как с одним, используя 'multiword' (многословные) конструкции.

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

Множественное число от 'record player' — это 'record players', то есть используется та же парадигма, что и для gramophone (gramophone__n)— мы просто добавляем 's'. Всё, что нам нужно сделать — это добавить новый элемент в главный раздел.

<e lm="record player"><i>record<b/>player</i><par n="gramophone__n"/></e>

Единственное различие — использование тега , хотя и это не ново, поскольку мы видели это в файле с правилами.

Перекомпилируем и тестируем:

$ echo "vidim gramofone" | lt-proc sh-en.automorf.bin | \
  gawk 'BEGIN{RS="$"; FS="/";}{nf=split($1,COMPONENTS,"^"); for(i = 1; i<nf; i++) printf COMPONENTS[i]; if($2 != "") printf("^%s$",$2);}' | \
  apertium-transfer apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin  | \
  lt-proc -g sh-en.autogen.bin
I see record players


Отлично. Огромная выгода использования 'multiwords' (многословные конструкции) заключается в том, что можно переводить идиоматические выражения дословно, без необходимости пословного перевода. Например, английская фраза "at the moment" (сейчас, в данный момент) будет переведена на сербскохорватский как "trenutno" (trenutak — момент, trenutno — наречие, образованное от него) — было бы невозможно перевести эту фразу на сербскохорватский пословно.

Работа с незначительными вариациями[edit]

Сербскохорватский язык имеет несколько вариантов написания, из-за диалектических вариаций. Этот язык имеет интересную фонетическую письменную систему — как слышится, так и пишется. Например, люди, говорящие на Иекавском диалекте сказали бы "rječnik", в то же время, кто-нибудь говорящий на Экавском сказал бы "rečnik". Это отражает разницу в произношении праславянской гласной 'ят'.

Анализ[edit]

Должен существовать легкий способ борьбы с этим, и он есть: снова использовать парадигмы. Они используются не только для добавления грамматических символов, но и для замены букв и символов. Для примера, посмотрите на парадигму для распознавания при анализе и "e" и "je". Эта парадигма, как и остальные, должна быть записана в cербохорватский словарь.

  <pardef n="e_je__yat">
    <e>
      <p>
        <l>e</l>
        <r>e</r>
      </p>
    </e>
    <e>
      <p>
        <l>je</l>
        <r>e</r>
      </p>
    </e>
  </pardef>

Затем в главном разделе:

    <e lm="rečnik"><i>r</i><par n="e_je__yat"/><i>čni</i><par n="rečni/k__n"/></e>

Это позволяет нам только анализировать обе формы, а если мы хотим и генерировать обе формы, то нужно проделать больше работы.

Генерация[edit]

См. также[edit]