`;
t.querySelector(".do-len").addEventListener("click", ()=>{
t._cm = RULER_CMS[(RULER_CMS.indexOf(t._cm)+1) % RULER_CMS.length]; drawRuler();
@@ -764,6 +768,7 @@ function toggleDTool(kind){
+
`;
t.querySelector(".do-len").addEventListener("click", ()=>{
t._cm = GEO_CMS[(GEO_CMS.indexOf(t._cm)+1) % GEO_CMS.length]; drawGeo();
@@ -852,6 +857,18 @@ function toggleDTool(kind){
const rot = document.createElement("button");
rot.className = "dtool-rot"; rot.textContent = "↻";
t.appendChild(rot);
+ /* slot: zet het gereedschap vast op zijn plek - niets kan hem meer
+ verschuiven of draaien, zodat er rustig langs getekend kan worden */
+ const lockBtn = t.querySelector(".do-lock");
+ const syncLock = ()=>{
+ lockBtn.textContent = t._locked ? "🔒" : "🔓";
+ lockBtn.title = T("dtLock");
+ lockBtn.setAttribute("aria-pressed", String(!!t._locked));
+ lockBtn.classList.toggle("on", !!t._locked);
+ rot.style.display = t._locked ? "none" : "";
+ };
+ lockBtn.addEventListener("click", ()=>{ t._locked = !t._locked; syncLock(); });
+ syncLock();
}
makeMovable(t);
board.appendChild(t);
@@ -952,22 +969,31 @@ function snapPoint(x, y){
/* start van een haal; ook aanroepbaar vanaf de liniaal/geodriehoek zelf
(pen op de randzone van de lat = tekenen, niet verslepen) - de pointer
capture op bInk stuurt de vervolg-events vanzelf hierheen.
- snapDist: naast de lat een kleine zone (10px, anders "grijpt" de lat
- halen die vrij bedoeld zijn), óp de lat zelf ruimer (24px, zie makeMovable). */
-function startInkStroke(e, snapDist = 10){
+ Naast de lat beslist de RICHTING: binnen 22px van een rand wachten we de
+ eerste ~7px beweging af; loopt die grofweg evenwijdig aan de rand (≤30°),
+ dan kleeft de haal - anders blijft hij vrij. Zo grijpt de lat geen vrije
+ halen en werkt langs de rand tekenen toch betrouwbaar. Op de lat zelf
+ (fromTool) is de intentie ondubbelzinnig en kleeft de haal direct. */
+let bPend = null;
+function startInkStroke(e, fromTool = false){
if(PEN.tool==="text"){ startBoardText(e); return; }
bInk.setPointerCapture(e.pointerId);
bDraw = true;
PEN.nib = PEN.size*0.8;
[bx,by] = bPos(e);
- bSnap = null;
+ bSnap = null; bPend = null;
+ bMidX = bMidY = null;
if(PEN.tool!=="erase" && PEN.tool!=="hand"){
const k = bInk.width / board.clientWidth;
const hit = nearestEdge(bx/k, by/k);
- if(hit && hit.d <= snapDist) bSnap = hit;
+ if(fromTool){
+ if(hit && hit.d <= 24) bSnap = hit;
+ }else if(hit && hit.d <= 22){
+ bPend = { x0:bx, y0:by, hit };
+ return; /* nog niets tekenen; de eerste beweging beslist (flush hieronder) */
+ }
}
[bx,by] = snapPoint(bx, by);
- bMidX = bMidY = null;
bStroke(bx+0.01, by+0.01, e.pressure, e.pointerType);
}
bInk.addEventListener("pointerdown", e=>{
@@ -979,11 +1005,30 @@ bInk.addEventListener("pointermove", e=>{
if(!bDraw) return;
(e.getCoalescedEvents ? e.getCoalescedEvents() : [e]).forEach(ev=>{
const [rx,ry] = bPos(ev);
+ if(bPend){
+ const k = bInk.width / board.clientWidth;
+ const dx = rx - bPend.x0, dy = ry - bPend.y0;
+ if(Math.hypot(dx, dy)/k < 7) return; /* nog te weinig beweging om te beslissen */
+ const move = Math.atan2(dy, dx), edge = Math.atan2(bPend.hit.uy, bPend.hit.ux);
+ let diff = Math.abs(move - edge) % Math.PI;
+ diff = Math.min(diff, Math.PI - diff);
+ if(diff <= Math.PI/6) bSnap = bPend.hit;
+ const [sx, sy] = snapPoint(bPend.x0, bPend.y0);
+ bx = sx; by = sy; bMidX = bMidY = null;
+ bStroke(sx+0.01, sy+0.01, ev.pressure, ev.pointerType);
+ bPend = null;
+ }
const [x,y] = snapPoint(rx, ry);
bStroke(x, y, ev.pressure, ev.pointerType);
});
});
const bStop = ()=>{
+ if(bDraw && bPend){
+ /* tik zonder beweging vlak naast de lat: gewoon een vrije stip zetten */
+ bx = bPend.x0; by = bPend.y0; bMidX = bMidY = null;
+ bStroke(bx+0.01, by+0.01, 0, "mouse");
+ bPend = null;
+ }
if(bDraw){
/* markeerstift: de haal staat dekkend op de overlay - nu in één keer
met vaste transparantie op de inktlaag zetten (egale kleur, geen
diff --git a/public/js/core.js b/public/js/core.js
index bbd5e51..f7fad1a 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.3.75-beta";
+const VERSION = "0.3.76-beta";
(function(){
const tag = document.getElementById("verTag");
tag.textContent = "v"+VERSION;
@@ -96,15 +96,16 @@ const I18N = {
wFull:"Maximaliseren", wUnfull:"Terugzetten",
wZoom:"Inhoud groter of kleiner (voor slechtzienden)",
wg_flits:"Flitswoorden", wg_flits_d:"Een woord flitst kort in beeld – lezen voordat het verdwijnt!",
- flFlash:"⚡ Flits", flShow:"👁 Toon", flNext:"Volgende ▸", flSec:"sec",
+ flFlash:"⚡ Flits", flShow:"👁 Toon", flNext:"Volgende ▸", flSec:"sec", flMission:"Lees het woord voordat het verdwijnt.", flQuestion:"Kon je het woord zelf lezen?", flGotIt:"🌟 Gelukt!", flAgain:"Nog oefenen", flScore:"{score} sterren",
wg_dice:"Dobbelstenen", wg_dice_d:"Gooi 1, 2 of 3 grote dobbelstenen.",
- diceRoll:"🎲 Gooi!", diceSum:"Samen",
- wg_light:"Stoplicht", wg_light_d:"Rood, oranje of groen – bijvoorbeeld voor het werkrumoer.",
+ diceRoll:"🎲 Gooi!", diceSum:"Samen", diceMission:"Gooi, tel de ogen en controleer de uitkomst.", diceHistory:"Vorige worpen",
+ wg_light:"Klassenstoplicht", wg_light_d:"Maak in één oogopslag duidelijk of kinderen luisteren, fluisteren of rustig mogen werken.",
+ lightRed:"Rood", lightRedHint:"Stop en luister", lightOrange:"Oranje", lightOrangeHint:"Fluister en rond af", lightGreen:"Groen", lightGreenHint:"Je mag rustig werken", lightStatus:"{color}: {hint}",
wg_names:"Namenkiezer", wg_names_d:"Kies willekeurig een naam uit de klas.",
namesPh:"Eén naam per regel…", namesPick:"🎯 Kies!", namesNoRep:"Zonder herhaling",
- namesDone:"Iedereen is geweest! 🎉",
+ namesDone:"Iedereen is geweest! 🎉", namesReset:"Opnieuw", namesProgress:"{used} van {total} geweest",
wg_hak:"Hakken & plakken", wg_hak_d:"Woorden in klanken hakken en weer plakken, met voorlezen.",
- hakChop:"✂️ Hak", hakGlue:"🔗 Plak", hakSay:"🔊 Lees voor",
+ hakChop:"✂️ Hak", hakGlue:"🔗 Plak", hakSay:"🔊 Lees voor", hakHint:"Bekijk en hoor de klankgroepen in het woord.",
wg_ball:"Ballonnenwoord", wg_ball_d:"Raad het woord letter voor letter voordat de ballonnen knappen.",
wg_anchor:"Ankerwoorden", wg_anchor_d:"Woordweb voor woordenschatonderwijs: leer woorden in samenhang rond een themawoord (het anker), met plaatjes. Elk woord verankert aan de woorden eromheen.",
fabAnchor:"Ankerdiagram (woordweb)",
@@ -114,15 +115,15 @@ const I18N = {
birthdaySprinkles:"Spikkels", birthdayFruit:"Fruit", birthdayStars:"Sterren", birthdayNone:"Geen versiering",
wg_numberline:"Getallenlijn", wg_numberline_d:"Oefen getalbegrip met een instelbare, interactieve getallenlijn.",
numberlineFrom:"Van", numberlineTo:"Tot", numberlineStep:"Stap", numberlineNew:"Nieuwe opdracht", numberlineTask:"Zet de stip op {number}",
- numberlineCheck:"Controleren", numberlineGood:"Goed gevonden! 🌟", numberlineTry:"Kijk nog eens naar de getallenlijn.",
- wg_fractions:"Breukenmuur", wg_fractions_d:"Vergelijk breuken visueel en markeer gelijke delen.",
+ numberlineCheck:"Controleren", numberlineGood:"Goed gevonden! 🌟", numberlineTry:"Kijk nog eens naar de getallenlijn.", numberlineScore:"{score} sterren · reeks {streak}",
+ wg_fractions:"Breukenmuur", wg_fractions_d:"Bouw breuken, vergelijk de gekleurde delen en ontdek gelijkwaardige breuken.",
wg_clock:"Oefenklok", wg_clock_d:"Leer kloktijden op vier niveaus met meerdere leerwijzen en spellen.",
wg_placevalue:"Plaatswaardetabel", wg_placevalue_d:"Ontdek de waarde van cijfers tot honderdduizend.",
wg_money:"Geldrekenen", wg_money_d:"Oefen bedragen maken, geld tellen en wisselgeld op drie niveaus.",
wg_trees:"Bomen & bladeren", wg_trees_d:"Leer achttien Nederlandse boomsoorten met vijf foto-, kenmerk- en koppeloefeningen.",
wg_birds:"Vogels herkennen", wg_birds_d:"Leer achttien Nederlandse vogels met vier foto-, kenmerk- en naamoefeningen.",
wg_plants:"Wilde planten", wg_plants_d:"Herken twaalf algemene wilde planten aan echte foto's en duidelijke veldkenmerken.",
- wg_topography:"Topografie Nederland", wg_topography_d:"Oefen provincies, plaatsen, landsdelen, rivieren en werelddelen op nauwkeurige kaarten.",
+ wg_topography:"Topografie", wg_topography_d:"Oefen Nederland én de wereld: provincies, plaatsen, landsdelen, rivieren en werelddelen op nauwkeurige kaarten.",
worldActivity:"Werkvorm", worldLearn:"Leren", worldQuiz:"Quiz", worldExercise:"Oefening", worldLevel:"Niveau", worldTreeView:"Wat zie je?", worldTreeWhole:"Hele boom", worldTreeLeaf:"Blad", worldTreeMixed:"Boom en blad",
worldExerciseRecognize:"Herken de soort", worldExercisePair:"Koppel boom en blad", worldExerciseClue:"Raad met kenmerken", worldExercisePhoto:"Kies de juiste foto", worldExerciseLatin:"Wetenschappelijke naam",
worldScore:"Score: {score} · reeks: {streak}", worldExploreHint:"Bekijk de kenmerken en vergelijk de soorten.", worldQuestionTree:"Welke boom zie je?", worldQuestionLeaf:"Bij welke boom hoort dit blad?", worldQuestionBird:"Welke vogel zie je?", worldQuestionPlant:"Welke wilde plant zie je?",
@@ -146,10 +147,10 @@ const I18N = {
wg_mood:"Gevoelsmeter", wg_mood_d:"Doe een snelle, anonieme check-in met de klas.",
wg_poll:"Klaspoll", wg_poll_d:"Stem samen op maximaal zes antwoorden.",
clock24Hour:"24-uursklok",
- widgetSettings:"Instellingen", clockWelcome:"Oefenen met de klok", clockWelcomeHint:"Kies bovenaan niveau 1, 2 of 3. Kies bij Instellingen hoe de opdracht wordt getoond en start daarna.", clockSetTitle:"Zet de wijzers op de goede tijd", clockReadTitle:"Bekijk de opdracht en maak de tijd", clockChooseTitle:"Kies het juiste tijdblok", clockYourTask:"Jouw opdracht", clockLinkHands:"Grote wijzer draait mee", clockTypeHint:"Voer de tijd in als UU:MM.", clockLevel1Hint:"Niveau 1: hele en halve uren", clockLevel2Hint:"Niveau 2: stappen van vijf minuten", clockLevel3Hint:"Niveau 3: alle minuten, met optioneel 24 uur en dagdelen", clockBuildHint:"Sleep vier cijfers naar de vakken en maak UU:MM.", clockDigitGhost:"?", clockDigit:"Cijfer {digit}", clockIncomplete:"Maak eerst de volledige tijd af.", clockCorrect:"Goed gedaan! Kies de volgende opdracht. 🌟", clockTryAgain:"Bijna! Probeer het nog een keer.", clockStartTask:"Start opdracht", clockNextTask:"Volgende opdracht", clockLevel:"Niveau", clockLevelHour:"Hele uren", clockLevelQuarter:"Kwartieren", clockLevelFive:"Vijf minuten", clockLevelMinute:"Iedere minuut", clockLearningStyle:"Opdracht tonen", clockStyleAnalogue:"Analoge klok", clockStyleDigital:"Grote digitale tijd", clockStyleWords:"In woorden", clockStyleBoth:"Klok, cijfers en woorden", clockDragHint:"Sleep de wijzers om de tijd te veranderen.", clockGame:"Spel", clockGameSet:"Klok zetten", clockGameRead:"Tijd aflezen", clockGameChoose:"Kies de tijd", clockStart:"Kies ‘Nieuwe opdracht’ om te beginnen", clockRead:"Welke tijd zie je? Stel je antwoord hieronder in.", clockChoose:"Welke digitale tijd hoort bij deze klok?", clockTry:"Nog niet. Het goede antwoord is {time}.", clockScore:"Score: {score} · reeks: {streak}", clockWordsHour:"{hour} uur", clockWordsQuarterPast:"kwart over {hour}", clockWordsHalf:"half {hour}", clockWordsQuarterTo:"kwart voor {hour}", clockWordsPast:"{minutes} over {hour}", clockWordsTo:"{minutes} voor {hour}", clockMorning:"in de ochtend", clockAfternoon:"in de middag", clockEvening:"in de avond", clockNight:"in de nacht", fractionRows:"Rijen", fractionLabels:"Breuken tonen", clockTask:"Oefenopdracht", clockSet:"Zet de klok op {time}", clockHour:"Uur", clockMinute:"Minuten", placeNumber:"Getal", moneyMake:"Maak € {amount}", wordtypeSentence:"Zin", wordtypeHint:"Tik: blauw zelfstandig naamwoord · groen werkwoord · geel bijvoeglijk naamwoord", scheduleActivity:"activiteit…", scheduleEmpty:"Voeg de eerste activiteit toe.", pollReset:"Opnieuw", pollQuestion:"Vraag", pollOptions:"Antwoorden (één per regel)", galleryFavorites:"Favorieten", galleryFavorite:"Favoriet maken", galleryEmpty:"Geen widgets gevonden.", gallerySearch:"Zoek widgets…", templateMath:"Rekenles", templateLanguage:"Taalles", templateDay:"Dagstart", exportBoard:"Exporteren", importBoard:"Importeren", importError:"Dit is geen geldig Teach-bordbestand.", widgetDuplicate:"Dupliceren", widgetLock:"Vastzetten", widgetUnlock:"Losmaken", widgetPreview:"Voorbeeld zonder bediening", undo:"Ongedaan maken", redo:"Opnieuw",
+ widgetSettings:"Instellingen", clockWelcome:"Oefenen met de klok", clockWelcomeHint:"Kies bovenaan niveau 1, 2 of 3. Kies bij Instellingen hoe de opdracht wordt getoond en start daarna.", clockSetTitle:"Zet de wijzers op de goede tijd", clockReadTitle:"Bekijk de opdracht en maak de tijd", clockChooseTitle:"Kies het juiste tijdblok", clockYourTask:"Jouw opdracht", clockLinkHands:"Grote wijzer draait mee", clockTypeHint:"Voer de tijd in als UU:MM.", clockLevel1Hint:"Niveau 1: hele en halve uren", clockLevel2Hint:"Niveau 2: stappen van vijf minuten", clockLevel3Hint:"Niveau 3: alle minuten, met optioneel 24 uur en dagdelen", clockBuildHint:"Sleep vier cijfers naar de vakken en maak UU:MM.", clockDigitGhost:"?", clockDigit:"Cijfer {digit}", clockIncomplete:"Maak eerst de volledige tijd af.", clockCorrect:"Goed gedaan! Kies de volgende opdracht. 🌟", clockTryAgain:"Bijna! Probeer het nog een keer.", clockStartTask:"Start opdracht", clockNextTask:"Volgende opdracht", clockLevel:"Niveau", clockLevelHour:"Hele uren", clockLevelQuarter:"Kwartieren", clockLevelFive:"Vijf minuten", clockLevelMinute:"Iedere minuut", clockLearningStyle:"Opdracht tonen", clockStyleAnalogue:"Analoge klok", clockStyleDigital:"Grote digitale tijd", clockStyleWords:"In woorden", clockStyleBoth:"Klok, cijfers en woorden", clockDragHint:"Sleep de wijzers om de tijd te veranderen.", clockGame:"Spel", clockGameSet:"Klok zetten", clockGameRead:"Tijd aflezen", clockGameChoose:"Kies de tijd", clockStart:"Kies ‘Nieuwe opdracht’ om te beginnen", clockRead:"Welke tijd zie je? Stel je antwoord hieronder in.", clockChoose:"Welke digitale tijd hoort bij deze klok?", clockTry:"Nog niet. Het goede antwoord is {time}.", clockScore:"Score: {score} · reeks: {streak}", clockWordsHour:"{hour} uur", clockWordsQuarterPast:"kwart over {hour}", clockWordsHalf:"half {hour}", clockWordsQuarterTo:"kwart voor {hour}", clockWordsPast:"{minutes} over {hour}", clockWordsTo:"{minutes} voor {hour}", clockMorning:"in de ochtend", clockAfternoon:"in de middag", clockEvening:"in de avond", clockNight:"in de nacht", fractionRows:"Rijen", fractionLabels:"Breuken tonen", fractionHint:"Tik in een rij tot waar je de breuk wilt kleuren.", fractionSelected:"Gekozen breuk: {fraction}", fractionClear:"Leegmaken", clockTask:"Oefenopdracht", clockSet:"Zet de klok op {time}", clockHour:"Uur", clockMinute:"Minuten", placeNumber:"Getal", moneyMake:"Maak € {amount}", wordtypeSentence:"Zin", wordtypeHint:"Tik: blauw zelfstandig naamwoord · groen werkwoord · geel bijvoeglijk naamwoord", scheduleActivity:"activiteit…", scheduleEmpty:"Voeg de eerste activiteit toe.", scheduleCount:"{count} momenten op de planning", pollReset:"Opnieuw", pollQuestion:"Vraag", pollOptions:"Antwoorden (één per regel)", pollTotal:"{count} stemmen", moodTotal:"{count} kinderen hebben gekozen", moodVote:"Kies {face}", galleryFavorites:"Favorieten", galleryFavorite:"Favoriet maken", galleryEmpty:"Geen widgets gevonden.", gallerySearch:"Zoek widgets…", templateMath:"Rekenles", templateLanguage:"Taalles", templateDay:"Dagstart", exportBoard:"Exporteren", importBoard:"Importeren", importError:"Dit is geen geldig Teach-bordbestand.", widgetDuplicate:"Dupliceren", widgetLock:"Vastzetten", widgetUnlock:"Losmaken", widgetPreview:"Voorbeeld zonder bediening", undo:"Ongedaan maken", redo:"Opnieuw",
wg_sentence:"Zinsbouwer", wg_sentence_d:"Bouw zinnen met kleurgecodeerde zinsdelen en voeg eigen woorden toe.",
sentence_who:"Wie?", sentence_does:"Doet wat?", sentence_what:"Wat of waar?", sentenceHint:"Kies woorden om een zin te maken…",
- sentenceAdd:"eigen woord of zinsdeel…", sentenceClear:"Wissen", sentenceSpeak:"🔊 Lees voor", sentenceRemove:"Verwijder woord",
+ sentenceAdd:"eigen woord of zinsdeel…", sentenceClear:"Wissen", sentenceSpeak:"🔊 Lees voor", sentenceRemove:"Verwijder woord", sentenceSurprise:"✨ Verrassingszin",
anchorPh:"thema…", anchorHint:"Woordweb: zet het themawoord in het midden en bouw eromheen · tik op een vak en typ · sleep om te schuiven",
anchorHintReadonly:"Sleep de achtergrond om te schuiven",
anchorColor:"Kleur: klik om te wisselen (verbind woorden met dezelfde kleur)",
@@ -245,6 +246,7 @@ const I18N = {
parentUnlinkWarn:"Verwijdert alleen de koppeling; het account van je kind blijft bestaan.",
parentProgress:"📈 Voortgang", parentProgressEmpty:"Nog geen voortgang.",
dtLen:"Lengte", dtContrast:"Hoog contrast",
+ dtLock:"Vastzetten: kan niet meer verschuiven of draaien, alleen nog langs tekenen",
dtMode:"Basis: grote hoofdhoeken en hele centimeters. Volledig: graden per 2° met dubbele schaal, millimeters en evenwijdige hulplijnen.",
dtModeBasic:"basis", dtModeFull:"volledig",
pupilEmpty:"Je leerkracht heeft nog niets voor je klaargezet.",
@@ -370,15 +372,16 @@ const I18N = {
wFull:"Maximize", wUnfull:"Restore",
wZoom:"Content bigger or smaller (low vision)",
wg_flits:"Flash words", wg_flits_d:"A word flashes briefly – read it before it disappears!",
- flFlash:"⚡ Flash", flShow:"👁 Show", flNext:"Next ▸", flSec:"sec",
+ flFlash:"⚡ Flash", flShow:"👁 Show", flNext:"Next ▸", flSec:"sec", flMission:"Read the word before it disappears.", flQuestion:"Could you read the word by yourself?", flGotIt:"🌟 Got it!", flAgain:"Practise again", flScore:"{score} stars",
wg_dice:"Dice", wg_dice_d:"Roll 1, 2 or 3 big dice.",
- diceRoll:"🎲 Roll!", diceSum:"Total",
- wg_light:"Traffic light", wg_light_d:"Red, orange or green – e.g. for classroom noise.",
+ diceRoll:"🎲 Roll!", diceSum:"Total", diceMission:"Roll, count the dots and check the total.", diceHistory:"Previous rolls",
+ wg_light:"Class traffic light", wg_light_d:"Show at a glance whether children listen, whisper or work quietly.",
+ lightRed:"Red", lightRedHint:"Stop and listen", lightOrange:"Amber", lightOrangeHint:"Whisper and finish", lightGreen:"Green", lightGreenHint:"You may work quietly", lightStatus:"{color}: {hint}",
wg_names:"Name picker", wg_names_d:"Pick a random name from the class.",
namesPh:"One name per line…", namesPick:"🎯 Pick!", namesNoRep:"No repeats",
- namesDone:"Everyone has had a turn! 🎉",
+ namesDone:"Everyone has had a turn! 🎉", namesReset:"Start over", namesProgress:"{used} of {total} picked",
wg_hak:"Chop & blend", wg_hak_d:"Chop words into sounds and blend them back, with read-aloud.",
- hakChop:"✂️ Chop", hakGlue:"🔗 Blend", hakSay:"🔊 Read aloud",
+ hakChop:"✂️ Chop", hakGlue:"🔗 Blend", hakSay:"🔊 Read aloud", hakHint:"See and hear the sound groups in the word.",
wg_ball:"Balloon word", wg_ball_d:"Guess the word letter by letter before the balloons pop.",
wg_anchor:"Anchor words", wg_anchor_d:"Word web for vocabulary teaching: learn words in meaningful clusters around a theme word (the anchor), with pictures. Every word anchors to its neighbours.",
fabAnchor:"Anchor diagram (word web)",
@@ -388,15 +391,15 @@ const I18N = {
birthdaySprinkles:"Sprinkles", birthdayFruit:"Fruit", birthdayStars:"Stars", birthdayNone:"No decoration",
wg_numberline:"Number line", wg_numberline_d:"Practise number sense with an adjustable, interactive number line.",
numberlineFrom:"From", numberlineTo:"To", numberlineStep:"Step", numberlineNew:"New task", numberlineTask:"Move the marker to {number}",
- numberlineCheck:"Check", numberlineGood:"Well done! 🌟", numberlineTry:"Take another look at the number line.",
- wg_fractions:"Fraction wall", wg_fractions_d:"Compare fractions visually and mark equal parts.",
+ numberlineCheck:"Check", numberlineGood:"Well done! 🌟", numberlineTry:"Take another look at the number line.", numberlineScore:"{score} stars · streak {streak}",
+ wg_fractions:"Fraction wall", wg_fractions_d:"Build fractions, compare coloured parts and discover equivalent fractions.",
wg_clock:"Practice clock", wg_clock_d:"Learn time at four levels with multiple learning styles and games.",
wg_placevalue:"Place value", wg_placevalue_d:"Explore digit values up to hundred thousands.",
wg_money:"Money", wg_money_d:"Practise making amounts, counting money and change at three levels.",
wg_trees:"Trees & leaves", wg_trees_d:"Learn eighteen Dutch tree species with five photo, feature and matching exercises.",
wg_birds:"Bird identification", wg_birds_d:"Learn eighteen Dutch birds with four photo, feature and naming exercises.",
wg_plants:"Wild plants", wg_plants_d:"Recognise twelve common wild plants from real photographs and clear field marks.",
- wg_topography:"Map of the Netherlands", wg_topography_d:"Practise provinces, places, regions, rivers and continents on accurate maps.",
+ wg_topography:"Topography", wg_topography_d:"Practise the Netherlands and the world: provinces, places, regions, rivers and continents on accurate maps.",
worldActivity:"Activity", worldLearn:"Learn", worldQuiz:"Quiz", worldExercise:"Exercise", worldLevel:"Level", worldTreeView:"What do you see?", worldTreeWhole:"Whole tree", worldTreeLeaf:"Leaf", worldTreeMixed:"Tree and leaf",
worldExerciseRecognize:"Recognise the species", worldExercisePair:"Match tree and leaf", worldExerciseClue:"Guess from features", worldExercisePhoto:"Choose the correct photo", worldExerciseLatin:"Scientific name",
worldScore:"Score: {score} · streak: {streak}", worldExploreHint:"Study the features and compare the species.", worldQuestionTree:"Which tree do you see?", worldQuestionLeaf:"Which tree does this leaf belong to?", worldQuestionBird:"Which bird do you see?", worldQuestionPlant:"Which wild plant do you see?",
@@ -420,10 +423,10 @@ const I18N = {
wg_mood:"Mood check-in", wg_mood_d:"Run a quick anonymous class check-in.",
wg_poll:"Class poll", wg_poll_d:"Vote together on up to six answers.",
clock24Hour:"24-hour clock",
- widgetSettings:"Settings", clockWelcome:"Practise telling time", clockWelcomeHint:"Choose level 1, 2 or 3 at the top. In Settings, choose how the task is shown, then start.", clockSetTitle:"Move the hands to the correct time", clockReadTitle:"View the task and make the time", clockChooseTitle:"Choose the correct time block", clockYourTask:"Your task", clockLinkHands:"Move the minute hand along", clockTypeHint:"Enter the time as HH:MM.", clockLevel1Hint:"Level 1: whole and half hours", clockLevel2Hint:"Level 2: five-minute steps", clockLevel3Hint:"Level 3: every minute, with optional 24-hour time and day parts", clockBuildHint:"Drag four digits into the slots to make HH:MM.", clockDigitGhost:"?", clockDigit:"Digit {digit}", clockIncomplete:"Complete the full time first.", clockCorrect:"Well done! Choose the next task. 🌟", clockTryAgain:"Almost! Try again.", clockStartTask:"Start task", clockNextTask:"Next task", clockLevel:"Level", clockLevelHour:"Whole hours", clockLevelQuarter:"Quarter hours", clockLevelFive:"Five minutes", clockLevelMinute:"Every minute", clockLearningStyle:"Show task as", clockStyleAnalogue:"Analogue clock", clockStyleDigital:"Large digital time", clockStyleWords:"In words", clockStyleBoth:"Clock, digits and words", clockDragHint:"Drag the hands to change the time.", clockGame:"Game", clockGameSet:"Set the clock", clockGameRead:"Read the time", clockGameChoose:"Choose the time", clockStart:"Choose ‘New task’ to begin", clockRead:"What time is it? Set your answer below.", clockChoose:"Which digital time matches this clock?", clockTry:"Not yet. The correct answer is {time}.", clockScore:"Score: {score} · streak: {streak}", clockWordsHour:"{hour} o'clock", clockWordsQuarterPast:"quarter past {hour}", clockWordsHalf:"half past {hour}", clockWordsQuarterTo:"quarter to {hour}", clockWordsPast:"{minutes} past {hour}", clockWordsTo:"{minutes} to {hour}", clockMorning:"in the morning", clockAfternoon:"in the afternoon", clockEvening:"in the evening", clockNight:"at night", fractionRows:"Rows", fractionLabels:"Show fractions", clockTask:"Practice task", clockSet:"Set the clock to {time}", clockHour:"Hour", clockMinute:"Minutes", placeNumber:"Number", moneyMake:"Make € {amount}", wordtypeSentence:"Sentence", wordtypeHint:"Tap: blue noun · green verb · yellow adjective", scheduleActivity:"activity…", scheduleEmpty:"Add the first activity.", pollReset:"Reset", pollQuestion:"Question", pollOptions:"Answers (one per line)", galleryFavorites:"Favourites", galleryFavorite:"Add favourite", galleryEmpty:"No widgets found.", gallerySearch:"Search widgets…", templateMath:"Maths lesson", templateLanguage:"Language lesson", templateDay:"Day start", exportBoard:"Export", importBoard:"Import", importError:"This is not a valid Teach board file.", widgetDuplicate:"Duplicate", widgetLock:"Lock", widgetUnlock:"Unlock", widgetPreview:"Preview without controls", undo:"Undo", redo:"Redo",
+ widgetSettings:"Settings", clockWelcome:"Practise telling time", clockWelcomeHint:"Choose level 1, 2 or 3 at the top. In Settings, choose how the task is shown, then start.", clockSetTitle:"Move the hands to the correct time", clockReadTitle:"View the task and make the time", clockChooseTitle:"Choose the correct time block", clockYourTask:"Your task", clockLinkHands:"Move the minute hand along", clockTypeHint:"Enter the time as HH:MM.", clockLevel1Hint:"Level 1: whole and half hours", clockLevel2Hint:"Level 2: five-minute steps", clockLevel3Hint:"Level 3: every minute, with optional 24-hour time and day parts", clockBuildHint:"Drag four digits into the slots to make HH:MM.", clockDigitGhost:"?", clockDigit:"Digit {digit}", clockIncomplete:"Complete the full time first.", clockCorrect:"Well done! Choose the next task. 🌟", clockTryAgain:"Almost! Try again.", clockStartTask:"Start task", clockNextTask:"Next task", clockLevel:"Level", clockLevelHour:"Whole hours", clockLevelQuarter:"Quarter hours", clockLevelFive:"Five minutes", clockLevelMinute:"Every minute", clockLearningStyle:"Show task as", clockStyleAnalogue:"Analogue clock", clockStyleDigital:"Large digital time", clockStyleWords:"In words", clockStyleBoth:"Clock, digits and words", clockDragHint:"Drag the hands to change the time.", clockGame:"Game", clockGameSet:"Set the clock", clockGameRead:"Read the time", clockGameChoose:"Choose the time", clockStart:"Choose ‘New task’ to begin", clockRead:"What time is it? Set your answer below.", clockChoose:"Which digital time matches this clock?", clockTry:"Not yet. The correct answer is {time}.", clockScore:"Score: {score} · streak: {streak}", clockWordsHour:"{hour} o'clock", clockWordsQuarterPast:"quarter past {hour}", clockWordsHalf:"half past {hour}", clockWordsQuarterTo:"quarter to {hour}", clockWordsPast:"{minutes} past {hour}", clockWordsTo:"{minutes} to {hour}", clockMorning:"in the morning", clockAfternoon:"in the afternoon", clockEvening:"in the evening", clockNight:"at night", fractionRows:"Rows", fractionLabels:"Show fractions", fractionHint:"Tap a row up to the part you want to colour.", fractionSelected:"Selected fraction: {fraction}", fractionClear:"Clear", clockTask:"Practice task", clockSet:"Set the clock to {time}", clockHour:"Hour", clockMinute:"Minutes", placeNumber:"Number", moneyMake:"Make € {amount}", wordtypeSentence:"Sentence", wordtypeHint:"Tap: blue noun · green verb · yellow adjective", scheduleActivity:"activity…", scheduleEmpty:"Add the first activity.", scheduleCount:"{count} moments in the schedule", pollReset:"Reset", pollQuestion:"Question", pollOptions:"Answers (one per line)", pollTotal:"{count} votes", moodTotal:"{count} children have chosen", moodVote:"Choose {face}", galleryFavorites:"Favourites", galleryFavorite:"Add favourite", galleryEmpty:"No widgets found.", gallerySearch:"Search widgets…", templateMath:"Maths lesson", templateLanguage:"Language lesson", templateDay:"Day start", exportBoard:"Export", importBoard:"Import", importError:"This is not a valid Teach board file.", widgetDuplicate:"Duplicate", widgetLock:"Lock", widgetUnlock:"Unlock", widgetPreview:"Preview without controls", undo:"Undo", redo:"Redo",
wg_sentence:"Sentence builder", wg_sentence_d:"Build sentences with colour-coded parts and add your own words.",
sentence_who:"Who?", sentence_does:"Does what?", sentence_what:"What or where?", sentenceHint:"Choose words to build a sentence…",
- sentenceAdd:"your own word or phrase…", sentenceClear:"Clear", sentenceSpeak:"🔊 Read aloud", sentenceRemove:"Remove word",
+ sentenceAdd:"your own word or phrase…", sentenceClear:"Clear", sentenceSpeak:"🔊 Read aloud", sentenceRemove:"Remove word", sentenceSurprise:"✨ Surprise sentence",
anchorPh:"theme…", anchorHint:"Word web: put the theme word in the middle and build around it · tap a cell and type · drag to pan",
anchorHintReadonly:"Drag the background to pan",
anchorColor:"Colour: click to cycle (connect words with the same colour)",
@@ -464,7 +467,7 @@ const I18N = {
imgQuotaMb:"limit in MB", imgQuotaInvalid:"Enter a valid limit.", imgSchools:"Schools",
imgUsers:"Users", imgSearchUsers:"Search user…",
cats:["Animals","Food","Nature","Transport","Things","Body"],
- notesPh:"Write here…",
+ notesPh:"Write here…", notesColor:"Note colour", notesLarge:"Large letters", notesCount:"{count} characters",
start:"Start", pause:"Pause", reset:"Reset", min:"min",
tmDigits:"Digits", tmVisual:"Visual clock", tmBoth:"Both", tmSound:"Sound on/off",
tmHint:"Drag the red disc to set the time.",
@@ -519,6 +522,7 @@ const I18N = {
parentUnlinkWarn:"Removes only the link; your child's account remains.",
parentProgress:"📈 Progress", parentProgressEmpty:"No progress yet.",
dtLen:"Length", dtContrast:"High contrast",
+ dtLock:"Lock in place: can no longer move or rotate, only draw along it",
dtMode:"Basic: big main angles and whole centimetres. Full: degrees every 2° with a double scale, millimetres and parallel guide lines.",
dtModeBasic:"basic", dtModeFull:"full",
pupilEmpty:"Your teacher hasn't set up anything for you yet.",