wikitongues-db 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # wikitongues-db
2
2
 
3
- > A zero-dependency, in-memory database and search engine mapping ISO 639-3, BCP 47, Glottolog, autonyms, and dialects to curated Wikitongues video recordings. Published for **TypeScript / JavaScript (npm)**.
3
+ > A zero-dependency, in-memory database and search engine mapping three independent language classifications — **ISO 639-3**, **Glottolog** and **BCP 47** plus autonyms and Wikitongues' own labels to curated Wikitongues video recordings. Published for **TypeScript / JavaScript (npm)**.
4
4
 
5
5
  ---
6
6
 
@@ -11,9 +11,9 @@
11
11
  However, existing metadata across YouTube and Commons is heterogeneous, with free-text descriptions, unstructured notes, and no unified linguistic index.
12
12
 
13
13
  **`wikitongues-db`** bridges this gap by providing:
14
- 1. **A curated, deterministic dataset**: 863 normalized records across 460+ languages with structured speaker roles, dialects, geographic provenance, licensing, and transcript status.
15
- 2. **Strict linguistic validation**: Verified against official **SIL ISO 639-3** tables, **BCP 47** tags, and **Glottolog** identifiers.
16
- 3. **Multi-faceted resolution**: Instant matching by ISO code, BCP 47 tag, Glottocode, English canonical name, multilingual common name (e.g. `russe`, `espagnol`), native script autonym (`Qhichwa`, `Asụsụ Igbo`, `Русский`), or dialect variety (`Arbëresh`, `Gascon`, `Biscayan`).
14
+ 1. **A curated, deterministic dataset**: 862 normalized records across 460+ languages with structured speaker roles, geographic provenance, licensing, and transcript status.
15
+ 2. **Tri-ontological classification**: every language carries its **SIL ISO 639-3** code, its **Glottolog** node (language *or dialect*) and its **BCP 47** tag, each recorded independently according to its own authority's logic and resolved at load time against the bundled reference tables (see [CLASSIFICATION_RULES.md](CLASSIFICATION_RULES.md)). A record that does not resolve does not load.
16
+ 3. **Multi-faceted resolution**: Instant matching by ISO code, BCP 47 tag, Glottocode (a language node also matches its dialect nodes), ISO / Glottolog names, Wikitongues' own label (`Sorani`, `Gascon`, `Biscayan`), multilingual common name (e.g. `russe`, `espagnol`), or native script autonym (`Qhichwa`, `Asụsụ Igbo`, `Русский`).
17
17
  4. **Rich content types**: Covers oral histories (81%), spontaneous conversations (13%), sign languages (2.5%), readings/songs (1.5%), and fellowship documentaries.
18
18
  5. **Zero-dependency TypeScript client**: Embedded in-memory database with $O(1)$ inverted indices, fluent query builder, and full-text search engine.
19
19
 
@@ -28,33 +28,69 @@ However, existing metadata across YouTube and Commons is heterogeneous, with fre
28
28
  │ (Curated Metadata)
29
29
 
30
30
  ┌─────────────────────────────────────────┐
31
- SIL ISO 639-3 & Glottolog Validator <-- Anti-hallucination safeguard
31
+ Persisted anchor keys per language
32
+ │ standards: { iso639_3, glottocode, │
33
+ │ bcp47 } │
34
+ │ + speaker_claim, wikitongues_ │
35
+ │ classification, wikitongues_lineage, │
36
+ │ autonym │
32
37
  └────────────────────┬────────────────────┘
33
- │ (Deterministic Indexing)
38
+ │ (Deterministic hydration at load time)
39
+ │ ← iso-639-3.tab / glottolog_languages.csv /
40
+ │ IANA subtag registry (pruned, bundled)
34
41
 
35
42
  ┌─────────────────────────────────────────┐
36
- wikitongues-db (Static JSON / DB)
43
+ Language.standards = {
44
+ │ iso639_3: { code, name, scope … } │
45
+ │ glottolog: { code, name, level, │
46
+ │ parentLanguageId … } │
47
+ │ bcp47: { tag, primarySubtag, │
48
+ │ regionSubtag … } │
49
+ │ } │
37
50
  └────────────────────┬────────────────────┘
38
-
39
51
 
40
52
  TypeScript (npm)
41
53
  O(1) in-memory API
42
54
  ```
43
55
 
56
+ ### The language model
57
+
58
+ Three institutional standards answer three different questions, so the dataset never collapses them into a single `name` / `dialect` pair:
59
+
60
+ | Standard | Question it answers | Example (Ygor speaking Brazilian Portuguese) |
61
+ | :--- | :--- | :--- |
62
+ | `standards.iso639_3` | Which individual language does SIL register? | `por` — Portuguese |
63
+ | `standards.glottolog` | Which node of the phylogenetic tree? | `braz1246` — Brazilian Portuguese, *dialect* of `port1283` |
64
+ | `standards.bcp47` | Which locale tag? | `pt-BR` |
65
+
66
+ Alongside them, three cultural identifiers are persisted verbatim: `speaker_claim` (how the speaker names their language in the video, `null` if they never do), `wikitongues_classification` (the label Wikitongues itself uses, e.g. `Jèrriais`) with `wikitongues_lineage` (`Norman Romance`), and `autonym` (`Português`).
67
+
68
+ ```typescript
69
+ const lang = db.get('qpfxFvpLAJ8')!.primaryLanguage;
70
+ lang.standards.iso639_3; // { code: 'por', name: 'Portuguese', scope: 'I', type: 'L', part1: 'pt' }
71
+ lang.standards.glottolog; // { code: 'braz1246', name: 'Brazilian Portuguese', level: 'dialect', parentLanguageId: 'port1283', familyId: 'indo1319', … }
72
+ lang.standards.bcp47; // { tag: 'pt-BR', primarySubtag: 'pt', regionSubtag: 'BR', variantSubtags: [] }
73
+ lang.wikitonguesClassification; // 'Brazilian Portuguese'
74
+ lang.iso639_3; lang.glottocode; lang.bcp47; lang.name; // short accessors
75
+ ```
76
+
44
77
  ---
45
78
 
46
79
  ## Dataset Overview
47
80
 
48
81
  | Metric | Value |
49
82
  | :--- | :--- |
50
- | **Total Curated Videos** | `863` |
51
- | **Unique Primary ISO 639-3 Languages** | `462` |
52
- | **Unique BCP 47 Language Tags** | `515` |
53
- | **Glottocode Resolution** | `466 / 863` (54.0%) |
54
- | **Native Script Autonyms** | `820 / 863` (95.0%) |
55
- | **Resolved Dialects / Varieties** | `266 / 863` (30.8%) |
56
- | **Total Archival Duration** | `53h 54m 30s` (`194,070` seconds) |
57
- | **Videos with Subtitles / Captions** | `275` |
83
+ | **Total Curated Videos** | `862` |
84
+ | **Unique Primary ISO 639-3 Languages** | `466` |
85
+ | **Unique Primary Glottolog Nodes** | `485` (`72` dialect-level) |
86
+ | **Unique BCP 47 Language Tags** | `501` |
87
+ | **Fully Classified (ISO + Glottolog + BCP 47)** | `862 / 862` (100%, enforced at load time) |
88
+ | **Native Script Autonyms** | `862 / 862` (100.0%) |
89
+ | **Wikitongues Lineage Labels** | `120` |
90
+ | **Identified Recorders** | `491 / 862` (57.0%) |
91
+ | **Embedded Transcripts / Translations** | `56` |
92
+ | **Total Archival Duration** | `53h 52m 42s` (`193,962` seconds) |
93
+ | **Videos with Subtitles / Captions** | `283` |
58
94
  | **Runtime Dependencies** | `0` |
59
95
 
60
96
  ---
@@ -78,17 +114,18 @@ pnpm add wikitongues-db
78
114
  ```typescript
79
115
  import { WikitonguesDB } from 'wikitongues-db';
80
116
 
81
- // Initializes in-memory inverted indices across 863 curated recordings instantly
117
+ // Hydrates and indexes 862 curated recordings instantly (throws HydrationError on an invalid record)
82
118
  const db = new WikitonguesDB();
83
119
 
84
- // 1. Smart Language Search (supports ISO 639-3, BCP 47, Glottolog, French/English aliases, autonyms)
120
+ // 1. Smart Language Search (ISO 639-3, BCP 47, Glottolog, ISO / Glottolog / Wikitongues names, aliases, autonyms)
85
121
  const russianVids = db.findByLanguage('russe'); // or "Russian", "rus", "ru", "Русский", "russ1263"
86
122
  const quechuaVids = db.findByLanguage('Qhichwa'); // by native autonym
87
- const arbereshVids = db.findByLanguage('Arbëresh'); // by dialect
123
+ const soraniVids = db.findByLanguage('Sorani'); // by Wikitongues' label (ISO says "Central Kurdish")
88
124
 
89
125
  // 2. O(1) Indexed Lookups
90
126
  const video = db.get('nXBPa_wb3dM'); // Lookup by YouTube ID
91
127
  const basqueVids = db.getByIso('eus'); // Lookup by ISO 639-3
128
+ const portuguese = db.getByGlottocode('port1283'); // Language node: includes dialect nodes such as braz1246
92
129
  const peruVids = db.getByCountry('PE'); // Lookup by ISO 3166-1 alpha-2 or country name
93
130
  ```
94
131
 
@@ -118,7 +155,7 @@ for (const v of results) {
118
155
  ```typescript
119
156
  const matches = db.search('dagestan caucasian oral history', 5);
120
157
  for (const v of matches) {
121
- console.log(v.title, v.primaryLanguage.name, v.url);
158
+ console.log(v.title, v.primaryLanguage.wikitonguesClassification, v.url);
122
159
  }
123
160
  ```
124
161
 
@@ -152,8 +189,42 @@ import dataset from 'wikitongues-db/data';
152
189
  // or: import { dataset } from 'wikitongues-db';
153
190
 
154
191
  console.log(`Loaded ${dataset.length} normalized records directly`);
192
+ // dataset[0].primary_language.standards → { iso639_3: 'quz', glottocode: 'cusc1236', bcp47: 'quz' }
193
+ ```
194
+
195
+ The raw dataset holds only the anchor keys; use `WikitonguesDB` (or `ReferenceHydrator`) to resolve them into names, levels and subtags.
196
+
197
+ ### 6. Runnable demos
198
+
199
+ ```bash
200
+ npm run demo # runs demos/01 … 08 in order
201
+ npx tsx demos/02-smart-search.ts Sorani # most scripts take arguments
202
+ npx tsx demos/03-tri-ontological-view.ts PeZHJcQYt3c
203
+ npx tsx demos/04-glottolog-tree.ts occi1239
204
+ ```
205
+
206
+ | Script | Shows |
207
+ | :--- | :--- |
208
+ | `demos/01-load-and-stats.ts` | Construction, `stats()`, the bundled reference tables |
209
+ | `demos/02-smart-search.ts` | One `findByLanguage()` call resolving ISO, BCP 47, Glottocode, names, aliases, autonyms |
210
+ | `demos/03-tri-ontological-view.ts` | The three resolved standards + cultural identifiers for one recording |
211
+ | `demos/04-glottolog-tree.ts` | A language node returning its dialect nodes, primary or additional |
212
+ | `demos/05-query-builder.ts` | Chained filters, grouping, pagination, `count()` / `exists()` |
213
+ | `demos/06-inventory.ts` | Where SIL, Glottolog, BCP 47 and Wikitongues disagree, as tables |
214
+ | `demos/07-fail-fast.ts` | Every kind of invalid record and the `HydrationError` it raises |
215
+ | `demos/08-export.ts` | Seeded sampling, CSV, JSONL, hydrated vs persisted form |
216
+ | `demos/09-find-a-standard.ts` | Finding the *standard* variety (Parisian French, British English…) via Glottolog nodes or by chaining ISO + country + label filters |
217
+
218
+ ### 7. Reference Tables
219
+
220
+ `src/generated/reference.json` is a pruned copy of the ISO 639-3 table, Glottolog and the IANA subtag registry containing exactly the codes the dataset uses (plus parent languages and families). Regenerate it after any change to the dataset or to `data/references/`:
221
+
222
+ ```bash
223
+ npm run build:reference # also run automatically by `npm run build`
155
224
  ```
156
225
 
226
+ The test suite fails if the committed file is out of date.
227
+
157
228
  ---
158
229
 
159
230
  ## Roadmap
@@ -161,7 +232,8 @@ console.log(`Loaded ${dataset.length} normalized records directly`);
161
232
  - [x] **Phase 1 — Normalization & Semantic Validation**: Curate structured entities strictly against SIL ISO 639-3 and Glottolog tables.
162
233
  - [x] **Phase 2 — Inverted Indexing & Smart Resolution**: $O(1)$ lookups, multilingual search, and query engine.
163
234
  - [x] **Phase 3 — TypeScript (npm) Package**: Zero-dependency package with embedded dataset, dual ESM/CJS, and full TypeScript types.
164
- - [ ] **Phase 4 — Rust (crates.io)**: High-performance, zero-alloc lookup engine.
235
+ - [x] **Phase 4 — Tri-ontological classification (v0.2.0)**: independent ISO 639-3 / Glottolog / BCP 47 anchors hydrated from bundled reference tables; no nullable standards.
236
+ - [ ] **Phase 5 — Rust (crates.io)**: High-performance, zero-alloc lookup engine.
165
237
 
166
238
  ---
167
239