Naar hoofdinhoud gaan

Taalkaart Specificatie

Enige bron van waarheid. Dit document definieert de canonieke structuur van elke taalkaart. Elke kaart MOET elk veld op het hoogste niveau bevatten dat hier vermeld staat, zelfs wanneer de waarde null of [] is. Een kaart met een ontbrekend veld is niet-conform. Deze uniformiteit stelt geautomatiseerde tools, linters, verrijkingsscripts en menselijke reviewers in staat de kaartstructuur te vertrouwen.

Ontwerpprincipes

  1. Uniforme structuur. Alle 8.000+ kaarten hebben dezelfde velden op het hoogste niveau. Onbekende waarden zijn null, lege arrays zijn [], lege objecten zijn null (niet {}). Dit betekent dat code nooit hoeft te controleren "bestaat dit veld?" — alleen "is het ingevuld?"

  2. Bronvermelding voor alles. Elke feitelijke bewering is herleidbaar tot een benoemde, versioned, primaire bron. Ongedocumenteerde beweringen zijn niet-verifieerbare beweringen. Het veld dataSources (en per-veld source-annotaties in sub-objecten) maken herkomst expliciet.

  3. Meningsverschillen bewaren. Wanneer autoriteiten het oneens zijn (Wikidata zegt 50.000 sprekers, Ethnologue zegt 20.000), slaan we beide op met bronvermelding. We middelen niet, lossen niet op en kiezen geen kant. Gebruikers kunnen de nuance zelf beoordelen.

  4. Null betekent onbekend, niet niet-van-toepassing. Als een veld null is, betekent dit "we hebben hier nog geen gegevens voor gevonden." Als een veld werkelijk niet van toepassing is (bijv. grammatical gender voor een gebarentaal), moet de waarde dit toelichten: { "grammatical": false, "inclusiveGuidance": "Not applicable — ASL does not have grammatical gender." }

  5. Alleen samenvoegen. Verrijkingsscripts voegen gegevens toe, overschrijven nooit. Door mensen samengestelde waarden hebben prioriteit boven geautomatiseerde gegevens.


Drielaagse Architectuur

LaagLocatieDoel
Taalkaartenshared/language-cards/<code>.jsonPer-taal configuratie: identiteit, classificatie, bronnen, alles
Genuskaartenshared/language-cards/genera/<genus>.jsonGedeelde runtime-eigenschappen voor verwante talen (samengesteld, niet automatisch gegenereerd)
Taalboomshared/language-cards/language-tree.jsonVolledige Glottolog-hiërarchie — referentiegegevens voor Lab UI en taalontdekking

Overerving Model

Wanneer een kaart "extends": "family-dravidian" instelt, voegt de runtime de bovenliggende kaart samen met de onderliggende kaart via _deepMerge() (in lib/registers.js). Hierdoor kunnen genuskaarten gedeelde registers, formaliteitssystemen en genderbegeleiding definiëren die doorstromen naar alle lidtalen — zonder gegevens te dupliceren over honderden afzonderlijke kaarten.

Samenvoegingssemantiek

Waarde van kindGedragWaarom
nullOvernemen van oudernull betekent "ik definieer dit niet" — de waarde van de ouder stroomt door
Niet-nullOuder overschrijvenDe gegevens van het kind zijn specifieker — hebben prioriteit
Genest objectRecursief samenvoegenVelden van het kind overschrijven, velden van de ouder blijven behouden
ArrayVolledig vervangenArrays worden niet item-voor-item samengevoegd — de array van het kind wint

Identiteitsvelden (Nooit Overgeërfd)

Sommige velden behoren tot de kaart zelf en mogen NOOIT worden overgeërfd van een ouder:

code, extends, _migration, aliases, iso639_1, iso639_3

Zelfs als een ouderkaart aliases: ["macro-code"] definieert, zal een kindkaart die aliassen NIET overnemen. Deze velden zijn altijd de eigen waarden van het kind (inclusief null indien niet ingesteld).

Waarom: Zonder deze regel zou elke Cree-taal aliases: ["cre"] overnemen van de macrotaalbovenliggende, waardoor elke variant een alias van de macro wordt.

Voorbeeld: Hoe een Cree-kaart wordt opgelost

┌───────────────────────┐
│ family-algic.json │ formality: null, registers: null
│ (no registers) │
└──────────┬────────────┘
│ extends
┌──────────┴────────────┐
│ genus-cree.json │ formality: { system: "obviative-animate", ... }
│ (sourced registers) │ registers: { formal: {...}, informal: {...} }
└──────────┬────────────┘
│ extends
┌──────────┴────────────┐
│ crk.json │ code: "crk", extends: "genus-cree"
│ (Plains Cree) │ formality: null → inherits from genus-cree
│ │ registers: null → inherits from genus-cree
│ │ script: "Cans" → own value, no inheritance
│ │ code: "crk" → identity field, never inherited
└───────────────────────┘

Bij runtime retourneert getLanguageCard("crk") een samengevoegd object met de registers van genus-cree + de eigenschappen van family-algic (indien aanwezig) + de eigen identiteit en metadata van crk.

Genuskaart Sjabloon

Genuskaarten bevinden zich in shared/language-cards/genera/ en definiëren gedeelde eigenschappen voor een taalgroep. Ze volgen hetzelfde schema als gewone kaarten, maar met andere conventies:

{
// Identity — genus cards use a prefixed code, NOT an ISO 639-3 code
"code": "genus-cree", // "genus-", "family-", or "macrolanguage-" prefix
"name": "Cree Languages", // Human-readable group name
"extends": "family-algic", // Genus cards can extend family cards (chaining)

// Formality — shared across the group, sourced from typological databases
"formality": {
"system": "obviative-animate",
"description": "Cree languages use an obviative/proximate system...",
"default": "formal",
"source": "WALS 37A, 38A + Wolfart 1973"
},

// Registers — shared presets, if the group shares a formality system
"registers": {
"formal": {
"label": "Formal (Proximate)",
"description": "...",
"prompt": "...",
"isDefault": true
},
"informal": {
"label": "Informal",
"description": "...",
"prompt": "..."
}
},

// Gender — shared grammatical gender behavior
"gender": {
"grammatical": false, // Cree doesn't have grammatical gender
"inclusiveGuidance": null // so no inclusive guidance needed
},

// Everything else is null — individual cards provide their own
// classification, geography, resources, etc.
"classification": null,
"methodSupport": null,
// ...
}

Belangrijkste regel: Genuskaarten mogen ALLEEN gegevens bevatten die werkelijk gedeeld worden door de gehele groep en afkomstig zijn van gezaghebbende bronnen. Als een formaliteitssysteem verschilt tussen leden, hoort het op de afzonderlijke kaarten thuis, niet op de genuskaart.

Canoniek Sjabloon

Elke kaart MOET deze exacte structuur op het hoogste niveau hebben. Schema's van sub-objecten zijn gedocumenteerd in de Veldreferentie hieronder.

{
// ═══════════════════════════════════════════════════════════════════════
// § 1. IDENTITY
// Who is this language? What codes identify it?
// Sources: ISO 639-3 registry, ISO 639-1, BCP 47/IANA.
// ═══════════════════════════════════════════════════════════════════════

"code": "xxx", // REQUIRED. ISO 639-3 code. This IS the card ID and filename.
"name": "English Name", // REQUIRED. English reference name from ISO 639-3 registry.
"nativeName": null, // Endonym (name in the language itself). Source: Wikidata P1705.
// Examples: "nêhiyawêwin / ᓀᐦᐃᔭᐍᐏᐣ", "日本語", "Esperanto".
"alternateNames": [], // Other names this language is known by. Source: Glottolog, Ethnologue.
// Not aliases (those are code-level). These are name-level variants.
// Example: ["Qafar af", "Afaraf", "'Afar Af"] for Afar (aar).
"iso639_3": "xxx", // REQUIRED. Three-letter ISO 639-3 code. Same as `code`.
"iso639_1": null, // Two-letter ISO 639-1 code (e.g., "en", "fr"). null if none.
"bcp47": null, // IETF BCP 47 tag. Often same as iso639_1. Can include subtags
// (e.g., "iu-Cans-CA"). null if unknown.
"aliases": [], // Alternative code-level identifiers that resolve to this card.
// Example: ["fil"] for tl (Tagalog), ["iu"] for iku (Inuktitut).
// Used by code resolution: user types "fil", system loads tl.json.
"isoScope": "I", // REQUIRED. ISO 639-3 scope:
// "I" = Individual language
// "M" = Macrolanguage (e.g., Chinese, Arabic, Cree)
// "S" = Special (e.g., mis, mul, zxx)
"isoType": "L", // REQUIRED. ISO 639-3 type:
// "L" = Living "E" = Extinct "A" = Ancient
// "H" = Historical "C" = Constructed
"macrolanguage": null, // If this language is part of a macrolanguage, the macrolanguage
// ISO 639-3 code (e.g., "cre" for Plains Cree, "ara" for Arabic
// varieties). Source: ISO 639-3 macrolanguages.tab.
"extends": null, // Genus card key if shared properties are inherited from a genus
// card (e.g., "genus-cree", "genus-eskimo-aleut").
// null for most languages.

// ═══════════════════════════════════════════════════════════════════════
// § 2. CLASSIFICATION
// Where does this language sit in the family tree?
// Source: Glottolog. NEVER hand-build classifications.
// ═══════════════════════════════════════════════════════════════════════

"glottocode": null, // Glottolog identifier (e.g., "plai1258", "stan1293").
// null if the language is not in Glottolog.
"classification": null, // Genealogical classification from Glottolog. When populated:
// {
// "family": "Algic", // Top-level family. null for isolates.
// "familyGlottocode": "algi1248", // Glottocode of the family.
// "genus": "Plains Creeic", // WALS-style genus.
// "genusGlottocode": "plai1264", // Glottocode of the genus.
// "ancestry": ["Algic", "Algonquian-Blackfoot", "Algonquian",
// "Cree-Montagnais-Naskapi", "Cree", "Plains Creeic"]
// }
// For isolates: family = language name, genus = language name,
// ancestry = [language name].
"isIsolate": false, // true if a language isolate (no known genetic relatives).
// Source: Glottolog CLDF.

// ═══════════════════════════════════════════════════════════════════════
// § 3. GEOGRAPHY
// Where is this language spoken?
// Sources: Glottolog (coordinates, countries), census data, Ethnologue.
// ═══════════════════════════════════════════════════════════════════════

"macroarea": null, // Glottolog macroarea. One of: "Africa", "Australia",
// "Eurasia", "North America", "Papunesia", "South America".
// null if unknown. Source: Glottolog CLDF.
"coordinates": null, // Representative geographic point. When populated:
// { "lat": 52.1, "lng": -106.6, "source": "glottolog-5.3" }
// This is a representative point, not a boundary.
"countries": [], // ISO 3166-1 alpha-2 country codes where this language is spoken.
// Example: ["CA", "US"]. Source: Glottolog.
"regions": [], // Detailed regional breakdown with admin codes & speaker estimates.
// Each entry:
// {
// "country": "Canada",
// "countryCode": "CA",
// "officialStatus": "recognized", // official, co-official,
// // recognized, none
// "region": "Saskatchewan, Alberta, Manitoba",
// "speakerEstimate": "~20,000",
// "coordinates": [-106.6, 52.1], // [lng, lat]
// "admin1Codes": ["CA-SK", "CA-AB", "CA-MB"]
// }

"arealContext": null, // Linguistic area / Sprachbund membership. DISTINCT from
// contactInfluences (which is language-specific contact history).
// This field captures zone-level typological convergence patterns
// — i.e., what linguistic area the language exists within and
// what features are common across that area.
// {
// "zone": "Mainland Southeast Asian Sprachbund",
// "arealFeatures": "Tonal convergence, classifier systems,
// topic-prominence, monosyllabicity trend.",
// "typicalContacts": ["Classical Chinese", "Sanskrit/Pali"],
// "source": "areal-linguistics (Enfield 2005)"
// }
// NOT the same as contactInfluences. A language can exist within
// a convergence area without having specific contact history with
// any particular language in that area.

// ═══════════════════════════════════════════════════════════════════════
// § 4. WRITING SYSTEMS
// How is this language written?
// Sources: Wikidata P282, ISO 15924, manual research.
// Note: Some languages have NO standardized orthography. Some have
// competing orthographies. Some use multiple scripts routinely (e.g.,
// Serbian: Cyrillic + Latin; Japanese: Kanji + Hiragana + Katakana).
// Sign languages may use notation systems (SignWriting, HamNoSys) or
// none at all.
// ═══════════════════════════════════════════════════════════════════════

"script": null, // Primary ISO 15924 script code (e.g., "Latn", "Cyrl", "Cans",
// "Jpan"). null if no written form or unknown.
"scriptUnicodeName": null, // Unicode script block name derived from the script field.
// e.g., "Latin", "Cyrillic", "Canadian_Aboriginal", "CJK".
// Used by code_switching metric plugin. Auto-populated by
// enrich-script-unicode-names.mjs. null if script is null.
"scripts": [], // All writing systems with detail. Array of:
// {
// "code": "Cans",
// "name": "Unified Canadian Aboriginal Syllabics",
// "primary": true
// }
// A language with multiple scripts has multiple entries.
// A language with no written form has [].
"dir": null, // Writing direction: "ltr" (left-to-right) or "rtl" (right-to-left).
// null if no written form or unknown.
"scriptConverter": null, // Script converter key if we have a converter for this language
// (e.g., "crk" for SRO↔Syllabics). null for most languages.
"orthographicStatus": null, // Writing system standardization status. When populated:
// {
// "status": "standardized",
// // "standardized" — official/agreed orthography exists
// // "competing" — multiple orthographies in active use
// // "emerging" — orthography under development
// // "none" — primarily oral, no standard writing
// "notes": "Uses SIL-developed Latin orthography since 1960s.",
// "source": "ethnologue" // or "manual-curation"
// }
// Crucial for LRLs where orthographic variation directly impacts
// MT training data quality and evaluation consistency.

// ═══════════════════════════════════════════════════════════════════════
// § 5. DEMOGRAPHICS & VITALITY
// How many people speak this language? Is it endangered?
// Sources: Census, Ethnologue, UNESCO Atlas, Wikidata, Glottolog AES.
//
// CRITICAL: Store ALL estimates separately with source attribution.
// Never average or "resolve" conflicting data. Speaker counts are
// politically contested for many languages. Present the evidence,
// let the reader assess.
// ═══════════════════════════════════════════════════════════════════════

"speakerEstimates": [], // Array of speaker count estimates from different authorities.
// Each entry:
// {
// "source": "wikidata", // or "ethnologue-28",
// // "census-ph-2020", etc.
// "count": 20000, // Point estimate. null if range-only.
// "date": "2026-06-07", // When this data was retrieved.
// "countRange": { "min": 15000, "max": 25000 }, // Optional range.
// "note": "Wikidata has 2 estimates: 15,000 and 25,000"
// }
// Empty array means we have not yet found speaker count data.

"vitality": null, // Endangerment / vitality assessment. When populated:
// {
// "unescoStatus": "severely-endangered",
// // Enum: "safe", "vulnerable", "definitely-endangered",
// // "severely-endangered", "critically-endangered",
// // "extinct"
// "aesStatus": "shifting",
// // Glottolog AES label (free text from AES data).
// "egids": "6b",
// // Ethnologue Expanded Graded Intergenerational Disruption
// // Scale. Levels: 0 (international) to 10 (extinct).
// "trend": "declining",
// // Qualitative trend: "stable", "growing", "declining",
// // "shifting", "moribund", "awakening"
// "source": "glottolog-aes-5.3",
// "notes": "Intergenerational transmission breaking down."
// }

// ═══════════════════════════════════════════════════════════════════════
// § 5.5. DOCUMENTATION & DIGITAL PRESENCE
// How well-documented is this language? What digital footprint does it
// have? These fields answer the practical question: "What can I
// actually DO with this language?"
// Sources: Glottolog (references), Wikipedia, Common Voice, Tatoeba.
// ═══════════════════════════════════════════════════════════════════════

"documentationDepth": null, // How well-documented is this language in the literature?
// {
// "referenceCount": 42,
// // Number of published references in Glottolog.
// "med": "grammar",
// // Most Extensive Description type. One of:
// // "long_grammar", "grammar", "grammar_sketch",
// // "dictionary", "phonology", "text", "wordlist",
// // "comparative", "minimal", "unknown"
// "source": "glottolog-5.3"
// }

"digitalPresence": null, // Digital footprint across web platforms. When populated:
// {
// "wikipedia": {
// "edition": true, // Has its own Wikipedia edition?
// "articleCount": 75000, // Number of articles.
// "editionCode": "crk", // Wikipedia subdomain code.
// "source": "wikimedia-api-2026"
// },
// "commonVoice": {
// "validatedHours": 12.5,
// "totalHours": 25.0,
// "speakers": 45,
// "sentences": 1200,
// "source": "common-voice-20.0"
// },
// "tatoeba": {
// "sentenceCount": 342,
// "source": "tatoeba-2026"
// }
// }

"dialectCount": null, // Number of recognized dialects in Glottolog.
// Derived from child_dialect_count in languoid.csv.
// Simple integer. null if 0 or unknown.
// Source: glottolog-5.3.

// ═══════════════════════════════════════════════════════════════════════
// § 6. FORMALITY, REGISTERS & GENDER
// How does politeness work in this language? What translation registers
// do we offer? How should gender be handled?
//
// This section drives Champollion's register-preset system — the
// mechanism by which users select formal/informal/professional tone.
// These fields require genuine linguistic research, not automation.
// ═══════════════════════════════════════════════════════════════════════

"formality": null, // Formality system description. When populated:
// {
// "system": "T-V",
// // One of: "T-V", "speech-levels", "keigo", "particles",
// // "register-levels", "register-and-code-switching",
// // "code-switching", "none"
// "description": "French uses a vous/tu distinction...",
// "default": "formal-vous" // Key into the `registers` object.
// }

"registers": null, // Translation register presets. When populated, keyed by preset ID:
// {
// "formal-vous": {
// "label": "Formal (vouvoiement)",
// "description": "One sentence: when to use this preset.",
// "prompt": "The actual LLM system prompt instruction that
// steers translation tone. Must name specific
// linguistic features (pronouns, verb forms, particles).",
// "deeplFormality": "prefer_more"
// // Only if methodSupport.deepl.formality is true.
// // One of: "prefer_more", "prefer_less", "default".
// }
// }

"gender": null, // Grammatical gender and inclusive guidance. When populated:
// {
// "grammatical": true, // Does the language have gram. gender?
// "inclusiveGuidance": "Use gender-neutral forms when possible.
// Prefer 'iel' (neologism) or rephrase to
// avoid gendered agreement."
// }
// For languages without grammatical gender (Turkish, Finnish):
// { "grammatical": false, "inclusiveGuidance": null }

"codeSwitching": null, // Code-switching behavior (for languages where mixing with another
// language is the norm, not an error). When populated:
// {
// "contactLanguage": "Spanish",
// "contactIso639_3": "spa",
// "mixedVarietyName": "Jopará", // null if no named mixed variety
// "prevalence": "dominant", // "rare", "common", "dominant"
// "morphologicalIntegration": true,
// "pipelineStrategy": "hybrid-fst",
// "notes": "Jopará IS the everyday language of most Paraguayans..."
// }

// ═══════════════════════════════════════════════════════════════════════
// § 7. LINGUISTIC PROFILE
// What makes this language what it is? What are the specific challenges
// for machine translation? What rules govern its typography?
// What languages have shaped it through contact?
//
// These fields require genuine linguistic expertise. For many languages
// (especially low-resource), this section will remain null until a
// qualified researcher or community member contributes.
// ═══════════════════════════════════════════════════════════════════════

"linguisticChallenges": null, // MT-relevant challenges, keyed by challenge ID.
// When populated:
// {
// "polysynthesis": "Cree is highly polysynthetic. A single verb
// can incorporate subject, object, tense...",
// "animacy": "Verb conjugation changes based on whether the
// subject/object is animate or inanimate...",
// "neologisms": "Avoid literal translations of modern software
// concepts. Maintain Cree metaphorical logic..."
// }
// Aim for 3–6 challenges per language when researched.

"contactInfluences": [], // How other languages have shaped this one. Array of:
// {
// "source": "English",
// "sourceIso639_3": "eng", // null if proto-language/unknown
// "type": "superstrate",
// // Enum: "superstrate", "substrate", "adstrate",
// // "learned_borrowing", "lexical_borrowing",
// // "relexification"
// "domains": ["education", "government", "technology"],
// "depth": "deep",
// // Enum: "light", "moderate", "heavy", "structural",
// // "defining"
// "period": "1870–present",
// "notes": "Residential school era and ongoing...",
// "citation_needed": false
// // true if no published academic source found.
// // See language-card-citation-procedure.md.
// }

"rules": null, // Typography, plural, and capitalization rules. When populated:
// {
// "typography": {
// "quoteStart": "\u201c",
// "quoteEnd": "\u201d",
// "usesSpaces": true, // false for CJK, Thai, Lao, Khmer
// "punctuationSpacing": {
// "doublePunctuation": "none" // "thin-nbsp" for French
// }
// },
// "plurals": {
// "categories": ["one", "other"]
// // From CLDR. Possible values:
// // "zero", "one", "two", "few", "many", "other"
// },
// "capitalization": {
// "hasCase": true
// // true for Latin, Cyrillic, Greek, Armenian scripts.
// // false for CJK, Arabic, Devanagari, etc.
// }
// }
// Source: CLDR + ISO 15924 derivation.

"typologicalProfile": null, // Grambank typological features. When populated:
// {
// "featuresDocumented": 195,
// "featuresCoverage": 1, // 0.0–1.0 fraction of features
// "wordOrderDominant": "SVO",
// "hasDefiniteArticle": true,
// "hasIndefiniteArticle": true,
// "hasGenderSystem": true,
// "hasCaseMorphology": true,
// "hasEvidentiality": false,
// "hasToneSystem": false,
// "source": "grambank-1.0.3"
// }
// Auto-populated by enrich-grambank-typology.mjs.

"phonologicalInventory": null, // PHOIBLE phoneme inventory. When populated:
// {
// "consonants": 24,
// "vowels": 16,
// "tones": 0,
// "totalPhonemes": 40,
// "isTonal": false,
// "inventorySize": "moderately-large",
// // Enum: "small", "moderately-small", "average",
// // "moderately-large", "large"
// "source": "phoible-2.0"
// }
// Auto-populated by enrich-phoible-phonemes.mjs.

// ═══════════════════════════════════════════════════════════════════════
// § 8. ENCYCLOPEDIC
// General knowledge about the language for human context. History,
// dialect situation, institutional resources, representative sayings.
// This section is for understanding, not computation.
// ═══════════════════════════════════════════════════════════════════════

"encyclopedic": null, // General knowledge. When populated:
// {
// "family": "Algic", // Redundant with classification
// // but useful for human readers.
// "dialects": {
// "split": true, // Is there significant variation?
// "classification": "Plains Cree (y-dialect)",
// "variants": ["crk", "cwd", "csw"] // ISO codes of variants
// },
// "demographics": {
// "speakers": "Approx. 20,000 active speakers",
// "regions": ["Saskatchewan", "Alberta", "Manitoba"]
// },
// "history": "Plains Cree is the most widely spoken Algonquian
// language in western Canada...",
// "resources": {
// "wikipedia": "https://en.wikipedia.org/wiki/Plains_Cree",
// "foundations": [{ "name": "ALTLab", "url": "https://..." }],
// "dictionaries": [{ "name": "itwêwina", "url": "https://..." }]
// }
// }

"culturalAphorism": null, // A representative saying, proverb, or teaching in the language.
// When populated:
// {
// "text": "ê-wîcêhtonaniwahk kâ-kî-isi-wâpahtamâhk ôma pimâtisiwin",
// "transliteration": null, // Romanized form if non-Latin script.
// "translation": "Through helping each other we come to understand
// this life",
// "literal": "By-helping-one-another we-have-come-to-see this life",
// "source": "Cree teaching, documented in nêhiyawêwin educational
// resources"
// }
// Choose sayings that reveal something about the language's
// worldview or structure. Must be sourced.

"varieties": [], // For macrolanguages or languages with significant dialectal
// variation, the individual varieties with their own tool coverage.
// Each entry:
// {
// "name": "Cusco Quechua",
// "iso639_3": "quz",
// "region": "Cusco, Peru",
// "fstCoverage": true,
// "corpusCoverage": true,
// "nllbCoverage": false,
// "mutualIntelligibility": "Primary variety for this card",
// "notes": "SQUOIA FST was built for this variety."
// }

// ═══════════════════════════════════════════════════════════════════════
// § 9. DIGITAL RESOURCES & TOOLING
// What NLP tools, corpora, models, and datasets exist for this language?
// What translation APIs support it? What eval benchmarks are available?
//
// This is Champollion's operational core — these fields determine what
// we can actually DO with this language.
// ═══════════════════════════════════════════════════════════════════════

"resources": null, // NLP resources available for this language. When populated:
// {
// "fsts": [{ // Finite-state transducers
// "name": "GiellaLT Plains Cree FST (lang-crk)",
// "url": "https://github.com/giellalt/lang-crk/releases",
// "type": "morphological-analyzer"
// }],
// "corpora": [{ // Text corpora
// "name": "EDTeKLA Cree Language Textbook Corpus",
// "type": "parallel", // "parallel", "monolingual"
// "pairs": ["en-crk"],
// "url": "https://...",
// "exposure": "open-web" // "open-web", "restricted",
// // "holdout"
// }],
// "models": [{ // Pre-trained models
// "name": "NLLB-200 (crk_Cans)",
// "url": "https://...",
// "type": "nmt"
// }],
// "tools": [], // Other NLP tools
// "wordlists": [{ // Standardized wordlists
// "name": "Lexibank",
// "conceptCount": 200,
// "source": "lexibank"
// }],
// "treebanks": [{ // Syntactic treebanks
// "name": "UD_Korean-GSD",
// "tokens": 80000,
// "source": "universal-dependencies-2.14"
// }]
// }
// IMPORTANT: Only actual NLP/digital resources belong here.
// "This language has a WALS entry" is NOT a resource — that
// goes in databaseCoverage.

"databaseCoverage": null, // Which typological/reference databases cover this language.
// Separated from resources to avoid conflating "has a database
// entry" with "has usable NLP tooling."
// {
// "wals": true,
// "grambank": true,
// "phoible": true,
// "cldr": true,
// "lexibank": true,
// "commonVoice": true,
// "source": "derived"
// }

"corpusAvailability": null, // What text/parallel corpora exist for NLP use?
// {
// "bibleTranslation": {
// "textAvailable": true,
// "audioAvailable": true,
// "source": "bible-brain-api"
// },
// "opusCorpora": ["wikimedia", "ubuntu", "gnome"],
// "source": "multi-source"
// }

"keyboardSupport": null, // Input method / keyboard availability. When populated:
// {
// "keymanKeyboards": 3,
// // Number of Keyman keyboards available.
// "cldrKeyboard": true,
// // CLDR has keyboard layout data.
// "source": "keyman-api + cldr"
// }

"methodSupport": { // REQUIRED. Which Champollion translation methods support this
// language. Each method is an object with at minimum
// { "supported": boolean }.
"googleTranslate": { "supported": false },
"deepl": { "supported": false },
"microsoftTranslator": { "supported": false },
"libreTranslate": { "supported": false },
"nllb": { "supported": false },
// When NLLB is supported, include the code:
// { "supported": true, "code": "crk_Cans" }
"llm": { "supported": true }
// LLM is always true (quality varies by language).
// Optional: "verifiedDate": "2026-06-07" for audit trail.
},

"metricModelSupport": null, // Which MT evaluation models produce reliable scores.
// When populated:
// {
// "xlmr": "high", // "high", "medium", or "low"
// // XLM-R training representation tier.
// "africomet": false // true if AfriCOMET covers this language.
// }
// Drives automatic COMET model selection in metrics_comet.py.
// Auto-populated by enrich-metric-model-support.mjs.

"metricPlugins": null, // Which per-language metric plugin packs are available.
// When populated:
// {
// "formalityMarkers": true // Formality marker resource file exists
// // at plugins/resources/formality/{code}.json
// }
// Each key corresponds to a resource pack in
// arena/mt_eval_harness/plugins/resources/{packName}/.
// To add a new metric pack for a language, create the resource
// file and set the flag here. No code changes required.

"evalPack": null, // Evaluation dependency pack for language-specific metrics.
// When populated, declares the Python dependencies and
// post-install steps required by this language's eval standards.
// The harness uses this for dependency gating: if deps are
// missing, the harness warns the user and skips LYSS metrics
// (rather than crashing).
// When populated:
// {
// "pythonDeps": {
// "pyhfst": "pyhfst>=1.4", // PyPI package specs
// "requests": "requests>=2.28",
// "spacy": "spacy>=3.7"
// },
// "postInstall": [ // Commands to run after pip
// {
// "command": "spacy download en_core_web_md",
// "label": "spaCy English model (for LYSS-sem)"
// }
// ],
// "requiresFst": true, // true if GiellaLT FST needed
// "description": "LYSS equivalence linter + FST validation"
// }

"evalMetrics": null, // Language-specific evaluation metrics (LYSS standards).
// When populated, the harness dynamically imports these
// MetricPlugin classes from eval_standards/<lang>/ and applies
// them to every run targeting this language — regardless of
// which method (contestant) is being evaluated.
// Keyed by metric ID:
// {
// "lyss-eq": {
// "module": "eval_standards.crk.metrics",
// "class": "CrkLinterMetric",
// "description": "LYSS deterministic variant-class linter"
// },
// "lyss-sem": {
// "module": "eval_standards.crk.metrics",
// "class": "CrkSemanticMetric",
// "description": "LYSS FST-based semantic validator",
// "dependencies": ["spacy>=3.7"],
// "spacy_models": ["en_core_web_md"]
// }
// }
// Architecture: eval standards are referees, not contestants.
// They live in the harness (eval_standards/), not in method
// plugins. This ensures all methods are scored equally.
// Discovery: plugin_discovery.py reads this field via
// language_cards.get_eval_metrics() and instantiates metrics
// using importlib. Dependencies are checked against evalPack.

"omt1600": null, // Meta's OMT-1600 (One Model for Translation) coverage assessment.
// When populated:
// {
// "covered": true,
// "tier": "R1", // Meta's resource tier
// "evalMetrics": ["chrF++", "BLASER-3"],
// "notes": "Plains Cree: no web-crawled bitext..."
// }

"evalDatasets": [], // Evaluation dataset IDs available for this language.
// Example: ["flores-plus-devtest", "edtekla-dev-v1"].
// Empty means no standardized eval set exists.

"pipelineReadiness": null, // Assessment of readiness for Champollion's translation pipeline.
// When populated:
// {
// "tier": "tier-2-feasible",
// // "watch-list" — cataloged but no path to translation
// // "tier-3-cataloged" — basic metadata present
// // "tier-2-feasible" — tools exist, pipeline possible
// // "tier-1-ready" — pipeline operational
// "hasFST": true,
// "hasParallelCorpus": true,
// "hasEvalBenchmark": true,
// "blockers": ["Syllabics post-processing validation"],
// "notes": "FST-gated pipeline operational. EDTeKLA corpus..."
// }

// ═══════════════════════════════════════════════════════════════════════
// § 10. PROVENANCE & METADATA
// Where does this data come from? Who reviewed it? When was it
// generated? What's its overall quality level?
//
// This section exists to make the card auditable. Every automated
// enrichment, every human review, every source consulted should
// leave a trace here.
// ═══════════════════════════════════════════════════════════════════════

"dataSources": [], // REQUIRED. Sources consulted for this card's data.
// Can be a flat array (backwards-compatible):
// ["iso639-3-2024", "glottolog-5.3", "wikidata"]
//
// Or a structured per-field object (preferred for new cards):
// {
// "classification": ["glottolog-5.3"],
// "vitality": ["glottolog-aes-5.3", "unesco-atlas-2024"],
// "speakerEstimates": ["wikidata", "census-ca-2021"],
// "rules": ["cldr-48"],
// "methodSupport": ["google-translate-2026-06"]
// }

"supportTier": "cataloged", // Auto-derived tier summarizing the card's depth:
// "cataloged" — identity + classification only
// "emerging" — + vitality + speakerEstimates
// "developing" — + resources + methodSupport
// "supported" — full research: registers, challenges, etc.

"humanReviewed": null, // null until a qualified human reviews the card. When populated:
// {
// "reviewer": "Prof. Kenneth Jamandre",
// "affiliation": "University of the Philippines Diliman",
// "date": "2026-06-08",
// "scope": "full", // "full", "partial", "vitality-only"
// "notes": "Verified speaker count, vitality assessment,
// and contact influences for Tagalog."
// }

"notes": null, // Free-text notes about this language or this card's data quality.
// Example: "Low-resource language under active development.
// Translation pipeline uses FST-gated approach."

"firstDocumented": null, // Year of first known documentation. Negative for BCE.
// Example: -1500 (Sanskrit, ~1500 BCE), 1787 (some languages).
// Source: Glottolog CLDF.

"lastDocumented": null, // Year of last known documentation (relevant for extinct languages).
// Source: Glottolog CLDF.

"_generated": null // Auto-populated by enrichment scripts. When populated:
// {
// "by": "generate-all-cards.mjs",
// "at": "2026-06-07T12:34:56Z",
// "sources": ["iso639-3", "glottolog-5.3", "wikidata"],
// "completeness": "partial",
// // "partial" — has identity + classification + coords
// // "substantial" — + vitality + speakerEstimates + script
// // "complete" — all automatable fields populated
// "lastEnriched": "2026-06-07"
// }
}

Veldreferentie

§ 1. Identiteitsvelden

VeldTypeVereistAutomatiseerbaarBron
codestringISO 639-3 register
namestringISO 639-3 register
nativeNamestring | nullWikidata P1705
alternateNamesstring[]Glottolog, Ethnologue
iso639_3stringISO 639-3 register
iso639_1string | nullISO 639-1
bcp47string | nullGedeeltelijkIANA subtag register
aliasesstring[]Handmatige samenstelling
isoScopestringISO 639-3 register
isoTypestringISO 639-3 register
macrolanguagestring | nullISO 639-3 macrolanguages.tab
extendsstring | nullHandmatige samenstelling

§ 2. Classificatievelden

VeldTypeVereistAutomatiseerbaarBron
glottocodestring | nullGlottolog
classificationobject | nullGlottolog
isIsolatebooleanGlottolog CLDF

§ 3. Geografische Velden

VeldTypeVereistAutomatiseerbaarBron
macroareastring | nullGlottolog CLDF
coordinatesobject | nullGlottolog
countriesstring[]Glottolog
regionsobject[]Census, Ethnologue, handmatig
arealContextobject | nullCoördinaten + taalkundige gebiedszones

§ 4. Schrijfsysteemvelden

VeldTypeVereistAutomatiseerbaarBron
scriptstring | nullWikidata P282
scriptUnicodeNamestring | nullAfgeleid van script via ISO 15924 → Unicode-mapping
scriptsobject[]GedeeltelijkWikidata, handmatig
dirstring | nullAfleidbaar uit schrift
scriptConverterstring | nullHandmatig
orthographicStatusobject | nullGedeeltelijkEthnologue, handmatig

§ 5. Demografische & Vitaliteitsvelden

VeldTypeVereistAutomatiseerbaarBron
speakerEstimatesobject[]Wikidata, Ethnologue, census
vitalityobject | nullGlottolog AES, UNESCO

§ 5.5 Documentatie & Digitale Aanwezigheidsvelden

VeldTypeVereistAutomatiseerbaarBron
documentationDepthobject | nullGlottolog referenties
digitalPresenceobject | nullWikipedia, Common Voice, Tatoeba
dialectCountnumber | nullGlottolog

§ 6. Formaliteit, Register & Gendervelden

VeldTypeVereistAutomatiseerbaarBron
formalityobject | nullTaalkundig onderzoek
registersobject | nullTaalkundig onderzoek
genderobject | nullTaalkundig onderzoek
codeSwitchingobject | nullTaalkundig onderzoek

§ 7. Taalkundig Profielvelden

VeldTypeVereistAutomatiseerbaarBron
linguisticChallengesobject | nullTaalkundig onderzoek
contactInfluencesobject[]Gepubliceerde taalkunde
rulesobject | nullCLDR
typologicalProfileobject | nullGrambank 1.0.3 — automatisch ingevuld door enrich-grambank-typology.mjs
phonologicalInventoryobject | nullPHOIBLE 2.0 — automatisch ingevuld door enrich-phoible-phonemes.mjs

§ 8. Encyclopedische Velden

VeldTypeVereistAutomatiseerbaarBron
encyclopedicobject | nullHandmatig onderzoek
culturalAphorismobject | nullBijdrage van de gemeenschap
varietiesobject[]Handmatig onderzoek

§ 9. Digitale Bronvelden

VeldTypeVereistAutomatiseerbaarBron
resourcesobject | nullGedeeltelijkHandmatig + geautomatiseerd
databaseCoverageobject | nullAfgeleid van verrijking
corpusAvailabilityobject | nullBible Brain, OPUS, Lexibank
keyboardSupportobject | nullKeyman API, CLDR
methodSupportobjectGedeeltelijkAPI-verificatie
metricModelSupportobject | nullXLM-R paper, AfriCOMET paper
metricPluginsobject | nullKaartverrijking — declareert welke metrische plugin-pakketten van toepassing zijn (bijv. { formalityMarkers: true })
omt1600object | nullMeta-beoordeling
evalDatasetsstring[]Dataset register
pipelineReadinessobject | nullGedeeltelijkAfgeleid + handmatig

resources.fsts[].install: FST-vermeldingen in het resources-object kunnen een install-sub-object bevatten met velden: repo, releaseTag, assetPattern, format, maturity, en optioneel bundlePattern. Dit vervangt het voormalige hardgecodeerde GIELLALT_FST_REGISTRY-woordenboek. Zie get_fst_install_info() in language_cards.py.

§ 10. Herkomstvelden

VeldTypeVereistAutomatiseerbaarBron
dataSourcesarray | objectAutomatisch + handmatig
supportTierstringAfgeleid van volledigheid van kaart
humanReviewedobject | nullMenselijke reviewer
notesstring | nullHandmatig
firstDocumentednumber | nullGlottolog CLDF
lastDocumentednumber | nullGlottolog CLDF
_generatedobject | nullVerrijkingsscripts

Taalcodebeleid

Champollion gebruikt ISO 639-3 als canonieke identificator. Andere standaardcodes worden geregistreerd als aliassen en worden bij runtime omgezet naar de ISO 639-3-code.

PrioriteitStandaardVoorbeeldVeldGebruik
1 (canoniek)ISO 639-3crkcodeKaartbestandsnaam, configuratiesleutels, API-parameters
2 (alias)ISO 639-1iualiases[]Geaccepteerd in CLI, omgezet naar ISO 639-3
3 (alias)BCP 47filaliases[]Geaccepteerd in CLI, omgezet naar ISO 639-3
ReferentieGlottocodeplai1258glottocodeAlleen voor classificatie, niet voor runtime

Oplossingsvolgorde: Wanneer een gebruiker een code opgeeft:

  1. Directe overeenkomst op card.code → gevonden
  2. Overeenkomst op card.aliases[] → gevonden, retourneer de canonieke kaart
  3. Overeenkomst op card.iso639_1 → gevonden (terugvaloptie)
  4. Niet gevonden → fout

Migratiegeschiedenis: ISO 639-1 → ISO 639-3

Vóór v8 gebruikten kaartbestandsnamen ISO 639-1-codes waar beschikbaar (fr.json, de.json, ja.json). Bij de 639-3-migratie werden alle kaarten hernoemd naar hun ISO 639-3-equivalenten:

VóórNaWaarom
fr.jsonfra.json639-3 is canoniek
de.jsondeu.json639-3 is canoniek
zh.jsoncmn.jsonMacrotaal → standaard individuele taal
ar.jsonarb.jsonMacrotaal → Modern Standaard Arabisch
ms.jsonzsm.jsonMacrotaal → Standaard Maleis

Wat is er met de oude codes gebeurd?

  • De oude 639-1-code staat in card.iso639_1
  • De oude 639-1-code staat in card.aliases[]
  • resolveCode("fr") retourneert "fra" bij runtime — achterwaarts compatibel
  • Gebruikers kunnen nog steeds "fr" in hun configuratie schrijven — dit wordt transparant omgezet

Wat er architecturaal is veranderd:

  • _deepMerge() slaat nu null-waarden over (erft van ouder)
  • _deepMerge() heeft nu een identiteitsveldset (code, extends, aliassen worden nooit overgeërfd)
  • formality.default wordt nu afgeleid van register isDefault: true-vlaggen
  • 205 Grambank-afgeleide kaarten kregen een structurele formality.default-correctie
  • 38 genus/familie/macrotaalkaarten bieden overervingsdoelen

Randgevallen

Gebarentalen

Gebarentalen (bijv. ASE — American Sign Language) zijn volwaardige talen met ISO 639-3-codes. Ze hebben geografie en sprekerscijfers, maar:

  • script is doorgaans null (geen standaard geschreven vorm)
  • scripts kan "Sgnw" (SignWriting) bevatten als er een notatiesysteem wordt gebruikt
  • dir is null
  • linguisticChallenges moet ruimtelijke grammatica, classifiers, enz. behandelen
  • gender.grammatical is doorgaans false

Oude & Historische Talen

Talen zoals Latijn (lat, isoType H) en Sanskrit (san, isoType H) worden nog steeds gebruikt in specifieke contexten (liturgisch, academisch), maar hebben geen moedertaalsprekers:

  • vitality kan "geen moedertaalsprekers" vermelden met "trend": "stable" (niet afnemend — de gemeenschap die het gebruikt is stabiel, alleen klein)
  • speakerEstimates moet vermelden dat dit L2-sprekers zijn, geen L1-sprekers
  • firstDocumented / lastDocumented plaatsen ze in de tijd

Geconstrueerde Talen

Esperanto (epo, isoType C), Lojban, enz.:

  • classification kan verwijzen naar een "geconstrueerde" familie of null zijn
  • contactInfluences weerspiegelt het bronmateriaal (bijv. Esperanto put uit Romaanse, Germaanse, Slavische talen)
  • vitality is ongebruikelijk — groeiende sprekergemeenschap maar geen oorspronkelijk thuisland

Macrotalen

Arabisch (ara), Chinees (zho), Cree (cre), Quechua (que) zijn macrotalen die meerdere afzonderlijke talen omvatten:

  • isoScope: "M"
  • varieties moet de afzonderlijke talen met hun ISO-codes vermelden
  • methodSupport moet weerspiegelen wat de macrotaalkaart ondersteunt (doorgaans de gestandaardiseerde variant)
  • Afzonderlijke varianten moeten ook hun eigen kaarten hebben

Talen Zonder Gestandaardiseerde Orthografie

Veel talen (met name talen met een orale traditie) hebben geen gestandaardiseerd schrijfsysteem, of hebben concurrerende orthografieën:

  • script is null
  • scripts is []
  • dir is null
  • notes moet de orthografische situatie toelichten
  • linguisticChallenges moet vermelden hoe dit MT beïnvloedt (bijv. geen trainingsgegevens)

Diglossia

Talen zoals Arabisch (MSA vs. dialecten) of Guaraní (Jopará vs. puur Guaraní):

  • codeSwitching legt de situatie van de gemengde variant vast
  • registers kan presets aanbieden voor verschillende niveaus
  • varieties kan het diglossische paar vermelden

Contactinvloedtypen

TypeBetekenisVoorbeeld
superstrateDominante taal opgelegd aan een gemeenschapFrans → Engels (na 1066)
substrateMoedertaal die een opgelegde taal beïnvloedtKeltisch → Engels
adstrateNaburige taal met wederzijdse invloedNoors → Engels
learned_borrowingLeenwoorden via onderwijs/wetenschapLatijn → Engels
lexical_borrowingDirecte woordenschatontleningen via contactSpaans → Filipijns
relexificationVolledige vervanging van woordenschatPortugees → Papiamentu

Contactinvloeddiepten

DiepteBetekenis
lightEnkele leenwoorden, minimale structurele impact
moderateAanzienlijke woordenschat in specifieke domeinen
heavyDoordringende woordenschat en enkele structurele kenmerken
structuralGrammatica, syntaxis en fonologie beïnvloed
definingKernidentiteit gevormd door contact (creooltalen, gemengde talen)

Goede Registerpresets Schrijven

Goede presetprompts:

  • Benoem het formaliteitskenmerk expliciet (bijv. "해요체", "vous-vorm", "siz-vorm")
  • Leg het specifieke voornaamwoord of de werkwoordsvorm uit die gebruikt moet worden
  • Geef context voor wanneer dit register van toepassing is
  • Vermeld scriptoverwegingen indien van toepassing

Niet genderinclusieve begeleiding in de presetprompt opnemen. Genderbegeleiding hoort in card.gender.inclusiveGuidance — het wordt afzonderlijk ingevoegd.

❌ Bad: "Standard Thai. Professional register."
✔ Good: "Professional Thai. Use คุณ (khun) for second person, เรา (rao)
for first person when needed. Clear, concise phrasing
appropriate for digital interfaces."

Naamgevingsconventie voor Presets

Presetsleutels moeten beschrijvend en in kleine letters met koppeltekens zijn:

  • T-V-talen: formal-vous, informal-tu, formal-Sie, casual-du
  • Spreekregisters: polite-haeyo, formal-hapsyo, casual-hae
  • Neutraal: professional, neutral-professional
  • Code-switching: taglish-professional, pure-filipino

Verrijkingsprocedure

Verwerkingsvolgorde per Kaart

Raadpleeg bij het verrijken van een kaart bronnen in deze volgorde. Documenteer elke geraadpleegde bron, ook als er geen gegevens werden gevonden.

  1. ISO 639-3 registercode, name, isoScope, isoType
  2. ISO 639-3 macrolanguages.tabmacrolanguage
  3. Glottolog languoid.csvglottocode, classification, coordinates, countries
  4. Glottolog CLDFmacroarea, isIsolate, firstDocumented, lastDocumented
  5. Glottolog AESvitality (bedreigingsstatus)
  6. Wikidata SPARQLnativeName, speakerEstimates, script, scripts, dir
  7. CLDRrules (typografie, meervoudsregels, hoofdlettergebruik)
  8. NLLB-200 / FLORES+methodSupport.nllb, evalDatasets
  9. API-verificatie → resterende methodSupport-vermeldingen
  10. ML-modelpapersmetricModelSupport (XLM-R trainingsgegevens, AfriCOMET-dekking) Script: node scripts/enrich-metric-model-support.mjs

Conflictafhandeling

Wanneer bronnen het oneens zijn:

  1. Sla beide op met bronvermelding
  2. Middel NIET en kies geen kant
  3. Noteer de discrepantie in het relevante note-veld
  4. Geef de voorkeur aan de meest recente primaire bron alleen wanneer een enkele waarde nodig is voor berekening

Validatie

Voer de linter uit na elke verrijking of handmatige bewerking:

node scripts/lint-language-cards.mjs # all cards
node scripts/lint-language-cards.mjs --lang crk # single card

PR-checklist

Bij het indienen van een nieuwe of gewijzigde taalkaart:

  • Bestand genaamd <code>.json in shared/language-cards/
  • Alle velden op het hoogste niveau uit het canonieke sjabloon zijn aanwezig
  • classification ingevuld vanuit Glottolog (niet handmatig opgebouwd)
  • dataSources vermeldt alle geraadpleegde bronnen
  • methodSupport-vermeldingen geverifieerd tegen actuele API-taallijsten
  • contactInfluences-vermeldingen hebben gepubliceerde bronnen of citation_needed: true
  • linguisticChallenges met 3–6 MT-relevante uitdagingen (indien onderzocht)
  • rules ingevuld vanuit CLDR (als er localegegevens bestaan)
  • Linter slaagt zonder fouten

Professionele Referenties

StandaardBeheerd doorOns gebruik
ISO 639-3SIL InternationalCanonieke taalcodes, macrotaalrelaties
GlottologMax Planck InstituteClassificatie, coördinaten, AES-bedreigingsstatus
WALSMax Planck InstituteGenusdefinities, typologische kenmerken
ISO 15924Unicode/ISOSchriftcodes
CLDRUnicode ConsortiumLocalegegevens, meervoudsregels, typografie
WikidataWikimedia FoundationSprekerscijfers, endoniemen, schriftgegevens
EthnologueSIL InternationalEGIDS, sprekersinschattingen, DLS
UNESCO AtlasUNESCOBedreigingsclassificatie
Katig CollectiveUP DilimanFilipijnse taalcapsules

Zie ook: Citatieprocedure voor Taalkaarten voor gedetailleerde bron-voor-bron begeleiding.