diff --git a/VERSION b/VERSION
index 22314b3..9080e31 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.4.43-beta
+0.4.44-beta
diff --git a/public/js/core.js b/public/js/core.js
index bab0a9c..8b73329 100644
--- a/public/js/core.js
+++ b/public/js/core.js
@@ -2,7 +2,7 @@
"use strict";
/* version โ shown until /api/version resolves (or if the fetch fails, e.g. offline).
Kept in sync by hand with the VERSION file at the repo root on every release. */
-const VERSION = "0.4.43-beta";
+const VERSION = "0.4.44-beta";
(function(){
const tag = document.getElementById("verTag");
tag.textContent = "v"+VERSION;
diff --git a/public/js/data.js b/public/js/data.js
index 4b24da1..1445b73 100644
--- a/public/js/data.js
+++ b/public/js/data.js
@@ -411,6 +411,85 @@ const LANGUAGE_CONCEPTS = [
["season","time","seizoen","season","๐"]
].map(([id,theme,nl,en,pic])=>({id,theme,nl,en,pic}));
+/* Gecontroleerde Nederlandse beeldcorrecties. Bestaande handgekozen emoji
+ blijven de terugval; deze lijst corrigeert polyseme woorden en geeft veel
+ voorkomende concrete woorden een specifieker beeld. */
+const LANGUAGE_PICTURE_EXACT=Object.freeze({
+ groentekraam:"๐ฅ๐ช",veehouderij:"๐",wastafel:"๐ฐ",woonkamermeubel:"๐๏ธ",badkamertegel:"๐ฟ",prullenbak:"๐๏ธ",
+ tekstproductie:"โ๏ธ๐",verdrietverwerking:"๐ข๐ง ",bezorgd:"๐",ouderverzorging:"๐ฉโค๏ธ",spierkracht:"๐ช",
+ schoolslag:"๐",wedstrijdreglement:"๐๐",toneelspeler:"๐ญ",spellingspatroon:"๐ค",meetinstrument:"๐",
+ lentebloem:"๐ผ",zomerdag:"๐",herfstblad:"๐",winterjas:"โ",jaargetijde:"๐",gitaarspel:"๐ธ",
+ ruimtestation:"๐ฐ๏ธ",boekje:"๐",muziek:"๐ถ",onderzoeksverslag:"๐งช๐",grondrecht:"โ๏ธ",
+ bol:"๐ฅฏ",toast:"๐",korst:"๐",kruimel:"๐",karnemelk:"๐ฅ",room:"๐ฅ",boter:"๐ง",vla:"๐ฎ",
+ brie:"๐ง",plak:"๐ง",friet:"๐",puree:"๐ฅ",schil:"๐ฅ",knol:"๐ฅ",prei:"๐ฅฌ",kool:"๐ฅฌ",boon:"๐ซ",erwtje:"๐ซ",
+ koek:"๐ช",snoep:"๐ฌ",wafel:"๐ง",gebakje:"๐ง",slagroom:"๐ฐ",
+ stam:"๐ณ",tak:"๐ฟ",wortel:"๐ฑ",stengel:"๐ฑ",knop:"๐ท",boeket:"๐",druppel:"๐ง",plas:"๐ฆ",sloot:"๐๏ธ",beek:"๐๏ธ",
+ licht:"โ๏ธ",schaduw:"โ",bui:"๐ฆ๏ธ",vorst:"๐ฅถ",hagel:"๐จ๏ธ",vlok:"โ๏ธ",aarde:"๐",grond:"๐ซ",kiem:"๐ฑ",
+ bus:"๐",taxi:"๐",rit:"๐ฃ๏ธ",band:"๐",step:"๐ด",pedaal:"๐ฒ",bel:"๐",stuur:"๐ฒ",rail:"๐ค๏ธ",spoor:"๐ค๏ธ",
+ roeispaan:"๐ฃ",vleugel:"โ๏ธ",piloot:"๐งโโ๏ธ",vlucht:"โ๏ธ",pad:"๐ฅพ",bocht:"โช๏ธ",streep:"โ",file:"๐๐",route:"๐บ๏ธ",
+ kast:"๐๏ธ",nachtkast:"๐๏ธ",slaapkamer:"๐๏ธ",slaapkamerraam:"๐ช",flat:"๐ข",hut:"๐",dak:"๐ ",muur:"๐งฑ",deken:"๐๏ธ",kussen:"๐๏ธ",kruk:"๐ช",slot:"๐",sleutel:"๐",
+ pan:"๐ณ",pot:"๐ฒ",kom:"๐ฅฃ",lepel:"๐ฅ",bad:"๐",douche:"๐ฟ",wc:"๐ฝ",kraan:"๐ฐ",zeep:"๐งผ",
+ stof:"๐ซง",vuil:"๐๏ธ",bezem:"๐งน",dweil:"๐งฝ",spons:"๐งฝ",
+ duim:"๐",vinger:"โ๏ธ",nagel:"๐
",pols:"โ",teen:"๐ฆถ",hiel:"๐ฆถ",enkel:"๐ฆต",knie:"๐ฆต",
+ wang:"๐",kin:"๐",nek:"๐งฃ",keel:"๐ฃ๏ธ",lip:"๐",kies:"๐ฆท",tong:"๐
",speeksel:"๐ง",gebit:"๐",
+ trui:"๐",broek:"๐",rok:"๐",long:"๐ซ",bloed:"๐ฉธ",bot:"๐ฆด",spier:"๐ช",skelet:"๐ฆด",
+ bewegingsapparaat:"๐ฆด",bewegingsrichting:"๐งญ",lichaamsbeweging:"๐คธ",bewegingsreeks:"๐",bewegingsoefening:"๐คธ",bewegingspatroon:"๐",gaan:"๐ถ",stap:"๐ฃ",staan:"๐ง",zitten:"๐ช",racen:"๐",sprinten:"๐",haasten:"โฉ",vluchten:"๐",
+ hupsen:"๐",bukken:"๐",rollen:"๐คธ",draaien:"๐",blad:"๐",zin:"๐",tekst:"๐",schrift:"๐",
+ praten:"๐ฃ๏ธ",zeggen:"๐ฌ",vragen:"โ",roepen:"๐ฃ",fluisteren:"๐คซ",delen:"๐คฒ",geven:"๐",halen:"๐ฅ",brengen:"๐ค",
+ leuk:"๐",fijn:"๐",glimlach:"๐",sip:"๐",verdriet:"๐ข",pijn:"๐ค",kwaad:"๐ ",ruzie:"๐ข",zorgen:"๐",
+ rust:"๐ง",kalm:"๐",stil:"๐คซ",zacht:"๐ชถ",ademen:"๐ฌ๏ธ",dapper:"๐ฆธ",durven:"๐ช",winnen:"๐",raar:"๐ค",wauw:"๐คฉ",
+ gezin:"๐จโ๐ฉโ๐งโ๐ฆ",ouders:"๐ช",mama:"๐ฉ",tante:"๐ฉ",dochter:"๐ง",papa:"๐จ",oom:"๐จ",zoon:"๐ฆ",
+ jongen:"๐ฆ",meisje:"๐ง",kleuter:"๐ง",puber:"๐ง",maat:"๐งโ๐คโ๐ง",buur:"๐๏ธ",gast:"๐ง",juf:"๐ฉโ๐ซ",meester:"๐จโ๐ซ",
+ leraar:"๐งโ๐ซ",mentor:"๐งโ๐ซ",coach:"๐งโ๐ซ",team:"๐ฅ",klas:"๐ซ",paar:"๐ซ",kring:"โญ",
+ kaart:"๐",doel:"๐ฅ
",trap:"โฝ",veld:"๐๏ธ",basket:"๐",korf:"๐งบ",worp:"๐คพ",score:"๐ฏ",punt:"๐ต",stuk:"๐งฉ",rand:"๐งฉ",
+ plaat:"๐ผ๏ธ",beer:"๐งธ",blok:"๐งฑ",pion:"โ๏ธ",plons:"๐ฆ",slag:"๐",prijs:"๐",beker:"๐",medaille:"๐
",
+ straat:"๐ฃ๏ธ",landingsbaan:"๐ฌ",plattegrond:"๐บ๏ธ",landbouwer:"๐งโ๐พ",plein:"๐๏ธ",les:"๐",gym:"๐คธ",kassa:"๐งพ",kar:"๐",mand:"๐งบ",klant:"๐ง",arts:"๐งโโ๏ธ",zaal:"๐ช",zorg:"โค๏ธ",
+ boer:"๐งโ๐พ",stal:"๐๏ธ",schuur:"๐๏ธ",land:"๐พ",erf:"๐ก",balie:"๐๏ธ",lezer:"๐",buurt:"๐๏ธ",vijver:"๐๏ธ",
+ dag:"โ๏ธ",uur:"๐",tijd:"โฐ",middag:"๐ค๏ธ",vroeg:"๐
",wakker:"โฐ",ontbijt:"๐ฅฃ",avond:"๐",laat:"๐",
+ donker:"๐",week:"๐๏ธ",maand:"๐",jaar:"๐",datum:"๐
",agenda:"๐",feest:"๐ฅณ",kaars:"๐ฏ๏ธ",ballon:"๐",
+ lente:"๐ผ",zomer:"๐",herfst:"๐",winter:"โ",seconde:"โฑ๏ธ",kwart:"ยผ",half:"ยฝ",duur:"โณ",
+ kleur:"๐",verf:"๐จ",kwast:"๐๏ธ",doek:"๐ผ๏ธ",palet:"๐จ",tekening:"๐๏ธ",lijn:"โ",vorm:"๐ท",vak:"โป๏ธ",
+ toon:"๐ต",lied:"๐ถ",stem:"๐ฃ๏ธ",klank:"๐",trom:"๐ฅ",fluit:"๐ช",snaar:"๐ธ",toets:"๐น",
+ dans:"๐",sprong:"๐คธ",draai:"๐",toneel:"๐ญ",rol:"๐ญ",pak:"๐",podium:"๐ญ",foto:"๐ท",film:"๐ฌ",lens:"๐ท",
+ zoeken:"๐",vraag:"โ",vondst:"๐ก",proef:"๐งช",test:"โ
",buis:"๐งช",mengen:"๐ฅฃ",
+ magneet:"๐งฒ",ijzer:"๐ฉ",pool:"๐งฒ",kracht:"๐ช",wiel:"๐",as:"โ๏ธ",tand:"๐ฆท",veer:"๐ชถ",hefboom:"โ๏ธ",
+ stroom:"โก",draad:"๐งต",stekker:"๐",digitaal:"๐ป",internet:"๐",programmeren:"๐งโ๐ป",computer:"๐ป",muis:"๐ฑ๏ธ",scherm:"๐ฅ๏ธ",bestand:"๐",ruimte:"๐",
+ planeet:"๐ช",raket:"๐",satelliet:"๐ฐ๏ธ",heelal:"๐",astronaut:"๐งโ๐",
+ letter:"๐ค",woord:"๐ ",naam:"๐ท๏ธ",teken:"โ๏ธ",komma:",",titel:"๐ท๏ธ",prent:"๐ผ๏ธ",taal:"๐ฃ๏ธ",
+ spraak:"๐ฌ",verhaal:"๐",nul:"0๏ธโฃ",een:"1๏ธโฃ",twee:"2๏ธโฃ",drie:"3๏ธโฃ",getal:"๐ข",cijfer:"๐ฃ",reeks:"๐ข",
+ som:"โ",plus:"โ",min:"โ",keer:"โ๏ธ",hoek:"๐",vlak:"โป๏ธ",lengte:"๐",
+ samen:"๐ค",hulp:"๐",beurt:"๐",afspraak:"๐ค",regel:"๐",wijk:"๐๏ธ",wereld:"๐",grens:"๐ง",
+ noord:"โฌ๏ธ",zuid:"โฌ๏ธ",oost:"โก๏ธ",west:"โฌ
๏ธ",plek:"๐",richting:"๐งญ",nieuws:"๐ฐ",krant:"๐๏ธ",bericht:"๐ฌ",
+ radio:"๐ป",media:"๐บ",afval:"๐๏ธ",bak:"๐๏ธ",glas:"โป๏ธ",papier:"๐",recht:"โ๏ธ",plicht:"๐",keus:"๐",
+ wet:"โ๏ธ",eerlijk:"โ๏ธ",mening:"๐ญ",besluit:"โ
"
+});
+/* Betekenisdragende delen voor samenstellingen. Het familiebeeld blijft
+ voorop staan; maximaal รฉรฉn tweede symbool verduidelijkt het onderscheid. */
+const LANGUAGE_PICTURE_HINTS=Object.freeze([
+ ["bescherming","๐ก๏ธ"],["veiligheid","๐ก๏ธ"],["verzorging","๐งผ"],["vaardigheid","๐ฏ"],["onderzoek","๐ฌ"],
+ ["bereiding","๐ณ"],["productie","๐ญ"],["verwerking","๐ญ"],["organisatie","๐"],["ontwikkeling","๐"],
+ ["geschiedenis","๐"],["industrie","๐ญ"],["maatschappij","๐"],["informatie","โน๏ธ"],["technologie","๐ป"],
+ ["wedstrijd","๐"],["training","๐๏ธ"],["strategie","โ๏ธ"],["berekening","๐งฎ"],["verdeling","๐"],
+ ["winkel","๐ช"],["fabriek","๐ญ"],["bedrijf","๐ญ"],["centrum","๐๏ธ"],["gebouw","๐ข"],["kamer","๐ช"],
+ ["boek","๐"],["schrift","๐"],["kaart","๐บ๏ธ"],["verslag","๐"],["bericht","๐ฌ"],["programma","๐ป"],
+ ["verlichting","๐ก"],["licht","๐ก"],["water","๐ง"],["lucht","๐ฌ๏ธ"],["grond","๐ซ"],["bloem","๐ท"],
+ ["boom","๐ณ"],["tuin","๐ฑ"],["weide","๐ฟ"],["storm","๐ช๏ธ"],["regen","๐ง๏ธ"],["sneeuw","โ๏ธ"],
+ ["bak","๐ฆ"],["voer","๐ฝ๏ธ"],["hok","๐ "],["stal","๐๏ธ"],["riem","๐ฆฎ"],["kooi","๐ชน"],
+ ["boot","โต"],["reis","๐งณ"],["straat","๐๏ธ"],["station","๐"],["haven","โ"],
+ ["deur","๐ช"],["raam","๐ช"],["kast","๐๏ธ"],["tafel","๐ช"],["stoel","๐ช"],["bed","๐๏ธ"],
+ ["zorg","โค๏ธ"],["hulp","๐ค"],["school","๐ซ"],["leer","๐"],["taal","๐ค"],["reken","๐งฎ"],
+ ["spel","๐ฒ"],["sport","๐
"],["feest","๐ฅณ"],["dag","๐
"],["tijd","โฐ"],["jaar","๐๏ธ"],
+ ["kracht","๐ช"],["energie","โก"],["stroom","โก"],["machine","โ๏ธ"],["instrument","๐ต"],["muziek","๐ถ"],
+ ["groep","๐ฅ"],["team","๐ฅ"],["familie","๐จโ๐ฉโ๐ง"],["ouder","๐ช"],["kind","๐ง"],["mens","๐ง"],
+ ["wereld","๐"],["milieu","โป๏ธ"],["afval","๐๏ธ"],["bestuur","๐๏ธ"]
+]);
+function languageProgressionPicture(word,fallback){
+ if(LANGUAGE_PICTURE_EXACT[word])return LANGUAGE_PICTURE_EXACT[word];
+ const match=LANGUAGE_PICTURE_HINTS.filter(([part])=>word.includes(part)).sort((a,b)=>b[0].length-a[0].length)
+ .find(([,emoji])=>emoji!==fallback);
+ return match?fallback+match[1]:fallback
+}
+
/* Ruim duizend aanvullende Nederlandse woorden, geordend in woordfamilies.
Iedere regel loopt bewust van een kort, concreet basiswoord naar langere
afleidingen, samenstellingen en schooltaal. De positie op de regel bepaalt
@@ -444,7 +523,7 @@ const LANGUAGE_NL_PROGRESSION_WORDS=(()=>{
const word=raw.trim();if(!word||seen.has(word))return;seen.add(word);
const slug=word.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^a-z]/g,"");
const yearGroup=LANGUAGE_PROGRESSION_YEARS[Math.min(familyPosition++,LANGUAGE_PROGRESSION_YEARS.length-1)];
- out.push({id:"nl-"+theme+"-"+slug,theme,nl:word,pic,yearGroup});
+ out.push({id:"nl-"+theme+"-"+slug,theme,nl:word,pic:languageProgressionPicture(word,pic),yearGroup,pictureChecked:true});
});
}));
return out
@@ -474,7 +553,8 @@ function languageThemeList(lang=LANG){
})).filter(theme=>theme.words.length);
}
function languageEmojiDataUrl(emoji,colors=["#f4f8ff","#dce9fa"]){
- const svg=``;
+ const fontSize=emoji.length>4?104:emoji.length>2?122:148;
+ const svg=``;
return "data:image/svg+xml;charset=utf-8,"+encodeURIComponent(svg);
}
function languagePictureCatalog(lang=LANG){
diff --git a/test/language-library.test.js b/test/language-library.test.js
index b8a8ba2..4bd1ec6 100644
--- a/test/language-library.test.js
+++ b/test/language-library.test.js
@@ -48,6 +48,29 @@ test('taalwidgets delen ruim duizend extra Nederlandse woorden over leerjaar en
assert.equal(data.themesEn.reduce((sum,theme)=>sum+theme.words.length,0),data.concepts.length);
});
+test('alle aanvullende woorden hebben een gecontroleerd en correct gekoppeld woordplaatje',async()=>{
+ const data=await languageData();
+ const builtinByName=new Map(data.catalogNl.images.filter(image=>image.builtin).map(image=>[image.name,image]));
+ assert.ok(new Set(data.progression.map(word=>word.pic)).size>=400,'verwacht brede beeldvariatie');
+ for(const word of data.progression){
+ assert.equal(word.pictureChecked,true,word.nl);
+ const image=builtinByName.get(word.nl);
+ assert.ok(image,word.nl);
+ assert.equal(image.value,word.pic,word.nl);
+ assert.ok(image.src.startsWith('data:image/svg+xml;charset=utf-8,'),word.nl);
+ }
+ const expected={
+ kattenbak:'๐๐ฆ',kattenvoer:'๐๐ฝ๏ธ',groentekraam:'๐ฅ๐ช',landingsbaan:'๐ฌ',
+ kast:'๐๏ธ',slaapkamerraam:'๐ช',bewegingsapparaat:'๐ฆด',bewegingsrichting:'๐งญ',
+ digitaal:'๐ป',kaart:'๐',landbouwer:'๐งโ๐พ',straat:'๐ฃ๏ธ',plattegrond:'๐บ๏ธ',
+ veehouderij:'๐',wastafel:'๐ฐ',tekstproductie:'โ๏ธ๐',verdrietverwerking:'๐ข๐ง ',
+ bezorgd:'๐',schoolslag:'๐',toneelspeler:'๐ญ',spellingspatroon:'๐ค',
+ meetinstrument:'๐',ruimtestation:'๐ฐ๏ธ',grondrecht:'โ๏ธ'
+ };
+ for(const [word,picture] of Object.entries(expected))
+ assert.equal(data.progression.find(item=>item.nl===word)?.pic,picture,word);
+});
+
test('alle oude startwoorden blijven staan en krijgen ook een bibliotheekplaatje',async()=>{
const data=await languageData();
const oldNl=['aap','vis','zon','kat','bal','ei','boom','huis','maan','boot','kip','muis','boek','ster','roos','vuur','fiets','taart','jas','bril','klok','peer','kaas','eend','hand','voet','neus','oog','oor','mond'];