151 lines
5.3 KiB
Python
151 lines
5.3 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
r"""
|
||
names.py — сбор уникальных имён спикеров из .nsv файлов в CSV-таблицу
|
||
для перевода, и обратное применение переведённых имён в .nsv файлы.
|
||
|
||
Файлы .nsv всегда в UTF-8 (пишутся convert.py/translate.py) — здесь нет
|
||
нужды в автоопределении кодировки, в отличие от более ранней версии этого
|
||
скрипта, где угадывание cp932/shift_jis/utf-8 могло молча испортить текст
|
||
на символах вроде "①", которых нет в cp932, но которые cp932 способен
|
||
"прочитать" без ошибки, просто дав кракозябры.
|
||
"""
|
||
|
||
import csv
|
||
from pathlib import Path
|
||
|
||
from nsv_io import load_nsv_file, save_nsv_file
|
||
|
||
|
||
def get_target_dir():
|
||
folder_input = input("Укажите путь к папке с .nsv файлами [по умолчанию: translate]: ").strip()
|
||
folder_path = folder_input.strip('"\'') if folder_input else "translate"
|
||
target_dir = Path(folder_path)
|
||
|
||
if not target_dir.is_dir():
|
||
print(f"Ошибка: папка '{target_dir}' не найдена.\n")
|
||
return None
|
||
return target_dir
|
||
|
||
|
||
def mode_extract():
|
||
target_dir = get_target_dir()
|
||
if not target_dir:
|
||
return
|
||
|
||
nsv_files = list(target_dir.rglob("*.nsv"))
|
||
if not nsv_files:
|
||
print(f"В папке '{target_dir}' не найдено файлов .nsv.\n")
|
||
return
|
||
|
||
print(f"Найдено .nsv файлов: {len(nsv_files)}. Сбор имён...")
|
||
unique_speakers = set()
|
||
|
||
for file_path in nsv_files:
|
||
try:
|
||
entries = load_nsv_file(file_path)
|
||
except Exception as e:
|
||
print(f"Пропуск файла {file_path.name} (не удалось прочитать: {e})")
|
||
continue
|
||
|
||
for e in entries:
|
||
speaker = e.get("speaker")
|
||
if speaker is not None and speaker.strip():
|
||
unique_speakers.add(speaker.strip())
|
||
|
||
output_csv = Path(__file__).resolve().parent / "namestable.csv"
|
||
sorted_speakers = sorted(unique_speakers)
|
||
|
||
with open(output_csv, "w", encoding="utf-8-sig", newline="") as f:
|
||
writer = csv.writer(f)
|
||
writer.writerow(["Original", "Translated"])
|
||
for speaker in sorted_speakers:
|
||
writer.writerow([speaker, ""])
|
||
|
||
print(f"\nГотово! Уникальных имён собрано: {len(sorted_speakers)}")
|
||
print(f"Файл сохранён: {output_csv}\n")
|
||
|
||
|
||
def mode_apply():
|
||
csv_path = Path(__file__).resolve().parent / "namestable.csv"
|
||
if not csv_path.is_file():
|
||
print(f"Ошибка: файл '{csv_path.name}' рядом со скриптом не найден.\n")
|
||
return
|
||
|
||
translation_map = {}
|
||
with open(csv_path, "r", encoding="utf-8-sig") as f:
|
||
reader = csv.DictReader(f)
|
||
for row in reader:
|
||
orig = row.get("Original", "").strip()
|
||
trans = row.get("Translated", "").strip()
|
||
if orig and trans:
|
||
translation_map[orig] = trans
|
||
|
||
if not translation_map:
|
||
print("В таблице namestable.csv нет заполненных колонок 'Translated'. Нечего применять.\n")
|
||
return
|
||
|
||
print(f"Загружено переводов для замены: {len(translation_map)}")
|
||
|
||
target_dir = get_target_dir()
|
||
if not target_dir:
|
||
return
|
||
|
||
nsv_files = list(target_dir.rglob("*.nsv"))
|
||
if not nsv_files:
|
||
print(f"В папке '{target_dir}' не найдено файлов .nsv.\n")
|
||
return
|
||
|
||
print(f"Обработка {len(nsv_files)} файлов...")
|
||
total_replaced = 0
|
||
modified_files = 0
|
||
|
||
for file_path in nsv_files:
|
||
try:
|
||
entries = load_nsv_file(file_path)
|
||
except Exception as e:
|
||
print(f"Пропуск {file_path.name}: не удалось прочитать ({e}).")
|
||
continue
|
||
|
||
replaced_in_file = 0
|
||
for e in entries:
|
||
speaker = e.get("speaker")
|
||
if speaker is not None:
|
||
raw_val = speaker.strip()
|
||
if raw_val in translation_map:
|
||
e["speaker"] = translation_map[raw_val]
|
||
replaced_in_file += 1
|
||
|
||
if replaced_in_file > 0:
|
||
save_nsv_file(file_path, entries)
|
||
total_replaced += replaced_in_file
|
||
modified_files += 1
|
||
|
||
print(f"\nГотово!")
|
||
print(f"Изменено файлов: {modified_files}")
|
||
print(f"Всего произведено замен: {total_replaced}\n")
|
||
|
||
|
||
def main():
|
||
while True:
|
||
print("=== Меню ===")
|
||
print("1. Собрать уникальные имена в namestable.csv")
|
||
print("2. Применить перевод из namestable.csv обратно в .nsv")
|
||
print("0. Выход")
|
||
|
||
choice = input("Выберите действие [1/2/0]: ").strip()
|
||
print()
|
||
|
||
if choice == "1":
|
||
mode_extract()
|
||
elif choice == "2":
|
||
mode_apply()
|
||
elif choice == "0":
|
||
break
|
||
else:
|
||
print("Неверный ввод, попробуйте снова.\n")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|