Chỉ mục sách

Cập nhật số trang của chỉ mục trước khi in sách

Khi đọc sách, nhiều người cứ thế đọc từ đầu. Có người thì xem mục lục trước. Đôi khi có người xem cả danh mục tài liệu tham khảo (nếu có). Nhưng ít người để ý đến chỉ mục (index).

Tại vì ở xứ Việt Nam này rất ít sách có chỉ mục. Nói hơi chủ quan nhưng anh dám chắc là nhiều người chả biết chỉ mục là cái gì, hoặc nhầm nó là mục lục.

Tuy vậy, không giống như bài trước về chỉ mục ngữ cảnh, bài này thì không cần giải thích chỉ mục trong sách là gì. Vì nhìn tiêu đề cũng có thể thấy là bài này dành cho người biên tập sách.

Làm chỉ mục rất ngại

Chỉ mục thường chỉ có trong sách ngoại văn, chủ yếu là mảng khoa học. Sách tiếng Việt chắc hiếm có quyển nào làm chỉ mục. Vì thế, bài này cũng giới hạn luôn là chỉ nói về mảng sách dịch.

Đối với người dịch, họ sẽ chỉ dịch cái chỉ mục có sẵn trong bản gốc. Chứ bảo họ phải mở phần mềm chế bản ra định nghĩa từng mục thì chắc họ đổi nghề luôn.

Nếu bản gốc và bản tiếng Việt có cùng số trang và vị trí xuất hiện của từng từ khoá không thay đổi thì mọi việc rất đơn giản là chỉ việc sắp xếp lại danh sách theo thứ tự ABC. Nhưng nếu chỉ khác biệt dù chỉ một hai trang là mọi chuyện sẽ rất khác.

Mặc dù anh chưa làm sách bao giờ nhưng cứ suy luận lô-gích thì phải xong trang ruột thì lúc ấy mới chốt được chỉ mục. Vì cái quan trọng nhất là phải đúng số trang. Còn nếu người làm chế bản đủ kiên nhẫn mà định nghĩa lại từng mục để tự động cập nhật số trang thì quá tuyệt vời. Nhưng làm gì có chuyện ấy.

Trách nhiệm cập nhật số trang chắc sẽ thuộc về người biên tập. Nếu chỉ vài chục mục từ thì cũng không vấn đề gì to tát. Nhưng lên đến vài trăm hoặc cả nghìn thì quả là ong thủ. Còn chẳng may người dịch trong phần nội dung thì dịch một đằng, ở chỉ mục lại dịch một nẻo thì còn “chết” nữa. Hoặc vì một lí do giời ơi đất hỡi nào đấy mà trang ruột buộc phải điều chỉnh số trang thì lúc ấy chỉ muốn bỏ mẹ cái-chỉ-mục-chắc-chả-mấy-ai-thèm-xem này đi.

Lại dùng Python để giải quyết vấn đề

Nếu là người phải biên tập cái chỉ mục kia, anh sẽ đề nghị người chế bản xuất cho một bản ruột ở định dạng PDF. Chất lượng hình ảnh thấp càng tốt, vì anh chỉ quan tâm tới phần văn bản. Nhưng nhất định phải là định dạng trang đơn (single) chứ không phải trang đôi (dual) như bình thường. Anh đặt tên nó là content.pdf.

Thứ hai là anh chép riêng chỉ mục và lưu vào một tập tin văn bản thô có tên là index.txt. Còn đây là một ví dụ để anh chị hình dung cấu trúc của nó như nào (hơi khác một chút so với chỉ mục có trong ảnh ở đầu trang).

T
tảo 15
thiên nga
    kèn 72-74
thú (hay động vật có vú) 14, 22-25
Thú, lớp 13
thú mỏ vịt 84

Có hai tập tin trên rồi thì anh chạy một đoạn Python ngắn gọn như sau:

import fitz  #pip3 install PyMuPDF
import re

# Options
index_file = 'index.txt'
pdf_file = 'content.pdf'
from_page = 1 # zero based
remove_last_pages = 2

# Open index file
with open(index_file) as f:
    index = f.read() + '\n'

# Tab size is 4
index = re.sub('[ ]{4}', '\t', index)
index = re.sub('[ ]+\n', '\n', index)

keywords = index.split("\n")

# Open PDF file
pdf = fitz.open(pdf_file)

document = []
for i in range(from_page, pdf.page_count - remove_last_pages):
    text = re.sub('\n', ' ', pdf.load_page(i).get_text('text'))
    text = re.sub('[ ]{2,}', ' ', text)
    document.append(text)

output = []
for keyword in keywords:
    # Empty lines will be skipped
    if keyword.strip() == '':
        continue

    # Don't search for alphabet section header (eg: "A" or "E, Ê")
    if re.search(r'^(\w,\s+)?\w$', keyword.strip()):
        output.append('\n' + keyword)
        continue        

    # Don't search for shared terms (without page number)
    if re.search(r' [\d, -]+$', keyword) == None:
        output.append(keyword)
        continue

    # Determining the keyword
    keyword = re.sub(r'\b [\d, -]+$', '', keyword)
    keyword_ = re.sub(r' \((hay .*)\)$', '|\\1', keyword_)
    # "reversed" keyword, using commas in this case
    keyword_ = re.sub(r'^([^,].*), (.*)$', '\\1', keyword)
    keyword_ = keyword_.strip()

    inpages = []
    for num, page in enumerate(document):
        
        if re.search(rf'\b({keyword_})\b', page, re.IGNORECASE):
            page_num = num + 1 + from_page

            inpages.append(str(page_num))

    if len(inpages) > 0:
        output.append(keyword +  ' ' + ", ".join(inpages))
    else:
        output.append(keyword + ' : <không tìm thấy>')

with open('output.txt', 'w') as f:
    f.write("\n".join(output))
f.close()

Trong đoạn trên anh dùng PyMuPDF để lấy văn bản từ PDF. Toàn bộ văn bản này sẽ được lưu thành một list với mỗi phần tử là nội dung của một trang (vì thế phải dùng PDF trang đơn). Sau đó anh lần lượt tìm từng từ khoá, nếu trang nào có thì ghi lại số trang. Nếu người dịch làm ẩu thì sẽ không ra trang nào và sẽ được ghi là “<không tìm thấy>” cho tiện theo dõi và cập nhật.

Tầm khoảng một hai phút là xong, tiết kiệm được rất nhiều giờ, thậm chí nhiều ngày làm việc. Kết quả được anh cho lưu trong tập tin output.txt.

Tinh chỉnh số trang, sắp xếp theo ABC và định dạng văn bản

Tuỳ theo nội dung và lựa chọn của tác giả, không phải trang nào xuất hiện từ khoá cũng phải cho vào chỉ mục nên anh cũng phải đối chiếu với bản cũ để biết là sẽ giữ lại trang nào. Hoặc nếu lười thì anh tặc lưỡi tự biện hộ rằng “thừa còn hơn thiếu” và cứ thế gửi lại cho người chế bản chỉ mục đã cập nhật, hehe.

Sau khi có kết quả, anh sẽ phải sắp xếp lại theo đúng bảng chữ cái tiếng Việt (vì người dịch thường họ chỉ dịch thôi chứ không sắp xếp lại). Cái này thì dễ, anh truy cập Dự án S và sắp xếp với tuỳ chọn danh sách nhiều cấp.

Vì chỉ mục phải chuyển sang dạng văn bản thô để cập nhật số trang và sắp xếp nên sẽ mất hết định dạng (chủ yếu là in nghiêng, in đậm một số từ khoá). Vì thế anh cũng sẽ phải đối chiếu với bản cũ để định dạng lại. Nhưng do bản mới đã sắp xếp lại nên thứ tự hai bên không khớp nhau, rất khó đối chiếu. Lúc này anh sẽ dùng Word hoặc Excel sắp xếp lại bản cũ để giữ được định dạng. Tuy không chính xác lắm (giống như chỉ mục trong cái ảnh ở đầu trang này) nhưng về cơ bản thì việc đối chiếu giữa hai bản sẽ dễ dàng hơn nhiều.

Đánh giá chung

Như vậy, theo cách làm trên thì anh vẫn phải xử lí thủ công một số công đoạn liên quan đến định dạng và tinh chỉnh số trang. Nhưng cái việc mất thời gian và dễ nhầm lẫn nhất là cập nhật số trang thì đã được làm tự động. Tất nhiên để cập nhật được thì trong quá trình biên tập trước đó anh phải thống nhất một số thứ: cấu trúc chỉ mục, cách dịch từ khoá, cách viết i/y và vị trí đặt dấu thanh điệu.

Để tự động phát hiện những chỗ sử dụng i/y và dấu thanh điệu không thống nhất thì cũng có thể dùng Python. Nhưng để dịp khác đi, giờ anh phải đi chụp ảnh đã.