KWT-2024/lab/lab_01.ipynb
2024-04-13 14:10:00 +02:00

16 KiB

Logo 1

Komputerowe wspomaganie tłumaczenia

1. Podstawowe techniki wspomagania tłumaczenia [laboratoria]

Rafał Jaworski (2021)

Logo 2

Podstawowy scenariusz - tłumacz otrzymuje dokument będący ciągiem segmentów w języku źródłowym . Zadaniem tłumacza jest przetłumaczenie wszystkich segmentów na język docelowy. Oznacza to, że został wykonany już szereg operacji technicznych, a w tym:

  • przesłanie pliku do tłumaczenia
  • ekstrakcja tekstu z dokumentu
  • podział tekstu na segmenty.

Tłumacz tłumaczy jeden segment na raz. Widzi kilka poprzednich oraz kilka następnych segmentów, jednak jego uwaga powinna skupiać się na aktywnym, aktualnie tłumaczonym segmencie. Nie oznacza to jednak, że tłumacz jest pozbawiony pomocy. Ma możliwość korzystania z różnorakich technik komputerowego wspomagania tłumaczenia.

Pamięć tłumaczeń

Najbardziej podstawową techniką wspomagania tłumaczenia jest pamięć tłumaczeń. Pamięć tłumaczeń stanowi zbiór wcześniej przetłumaczonych zdań:

translation_memory = [('Wciśnij przycisk Enter', 'Press the ENTER button'), 
                      ('Sprawdź ustawienia sieciowe', 'Check the network settings')]

Kiedy tłumacz pracuje nad kolejnym zdaniem, program automatycznie przeszukuje pamięć tłumaczeń. Jeśli okaże się, że zdanie zostało już przetłumaczone, automatycznie pobierane jest jego tłumaczenie z pamięci:

def tm_lookup(sentence):
    return [entry[1] for entry in translation_memory if entry[0] == sentence]
tm_lookup('Wciśnij przycisk Enter')
['Press the ENTER button']

W takim przypadku tłumaczenie z pamięci jest najczęściej automatycznie wstawiane jako tłumaczenie segmentu źródłowego i tłumacz nie musi się już nim martwić (co więcej, nie dostaje za takie tłumaczenie zapłaty...)

Tłumacz pracuje dalej i każde wykonane przez niego tłumaczenie trafia do pamięci tłumaczeń (oczywiście dzieje się to automatycznie):

translation_memory.append(('Drukarka jest wyłączona', 'The printer is switched off'))
translation_memory.append(('Wymagane ponowne uruchomienie komputera', 'System restart required'))
translation_memory.append(('Wciśnij przycisk Enter', 'Press the ENTER key'))

Z całą pewnością tłumacz stara się przełożyć jakąś komputerową instrukcję. Po wielu godzinach pracy trafia na znane sobie zdanie "Wciśnij przycisk Enter". Następuje przeszukanie pamięci tłumaczeń:

tm_lookup('Wciśnij przycisk Enter')
['Press the ENTER button', 'Press the ENTER key']

Jak widać, mamy w pamięci dwa tłumaczenia tego zdania. To tłumacz musi zadecydować, które tłumaczenie wybrać. O metodach wspomagania decyzji tłumacza w takich przypadkach będziemy jeszcze mówić.

Przeanalizujmy teraz następujący przypadek: do tłumaczenia trafia zdanie: "Wciśnij przycisk ENTER":

tm_lookup('Wciśnij przycisk ENTER')
[]

Tutaj tłumacz nie ma szczęścia - restrykcyjny mechanizm wyszukiwania nie podaje mu podpowiedzi. Możemy jednak sprawić, żeby przeszukiwanie pamięci tłumaczeń nie brało pod uwagę wielkości liter.

Ćwiczenie 1: zmodyfikuj funkcję tm_lookup w taki sposób, aby nie brała pod uwagę wielkości liter. Przetestuj zmodyfikowaną funkcję.

def preprocess(sentence):
    return sentence.lower()

def tm_lookup(sentence):
    return [entry[1] for entry in translation_memory if preprocess(entry[0]) == preprocess(sentence)]
tm_lookup('Wciśnij przycisk ENTER')
['Press the ENTER button', 'Press the ENTER key']

Nasz tłumacz powinien być teraz zadowolony. Jednak w dalszej części dokumentu pojawiło się inne podobne zdanie, dla którego nie było tłumaczenia:

tm_lookup('Wciśnij przycisk [ENTER]')
[]

Ćwiczenie 2: zmodyfikuj funkcję tm_lookup w taki sposób, aby nie brała pod uwagę znaków interpunkcyjnych. Rada - zdefiniuj funkcję sentence_similar.

import string

def preprocess(s):
    translator = str.maketrans('', '', string.punctuation)
    return s.translate(translator).lower()

def tm_lookup(sentence):
    return [entry[1] for entry in translation_memory if preprocess(entry[0]) == preprocess(sentence)]
tm_lookup('Wciśnij przycisk [ENTER]')
['Press the ENTER button', 'Press the ENTER key']

Praca tłumacza oczywiście trwa nadal. Spróbujmy teraz zaradzić następującej sytuacji - tłumacz otrzymuje do tłumaczenia następujące zdanie:

tm_lookup('Wymagane ponowne uruchomienie maszyny')
[]

Znów nie otrzymuje od nas podpowiedzi i znów nic w tym dziwnego - w pamięci tłumaczeń nie znajduje się takie zdanie. Jest jednak zdanie podobne, różniące się jednym słowem.

Ćwiczenie 3: zmodyfikuj funkcję tm_lookup w taki sposób, aby zwracała podpowiedzi także wtedy, gdy zdania różnią się tylko jednym słowem.

def compare_sentences(l1, l2):
    return sum([1 for i, j in zip(l1.split(), l2.split()) if i != j]) <= 1

import string

def preprocess(s):
    translator = str.maketrans('', '', string.punctuation)
    return s.translate(translator).lower()

def tm_lookup(sentence):
    return [entry[1] for entry in translation_memory if compare_sentences(preprocess(entry[0]), preprocess(sentence))]
tm_lookup('Wymagane ponowne uruchomienie maszyny')
['System restart required']

Słownik kontekstowy / glosariusz

Inną podstawową pomocą dla naszego tłumacza jest słownik, zwany także glosariuszem. Stanowi on zbiór terminów w języku źródłowym wraz z ich tłumaczeniami na język docelowy:

glossary = [('komputer', 'computer'), ('przycisk', 'button'), ('drukarka', 'printer')]

Podczas tłumaczenia, glosariusz jest przeszukiwany w celu znalezienia aktualnie tłumaczonych słów.

def glossary_lookup(sentence):
    sentence_words = sentence.split()
    return [entry for entry in glossary if entry[0] in sentence_words]
glossary_lookup('Każda drukarka posiada przycisk wznowienia drukowania')
[('przycisk', 'button'), ('drukarka', 'printer')]

Ćwiczenie 4: (tym razem teoretyczne) Jaka jest złożoność obliczeniowa czasowa przedstawionego powyżej algorytmu względem liczby haseł w słowniku (n) oraz liczby słów w zdaniu do tłumaczenia (m)?

Odpowiedź: Jeżeli implementacja wygląda tak jak powyżej, złożoność to O(n*m), ponieważ dla każdego słowa iteracyjnie przechodzimy przez cały nasz słownik i szukamy odpowiednika

Ćwiczenie 5: zmodyfikuj funkcję glossary_lookup w taki sposób, aby nie brała pod uwagę wielkości liter.

glossary_lookup('Każda Drukarka posiada przycisk wznowienia drukowania')
[('przycisk', 'button')]
def glossary_lookup(sentence):
    sentence_words = [word.lower() for word in sentence.split()]
    return [entry for entry in glossary if entry[0] in sentence_words]
glossary_lookup('Każda drukarka posiada przycisk wznowienia drukowania')
[('przycisk', 'button'), ('drukarka', 'printer')]

Ćwiczenie 6: zmodyfikuj funkcję glossary_lookup w taki sposób, aby jej złożoność obliczeniowa była mniejsza.

glossary = [('komputer', 'computer'), ('przycisk', 'button'), ('drukarka', 'printer')]
glossary = {
    'komputer': 'computer',
    'przycisk': 'button',
    'drukarka': 'printer'
}
def glossary_lookup(sentence):
    sentence_words = [word.lower() for word in sentence.split() if word.lower() in glossary]
    return [(word, glossary[word]) for word in sentence_words]
glossary_lookup('Każda drukarka posiada przycisk wznowienia drukowania')
[('drukarka', 'printer'), ('przycisk', 'button')]