KWT-2024/lab/lab_01.ipynb
2024-04-14 16:26:09 +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')
['Press the ENTER button', 'Press the ENTER key']

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 tm_lookup(sentence):
    return [entry[1] for entry in translation_memory if entry[0].lower() == sentence.lower()]

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]')
['Press the ENTER button', 'Press the ENTER key']

Ć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 sentence_similar(sentence):
    translator = str.maketrans('', '', string.punctuation)
    return sentence.translate(translator)

def tm_lookup(sentence):
    return [entry[1] for entry in translation_memory if entry[0].lower() == sentence_similar(sentence).lower()]

#print(string.punctuation)

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')
['System restart required']

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 tm_lookup(sentence):
    inWords = sentence_similar(sentence).lower().split(" ")
    lenSentence = len(inWords)
    matchWords = 0
    answer = []
    for entry in translation_memory:
        dicWords = entry[0].lower().split(" ")
        
        for i in range(lenSentence-1):
            if inWords[i] == dicWords[i]:
                matchWords += 1
        
        if matchWords >= lenSentence-1:
            answer.append(entry[1])
            matchWords = 0
        else:
            matchWords = 0

    return answer

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]

def exercise4help(sentence):
    sentence_words = sentence.split()
    answer = []
    for entry in glossary: #przechodzimy przez każdą tuple więc (n)
        if entry[0] in sentence_words: # (m) porównań
            answer.append(entry)
    return answer

#dla każdego hasła w słowniku, robimy tyle porównań ile jest słów w zdaniu O(n*m)
glossary_lookup('Każda drukarka posiada przycisk wznowienia drukowania')
[('przycisk', 'button'), ('drukarka', 'printer')]
exercise4help('Każda drukarka posiada przycisk wznowienia drukowania')
3
[('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ź: O(m*n)

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

def glossary_lookup(sentence):
    sentence_words = sentence.lower().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.get('komputer') == None

def glossary_lookup(sentence):
    sentence_words = set(sentence.split()) #umieszczamy w zbiorze aby uniknąć przetwarzania mniejszej ilości słów.
    answer = []
    for word in sentence_words: # dla każdego słowa w zdaniu (m)
        translated_word = glossary.get(word) #pobieramy zawartosć ze słownika 
        if translated_word != None: # (porównanie m razy)
            answer.append((word,translated_word)) # dodanie do odpowiedzi m razy
    
    return answer

glossary_lookup('drukarka - Każda drukarka posiada przycisk wznowienia drukowania')
[('drukarka', 'printer'), ('drukarka', 'printer'), ('przycisk', 'button')]