Ứng dụng vị trí đặt dấu thanh điệu

Sửa lỗi sai vị trí dấu thanh điệu

Lần trước anh đã dùng Python để chuẩn hoá vị trí dấu thanh điệu ở các vần -oa, -oe, -uy. Nhưng còn các lỗi sai vị trí dấu thanh khác, ví dụ: taì, ýêu, thừơng,… thì chưa.

Nếu áp dụng cách làm cũ là tìm kiếm và thay thế bằng những tổ hợp định sẵn thì quá là cồng kềnh và dễ bỏ sót. Vì thế, anh chọn cách khác là dựa vào cấu trúc vần để tìm lỗi rồi tự động tạo tổ hợp thay thế tương ứng.

import re

sample = """Òa khóc, những giọt nứơc mắt tuôn rơi không trói bụôc.
Cụ HÒE phaỉ quày qủa đi học "ây ai" cho bíêt.
Bao nhiêu qùa kỉ niệm quí gía tuí bụi uà về như được muà.
Một món đồ gỉa màu tiá.
“Cò lả” không phải là "Cò Iả".
Người đêủ đếm không xủê.
Con thuỳên qủi sơn màu đen tùyên đã bị ỷêm."""

# Regex pattern for incorrect tone mark placement
pattern = (
    r'[bcdđghklmnprstvx][aoôơuư][ìỉĩíị]\b|\b[aoôơuư][ìỉĩíị]\b'
    r'|[ae][òỏõóọ]\b|[aâêiyươ][ùũủúụ]\b|[aâ][ỳỷỹýỵ]\b'
    r'|[aâ][ỳỷỹýỵ]\b|[ae][òỏõóọ]\b'
    r'|[bcdđhklmnprstvx][aâêiyươ][ùũủúụ]\b|\b[aâêiyươ][ùũủúụ]\b'
    r'|[òỏõóọ][aăeo]|[ùũủúụ]yê|[ùũủúụ][âêyơô]|[ìỉĩíịỳỷỹýỵ]ê|[ừửữứự]ơ'
    r'|g[ìỉĩíị][aăeêoôơuư]|q[ùũủúụ][ai]'
)

# Vietnamese tone mark sets
sets = [
    'aăâeêioôơuưy',
    'àằầèềìòồờùừỳ',
    'ảẳẩẻểỉỏổởủửỷ',
    'ãẵẫẽễĩõỗỡũữỹ',
    'áắấéếíóốớúứý',
    'ạặậẹệịọộợụựỵ'
]

# Find all incorrect tone mark placements
found = re.findall(rf'\b\w*?({pattern})\w*?\b', sample, re.IGNORECASE)

print(found)

# Dictionary to store corrections
replacing = {}

for combination in found:

    tone, toned_char, toned_char_index = 0, '', 0

    consonant = '' if not re.match(r'^[bcdđghklmnpqrstvx].*', combination, re.IGNORECASE) else combination[0].lower()

    # Identify the misplaced tone mark
    for i in range(1, 6):
        if (char := re.search(rf"[{sets[i]}]", combination, re.IGNORECASE)):
            toned_char = char[0]
            toned_char_index = sets[i].index(toned_char.lower())
            tone = i
            break

    # Identify the nuclear character
    position_ = combination.index(toned_char)

    position = position_ - 1

    if consonant in ['g', 'q']:
        position = position_ + 1

    nuclear = combination[position]

    # Correct the tone mark
    nuclear_index = sets[0].index(nuclear.lower())
    new_combination = sets[0][toned_char_index] + sets[tone][nuclear_index]

    if len(combination) > 2 and consonant == '':
        new_combination = sets[0][toned_char_index] + combination[1] + sets[tone][nuclear_index]

    if position == 0 or (len(combination) > 2 and consonant not in ['', 'g', 'q']):
        new_combination = new_combination[::-1]

    new_combination = consonant + new_combination

    # Maintain original capitalization
    if combination.isupper():
        new_combination = new_combination.upper()
    elif combination[0].isupper():
        new_combination = new_combination.capitalize()

    replacing[combination] = new_combination

# Apply corrections
for original, corrected in replacing.items():

    # distinguish "uà (ùa)" as a word or as a rhyme in "qùa (quà)"
    if not re.match(r'^([iu][àảãáạ]|u[ìỉĩíị])$', f'{original}', re.IGNORECASE):
        sample = re.sub(rf"\b(\w*?){original}(\w*?)\b", rf"_\1{corrected}\2_", sample)
    else:
        sample = re.sub(rf"\b{original}\b", rf"_{corrected}_", sample)

print(sample)

Kết quả:

_Oà_ khóc, những giọt _nước_ mắt tuôn rơi không trói _buộc_.
Cụ _HOÈ_ _phải_ quày _quả_ đi học "ây ai" cho _biết_.
Bao nhiêu _quà_ kỉ niệm quí _giá_ _túi_ bụi _ùa_ về như được _mùa_.
Một món đồ _giả_ màu _tía_.
“Cò lả” không phải là "Cò _Ỉa_".
Người _đểu_ đếm không _xuể_.
Con _thuyền_ _quỉ_ sơn màu đen _tuyền_ đã bị _yểm_.

(Trường hợp “quỉ” sẽ được tiếp tục sửa thành cách viết đúng là “quỷ”).

Giải pháp này cũng đã được chuyển sang JavaScript và sử dụng cho ứng dụng Chuẩn hoá cách viết I/Y và vị trí đặt dấu thanh điệu của Dự án S.

Sở dĩ anh phải mất công chuyển sang JavaScript là vì anh muốn ứng dụng có thể xử lí trên ngay máy khách mà không phải đẩy dữ liệu lên máy chủ. Làm thế không phải chỉ để giảm tải cho máy chủ mà cái chính là để đảm bảo bí mật nội dung của người dùng.

Lưu ý

Thực ra thì các bộ gõ tiếng Việt bây giờ đã tự động điều chỉnh đúng vị trí dấu thanh khi soạn thảo rồi. Thậm chí là có muốn sai cũng khó. Còn các mô hình ngôn ngữ lớn như ChatGPT cũng sửa được lỗi này với độ chính xác cực cao. Nhưng mà mình làm được thì mình làm thôi.