NAZWA¶
Locale::Po4a::TransTractor - ogólny moduł wyodrębniania
tłumaczeń.
OPIS¶
Celem projektu po4a ("PO for anything") jest ułatwienie
tłumaczeń (oraz, co ciekawsze, zarządzania tłumaczeniami)
przy użyciu narzędzi gettext w tych obszarach, gdzie nie były
używane, jak na przykład w obszarze dokumentacji.
Ta klasa jest przodkiem wszystkich parserów po4a używanych do
przetwarzania dokumentu w poszukiwaniu komunikatów do
przetłumaczenia, wyodrębniania ich do pliku PO oraz
zastępowania ich tłumaczeniami w wyjściowym dokumencie.
Bardziej formalnie mówiąc, przyjmuje następujące argumenty
jako wejście:
- -
- dokument do przetłumaczenia;
- -
- plik PO zawierający tłumaczenia do
użycia.
Jako wynik dostajemy:
- -
- inny plik PO, czego wynikiem jest wyciągnięcie
komunikatów możliwych do przetłumaczenia z dokumentu
wejściowego;
- -
- przetłumaczony dokument o takiej samej strukturze, co
dokument wejściowy, ale ze wszystkimi komunikatami możliwymi do
przetłumaczenia zamienionymi na tłumaczenia znalezione w
wejściowym pliku PO.
Graficzna reprezentacja tego procesu:
Dokument wejściowy --\ /--> Dokument wyjściowy
\ / (przetłumaczony)
+-> funkcja parse() ---+
/ \
Wejściowy PO --------/ \--> Wyjściowy PO
(wyodrębniony)
FUNKCJE, KTÓRE TWÓJ PARSER POWINIEN NADPISAƶ
- parse()
- Jest to miejsce, gdzie odbywa się cała praca:
parsowanie dokumentów wejściowych, generowanie wyjścia,
wyodrębnianie komunikatów do przetłumaczenia. Jest to
bardzo proste, jeśli użyje się funkcji opisanych
poniżej, w sekcji FUNKCJE WEWNĘTRZNE. Patrz także
sekcja SKŁADNIA, zawierająca przykład.
Ta funkcja jest wywoływana przez poniższą funkcję
proces(), ale jeżeli wybierze się użycie funkcji
new() i ręczenie się doda zawartość do
dokumentu, trzeba będzie wywołać tę funkcję
samemu.
- docheader()
- Funkcja zwraca nagłówek, który powinien
zostać dodany do wygenerowanego dokumentu, odpowiednio przygotowany,
tak żeby mógł być komentarzem w języku docelowym.
Aby dowiedzieć się, do czego to służy, proszę
przeczytać sekcję Przekazywanie deweloperom wiedzy o
tłumaczeniu w po4a(7).
SKŁADNIA¶
Następujący przykład przetwarza listę akapitów
rozpoczynających się od "<p>". Dla uproszczenia,
zakładamy, że dokument jest dobrze sformatowany, tj.
występują tylko elementy "<p>" i są one
umieszczone na samym początku każdego akapitu.
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--; ) {
# Nie po raz pierwszy widzimy <p>.
# Włóż z powrotem bieżącą linię do wejścia,
# i dodaj zbudowany akapit do wyjścia
$self->unshiftline($line,$lref);
# Teraz, gdy dokument jest sformatowany, przetłumaczmy go:
# - Usunięcie początkowych tagów
$paragraph =~ s/^<p>//s;
# - dodanie do wyjścia początkowego elementu (nieprzetłumaczonego)
# i reszty akapitu (przetłumaczonej)
$self->pushline( "<p>"
. $document->translate($paragraph,$pararef)
);
next PARAGRAPH;
} else {
# Dodanie do akapitu
$paragraph .= $line;
$pararef = $lref unless(length($pararef));
}
# Ponowna inicjacja pętli
($line,$lref)=$self->shiftline();
}
# Nie dostaliśmy zdefiniowanej linii? Koniec pliku wejściowego.
return;
}
}
Po zaimplementowaniu funkcji parsującej, można użyć
własnych klas dokumentu, używając publicznego interfejsu
zaprezentowanego w następnym rozdziale.
INTERFEJS PUBLICZNY dla skryptów używających
Twojego parsera¶
Konstruktor¶
- process(%)
- Funkcja zrobi w jednym uruchomieniu wszystko, co tylko
trzeba zrobić z dokumentem po4a. Jej argumenty muszą być
umieszczone w hashu. AKCJE:
- a.
- Czyta wszystkie pliki określone w po_in_name
- b.
- Czyta wszystkie oryginalne dokumenty określone w
file_in_name
- c.
- Przetwarza (parsuje) dokument
- d.
- Dodaje i stosuje wszystkie podane załączniki
- e.
- Zapisuje przetłumaczony dokument do file_out_name
(jeśli podano)
- f.
- Zapisuje wygenerowany plik PO do po_out_name (jeśli
podano)
ARGUMENTY, poza tymi akceptowanymi przez
new() (z oczekiwanym typem):
- file_in_name (@)
- Lista nazw plików, z których powinniśmy
odczytać plik wejściowy.
- file_in_charset ($)
- Kodowanie znaków dokumentu wejściowego
(jeśli nie podano, nastąpi próba określenia kodowania
z dokumentu wejściowego).
- file_out_name ($)
- Nazwa pliku, do którego należy zapisać
wynikowy dokument.
- file_out_charset ($)
- Kodowanie znaków wyjściowego dokumentu
(jeśli nie podano, będzie użyte kodowanie znaków pliku
PO).
- po_in_name (@)
- Lista nazw plików, z których powinniśmy
odczytać wejściowe pliki PO zawierające tłumaczenia,
które będą użyte podczas tłumaczenia
dokumentu.
- po_out_name ($)
- Nazwa pliku, do którego powinien być zapisany
wynikowy plik PO, zawierający komunikaty wyciągnięte z
dokumentu wejściowego.
- addendum (@)
- Lista nazw plików, z których powinniśmy
odczytać pliki załączników.
- addendum_charset ($)
- Kodowanie znaków załączników.
- new(%)
- Tworzy nowy dokument po4a. Akceptowane opcje
(będące w hashu):
- verbose ($)
- Ustawia gadatliwość.
- debug ($)
- Ustawia debugowanie.
Manipulowanie plikami z dokumentacją¶
- read($)
- Dodaje kolejny dokument wejściowy na koniec
istniejącego dokumentu. Argumentem jest nazwa pliku do odczytania.
Proszę zauważyć, że to niczego nie przetwarza.
Należy użyć funkcji parse() po zakończeniu
pakowania plików wejściowych do dokumentu.
- write($)
- Zapisuje przetłumaczony dokument do pliku o podanej
nazwie.
Manipulowanie plikami PO¶
- readpo($)
- Dodaje zawartość pliku (którego nazwa jest
podawana w argumencie) do istniejącego pliku wejściowego PO.
Stara zawartość nie jest tracona.
- writepo($)
- Zapisuje wygenerowany plik PO do pliku o podanej
nazwie.
- stats()
- Zwraca statystyki dotyczące tłumaczeń.
Proszę zauważyć, że nie są to te same statystyki,
które wypisuje msgfmt --statistic. Tutaj są to statystyki o
obecnym wykorzystaniu pliku PO, podczas gdy msgfmt wyświetla status
tego pliku. Funkcja jest opakowaniem funkcji Locale::Po4a::Po::stats_get
zastosowanej do wejściowego pliku PO. Przykład użycia:
[zwykłe użycie dokumentu po4a ...]
($percent,$hit,$queries) = $document->stats();
print "Znaleźliśmy tłumaczenia $percent\% ($hit z $queries) komunikatów.\n";
Manipulowanie załącznikami¶
- addendum($)
- Więcej informacji o tym, czym są
załączniki, i jak tłumacze powinni je pisać,
można znaleźć w po4a(7). Aby dodać
załącznik do przetłumaczonego dokumentu, wystarczy po
prostu tej funkcji przekazać nazwę pliku, w którym się
znajduje, i gotowe ;)
Funkcja zwraca liczbę nie będącą nullem lub
błąd.
FUNKCJE WEWNĘTRZNE, używane do pisania
parserów¶
Pobieranie wejścia, dostarczanie wyjścia¶
Dostarczone są cztery funkcje pobierania wejścia i zwracania
wyjścia. Są one bardzo podobne do shift/unshift i push/pop. Pierwsza
para dotyczy wejścia, a druga - wyjścia. Mnemonik: w wejściu
interesuje Cię pierwsza linia, co daje shift, a w wyjściu chcesz
dostać wynik na końcu, tak jak do robi push.
- shiftline()
- Funkcja zwraca kolejną linię z doc_in do
przetworzenia oraz jej odnośnik (spakowany jako tablica).
- unshiftline($$)
- Zwraca z powrotem linię dokumentu wejściowego i
jej odnośnik.
- pushline($)
- Dodaje nową linię na koniec doc_out.
- popline()
- Pobiera ostatnio wstawioną linię z doc_out.
Zaznaczanie łańcuchów znaków jako
możliwych do przetłumaczenia¶
Dostarczona jest jedna funkcja obsługująca tekst, który powinien
być przetłumaczony.
- translate($$$)
- Argumenty obowiązkowe:
- -
- Łańcuch znaków do przetłumaczenia
- -
- Odnośnik tego komunikatu (tj. pozycja w pliku
wejściowym)
- -
- Typ tego komunikatu (tj. tekstowy opis jego roli w
strukturze; używany w Locale::Po4a::Po::gettextization();
patrz także po4a(7), sekcja Proces przekształcania do
formatu gettext: jak to działa?)
Funkcja przyjmuje także kilka dodatkowych argumentów. Muszą
być zorganizowane jako hash. Na przykład:
$self->translate("string","ref","type",
'wrap' => 1);
- wrap
- flaga logiczna określająca, czy traktujemy
białe znaki w komunikacie jako nieistotne. Jeśli tak, to funkcja
przed wyszukaniem lub wyciągnięciem tłumaczenia kanonizuje
komunikat, a następnie zawija tekst tłumaczenia.
- wrapcol
- kolumna, w której tekst powinien być zawijany
(domyślnie: 76).
- comment
- dodatkowy komentarz do dodania do wpisu.
Akcje:
- -
- Dodaje nowy komunikat, odnośnik i typ do po_out.
- -
- Zwraca tłumaczenie tekstu (znalezione w po_in), tak
że parser może zbudować doc_out.
- -
- Obsługuje kodowania znaków, aby zmienić
kodowanie komunikatów przed wysłaniem do po_out i przed
zwróceniem tłumaczeń.
Różne funkcje¶
- verbose()
- Zwraca informację, czy podczas uruchomienia
TransTractora, podano opcję verbose.
- debug()
- Zwraca informację, czy podczas uruchomienia
TransTractora podano opcję debug.
- detected_charset($)
- Mówi TransTractorowi, że w dokumencie
źródłowym wykryto nowe kodowanie znaków (podane jako
pierwszy argument wywołania). Zwykle kodowanie może być
odczytane z nagłówka dokumentu. Pozostawione będzie tylko
pierwsze kodowanie znaków, pochodzące albo z argumentów
funkcji process(), albo z dokumentu.
- get_out_charset()
- Funkcja zwraca kodowanie znaków, które powinno
być użyte w dokumencie wyjściowym (zazwyczaj użyteczne
do zamienienia wykrytego kodowania znaków dokumentu wejściowego,
tam gdzie został znaleziony).
Użyje wyjściowego kodowania znaków podanego w linii
poleceń. Jeśli go nie podano, użyje kodowania znaków
wejściowego pliku PO, a jeżeli jako to kodowanie w pliku
był ustawiony domyślny tekst "CHARSET", to zwróci
kodowanie znaków wejściowego dokumentu, tak że nie zostanie
przeprowadzona żadna konwersja kodowań.
- recode_skipped_text($)
- Funkcja zwraca tekst przekazany jako argument przekodowany
z kodowania znaków dokumentu wejściowego na kodowanie
znaków dokumentu wyjściowego. Nie jest to potrzebne podczas
tłumaczenia komunikatu ( translate() wszystko przekodowuje
samodzielnie), ale wtedy, gdy pominięto komunikat z dokumentu
wejściowego, a dokument wyjściowy powinien mieć spójne
kodowanie znaków.
DALSZE WSKAZÓWKI¶
Mankamentem obecnego TransTractora jest brak obsługi dokumentów
zawierających wszystkie języki naraz, jak na przykład szablony
debconf lub pliki .desktop.
Aby rozwiązać ten problem, jedynymi potrzebnymi zmianami w interfejsie
są:
- -
- pobieranie hasha jak po_in_name (lista dla
języka)
- -
- dodawanie argumentu do przetłumaczenia, wskazując
język docelowy
- -
- stworzenie funkcję pushline_all, która
robiłaby pushline jej zawartości dla wszystkich
języków, używając składni podobnej do
składni map:
$self->pushline_all({ "Description[".$langcode."]=".
$self->translate($line,$ref,$langcode)
});
Zobaczymy, czy to wystarczy ;)
AUTORZY¶
Denis Barbier <barbier@linuxfr.org>
Martin Quinson (mquinson#debian.org)
Jordi Vilalta <jvprat@gmail.com>