DEV Community

Cover image for Viết một readability linter nhỏ cho bài tiếng Việt khi plugin không hỗ trợ
Onic Ai
Onic Ai

Posted on Originally published at onic.vn

Viết một readability linter nhỏ cho bài tiếng Việt khi plugin không hỗ trợ

Các công thức readability nổi tiếng như Flesch tính theo số âm tiết mỗi từ, vốn được thiết kế cho tiếng Anh. Phân tích đọc của Yoast cũng không hỗ trợ tiếng Việt cho các phép kiểm như độ dài câu, câu bị động, từ nối. Thay vì cố chấm một điểm số, bài này viết một linter nhỏ bắt các lỗi trình bày cụ thể, những lỗi mà người duyệt bài sửa nhiều nhất.

Các luật

  • Đoạn dài hơn 120 chữ (mốc Rank Math dùng trong phép kiểm đoạn ngắn).
  • Câu quá dài, dấu hiệu câu ghép nhiều ý.
  • Đoạn dài liên tục không có heading.
  • Bảng nhiều hơn 4 cột, khó đọc trên điện thoại.
  • Một khái niệm gọi bằng nhiều tên trong cùng bài.

Code

import re
from bs4 import BeautifulSoup

DONG_NGHIA = [
    {"liên kết nội bộ", "internal link", "link trong"},
    {"văn bản thay thế", "alt text", "thẻ alt"},
]

def tach_cau(doan: str) -> list:
    return [c for c in re.split(r"(?<=[.!?])\s+", doan) if c.strip()]

def lint(html: str, max_doan=120, max_cau=40, max_chu_khong_heading=350) -> list:
    soup = BeautifulSoup(html, "html.parser")
    loi, tu_heading_cuoi = [], 0
    for el in soup.find_all(["h2", "h3", "p", "table"]):
        if el.name in ("h2", "h3"):
            tu_heading_cuoi = 0
            continue
        if el.name == "table":
            cot = len(el.find("tr").find_all(["th", "td"])) if el.find("tr") else 0
            if cot > 4:
                loi.append(("bang_nhieu_cot", cot))
            continue
        text = el.get_text(" ", strip=True)
        so_chu = len(text.split())
        tu_heading_cuoi += so_chu
        if so_chu > max_doan:
            loi.append(("doan_dai", text[:50]))
        for cau in tach_cau(text):
            if len(cau.split()) > max_cau:
                loi.append(("cau_dai", cau[:50]))
        if tu_heading_cuoi > max_chu_khong_heading:
            loi.append(("thieu_heading", text[:50]))
            tu_heading_cuoi = 0
    toan_bai = soup.get_text(" ").lower()
    for nhom in DONG_NGHIA:
        dung = [t for t in nhom if t in toan_bai]
        if len(dung) > 1:
            loi.append(("goi_ten_khong_nhat_quan", dung))
    return loi
Enter fullscreen mode Exit fullscreen mode

Về các ngưỡng

Đếm chữ theo khoảng trắng nên mỗi tiếng Việt là một chữ, giống bộ đếm của WordPress. Ngưỡng 40 chữ cho câu và 350 chữ không heading là điểm bắt đầu để thử trên bài của chính mình, không phải chuẩn. Một ví dụ thực tế: đoạn mở bài kiểu "Trong thời đại công nghệ số phát triển mạnh mẽ như hiện nay thì..." dài hơn 70 chữ trong một câu, linter sẽ bắt ngay.

Luật nhất quán thuật ngữ

Luật cuối hay bị bỏ qua nhất. Đổi qua lại giữa "liên kết nội bộ", "internal link", "link trong" làm người đọc tưởng là ba thứ khác nhau. Danh sách đồng nghĩa nên do đội nội dung tự định nghĩa theo bảng thuật ngữ của mình. Lưu ý một bài giải thích thuật ngữ lần đầu kiểu "liên kết nội bộ (internal link)" sẽ bị báo; đó là chỗ người duyệt bỏ qua.

Những gì linter không làm được

Linter không biết câu trả lời có nằm ở đầu bài không, hay đoạn văn có lặp ý không. Phép thử tốt nhất vẫn là đọc to bài lên. Linter chỉ giúp người duyệt không phải soi tay những lỗi hình thức.

Sáu cách viết dễ đọc cho người viết nội dung và ví dụ trước, sau khi sửa có trong bài Readability là gì trên Onic.vn.


Bài gốc: https://onic.vn/kien-thuc/readability-la-gi/

Top comments (0)