wikitongues-db 0.1.1 → 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,35 +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** | `467` |
52
- | **Unique BCP 47 Language Tags** | `541` |
53
- | **Glottocode Resolution** | `862 / 863` (99.9%) |
54
- | **Native Script Autonyms** | `863 / 863` (100.0%) |
55
- | **Resolved Dialects / Varieties** | `296 / 863` (34.3%) |
56
- | **Identified Recorders** | `491 / 863` (56.9%) |
57
- | **Embedded Transcripts / Translations** | `57` |
58
- | **Total Archival Duration** | `53h 54m 30s` (`194,070` seconds) |
59
- | **Videos with Subtitles / Captions** | `284` |
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` |
60
94
  | **Runtime Dependencies** | `0` |
61
95
 
62
96
  ---
@@ -80,17 +114,18 @@ pnpm add wikitongues-db
80
114
  ```typescript
81
115
  import { WikitonguesDB } from 'wikitongues-db';
82
116
 
83
- // Initializes in-memory inverted indices across 863 curated recordings instantly
117
+ // Hydrates and indexes 862 curated recordings instantly (throws HydrationError on an invalid record)
84
118
  const db = new WikitonguesDB();
85
119
 
86
- // 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)
87
121
  const russianVids = db.findByLanguage('russe'); // or "Russian", "rus", "ru", "Русский", "russ1263"
88
122
  const quechuaVids = db.findByLanguage('Qhichwa'); // by native autonym
89
- const arbereshVids = db.findByLanguage('Arbëresh'); // by dialect
123
+ const soraniVids = db.findByLanguage('Sorani'); // by Wikitongues' label (ISO says "Central Kurdish")
90
124
 
91
125
  // 2. O(1) Indexed Lookups
92
126
  const video = db.get('nXBPa_wb3dM'); // Lookup by YouTube ID
93
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
94
129
  const peruVids = db.getByCountry('PE'); // Lookup by ISO 3166-1 alpha-2 or country name
95
130
  ```
96
131
 
@@ -120,7 +155,7 @@ for (const v of results) {
120
155
  ```typescript
121
156
  const matches = db.search('dagestan caucasian oral history', 5);
122
157
  for (const v of matches) {
123
- console.log(v.title, v.primaryLanguage.name, v.url);
158
+ console.log(v.title, v.primaryLanguage.wikitonguesClassification, v.url);
124
159
  }
125
160
  ```
126
161
 
@@ -154,8 +189,42 @@ import dataset from 'wikitongues-db/data';
154
189
  // or: import { dataset } from 'wikitongues-db';
155
190
 
156
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`
157
224
  ```
158
225
 
226
+ The test suite fails if the committed file is out of date.
227
+
159
228
  ---
160
229
 
161
230
  ## Roadmap
@@ -163,7 +232,8 @@ console.log(`Loaded ${dataset.length} normalized records directly`);
163
232
  - [x] **Phase 1 — Normalization & Semantic Validation**: Curate structured entities strictly against SIL ISO 639-3 and Glottolog tables.
164
233
  - [x] **Phase 2 — Inverted Indexing & Smart Resolution**: $O(1)$ lookups, multilingual search, and query engine.
165
234
  - [x] **Phase 3 — TypeScript (npm) Package**: Zero-dependency package with embedded dataset, dual ESM/CJS, and full TypeScript types.
166
- - [ ] **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.
167
237
 
168
238
  ---
169
239