← back to Dear Bubbe Nextjs
lib/yiddish-dictionary/schema.sql
175 lines
-- Yiddish Dictionary Schema for Dear Bubbe
-- Supports multiple dictionary sources with deduplication
-- Includes Bubbe-safe filtering capabilities
PRAGMA foreign_keys = ON;
-- Dictionary sources (different GitHub repos, community contributions, etc.)
CREATE TABLE IF NOT EXISTS sources (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
url TEXT,
license TEXT,
notes TEXT,
imported_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Main dictionary entries
CREATE TABLE IF NOT EXISTS entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
yiddish TEXT NOT NULL, -- Original Yiddish text (Hebrew script)
yiddish_latin TEXT, -- Latin transliteration
english TEXT NOT NULL, -- English translation
pos TEXT, -- Part of speech (noun, verb, adj, etc.)
gender TEXT, -- Grammatical gender (m/f/n)
plural TEXT, -- Plural form
tags TEXT, -- Comma-separated tags (slang, archaic, etc.)
usage_example TEXT, -- Example sentence
cultural_note TEXT, -- Cultural context or usage notes
source_id INTEGER NOT NULL,
source_entry_id TEXT, -- Original ID from source
bubbe_approved INTEGER DEFAULT 1, -- 1=safe for Bubbe, 0=needs review, -1=banned
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (source_id) REFERENCES sources(id),
UNIQUE (yiddish, english, source_id) ON CONFLICT IGNORE
);
-- Indexes for fast lookups
CREATE INDEX IF NOT EXISTS idx_entries_yiddish ON entries(yiddish);
CREATE INDEX IF NOT EXISTS idx_entries_yiddish_latin ON entries(yiddish_latin);
CREATE INDEX IF NOT EXISTS idx_entries_english ON entries(english);
CREATE INDEX IF NOT EXISTS idx_entries_source ON entries(source_id);
CREATE INDEX IF NOT EXISTS idx_entries_bubbe_approved ON entries(bubbe_approved);
CREATE INDEX IF NOT EXISTS idx_entries_pos ON entries(pos);
-- Synonyms and variations
CREATE TABLE IF NOT EXISTS variations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
entry_id INTEGER NOT NULL,
variation TEXT NOT NULL,
variation_type TEXT, -- 'spelling', 'regional', 'historical'
notes TEXT,
FOREIGN KEY (entry_id) REFERENCES entries(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_variations_entry ON variations(entry_id);
CREATE INDEX IF NOT EXISTS idx_variations_text ON variations(variation);
-- Phrases and idioms (multi-word expressions)
CREATE TABLE IF NOT EXISTS phrases (
id INTEGER PRIMARY KEY AUTOINCREMENT,
yiddish TEXT NOT NULL,
yiddish_latin TEXT,
english TEXT NOT NULL,
literal_meaning TEXT, -- Word-for-word translation
usage_context TEXT, -- When/how to use it
cultural_note TEXT,
source_id INTEGER,
bubbe_approved INTEGER DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (source_id) REFERENCES sources(id)
);
CREATE INDEX IF NOT EXISTS idx_phrases_yiddish ON phrases(yiddish);
CREATE INDEX IF NOT EXISTS idx_phrases_english ON phrases(english);
-- Terms that should never be used (supplements banned-terms.json)
CREATE TABLE IF NOT EXISTS banned_terms (
id INTEGER PRIMARY KEY AUTOINCREMENT,
term TEXT NOT NULL UNIQUE,
language TEXT NOT NULL, -- 'yi' for Yiddish, 'en' for English
category TEXT, -- 'ethnic_slur', 'offensive', 'inappropriate'
severity TEXT, -- 'critical', 'high', 'medium'
reason TEXT,
replacement TEXT, -- Suggested alternative
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_banned_term ON banned_terms(term);
CREATE INDEX IF NOT EXISTS idx_banned_language ON banned_terms(language);
-- Usage statistics for learning which terms Bubbe uses most
CREATE TABLE IF NOT EXISTS usage_stats (
id INTEGER PRIMARY KEY AUTOINCREMENT,
entry_id INTEGER,
phrase_id INTEGER,
term TEXT NOT NULL,
usage_count INTEGER DEFAULT 1,
last_used TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
context TEXT, -- 'greeting', 'insult', 'advice', etc.
FOREIGN KEY (entry_id) REFERENCES entries(id),
FOREIGN KEY (phrase_id) REFERENCES phrases(id)
);
CREATE INDEX IF NOT EXISTS idx_usage_stats_entry ON usage_stats(entry_id);
CREATE INDEX IF NOT EXISTS idx_usage_stats_term ON usage_stats(term);
-- Curated Bubbe responses (her favorite expressions)
CREATE TABLE IF NOT EXISTS bubbe_favorites (
id INTEGER PRIMARY KEY AUTOINCREMENT,
yiddish TEXT NOT NULL,
english TEXT NOT NULL,
context TEXT, -- 'scolding', 'complaining', 'advice'
intensity INTEGER DEFAULT 5, -- 1-10 scale of harshness
usage_example TEXT,
notes TEXT
);
-- View for easy access to approved terms with all variations
CREATE VIEW IF NOT EXISTS approved_vocabulary AS
SELECT
e.id,
e.yiddish,
e.yiddish_latin,
e.english,
e.pos,
e.gender,
e.tags,
e.usage_example,
e.cultural_note,
s.name as source_name,
GROUP_CONCAT(v.variation, ', ') as variations
FROM entries e
LEFT JOIN sources s ON e.source_id = s.id
LEFT JOIN variations v ON e.id = v.entry_id
WHERE e.bubbe_approved = 1
GROUP BY e.id;
-- View for Bubbe's active vocabulary (frequently used + favorites)
CREATE VIEW IF NOT EXISTS bubbe_active_vocabulary AS
SELECT
'entry' as type,
e.yiddish,
e.yiddish_latin,
e.english,
e.usage_example,
us.usage_count,
us.last_used
FROM entries e
JOIN usage_stats us ON e.id = us.entry_id
WHERE e.bubbe_approved = 1
UNION ALL
SELECT
'phrase' as type,
p.yiddish,
p.yiddish_latin,
p.english,
p.usage_context as usage_example,
us.usage_count,
us.last_used
FROM phrases p
JOIN usage_stats us ON p.id = us.phrase_id
WHERE p.bubbe_approved = 1
UNION ALL
SELECT
'favorite' as type,
bf.yiddish,
NULL as yiddish_latin,
bf.english,
bf.usage_example,
NULL as usage_count,
NULL as last_used
FROM bubbe_favorites bf
ORDER BY usage_count DESC, last_used DESC;