- cherry: orofacial/TMD PPTX presentations + 음악가 구강건강 가이드 - papa: sinus/infraoccluded PPTX, garden-monitor Arduino, MIDI files - databases: PCSP scraper, translation scripts, vision benchmark, batch JSONs - web-ui: code.js/companion.py/styles.css major updates, autostart installer - src: ollama-client, session, LLMProvider, ollama-adapter patches - .gitignore: add claude-key, SQLite WAL/SHM, __pycache__, nohup.out Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
299 lines
12 KiB
Python
299 lines
12 KiB
Python
#!/usr/bin/env python3
|
|
"""Fast batch translate PCSP titles using pattern-based approach + key term mapping.
|
|
For case_study types, creates more detailed translations.
|
|
For commentary/response types, creates shorter descriptive translations."""
|
|
|
|
import sqlite3
|
|
import re
|
|
import html
|
|
|
|
DB_PATH = "/home/kim/homeclaw/.smallclaw/databases/psychotherapy_cases.db"
|
|
|
|
# Comprehensive term mapping (longest first for proper matching)
|
|
TERM_MAP = [
|
|
# Therapy approaches (long phrases first)
|
|
("Accelerated Experiential Dynamic Psychotherapy", "가속적경험적역동치료"),
|
|
("Accelerated Experiential Dynamic", "가속적경험적역동"),
|
|
("Emotionally Focused Couple Therapy", "정서초점부부치료"),
|
|
("Emotionally Focused Therapy", "정서초점치료"),
|
|
("Affect Phobia Therapy", "정서공포치료"),
|
|
("Affect Phobia", "정서공포"),
|
|
("Regulation Focused Psychotherapy for Children", "아동조절초점치료"),
|
|
("Regulation Focused Psychotherapy", "조절초점치료"),
|
|
("Dialectical Behavior Therapy", "변증법적행동치료"),
|
|
("Cognitive Behavioral Therapy", "인지행동치료"),
|
|
("Cognitive-Behavioral Therapy", "인지행동치료"),
|
|
("Cognitive Behavior Therapy", "인지행동치료"),
|
|
("Short-Term Psychodynamic Psychotherapy", "단기정신역동치료"),
|
|
("Short-Term Psychodynamic", "단기정신역동"),
|
|
("Written Exposure Therapy", "작성노출치료"),
|
|
("Exposure and Response Prevention", "노출및반응방지"),
|
|
("Exposure Therapy", "노출치료"),
|
|
("Prolonged Exposure", "지속노출"),
|
|
("Schema Therapy", "도식치료"),
|
|
("Narrative Therapy", "내러티브치료"),
|
|
("Solution-Focused Brief Therapy", "해결중심단기치료"),
|
|
("Solution-Focused", "해결중심"),
|
|
("Client-Centered Psychotherapy", "내담자중심치료"),
|
|
("Client-Centered Therapy", "내담자중심치료"),
|
|
("Person-Centered Therapy", "인간중심치료"),
|
|
("Psychodynamic Psychotherapy", "정신역동치료"),
|
|
("Psychodynamic Therapy", "정신역동치료"),
|
|
("Dynamic Psychotherapy", "역동치료"),
|
|
("Psychoanalytic Therapy", "정신분석치료"),
|
|
("Integrative Psychotherapy", "통합심리치료"),
|
|
("Integrative Therapy", "통합치료"),
|
|
("Group Cognitive Behavioral", "집단인지행동"),
|
|
("Group Therapy", "집단치료"),
|
|
("Couple Therapy", "부부치료"),
|
|
("Couples Therapy", "부부치료"),
|
|
("Family Therapy", "가족치료"),
|
|
("Acceptance and Commitment Therapy", "수용전념치료"),
|
|
("Paradoxical Intention", "역설적의도"),
|
|
("Mentalization", "정신화"),
|
|
("Mindfulness-Based", "마음챙김기반"),
|
|
("Mindfulness", "마음챙김"),
|
|
("Hypnosis", "최면"),
|
|
("Hypnotherapy", "최면치료"),
|
|
("Hypnotic", "최면"),
|
|
("Psychotherapy", "심리치료"),
|
|
("psychotherapy", "심리치료"),
|
|
# Disorders
|
|
("Post-Traumatic Stress Disorder", "외상후스트레스장애"),
|
|
("Posttraumatic Stress Disorder", "외상후스트레스장애"),
|
|
("Complex PTSD", "복합외상후스트레스장애"),
|
|
("Obsessive-Compulsive Disorder", "강박장애"),
|
|
("Obsessive Compulsive Disorder", "강박장애"),
|
|
("Borderline Personality Disorder", "경계선인격장애"),
|
|
("Bipolar Disorder", "양극성장애"),
|
|
("Panic Disorder", "공황장애"),
|
|
("Anxiety Disorders", "불안장애"),
|
|
("Anxiety Disorder", "불안장애"),
|
|
("Social Phobia", "사회공포증"),
|
|
("Social Anxiety", "사회불안"),
|
|
("Obsessive-Compulsive", "강박"),
|
|
("Obsessive Compulsive", "강박"),
|
|
("Alcohol Use Disorder", "알코올사용장애"),
|
|
("Alcohol Abuse", "알코올남용"),
|
|
("Body Dysmorphic", "신체이형"),
|
|
("Attention Deficit Hyperactivity Disorder", "주의력결핍과다행동장애"),
|
|
("Tourette Syndrome", "투렛증후군"),
|
|
("Agoraphobia", "광장공포증"),
|
|
("Relational Trauma", "관계적외상"),
|
|
("Developmental Disability", "발달장애"),
|
|
("Developmental Disabilities", "발달장애"),
|
|
("Executive Dysfunction", "실행기능장애"),
|
|
("Cognitive Difficulties", "인지어려움"),
|
|
("Externalizing Behavior", "외현화행동"),
|
|
("Conduct Problem", "품행문제"),
|
|
("Child Maltreatment", "아동학대"),
|
|
("Masculinity Norms", "남성성규범"),
|
|
("Inflexibly Enacted Traditional Masculinity", "경직된전통적남성성"),
|
|
("Suicide Prevention", "자살예방"),
|
|
("Psychosis", "정신병"),
|
|
("Psychotic", "정신병적"),
|
|
("Schizophrenia", "조현병"),
|
|
("Depression", "우울증"),
|
|
("Depressive", "우울"),
|
|
("Anxiety", "불안"),
|
|
("Trauma", "외상"),
|
|
("Traumatic", "외상"),
|
|
("PTSD", "외상후스트레스장애"),
|
|
("OCD", "강박장애"),
|
|
("BPD", "경계선인격장애"),
|
|
("DBT", "변증법적행동치료"),
|
|
("CBT", "인지행동치료"),
|
|
("ACT", "수용전념치료"),
|
|
("EFT", "정서초점치료"),
|
|
("AEDP", "가속적경험적역동치료"),
|
|
# Common patterns
|
|
("Case Study", "사례연구"),
|
|
("case study", "사례연구"),
|
|
("Case Formulation", "사례공식화"),
|
|
("Theory-Building", "이론구축"),
|
|
("Theory Building", "이론구축"),
|
|
("Practice-Based Evidence", "실천기반근거"),
|
|
("Evidence-Based Practice", "근거기반실천"),
|
|
("Evidence-Based", "근거기반"),
|
|
("Outcome Management", "결과관리"),
|
|
("Therapeutic Alliance", "치료적동맹"),
|
|
("Working Alliance", "작업동맹"),
|
|
("Autobiographical Memory", "자전적기억"),
|
|
("Religious Delusion", "종교적망상"),
|
|
("Altered State of Consciousness", "변된의식상태"),
|
|
("Three-Party Dialogue", "3자대화"),
|
|
("Incredible Years", "인크레더블연구"),
|
|
("Qualitative Analysis", "질적분석"),
|
|
("Qualitative", "질적"),
|
|
("Quantitative", "양적"),
|
|
("Mixed Methods", "혼합방법"),
|
|
("Short-Term", "단기"),
|
|
("Long-Term", "장기"),
|
|
("Later-Life", "노년기"),
|
|
("Late-Life", "노년기"),
|
|
("Older Adult", "노인"),
|
|
("Young Children", "영유아"),
|
|
("Commentary", "논평"),
|
|
("commentary", "논평"),
|
|
("Commentaries", "논평"),
|
|
("Reflections", "고찰"),
|
|
("Reflection", "고찰"),
|
|
("Response to Commentaries", "논평에 대한 응답"),
|
|
("Additional Perspectives", "추가 관점"),
|
|
("Introduction", "서론"),
|
|
("Clinician-Guided", "임상가안내"),
|
|
("Manualized", "매뉴얼화"),
|
|
("Self-Help", "자가도움"),
|
|
("Telepsych", "원격심리"),
|
|
("Online Therapy", "온라인치료"),
|
|
("Cultural Competence", "문화적역량"),
|
|
("Cultural", "문화적"),
|
|
("Multicultural", "다문화"),
|
|
("Feminist", "페미니스트"),
|
|
("Existential", "실존적"),
|
|
("Existentialism", "실존주의"),
|
|
("Sociocultural", "사회문화적"),
|
|
("Interpersonal", "대인관계"),
|
|
("Integrative", "통합적"),
|
|
("Integrating", "통합한"),
|
|
("Integrating", "~에 통합한"),
|
|
("Comparative", "비교"),
|
|
("Comparing", "비교"),
|
|
("Contrasting", "대조"),
|
|
("Methodological", "방법론적"),
|
|
("Methodology", "방법론"),
|
|
("Systematic", "체계적"),
|
|
("Pragmatic", "실용적"),
|
|
("Empirical", "실증적"),
|
|
("Epistemology", "인식론"),
|
|
("Objectivity", "객체성"),
|
|
("Causality", "인과성"),
|
|
("Clinical", "임상"),
|
|
("Therapeutic", "치료적"),
|
|
("Adolescent", "청소년"),
|
|
("Youth", "청소년"),
|
|
("Children", "아동"),
|
|
("Child", "아동"),
|
|
("Veterans", "참전군인"),
|
|
("Veteran", "참전군인"),
|
|
("Suicide", "자살"),
|
|
("Suicidal", "자살"),
|
|
("Treatment", "치료"),
|
|
("treatment", "치료"),
|
|
("Therapy", "치료"),
|
|
("therapy", "치료"),
|
|
("Psychotherapy", "심리치료"),
|
|
]
|
|
|
|
def clean_title(title):
|
|
"""Clean HTML entities and whitespace."""
|
|
title = html.unescape(title)
|
|
title = re.sub(r'\s+', ' ', title).strip()
|
|
return title
|
|
|
|
def translate_title(title_en, category_en, category_ko, article_type):
|
|
"""Translate title using pattern matching with category-aware fallback."""
|
|
title = clean_title(title_en)
|
|
|
|
if not title:
|
|
return ""
|
|
|
|
# Apply term replacements (longest first)
|
|
result = title
|
|
for en, ko in TERM_MAP:
|
|
# Case-sensitive for proper nouns, case-insensitive for common terms
|
|
if en[0].isupper() and len(en) > 3:
|
|
result = result.replace(en, ko)
|
|
else:
|
|
result = re.sub(re.escape(en), ko, result, flags=re.IGNORECASE)
|
|
|
|
# Clean up spacing
|
|
result = re.sub(r'\s+', ' ', result).strip()
|
|
|
|
# Check translation quality - how much Korean content
|
|
korean_chars = len(re.findall(r'[가-힣]', result))
|
|
total_chars = len(result.replace(' ', ''))
|
|
|
|
if total_chars > 0 and korean_chars / total_chars > 0.3:
|
|
# Decent translation - clean up any remaining artifacts
|
|
result = re.sub(r'\s{2,}', ' ', result).strip()
|
|
return result
|
|
else:
|
|
# Poor translation - use category prefix + original
|
|
type_prefix = {
|
|
"case_study": "사례연구:",
|
|
"commentary": "논평:",
|
|
"response": "응답:",
|
|
"article": "",
|
|
}
|
|
prefix = type_prefix.get(article_type, "")
|
|
return f"[{category_ko}] {prefix} {title}" if prefix else f"[{category_ko}] {title}"
|
|
|
|
def main():
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
|
|
# Get untranslated titles
|
|
c.execute("SELECT id, title_en, category_en, category_ko, article_type FROM cases WHERE title_ko = '' OR title_ko IS NULL ORDER BY id")
|
|
rows = c.fetchall()
|
|
|
|
print(f"Translating {len(rows)} remaining titles...")
|
|
|
|
translated = 0
|
|
partial = 0
|
|
fallback = 0
|
|
|
|
for row in rows:
|
|
id_, title_en, cat_en, cat_ko, art_type = row
|
|
title_ko = translate_title(title_en, cat_en, cat_ko, art_type)
|
|
|
|
korean_chars = len(re.findall(r'[가-힣]', title_ko))
|
|
total_chars = len(title_ko.replace(' ', ''))
|
|
|
|
if total_chars > 0 and korean_chars / total_chars > 0.5:
|
|
translated += 1
|
|
elif total_chars > 0 and korean_chars / total_chars > 0.2:
|
|
partial += 1
|
|
else:
|
|
fallback += 1
|
|
|
|
c.execute("UPDATE cases SET title_ko = ? WHERE id = ?", (title_ko, id_))
|
|
|
|
conn.commit()
|
|
|
|
# Final stats
|
|
c.execute("SELECT COUNT(*) FROM cases WHERE title_ko != '' AND title_ko IS NOT NULL")
|
|
total_done = c.fetchone()[0]
|
|
c.execute("SELECT COUNT(*) FROM cases WHERE title_ko = '' OR title_ko IS NULL")
|
|
remaining = c.fetchone()[0]
|
|
|
|
print(f"\nTranslation stats:")
|
|
print(f" Well translated: {translated}")
|
|
print(f" Partially translated: {partial}")
|
|
print(f" Fallback (category + original): {fallback}")
|
|
print(f" Total in DB: {total_done}, Remaining: {remaining}")
|
|
|
|
# Samples by quality
|
|
print("\n--- Well translated samples ---")
|
|
c.execute("""SELECT title_en, title_ko FROM cases
|
|
WHERE title_ko != '' AND title_ko IS NOT NULL
|
|
AND LENGTH(title_ko) - LENGTH(REPLACE(title_ko, ' ', '')) > 3
|
|
ORDER BY RANDOM() LIMIT 5""")
|
|
for row in c.fetchall():
|
|
print(f" EN: {row[0][:80]}")
|
|
print(f" KO: {row[1][:80]}")
|
|
print()
|
|
|
|
print("--- Fallback samples ---")
|
|
c.execute("""SELECT title_en, title_ko FROM cases
|
|
WHERE title_ko LIKE '[%'
|
|
ORDER BY RANDOM() LIMIT 5""")
|
|
for row in c.fetchall():
|
|
print(f" EN: {row[0][:80]}")
|
|
print(f" KO: {row[1][:80]}")
|
|
print()
|
|
|
|
conn.close()
|
|
|
|
if __name__ == "__main__":
|
|
main() |