update bugfixes
This commit is contained in:
@@ -3,4 +3,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2026-present Wolfang Torres <wolfang.torres@gmail.com>
|
# SPDX-FileCopyrightText: 2026-present Wolfang Torres <wolfang.torres@gmail.com>
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
__version__ = "0.2.0"
|
__version__ = "0.2.1"
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from pinyin_tone_converter.pinyin_tone_converter import PinyinToneConverter
|
|||||||
|
|
||||||
# Local
|
# Local
|
||||||
from .utility import DictionaryResult, ProcessFile, ProcessFolder, TranslationResult
|
from .utility import DictionaryResult, ProcessFile, ProcessFolder, TranslationResult
|
||||||
|
from .constants import DICT_TYPE, DICTATION_TYPE, PHRASES_TYPE
|
||||||
|
|
||||||
# Constants
|
# Constants
|
||||||
|
|
||||||
@@ -241,31 +242,60 @@ def output_anki_phrase(
|
|||||||
def output_anki_package(
|
def output_anki_package(
|
||||||
process_folder: ProcessFolder, results: dict[ProcessFile, list[TranslationResult]]
|
process_folder: ProcessFolder, results: dict[ProcessFile, list[TranslationResult]]
|
||||||
):
|
):
|
||||||
final_file = process_file.output_name.with_suffix(".apkg")
|
final_file = process_folder.output_name.with_suffix(".apkg")
|
||||||
decks = []
|
decks = []
|
||||||
audios = []
|
audios = []
|
||||||
for process_file, results in results.items():
|
for process_file, results in results.items():
|
||||||
deck_name = "::".join(
|
deck_name = "::".join(
|
||||||
ProcessFolder.input_folder.parts[:-1] + (ProcessFolder.output_name.stem,)
|
process_file.input_file.parts[:-1] + (process_file.output_name.stem,)
|
||||||
)
|
)
|
||||||
deck = Deck(
|
deck = Deck(
|
||||||
random.randrange(1 << 30, 1 << 31),
|
random.randrange(1 << 30, 1 << 31),
|
||||||
deck_name,
|
deck_name,
|
||||||
f"Deck for {final_file.name}, "
|
f"Deck for {process_file.input_file}, "
|
||||||
"created in https://www.wolfang.info.ve/hskankicreator/",
|
"created in https://www.wolfang.info.ve/hskankicreator/",
|
||||||
)
|
)
|
||||||
for result in results:
|
if process_file.file_type is DICTATION_TYPE:
|
||||||
note = Note(
|
for result in results:
|
||||||
model=DICTATION_MODEL,
|
note = Note(
|
||||||
fields=[
|
model=DICTATION_MODEL,
|
||||||
result.translated,
|
fields=[
|
||||||
result.line,
|
result.translated,
|
||||||
f"[sound:{result.audio_path}]",
|
result.line,
|
||||||
],
|
f"[sound:{result.audio_path}]",
|
||||||
)
|
],
|
||||||
deck.add_note(note)
|
)
|
||||||
audios.append(result.audio_path)
|
deck.add_note(note)
|
||||||
|
audios.append(result.audio_path)
|
||||||
|
elif process_file.file_type is DICT_TYPE:
|
||||||
|
for result in results:
|
||||||
|
note = Note(
|
||||||
|
model=HSK_MODEL,
|
||||||
|
fields=[
|
||||||
|
# "\n ".join(f"{n+1}. {m}" for n, m in enumerate(result.meanings)),
|
||||||
|
result.meaning,
|
||||||
|
PinyinToneConverter().convert_text(result.pinyin),
|
||||||
|
result.simplified,
|
||||||
|
result.traditional,
|
||||||
|
f"[sound:{result.audio_path}]",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
deck.add_note(note)
|
||||||
|
audios.append(result.audio_path)
|
||||||
|
elif process_file.file_type is PHRASES_TYPE:
|
||||||
|
for result in results:
|
||||||
|
note = Note(
|
||||||
|
model=PHRASE_MODEL,
|
||||||
|
fields=[
|
||||||
|
result.translated,
|
||||||
|
result.line,
|
||||||
|
f"[sound:{result.audio_path}]",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
deck.add_note(note)
|
||||||
|
audios.append(result.audio_path)
|
||||||
decks.append(deck)
|
decks.append(deck)
|
||||||
package = Package(decks)
|
package = Package(decks)
|
||||||
package.media_files = audios
|
package.media_files = audios
|
||||||
package.write_to_file(final_file)
|
package.write_to_file(final_file)
|
||||||
|
return final_file
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from .anki_generation import (
|
|||||||
output_anki_dictation,
|
output_anki_dictation,
|
||||||
output_anki_dictionary,
|
output_anki_dictionary,
|
||||||
output_anki_phrase,
|
output_anki_phrase,
|
||||||
|
output_anki_package,
|
||||||
)
|
)
|
||||||
from .constants import (
|
from .constants import (
|
||||||
DICTATION_TYPE,
|
DICTATION_TYPE,
|
||||||
@@ -84,7 +85,7 @@ def select_file(file_path: Path) -> ProcessFile:
|
|||||||
def select_folder(file_path: Path) -> ProcessFile:
|
def select_folder(file_path: Path) -> ProcessFile:
|
||||||
"""Given a relative path from `list_input_files`, return a ProcessFile"""
|
"""Given a relative path from `list_input_files`, return a ProcessFile"""
|
||||||
if (INPUT / file_path).is_dir():
|
if (INPUT / file_path).is_dir():
|
||||||
return ProcessFile(file_path)
|
return ProcessFolder(file_path)
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"{file_path} is not a folder")
|
raise ValueError(f"{file_path} is not a folder")
|
||||||
|
|
||||||
@@ -254,25 +255,27 @@ def folder_proccess(process_folder: ProcessFolder, language_id: str):
|
|||||||
TRANS.create_translator(LANGUAGES.CN, language_id)
|
TRANS.create_translator(LANGUAGES.CN, language_id)
|
||||||
CCCEDICT.create_cedict(language_id)
|
CCCEDICT.create_cedict(language_id)
|
||||||
results = {}
|
results = {}
|
||||||
for file in process_folder.input_files:
|
for process_file in process_folder.input_files:
|
||||||
if file.file_type is DICT_TYPE:
|
print(f"Proccessing {process_file}")
|
||||||
with file.absolute_input_file.open(
|
if process_file.file_type is DICT_TYPE:
|
||||||
|
with process_file.absolute_input_file.open(
|
||||||
"r", encoding="utf8", newline="\n"
|
"r", encoding="utf8", newline="\n"
|
||||||
) as file:
|
) as file:
|
||||||
words_list = [word.strip() for word in file.readlines() if word]
|
words_list = [word.strip() for word in file.readlines() if word]
|
||||||
dictionary_bulk_process(words_list, file)
|
dictionary_bulk_process(words_list, process_file)
|
||||||
results[file] = dictionary_process(file)
|
results[process_file] = dictionary_process(process_file)
|
||||||
elif file.file_type is DICTATION_TYPE:
|
elif process_file.file_type is DICTATION_TYPE:
|
||||||
with file.absolute_input_file.open(
|
with process_file.absolute_input_file.open(
|
||||||
"r", encoding="utf8", newline="\n"
|
"r", encoding="utf8", newline="\n"
|
||||||
) as file:
|
) as file:
|
||||||
text_lines = [
|
text_lines = [
|
||||||
line.strip() for line in file.read().split("。") if line.strip()
|
line.strip() for line in file.read().split("。") if line.strip()
|
||||||
]
|
]
|
||||||
results[file] = dictation_process(text_lines, file)
|
results[process_file] = dictation_process(text_lines, process_file)
|
||||||
elif file.file_type is PHRASES_TYPE:
|
elif process_file.file_type is PHRASES_TYPE:
|
||||||
with file.absolute_input_file.open(
|
with process_file.absolute_input_file.open(
|
||||||
"r", encoding="utf8", newline="\n"
|
"r", encoding="utf8", newline="\n"
|
||||||
) as file:
|
) as file:
|
||||||
text_lines = [line.strip() for line in file.readlines() if line.strip()]
|
text_lines = [line.strip() for line in file.readlines() if line.strip()]
|
||||||
results[file] = translator_process(text_lines, file)
|
results[process_file] = translator_process(text_lines, process_file)
|
||||||
|
return output_anki_package(process_folder, results)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ from .utility import CCCEDICT, TTS, DictionaryResult, ProcessFile, TranslationRe
|
|||||||
|
|
||||||
# Constants
|
# Constants
|
||||||
|
|
||||||
FIELDNAMES = ["n" "simplified", "traditional", "pinyin", "meaning"]
|
FIELDNAMES = ["n", "simplified", "traditional", "pinyin", "meaning"]
|
||||||
DIALECT = "excel-tab"
|
DIALECT = "excel-tab"
|
||||||
|
|
||||||
# Results Classes
|
# Results Classes
|
||||||
@@ -80,38 +80,36 @@ def dictionary_bulk_process(words_list: list[str], process_file: ProcessFile):
|
|||||||
[
|
[
|
||||||
entry
|
entry
|
||||||
for entry in entries
|
for entry in entries
|
||||||
for meaning in entry.meaning
|
for meaning in entry.meanings
|
||||||
if hint in meaning
|
if hint in meaning
|
||||||
]
|
]
|
||||||
if hint
|
if hint
|
||||||
else []
|
else []
|
||||||
)
|
)
|
||||||
pos_entries = pos_meanings or entries
|
pos_entries = pos_meanings or entries
|
||||||
meanings = "\n".join(
|
meanings = []
|
||||||
f"{i} - {entry.meaning}" for i, entry in enumerate(pos_entries)
|
for entry in pos_entries:
|
||||||
)
|
for meaning in entry.meanings:
|
||||||
|
if hint and hint in meaning:
|
||||||
|
meanings.append(meaning)
|
||||||
|
if not meanings:
|
||||||
|
meanings = [
|
||||||
|
meaning for entry in pos_entries for meaning in entry.meanings
|
||||||
|
]
|
||||||
|
meanings_text = meanings[0]
|
||||||
tsv_writer.writerow(
|
tsv_writer.writerow(
|
||||||
{
|
{
|
||||||
"n": n,
|
"n": number,
|
||||||
"simplified": entry.simplified,
|
"simplified": entry.simplified,
|
||||||
"traditional": entry.traditional,
|
"traditional": entry.traditional,
|
||||||
"pinyin": entry.pinyin,
|
"pinyin": entry.pinyin,
|
||||||
"meaning": meanings,
|
"meaning": meanings_text,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
print("============================================")
|
print("============================================")
|
||||||
print(f"===================>ERROR: {word} not found")
|
print(f"===================>ERROR: {word} not found")
|
||||||
print("============================================")
|
print("============================================")
|
||||||
tsv_writer.writerow(
|
|
||||||
{
|
|
||||||
"n": number,
|
|
||||||
"simplified": word,
|
|
||||||
"traditional": None,
|
|
||||||
"pinyin": None,
|
|
||||||
"meaning": None,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
number += 1
|
number += 1
|
||||||
|
|
||||||
|
|
||||||
@@ -163,7 +161,7 @@ def dictionary_pre_process(words_list: list[str], process_file: ProcessFile):
|
|||||||
print("============================================")
|
print("============================================")
|
||||||
tsv_writer.writerow(
|
tsv_writer.writerow(
|
||||||
{
|
{
|
||||||
"n": n,
|
"n": number,
|
||||||
"simplified": word,
|
"simplified": word,
|
||||||
"traditional": None,
|
"traditional": None,
|
||||||
"pinyin": None,
|
"pinyin": None,
|
||||||
|
|||||||
@@ -161,7 +161,6 @@ class TTS:
|
|||||||
DEVICE = None
|
DEVICE = None
|
||||||
DEFAULTS = {
|
DEFAULTS = {
|
||||||
"language": "Chinese",
|
"language": "Chinese",
|
||||||
"speaker": "Uncle_Fu",
|
|
||||||
"instruct": "语速缓慢而审慎,每个音节的语调都拿捏得恰到好处,宛如教授在指导新生。",
|
"instruct": "语速缓慢而审慎,每个音节的语调都拿捏得恰到好处,宛如教授在指导新生。",
|
||||||
"instruct": "Speak in a slow pace and enuntiate every word, as a teacher to a learning student",
|
"instruct": "Speak in a slow pace and enuntiate every word, as a teacher to a learning student",
|
||||||
}
|
}
|
||||||
@@ -189,11 +188,13 @@ class TTS:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def generate(text: str):
|
def generate(text: str):
|
||||||
"""Generates a Waw using the defaulst values"""
|
"""Generates a Waw using the defaulst values"""
|
||||||
|
print(f"starting to generate {text}")
|
||||||
speaker = random.choice(TTS.VOICES)
|
speaker = random.choice(TTS.VOICES)
|
||||||
return TTS.MODEL.generate_custom_voice(
|
audio = TTS.MODEL.generate_custom_voice(
|
||||||
text=text, **TTS.DEFAULTS, speaker=speaker
|
text=text, **TTS.DEFAULTS, speaker=speaker
|
||||||
)
|
)
|
||||||
|
print(f"finish to generate {text}")
|
||||||
|
return audio
|
||||||
|
|
||||||
# Clases
|
# Clases
|
||||||
|
|
||||||
@@ -207,6 +208,7 @@ class ProcessFolder:
|
|||||||
def __init__(self, input_folder: Path, language_id: str = None):
|
def __init__(self, input_folder: Path, language_id: str = None):
|
||||||
self.input_folder = input_folder
|
self.input_folder = input_folder
|
||||||
self._language_id = language_id
|
self._language_id = language_id
|
||||||
|
self.absolute_input_folder = INPUT / self.input_folder
|
||||||
# process file type
|
# process file type
|
||||||
self.out_folder = OUTPUT / input_folder
|
self.out_folder = OUTPUT / input_folder
|
||||||
self.out_folder.mkdir(parents=True, exist_ok=True)
|
self.out_folder.mkdir(parents=True, exist_ok=True)
|
||||||
@@ -214,24 +216,23 @@ class ProcessFolder:
|
|||||||
self.resources.mkdir(parents=True, exist_ok=True)
|
self.resources.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def output_name():
|
def output_name(self):
|
||||||
"""Posible name for the output file, still missing the filetype"""
|
"""Posible name for the output file, still missing the filetype"""
|
||||||
if self.language_id is None:
|
if self.language_id is None:
|
||||||
raise ValueError("Not a valid language selected")
|
raise ValueError("Not a valid language selected")
|
||||||
return self.out_folder / f"{self.input_file.stem}.{self.language_id}.temp"
|
return self.out_folder / f"{self.input_folder.stem}.{self.language_id}.temp"
|
||||||
|
|
||||||
@property
|
|
||||||
def absolute_input_file(self):
|
|
||||||
"""Absolute input file"""
|
|
||||||
return INPUT / self.input_file
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def input_files(self):
|
def input_files(self):
|
||||||
input_files = []
|
input_files = []
|
||||||
for file in self.absolute_input_file.glob(f"*.txt"):
|
for file in self.absolute_input_folder.glob(f"*.txt"):
|
||||||
for file_type in (DICT_TYPE, PHRASES_TYPE, DICTATION_TYPE):
|
for file_type in (DICT_TYPE, PHRASES_TYPE, DICTATION_TYPE):
|
||||||
if file_type in file.suffixes:
|
if file_type in file.suffixes:
|
||||||
input_files.append(ProcessFile(file, language_id=self.language_id))
|
input_files.append(
|
||||||
|
ProcessFile(
|
||||||
|
file.relative_to(INPUT), language_id=self.language_id
|
||||||
|
)
|
||||||
|
)
|
||||||
return input_files
|
return input_files
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -339,6 +340,7 @@ class DictionaryResult:
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
n: str,
|
||||||
language_id: str,
|
language_id: str,
|
||||||
simplified: str,
|
simplified: str,
|
||||||
traditional: str,
|
traditional: str,
|
||||||
@@ -346,6 +348,7 @@ class DictionaryResult:
|
|||||||
meaning: str,
|
meaning: str,
|
||||||
audio_path: Path,
|
audio_path: Path,
|
||||||
):
|
):
|
||||||
|
self.n = n
|
||||||
self.language_id = language_id
|
self.language_id = language_id
|
||||||
self.simplified = simplified
|
self.simplified = simplified
|
||||||
self.traditional = traditional
|
self.traditional = traditional
|
||||||
|
|||||||
Reference in New Issue
Block a user