Files
VRCT/src-python/models/translation/translation_languages.py
misyaguziya 9e88cff889 Refactor translation settings and prompts
- Updated paths for translation settings in backend.spec and backend_cuda.spec to reflect new directory structure.
- Renamed loadPromptConfig to loadTranslatePromptConfig in translation utility files for consistency.
- Created new YAML files for translation prompts (gemini, groq, lmstudio, ollama, openai, openrouter, plamo) with standardized system prompts.
- Added languages.yml file to define language mappings for various translation backends.
2025-12-14 16:10:40 +09:00

144 lines
5.3 KiB
Python

"""Load translation language code mappings from YAML.
YAML ファイル: languages/languages.yml
構造:
<BackendName>:
source: { DisplayName: Code, ... }
target: { DisplayName: Code, ... }
CTranslate2:
<ModelName>:
source: {...}
target: {...}
"""
import os
import threading
from typing import Any, Dict
import yaml
try:
from utils import printLog, errorLogging
except ImportError:
def printLog(data, *args, **kwargs):
print(data, *args, **kwargs)
def errorLogging():
import traceback
traceback.print_exc()
# 型: translation_lang[backend][(model)?]['source'|'target'][display_name] = code
translation_lang: Dict[str, Dict[str, Dict[str, str]]] = {}
_loaded = False
_lock = threading.Lock()
def _load_languages(path: str, filename: str) -> str:
"""Get absolute path to resource file relative to this module.
Args:
filename: relative filename from this module's directory
Returns:
Absolute path to the resource file
"""
if os.path.exists(os.path.join(path, "_internal", "translation_settings", "languages", filename)):
languages_path = os.path.join(path, "_internal", "translation_settings", "languages", filename)
elif os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), "models", "translation", "translation_settings", "languages", filename)):
languages_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "models", "translation", "translation_settings", "languages", filename)
elif os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), "translation_settings", "languages", filename)):
languages_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "translation_settings", "languages", filename)
else:
raise FileNotFoundError(f"Languages file not found: {filename}")
with open(languages_path, "r", encoding="utf-8") as f:
return yaml.safe_load(f)
def _validate_source_target(backend: str, mapping: Any) -> None:
"""Validate that a backend mapping has proper source/target structure.
Args:
backend: backend name for error messages
mapping: mapping to validate
Raises:
ValueError: If mapping structure is invalid
"""
if not isinstance(mapping, dict):
raise ValueError(f"{backend}: 値は dict である必要があります。")
if "source" not in mapping or "target" not in mapping:
raise ValueError(f"{backend}: 'source''target' が必要です。")
for key in ("source", "target"):
if not isinstance(mapping[key], dict):
raise ValueError(f"{backend}: '{key}' は dict である必要があります。")
# value は str を想定
for disp, code in mapping[key].items():
if not isinstance(disp, str) or not isinstance(code, str):
raise ValueError(
f"{backend}: '{key}' のエントリは str: str である必要があります。 ({disp} => {code})"
)
def loadTranslationLanguages(path: str, force: bool = False) -> Dict[str, Any]:
"""Load translation language mappings from YAML file.
Args:
path: Path to the YAML file
force: If True, reload even if already loaded
Returns:
Dictionary of translation language mappings
Raises:
FileNotFoundError: If languages/languages.yml is not found
ValueError: If YAML structure is invalid
"""
global _loaded, translation_lang
if _loaded and not force:
return translation_lang
with _lock:
if _loaded and not force:
return translation_lang
data = _load_languages(path, "languages.yml")
if not isinstance(data, dict):
raise ValueError(
"languages/languages.yml のルートはマッピング(dict)である必要があります。"
)
# 検証と正規化
validated: Dict[str, Dict[str, Dict[str, str]]] = {}
for backend, value in data.items():
if backend == "CTranslate2":
# NOTE: CTranslate2 はモデルごとに異なる言語セットを持つ
if not isinstance(value, dict):
raise ValueError(
"CTranslate2 の値はモデル名→ {source:, target:} の dict である必要があります。"
)
validated["CTranslate2"] = {}
for model_name, model_map in value.items():
_validate_source_target(
backend=f"CTranslate2/{model_name}", mapping=model_map
)
validated["CTranslate2"][model_name] = {
"source": model_map["source"],
"target": model_map["target"],
}
else:
_validate_source_target(backend=backend, mapping=value)
validated[backend] = {
"source": value["source"],
"target": value["target"],
}
translation_lang = validated
_loaded = True
return translation_lang
if __name__ == "__main__":
try:
langs = loadTranslationLanguages(path=".", force=True)
printLog("Loaded translation languages:")
printLog(langs)
except Exception:
errorLogging()