Jak zrobić nową parę języków

From Apertium
Revision as of 19:40, 4 December 2010 by J3rry (talk | contribs) (→‎Wprowadzenie: Poprawki stylistyczne/językowe)
Jump to navigation Jump to search

Ten artykuł opisuje, jak stworzyć od początku, nową parę języków dla systemu tłumaczenia automatycznego Apertium.

Nie zawiera, żadnej wiedzy na temat językoznawstwa lub tłumaczenia automatycznego powyżej poziomu możliwości odróżniania rzeczowników od czasowników (i przyimków itp.)

Wprowadzenie

Apertium jest, jak się zapewne domyślasz, systemem do automatycznego tłumaczenia komputerowego. Dokładniej mówiąc jest to platforma stworzona do tego celu. Zawiera silnik oraz zbiór narzędzi, które pozwalają na zbudowanie własnego systemu translacji. Jedyną rzeczą, którą użytkownik musi wykonać to wprowadzenie danych. Podstawowo są to trzy słowniki oraz kilka zasad (np. zmiany szyku zdania lub gramatyki).

Bardziej szczegółowe wprowadzenie na temat jak to wszystko działa znajdziesz w dziale Publications.

Wymagania

  • lttoolbox (>= 3.0.0)
  • libxml utils (xmllint itp.)
  • apertium (>= 3.0.0)
  • edytor tekstu (lub specjalny edytor XML)

Nie będę opisywał jak zainstalować powyższe narzędzia, informacje o tym możesz znaleźć w dokumentacji projektu.

Na czym polega para języków?

Apertium jest typem maszyn do translacji który pracuje na słownikach i płytkich reguł transferowych. Zasadniczą różnicą pomiędzy głębokimi a płytkimi zasadami jest to że płytkie zasady nie analizują składni i działają na grupach jednostek leksykalnych, zamiast używania drzew. Na początku wykorzystywane będą trzy główne słowniki:

  1. Jednojęzyczny slownik dla języka xx: zawiera on zasady jak odmienia się słowa w języku xx. W naszym przykładzie będzie to:

apertium-sh-en.sh.dix

  1. Jednojęzyczny slownik dla języka yy: zawiera on zasady jak odmienia się słowa w języku yy. W naszym przykładzie będzie to:

apertium-sh-en.en.dix

  1. Dwujęzyczny słownik: zawierający zależności pomiędzy słowami i symbolami w tych dwóch językach. W naszym przykłedzie będzie to:
apertium-sh-en.sh-en.dix

W parze tej, obydwa języki mogą być źródłem lub wynikiem translacji.

Istnieją również dwa pliki opisujące zasady transferu. Opisują one w jaki sposób przeorganizować szyk słów. Regulują one też wpływ płci, liczb itp. Zasady te mogą też być używane do dodawania lub usuwania elementów leksykalny, będzie to opisane później. Są to pliki:

  • zasady transferu języka xx do języka yy: ten plik zawiera jak powinno się zamieniać język xx w yy. W naszym przyĸładzie będzie to:

apertium-sh-en.sh-en.t1x

  • zasady transferu języka yy do języka xx: ten plik zawiera jak powinno się zamieniać język yy w xx. W naszym przyĸładzie będzie to:

apertium-sh-en.en-sh.t1x

Wiele par językowych posiada dodatkowe pliki, jednak nie będą tu opisywane. Powyższe pliki wystarczają do stworzenia funkcjonalnego systemu.

Przykładowa para

Jak możesz zauważyć po nazwach plików, ten artykuł będzie pokazywał przykład tworzenia podstaw translatora Serbsko-Chorwackiego do Angielskiego. Nie jest to idealna para, ponieważ system działa lepiej dla języków mających więcej wspólnego z sobą. Jednak nie powinno to przeszkadzać, dla tak prostych przykładów jakie będą zaprezentowane.

Wyjaśnienie używanych pojęć

Tutaj jest kilka pojęć które musisz zrozumieć zanim będziemy kontynuować.

Pierwszym jest lemma. Jest to forma podstawowa słowa. Jest to najczęściej najprostrza z dostępnych form. Dla przykładu, lemma słowa cats to cat. W języku angielskim lemmy rzeczowników są zazwyczaj w liczbie pojedynczej. Dla czasowników, lemma jest bezokolicznikiem, np. lemmaem was będzie be.

Następnym jest symbol. In the context of the Apertium system, symbol refers to a grammatical label. The word cats is a plural noun, therefore it will have the noun symbol and the plural symbol. In the input and output of Apertium modules these are typically given between angle brackets, as follows:

  • <n>; dla rzeczownika
  • <pl>; dla liczby mnogiej.

Nastepnymi przykładami symboli są <sg>; liczba pojedyńcza, <p1> pierwsza osoba etc. Kiedy napisane są w nawiasach kwadratowych, symole mogą być też traktowane jako tagi. Warto zauważyć, że w wielu obecnie dostępnych par jezykowych definicje symboli są akronimami lub skrótami. Symbole definiowane są w tagu <sdef> i używane w <s>

Trzecie pojęcie to paradygmat. W ramach systemu Apertium, paradygmat odnosi się do przykładu tego, jak powinno odmieniać się daną grupę słów. W słownikach jednojęzykowych, lemmy (patrz wyżej) są przypisane do paradygmatów, które pozwalają w jaki sposób dana lemma odmienia się, bez koniecznosci zapisywania wszystkich końcówek.

Poniższy przykład pokazuje użyteczność tego podejscia, weźmy dwa przymiotniki happy i lazy:

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

Możemy prosto zapisać jedno, a następnie powiedzieć, "lazy odmienia się jak happy" lub jeżeli potrzebujemy "shy odmienia się jak happy", "naughty odmienia się jak happy", "friendly odmienia się jak happy", itd. W tym przyĸładzie, happy może być modelem pokazyjącym jak powinno się odmieniać inne słowa. Parydgmaty definiuje się w tagu <paradef>, a używa w tagu <par>.

Na początek

Słowniki jednojęzyczne

See also: List of dictionaries and Incubator

Zacznijmy od stworzenia pierwszego słownika. Jest on dokumentem XML, uruchom swój edytor i wpisz:

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

</dictionary>

Tak więc plik opisuje na razie pusty słownik. Aby był przydatny musimy dodać kilka innych wpisów, pierwszym będzie alfabet. Definiuje on zbiór liter które mogą być użyte. Dla słownika Serbsko-Chorwackiego będzie wyglądał tak:

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

Umieść go poniżej tagu <dictionary>.

Następnie będziemy potrzebowali zdefiniować kilka symboli. Zacznijmy od prostych rzeczy jak: rzeczownik (n) w liczbie pojedynczej (sg) i mnogiej (pl).

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

Nazwy symboli nie muszą być tak krótkie, w rzeczywistości mogą być napisane w całości, lecz częste używanie długich nazw może być męczące.

Niestety, to nie jest tak proste, rzeczowniki w Sarbsko-Chorwackim odmieniają się także od płci i przypadku. Jednak zakładamy w tym przykładzie, że rzeczownik jest rodzaju męskiego w mianowniku ( jednak pełny przykład można znaleźć na końcu niniejszego dokumentu).

Następnym krokiem jest zdefinowanie sekcji dla paradygmatów,

<pardefs>

</pardefs>

oraz sekcji słownika:

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

</section>

Istnieją dwa typy sekcji, pierwszym jest sekcja standardowa, która zawiera słowa itp. Drugim typem sekcji jest inconditional section zawierająca znaki interpunkcyjne itp. Opisywany przykład nie zawiera drugiego typu.

Plik na obecną chwilę powinien wyglądać tak:

<?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>

Więc mamy szkielet, możemy juz rozpocząć pracę dodając rzeczownik. Rzecznikiem tym będzie 'gramofon'.

Pierwszą rzeczą, jaką musimy zrobić, jest określenie paradygmatu, ponieważ nie określiliśmy wcześniej żadnego.

Pamiętaj, że używamy rodzaju męskiego w mianowniku. Liczba pojedyncza tego rzeczownika jest 'gramofon', a mnoga 'gramofoni'. Tak więc:

<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>

Uwaga: '<l/>' (odpowiednik <l></l>) oznacza że niema do dodania dodatkowych znaków do rdzenia słowa w l. pojedynczej.

Może to wyglądać na dość rozwlekłą drogą do opisywania tego, lecz są do tego powody oraz dodatkowo szybko staje się naturalne. Prawdopodobnie zastanawiasz się co oznaczają tagi <e>,

, <l> i <r>. A więc:

  • e, jest głównym słowem.
  • p, jest dla par.
  • l, jest z lewej strony.
  • r, jest z prawej strony.

Dlaczego z lewej i prawej? 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:

* gramofoni (od lewej do prawej) gramofon<n><pl> (analiza)
* gramofon<n><pl> (od prawej do lewej) gramofoni (generowanie)

Więc zdefinowaliśmy paradygmat, teraz musimy połączyć z jego lemmaem, "gramofon". Umieśćmy to w sekcji w której go zdefinowaliśmy.

To co mamy zamiar umieścić w </dictionary>

Teraz musimy dodać wpis do translacji pomiędzy dwoma słowami. Wygląda to tak:

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

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.

Gdy to skończysz, uruchom poniższe komendy:

$ 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

Do wygenerowania analizatorów jednojęzykowych (automorf) jak i generatorów (autogen), tłumaczeń słów (autobil), bil oznacza dwujęzyczny.

Zasady Transferu

Więc, mamy dwa jednojęzyczne słowniki, oraz jeden dwujęzyczny. Wszystko czego potrzebujemy teraz jest przeniesienie zasad opisanych dla rzeczowników. Pliki te posiadają własne DTD (transfer.dtd) które możesz znaleść w pakiecie Apertium. Jeżeli potrzebujesz zaimplementować jakaś zasadę przydatnę jest spojrzenie jak zostało to zrobione w innych plikach. Wiele z nich może być używane ponownie pomiędzy róznymi językami. Przykład opisany poniżej może być używany dla wszystkich języków z domyślnym podmiotem.

Zacznijmy podobnie jak w poprzednich przykładach, od szkieletu:

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

</transfer>

W tym momencie musimy jedynie stworzyć zasadę, która będzie brała symbole gramatyczne i przesyłała je ponownie.

Pierw musimy zdefinować kategorie oraz atrybuty. Obydwie będą używane do grupowania symboli gramatycznych. Kategorie pozwalają nam do grupowania symboli które pasują do pewnego wzorca (dla przykładu 'n.*' dla wszystkich rzeczowników). Atrybuty z koleji zbiór grup symboli z którch możemy wybierać.

Dodajmy więć niezbędne sekcje:

<section-def-cats>

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

</section-def-attrs>

Jeżeli odmieniamy, przymiotniki od liczby to potrzebujemy dodać kategorie dla rzeczowników, a także atrybut. Coś takiego powinno wystarczyć.

W section-def-cats dodaj:

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

To wyłapuje wszystkie rzeczowniki, i odnosci się do "nom" (póżniej zobaczysz jak tego używać).

W sekcji section-def-attrs, dodaj:

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

a następnie

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

Pierwsza definiuje atrybut nbr (liczbę), która może być liczbą pojedyńczą (sg) lub mnogą pl).

Druga definiuje atrybut a_nom (atrybut rzeczownika).

Następnie musimy dodać sekcje dla globalnych zmiennych:

<section-def-vars>

</section-def-vars>

Te zmienne będą używane do przechowywania lub przenoszenia atrybutów pomiędzy zasadami. Na razie wystarczy tylko to,

<def-var n="number"/>

Ostatecznie, musimy dodać zasadę, która weźmie rzeczownik i odda go w poprawnej formie. Potrzebować będziemy do tego sekcji zasad...

<section-rules>

</section-rules>

Przyśpieszmy trochę. Po prostu dodaj poniższą zasadę, a następnie przejdź dalej.

<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>

Pierwszy tag jest oczywisty, definiuje zasadę. Drugi mówi: "zastosują tą zasadę, jęzeli pasuje do wzorca". W tym przykładzie wskazuje na rzeczownik w liczbie poj. (zdefinowany przez kategorię "nom"). Uwaga: wzorce sa dostosowywane w kolejnosci od najdłuższego pasującego. Więc jeżeli masz trzy asady, pierszą łapiącą "<prn><vblex><n>", drugą "<prn><vblex>" i trzecią łapiącą "<n>", pierszą zastosowaną regułą będzie właśnie reguła pierwsza.

Dla każdego wzorca, jest też akcja która powinna być wykonana, która produkuje na wyjście będące jednostką leksykalną (lu).

Pominięte tagi pozwalają użytkownikowi do wybrania i manipulowania na atrybutach i elementach języka źródłowego (side="sl") lub docelowego (side="tl") elementu leksykalnego.

Skompilujmy i przetestujmy więc to. Zasady transferu kompilujemy za pomocą:

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

Które powinno wygenerować plik sh-en.t1x.bin.

Teraz jesteśmy gotowi by przetestować własnego translatora. Pominięto to jedną ważną część, tagger part-of-speech (PoS), jednak będzie to później wytłumaczone krótko. Na razie możemy przetestować to.

Pierw, zanalizujmy słowo, gramofoni:

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

Normalnie tagger PoS powinien wybrać prawą wersje, jednak go teraz nieposiadamy, więć użyjmy tego skryptu (podziękowania dla Sergio), on powinien zwrócić tylko odpowiednią wersje.

$ 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>$

Wykorzystajmy to razem z zasadami transferu:

$ 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

Powinniśmy otrzymać:

^gramophone<n><pl>$^@
  • 'gramophone' jest w języku docelowym (side="tl") lemma (lem) na pozycji pierwszej (pos="1").
  • '<n>' jest a_nom na pozycji pierwszej w języku docelowym.
  • '<pl>' jest atrybutem numeru (nbr) na pozycji pierwszej w języku docelowym.

Spróbuj zakomentować jedną z zasad, zrekompilować i zobaczyć co się stanie.

Więc, mamy teraz plik wyjściowy z transferu, ostatnią rzeczą jaką musimy się zająć jest wygenerowanie odmienionych form języka docelowego. Do wykonania tej czynności użyjemy lt-proc, w trybie generacji (-g), a nie w trybie analizy (-a).

$ 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\@

Posiadasz teraz system tłumaczenia maszynowego, który tłumaczy serbsko-chorwacki rzeczownik na rzeczownik angielski. Oczywiście nie jest to bardzo przydatne, ale niedługo dojdziemy do bardziej skomplikowanych rzeczy. Nie martw się tym symbolem --> '@', później wyjaśnię po co się go używa.

Pomyśl o kilku innych słowach odmieniających się w ten sam sposób co słowo gramofon. Co myślisz o dodaniu tych słów. Nie musimy dodawać żadnych paradygmatów, wystarczy tylko dodać wpisy w głównych sekcjach słownika jednojęzycznego i dwujęzycznego.

Pora na czasowniki

Ok, mamy system, który tłumaczy rzeczowniki, ale jest to trochę bezużyteczne, chcemy też przecież tłumaczyć czasowniki, a nawet całe zdania! Może na początek zaczniemy z tłumaczeniem czasowników. W serbsko-chorwackim czasownik nazywa się 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
  • see<p1><sg>
  • I see

Note: <p1> denotes first person

To będzie bardzo ważne, gdy będziemy pisali zasadę transferu dla czasowników. Inne przykłady języków "null-subject" obejmują: Hiszpański, Rumuński i Polski. Wynika to także z tego, że, gdy w serbsko-chorwackim słowniku morfologicznym musimy dodać tylko czasownik, w angielskim słowniku morfologicznym musimy dodać czasownik i zaimek osobowy. Przeanalizujemy oba sposoby.


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.

There are two forms of you see, one is plural and formal singular (vidite) and the other is singular and informal (vidiš).

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.

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.

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'.

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

After we've done this, the same with the nouns, we add a paradigm for the verb conjugation. The first line will be:

<pardef n="vid/eti__vblex">

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:


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

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:

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

Note: the content of <i> </i> is the root, not the lemma.

Thats the work on the Serbo-Croatian dictionary done for now. Lets compile it then test it.

$ 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>$

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:

<pardef n="s/ee__vblex">

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.


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

and as always, an entry in the main section:

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

Then lets save, recompile and test:

$ 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>$

Now for the obligatory entry in the bilingual dictionary:

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

(again, don't forget to add the sdefs from earlier)

And recompile:

$ 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

Now to test:

$ 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>$^@

We get the analysis passed through correctly, but when we try and generate a surface form from this, we get a '#', like below:

$ 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\@

This '#' means that the generator cannot generate the correct lexical form because it does not contain it. Why is this?

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 (apertium-sh-en.sh-en.t1x sh-en.t1x.bin sh-en.autobil.bin in case you forgot).

We need to add a new category for 'verb'.

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

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.

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

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

We should also add an attribute for verbs.

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

Now onto the rule:

<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>

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).

So now, if we recompile that, we get:

$ 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>$^@

and:

$ 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\@

Try it with 'vidimo' (we see) to see if you get the correct output.

Now try it with "vidim gramofone":

$ 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\@

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:

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

Of the two symbols, prn is pronoun, and subj is subject (as in the subject of a sentence).

Because there is no root, or 'lemma' for personal subject pronouns, we just add the pardef as follows:

<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>

With 'prsubj' being 'personal subject'. The rest of them (You, We etc.) are left as an exercise to the reader.

We can add an entry to the main section as follows:

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

So, save, recompile and test, and we should get something like:

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

(Note: it's in capitals because 'I' is in capitals).

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):

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

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:

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

And now to input the rule:

<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>

This is pretty much the same rule as before, only we made a couple of small changes.

We needed to output:

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

so that the generator could choose the right pronoun and the right form of the verb.

So, a quick rundown:

  • <lit>, prints a literal string, in this case "prpers"
  • <lit-tag>, 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.
  • , prints a blank, a space.

Note that we retrieved the information for number and tense directly from the verb.

So, now if we recompile and test that again:

$ 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

Which, while it isn't exactly prize-winning prose (much like this HOWTO), is a fairly accurate translation.

So tell me about the record player (Multiwords)

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.

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

The only thing different about this is the use of the 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:

$ 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

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) — it would not be possible to translate this English phrase word-by-word into Serbo-Croatian.

Radzenie sobie z dialektami

Serbko-Chorwacki typowo posiada kilka dróg do zapisania każdego słowa, z powodu różnych dialektów. Posiada fajny system zapisywania fonetycznego więc morzesz pisać tak jak wymawiasz.

Analizer

Nie powinno być trudnę stworzenie czegoś takiego, prawda? I nie jest, można to wykonać też za pomocą parydgmatów. Nie są tylko do dodawania gramatycznych symboli, ale mogą być też używane do zamieniania dowolnego znaku/symbolu w inny. DLa przykładu, tutaj jest paradygmat który akceptuje "e" i "je" w analizie. Ten paradygmat powinien, trafić z innymi do jednojęzycznego słownika Serbsko-Chorwackiego.

  <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>

Następnie w głównej sekcji:

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

To pozwala tylko do analizy tych dwóch form, jednakże... czeka nas więcej pracy jeżeli chcemy generować obydwie formy.

Generator

Zobacz też