Locale::Po4a::TransTractor(3pm)

ИМЕ
Locale::Po4a::TransTractor - генерички транс(латор екс)трактор.

ОПИС
Циљ po4a (PO for anything – PO за било шта) пројекта је да поједностави превођење (и што је још интересантније, одржавање превода) употребом gettext алата на деловима на којима се не очекује њихова употреба, као што је документација.

Ова класа је предак сваког po4a парсера који се користи за парсирање документа, за претрагу стрингова који могу да се преведу, за њихово издвајање у PO фајл и њихову замену са својим преводима у излазном документу.

Формалније речено, она узима као улаз следеће аргументе:

-   документ који се преводи;

-   PO фајл са преводима који треба се употребе.

Као излаз, она креира:

-   други PO фајл, који настаје као резултат издвајања преводивих стрингова из улазног документа;

-   преведени документ, са истом структуром као и онај са улаза, али у коме су сви стрингови замењени са преводима пронађеним у PO фајлу који је наведен у улазу.

Ево графичке представе овога:

   Улазни документ --\                             /---> Излазни документ
                      \                           /       (преведен)
                       +-> parse() функција -----+
                      /                           \
   Улазни PO --------/                             \---> Излазни PO
                                                         (издвојен)

ФУНКЦИЈЕ КОЈЕ БИ ВАШ ПАРСЕР ТРЕБАЛО ДА ПРЕИНАЧИ

parse()
    Ово је место на којем се обавља сав посао: парсирање улазних докумената, генерисање излаза и издвајање преводивих стрингова. Ово је прилично једноставно употребом приложених функција приказаних у одељку ИНТЕРНЕ ФУНКЦИЈЕ испод. Погледајте такође СИНОПСИС, који представља пример.

    Ову функцију позива функција process() испод, али ако изаберете да користите функцију new(), и да ручно додате садржај у свој документ, ову функцију ћете морати сами да позовете.

docheader()
    Ова функција враћа заглавље које би требало да се дода у креирани документ, прописно цитирано тако да буде коментар у циљном језику. Погледајте одељак Едуковање девелопера у вези превода, из po4a(7), у вези онога за шта је добра ова функција.

СИНОПСИС
Следећи пример парсира листу пасуса који почињу са „<p>”. Ради једноставности, претпостављамо да је документ добро форматиран, тј. да су ’<p>’ ознаке једине присутне ознаке, и да се ова ознака налази на самом почетку сваког пасуса.

 sub parse {
   my $self = shift;

   PARAGRAPH: while (1) {
       my ($paragraph,$pararef)=("","");
       my $first=1;
       my ($line,$lref)=$self->shiftline();
       while (defined($line)) {
           if ($line =~ m/<p>/ && !$first--; ) {
               # Није први пут да видимо <p>.
               # Поново постави текућу линију у улаз,
               # и стави изграђени пасус у излаз
               $self->unshiftline($line,$lref);

               # Сада када је документ формиран, преведи га:
               #   - Уклони водећу ознаку
               $paragraph =~ s/^<p>//s;

               #   - гурни у излаз водећу ознаку (непреведену) као и
               #     остатак пасуса (преведен)
               $self->pushline(  "<p>"
                               . $self->translate($paragraph,$pararef)
                               );

               next PARAGRAPH;
           } else {
               # Додај на крај пасуса
               $paragraph .= $line;
               $pararef = $lref unless(length($pararef));
           }

           # Поново иницијализуј петљу
           ($line,$lref)=$self->shiftline();
       }
       # Није добијена дефинисана линија? Крај улазног фајла.
       return;
   }
 }

Једном када сте имплементирали функцију за парсирање, можете да употребите своју класу документа, користећи јавни интерфејс који је представљен у следећем одељку.

ЈАВНИ ИНТЕРФЕЈС за скрипте које користе ваш парсер

  Конструктор

process(%)
    Ова функција може да уради све што је потребно да се уради са po4a документом у једном позиву. Њени аргументи морају да се упакују као хеш. АКЦИЈЕ:

    а.  Чита све PO фајлове наведене у po_in_name

    б.  Чита све оригиналне документе наведене у file_in_name

    г.  Парсира документ

    д.  Чита и примењује све наведене додатке

    ђ.  Уписује преведени документ у file_out_name (ако је задато)

    е.  Уписује издвојени PO фајл у po_out_name (ако је задато)

    АРГУМЕНТИ, уз оне које прихвата new() (са очекиваним типом):

    file_in_name (@)
        Листа имена фајлова из којих би требало да прочитамо улазни документ.

    file_in_charset ($)
        Скуп карактера који се користи у улазном документу (ако није наведен, покушаће се са детекцијом из улазног документа).

    file_out_name ($)
        Име фајла у који би требало да упишемо излазни документ.

    file_out_charset ($)
        Скуп карактера који се користи у излазном документу (ако није наведен, користиће се скуп карактера PO фајла).

    po_in_name (@)
        Листа имена фајлова из којих би требало да се читају PO фајлови, они који садрже преведене стрингове који ће се користити за превод документа.

    po_out_name ($)
        Име фајла у који би требало да упишемо излазни PO фајл, који садржи стрингове издвојене из улазног документа.

    addendum (@)
        Листа имена фајлова из којих треба да се читају додаци.

    addendum_charset ($)
        Скуп карактера за додатке.

new(%)
    Креира нови po4a документ. Прихватају се опције (у хешу који се прослеђује као параметар):

    verbose ($)
        Поставља детаљност извештавања.

    debug ($)
        Поставља режим исправљања грешака.

  Манипулација фајловима докумената

read($$)
    Додаје податке другог улазног документа на крај постојећег низа "@{$self->{TT}{doc_in}}". Аргумент је име фајла који треба да се прочита. Ако се зада и други аргумент, он представља име фајла који треба да се користи у референцама.

    Низ "@{$self->{TT}{doc_in}}" чува податке из овог улазни документа као низ стрингова са наизменичним значењима.
     * Стринг $textline који држи сваку линију улазног текста.
     * Стринг "$filename:$linenum" који држи његову локацију и који се
       зове "reference" ("linenum" почиње од 1).

    Имајте на уму, молим вас, да ово још ништа не парсира. Када завршите са паковањем улазних фајлова у документ, требало би да употребите функцију parse().

write($)
    Уписује преведени документ у фајл са датим именом.

    Ови подаци преведеног документа се добијају из:
     * "$self->docheader()" који чува текст заглавља за модул додатка, и
     * "@{$self->{TT}{doc_out}}" који у низу чува сваку линију главног преведеног текста.

  Манипулација PO фајловима

readpo($)
    Додаје садржај фајла (чије име је прослеђено као аргумент) постојећем улазном PO. Стари садржај се не одбацује.

writepo($)
    Уписује издвојени PO фајл у дато име фајла.

stats()
    Враћа неке статистичке податке у вези до сада одрађеног превода. Имајте не уму, молим вас, да ово није иста статистика коју исписује msgfmt --statistic. Овде је то статистика у вези скорашње употребе PO фајла, док msgfmt пријављује статус фајла. То је функција која обавија функцију Locale::Po4a::Po::stats_get function примењену на улазни PO фајл. Пример употребе:

        [нормална употреба po4a документа...]

        ($percent,$hit,$queries) = $document->stats();
        print "Пронашли смо преводе за $percent\%  ($hit од $queries) стрингова.\n";

  Манипулација додацима

addendum($)
    Молимо погледајте po4a(7) за више информација о томе шта су додаци, и како би преводиоци требало да их пишу. Да бисте применили додатак на преведени документ, једноставно проследите име његовог фајла овој функцији и то је то ;)

    У случају грешке, ова функција враћа цео број различит од нуле.

ИНТЕРНЕ ФУНКЦИЈЕ које се користе за писање изведених парсера

  Добављање улаза, обезбеђивање излаза
За преузимање улаза и враћање излаза се користе четири функције. Оне су врло сличне са shift/unshift и push/pop у језику Perl.

 * Perl shift враћа прву ставку низа и уклања је из њега.
 * Perl unshift ставља ставку на почетак низа као прву.
 * Perl pop враћа последњу ставку низа и уклања је из њега.
 * Perl push додаје ставку у низ као последњу.

Први пар се тиче улаза, док је други у вези излаза. Да се лакше упамти: за улаз вам је од интереса прва линија, а то је управо оно што враћа shift, док за излаз желите да свој резултат додате на крај, као што то ради push.

shiftline()
    Ова функција враћа прву линију која треба да се парсира у њену одговарајућу референцу (упаковано као низ) из низа "@{$self->{TT}{doc_in}}" и уклања ове прве 2 ставке низа. Референцу овде обезбеђује стринг "$filename:$linenum".

unshiftline($$)
    Unshift-ује последњу shift-овану линију улазног документа и њену одговарајућу референцу назад на почетак "{$self->{TT}{doc_in}}".

pushline($)
    Ради push нове линије на крај "{$self->{TT}{doc_out}}".

popline()
    Ради pop последње push-оване линије са краја "{$self->{TT}{doc_out}}".

  Обележавање стрингова као преводивих
Достављена је једна функција која обрађује текст предвиђен за превођење.

translate($$$)
    Обавезни аргументи:

    -   Стринг за превођење

    -   Референца овог стринга (тј. позиција у улазном фајлу)

    -   Тип овог стринга (тј. текстуални опис његове структурне улоге; користи се у Locale::Po4a::Po::gettextization(); погледајте такође po4a(7), одељак На који начин програм функционише?)

    И ова функција може да узме неколико додатних аргумената. Они морају да се организују у хеш. На пример:

      $self->translate("string","ref","type",
                       'wrap' => 1);

    wrap
        логичка вредност која назначава можемо ли претпоставити да празни карактери у стрингу нису битни. Ако је истинита, функција канонизује стринг пре тражења превода или његовог издвајања, и обавија превод.

    wrapcol
        колона око које се врши обавијање (подразумевано: 76).

    comment
        допунски коментар који се додаје ставци.

    Акције:

    -   Ради push стринга, референце и типа у po_out.

    -   Враћа стринг превода (као што је пронађен у po_in) и омогућава да парсер изгради doc_out.

    -   Обрађује скупове карактера како би се стрингови рекодирали пре него што се пошаљу у po_out и пре враћања превода.

  Разне функције

verbose()
    Враћа информацију да ли је током креирања објекта TransTractor прослеђена опција детаљног извештавања.

debug()
    Враћа информацију да ли је приликом креирања објекта TransTractor била прослеђена опција детаљнијег извештавања.

detected_charset($)
    Ово говори TransTractor -у да је откривен нови скуп карактера (први аргумент) у улазном документу. Обично може да се прочита из заглавља документа. Преостаће само први скуп карактера, који долази или из аргумената функције process(), или се детектује из документа.

get_out_charset()
    Ова функција ће да врати скуп карактера који би требало да се користи у излазном документу (обично је корисно за замену скупа карактера детектованог у улазном документу у коме је пронађен).

    Користиће излазни скуп карактера наведен у командној линији. Ако није био задат, користиће се скуп карактера улазног PO, а ако улазни PO има подразумевану вредност „CHARSET”, вратиће скуп карактера улазног документа, тако да се не обавља кодирање..

recode_skipped_text($)
    Ова функција враћа рекодирани текст који јој је прослеђен као аргумент, из скупа карактера улазног документа у скуп карактера излазног документа. Ово није неопходно када се се стринг преводи (функција translate() сама све рекодира), али је неопходно када прескочите стринг из улазног документа и желите да излазни документ буде у сагласности са глобалним кодирањем.

СМЕРНИЦЕ ЗА БУДУЋНОСТ
Једна од лоших страна текуће TransTractor класе је да не може обрађивати преведене документе који садрже све језике, као што су debconf шаблони, или .desktop фајлови.

Како би се решио проблем, неопходне су само следеће измене интерфејса:

-   po_in_name треба да узима хеш (листу за сваки појединачни језик)

-   додати аргумент функцији translate који наводи циљни језик

-   креирати функцију pushline_all, која би одрадила pushline свог садржаја за све језике, користећи синтаксу сличну са map:

        $self->pushline_all({ "Description[".$langcode."]=".
                              $self->translate($line,$ref,$langcode)
                            });

Видећемо да ли је ово довољно ;)

АУТОРИ
 Дени Барбије <barbier@linuxfr.org>
 Мартин Квинсон (mquinson#debian.org)
 Жорди Вилалта <jvprat@gmail.com>