1 {-# LANGUAGE OverloadedLists #-}
3 module Rosetta.WritingSpec where
5 import Data.GenValidity.Map ()
6 import Data.GenValidity.Sequence ()
7 import Data.GenValidity.Set ()
8 import Data.GenValidity.Text ()
9 import Data.List qualified as List
10 import Data.Map.Strict qualified as Map
11 import Data.Text qualified as Text
12 import Data.Validity.Map ()
13 import Data.Validity.Set ()
14 import Data.Validity.Text ()
15 import System.FilePath (joinPath, pathSeparator, (<.>), (</>))
19 import Language.Chinese qualified as Chinese
20 import Language.Pronunciation qualified as Pron
21 import Rosetta.Reading qualified as Reading
22 import Rosetta.Writing
23 import Worksheets.Utils.Char qualified as Char
24 import Worksheets.Utils.HTML (cm)
25 import Worksheets.Utils.HTML qualified as HTML
26 import Worksheets.Utils.Prelude
28 runPages :: String -> Pages -> TestDefM (Chinese.ChineseDict : outers) () ()
29 runPages title pages_ = do
30 descrPath <- getTestDescriptionPath
32 List.reverse descrPath
36 (Text.singleton pathSeparator)
38 let outPath = "tests" </> dirPath </> title </> "rosetta" <.> "html"
39 itWithOuter title \dict -> do
40 goldenByteStringBuilderFile outPath $
41 pagesHTML dict (Text.pack title) pages_
43 spec :: HasCallStack => Spec
44 spec = aroundAll readDict do
45 -- runPage "Avion" avion
46 -- runPage "Bateau" bateau
47 -- runPage "Chocolat" chocolat
48 -- runPage "Pistache" pistache
50 -- runPage "Pluie" pluie
51 -- runPage "TarteAuxPommes" tarteAuxPommesDanniversaire
52 -- runPage "ChatChevalVélo" chatChevalVélo
53 -- runPage "chevauxDormirDebout" chevauxDormirDebout
54 forM_ (rosettas & Map.toList) \(name, pages) ->
57 readDict :: (Chinese.ChineseDict -> IO ()) -> IO ()
58 -- readDict k = k mempty
59 readDict = (Chinese.readChineseDict >>=)
66 { partPicture = "Plantes/Cacao/Fruit-cacao-tree-source-cocoa-chocolate-plant.avif"
67 , partDescription = ""
68 , partLangue = LangueFrançais
69 , partText = "Le chocolat contient du cacao"
72 { partPicture = "Plantes/Cacao/42f651_95f537d693fb48068880a02efa662822~mv2.avif"
73 , partDescription = ""
74 , partLangue = LangueAnglais
75 , partText = "Chocolate contains cocoa"
78 { partPicture = "Plantes/Cacao/Chocolate-Ingredients_520x500_c496776e-df9b-4348-a662-5ff65279f5ca.avif"
79 , partDescription = ""
80 , partLangue = LangueMandarin
81 , partText = "巧克力 含有 可可"
89 { partPicture = "Plantes/Pistache/581614a479ee6b4df250c4caddc04bca.avif"
90 , partDescription = ""
91 , partLangue = LangueFrançais
92 , partText = "La glace à la pistache est délicieuse"
95 { partPicture = "Plantes/Pistache/pistachios.avif"
96 , partDescription = ""
97 , partLangue = LangueAnglais
98 , partText = "Pistachio ice cream is delicious"
101 { partPicture = "Plantes/Pistache/No-Churn-Vegan-Pistachio-Ice-Cream-3-e1502503524224.avif"
102 , partDescription = ""
103 , partLangue = LangueMandarin
104 , partText = "开心果 冰淇淋 很 好吃"
112 { partPicture = "Avion/sound-barrier.avif"
113 , partDescription = ""
114 , partLangue = LangueFrançais
115 , partText = "Avion dans le ciel"
118 { partPicture = "Avion/mustang.avif"
119 , partDescription = ""
120 , partLangue = LangueAnglais
121 , partText = "Airoplane in the sky"
124 { partPicture = "Avion/cockpit.avif"
125 , partDescription = ""
126 , partLangue = LangueMandarin
127 , partText = "天空 中 有 一 架 飞机"
135 { partPicture = "Egg/R.avif"
136 , partDescription = ""
137 , partLangue = LangueFrançais
138 , partText = "Les poules pondent des œufs"
141 { partPicture = "Egg/everything-you-ever-wanted-to-know-about-chicken-eggs.avif"
142 , partDescription = ""
143 , partLangue = LangueAnglais
144 , partText = "Hens lay eggs"
147 { partPicture = "Egg/OIP.avif"
148 , partDescription = ""
149 , partLangue = LangueMandarin
158 { partPicture = "Pluie/R.avif"
159 , partDescription = ""
160 , partLangue = LangueFrançais
161 , partText = "L'eau de pluie retourne à l'océan"
164 { partPicture = "Pluie/OIP2.avif"
165 , partDescription = ""
166 , partLangue = LangueAnglais
167 , partText = "Rainwater returns to the ocean"
170 { partPicture = "Pluie/c1b4767475208de5a389045b7ad856a0.avif"
171 , partDescription = ""
172 , partLangue = LangueMandarin
173 , partText = "雨水 回归 海洋"
177 tarteAuxPommesDanniversaire =
181 { partPicture = "TarteAuxPommesDanniversaire/IMG_20250605_180725.avif"
182 , partDescription = ""
183 , partLangue = LangueFrançais
184 , partText = "Délicieuse tarte aux pommes d'anniversaire"
187 { partPicture = "TarteAuxPommesDanniversaire/VID_20250605_214924.mp4.00-01-40-421.avif"
188 , partDescription = ""
189 , partLangue = LangueAnglais
190 , partText = "Delicious birthday apple pie"
193 { partPicture = "TarteAuxPommesDanniversaire/VID_20250605_214924.mp4.00-01-47-284.avif"
194 , partDescription = ""
195 , partLangue = LangueMandarin
196 , partText = "美味 的 生日 苹果派"
204 { partPicture = "Chat/IMG_20250605_194233_truffe.avif"
205 , partDescription = ""
206 , partLangue = LangueFrançais
207 , partText = "chat cheval vélo"
210 { partPicture = "Cheval/IMG_20250602_170549_himalaya.avif"
211 , partDescription = ""
212 , partLangue = LangueAnglais
213 , partText = "cat horse bicycle"
216 { partPicture = "Vélo/IMG_20250602_155624.fav.vélos.avif"
217 , partDescription = ""
218 , partLangue = LangueMandarin
219 , partText = "猫 马 自行车"
228 { pagesDifficulties =
229 langues & Map.fromSet \_lang ->
230 Char.unicodeBlocks & Map.fromSet difficulty
231 -- <&> (\v -> v{difficultyHiddenPatterns = True})
232 -- & Map.mapWithKey (\k v -> v{difficultyReading = v & difficultyReading & })
237 difficulty :: Char.UnicodeBlock -> Difficulty
238 difficulty ub = case ub of
239 Char.UnicodeBlockLatin{} ->
241 { difficultyModel = True
242 , difficultyHiddenPatterns = True
243 , difficultyReading =
245 { Reading.difficultyCharWidth = 1 & cm
246 , Reading.difficultyCharHeight = 1 & cm
247 , Reading.difficultyWordSpacing = 0.5 & cm
248 , Reading.difficultyFontSize = 0.7 & cm
251 Char.UnicodeBlockCJK{} ->
253 { difficultyModel = False
254 , difficultyHiddenPatterns = False
255 , difficultyReading =
257 { Reading.difficultyCharWidth = 1.5 & cm
258 , Reading.difficultyCharHeight = 1.5 & cm
259 , Reading.difficultyWordSpacing = 0.5 & cm
260 , Reading.difficultyFontSize = 1.20 & cm
263 Char.UnicodeBlockHalfwidth_and_Fullwidth_Forms{} ->
265 { difficultyModel = True
266 , difficultyHiddenPatterns = False
267 , difficultyReading =
269 { Reading.difficultyCharWidth = 1.35 & cm
270 , Reading.difficultyCharHeight = 1.35 & cm
271 , Reading.difficultyWordSpacing = 0.5 & cm
272 , Reading.difficultyFontSize = 1.10 & cm
275 Char.UnicodeBlockMiscellaneous_Technical{} ->
276 difficulty $ Char.UnicodeBlockLatin Char.UnicodeBlockLatin_Basic
279 rosettas :: Map String Pages
287 { partPicture = "Bateau/pirate-boat.avif"
289 HTML.cssBlockObjectFitCover
290 <> ["object-position" := "center -1.2cm"]
291 , partDescription = ""
292 , partLangue = LangueFrançais
293 , partText = "Un bateau flotte si moins dense que l’eau"
296 { partPicture = "Bateau/tanker.avif"
298 HTML.cssBlockObjectFitCover
299 <> ["object-position" := "center -2.5cm"]
300 , partDescription = ""
301 , partLangue = LangueAnglais
302 , partText = "A boat floats if less dense than water"
305 { partPicture = "Bateau/catamaran.avif"
307 HTML.cssBlockObjectFitCover
308 <> ["object-position" := "center -0.8cm"]
309 , partDescription = ""
310 , partLangue = LangueMandarin
311 , partText = "船 漂浮 如果 小 密度 于 水"
320 { partPicture = "Plantes/Cacao/Fruit-cacao-tree-source-cocoa-chocolate-plant.avif"
321 , partDescription = ""
322 , partLangue = LangueFrançais
323 , partText = "Le chocolat contient du cacao"
326 { partPicture = "Plantes/Cacao/42f651_95f537d693fb48068880a02efa662822~mv2.avif"
327 , partDescription = ""
328 , partLangue = LangueAnglais
329 , partText = "Chocolate contains cocoa"
332 { partPicture = "Plantes/Cacao/Chocolate-Ingredients_520x500_c496776e-df9b-4348-a662-5ff65279f5ca.avif"
333 , partDescription = ""
334 , partLangue = LangueMandarin
335 , partText = "巧克力 含有 可可"
340 , "chevauxDormirDebout"
344 { partPicture = "Cheval/R5.avif"
345 , partDescription = ""
346 , partLangue = LangueFrançais
347 , partText = "Les chevaux peuvent dormir debout"
350 { partPicture = "Cheval/Do-Horses-Lay-Down-to-Sleep.avif"
351 , partDescription = ""
352 , partLangue = LangueAnglais
353 , partText = "Horses can sleep standing up"
356 { partPicture = "Cheval/3YVGNyR45fw5NwHQxvJ8P6.avif"
357 , partDescription = ""
358 , partLangue = LangueMandarin
359 , partText = "马 可以 站 着 睡觉"
368 { partPicture = "Poney/Horse-and-pony2.avif"
369 , partPictureCSS = HTML.cssBlockObjectFitCover
370 , partDescription = ""
371 , partLangue = LangueFrançais
372 , partText = "Les poneys sont petits mais costauds"
375 { partPicture = "Poney/A-girl-equestrian-athlete-jumps-on-a-horse-high-barrier-ss230301-768x448.jpg.avif"
376 , partPictureCSS = HTML.cssBlockObjectFitCover
377 , partDescription = ""
378 , partLangue = LangueAnglais
379 , partText = "Ponies are small but strong"
382 { partPicture = "Poney/horse-pull.avif"
383 , partPictureCSS = HTML.cssBlockObjectFitCover
384 , partDescription = ""
385 , partLangue = LangueMandarin
386 , partText = "小马 虽 小 但 很 强壮"
395 { partPicture = "Poney/Shetland/Canva-Ponies-of-the-New-Forest-scaled.avif"
396 , partPictureCSS = HTML.cssBlockObjectFitCover
397 , partDescription = "Shetland Pony"
398 , partLangue = LangueFrançais
399 , partText = "Il existe environ 159 races de poneys"
402 { partPicture = "Poney/PoneyFrançaisDeSelle/pho11-1441004372-ulk-modele1.avif"
403 , partPictureCSS = HTML.cssBlockObjectFitCover
404 , partDescription = "Poney Français de Selle"
405 , partLangue = LangueAnglais
406 , partText = "There are approximately 159 pony breeds"
409 { partPicture = "Poney/NorwegianFjord/shutterstock_2092896190-1024x683.avif"
410 , partPictureCSS = HTML.cssBlockObjectFitCover
411 , partDescription = "Norwegian Fjord Pony"
412 , partLangue = LangueMandarin
413 , partText = "有 大约 159 个 小马 品种"
422 { partPicture = "Poney/Haflinger/GettyImages-546441489-3087a0a3f3a0486f96e7e6d7eb0b6bc1.avif"
423 , partPictureCSS = HTML.cssBlockObjectFitCover
424 , partDescription = "Haflinger Pony"
425 , partLangue = LangueFrançais
426 , partText = "Il existe environ 159 races de poneys"
429 { partPicture = "Poney/Dartmoor/GettyImages-149824058-ee7fd8a5e9984f5a9dc73c5916a238aa.avif"
430 , partPictureCSS = HTML.cssBlockObjectFitCover
431 , partDescription = "Dartmoor Pony"
432 , partLangue = LangueAnglais
433 , partText = "There are approximately 159 pony breeds"
436 { partPicture = "Poney/Connemara/eaa17d54a2978f5962edc405f0beabb7.avif"
437 , partPictureCSS = HTML.cssBlockObjectFitCover
438 , partDescription = "Connemara Pony"
439 , partLangue = LangueMandarin
440 , partText = "有 大约 159 个 小马 品种"
449 { partPicture = "Poney/AmericanQuarter/American-Quarter-Horse-stallion-1024x614.avif"
450 , partPictureCSS = HTML.cssBlockObjectFitCover
451 , partDescription = "American Quarter Pony"
452 , partLangue = LangueFrançais
453 , partText = "Il existe environ 159 races de poneys"
456 { partPicture = "Poney/Welsh/GettyImages-1318833798-1024x768.avif"
457 , partPictureCSS = HTML.cssBlockObjectFitCover
458 , partDescription = "Welsh Pony"
459 , partLangue = LangueAnglais
460 , partText = "There are approximately 159 pony breeds"
463 { partPicture = "Poney/PonyOfTheAmericas/GettyImages-519556294-1024x683.avif"
464 , partPictureCSS = HTML.cssBlockObjectFitCover
465 , partDescription = "Pony of the Americas"
466 , partLangue = LangueMandarin
467 , partText = "有 大约 159 个 小马 品种"
476 { partPicture = "Poney/Haflinger/041221-haflinger-3.avif"
477 , partPictureCSS = HTML.cssBlockObjectFitCover
478 , partDescription = "Haflinger Pony"
479 , partLangue = LangueFrançais
480 , partText = "Il existe environ 159 races de poneys"
483 { partPicture = "Poney/Eriskay/shutterstock-2214350479-huge-licensed-scaled.avif"
484 , partPictureCSS = HTML.cssBlockObjectFitCover
485 , partDescription = "Eriskay Pony"
486 , partLangue = LangueAnglais
487 , partText = "There are approximately 159 pony breeds"
490 { partPicture = "Poney/BritishRiding/GettyImages-175411286-1024x683.avif"
491 , partPictureCSS = HTML.cssBlockObjectFitCover
492 , partDescription = "British Riding Pony"
493 , partLangue = LangueMandarin
494 , partText = "有 大约 159 个 小马 品种"
503 { partPicture = "Culicoides/Blood-Feeding-Culicoides-Midges.avif"
504 , partPictureCSS = HTML.cssBlockObjectFitCover
505 , partLangue = LangueFrançais
506 , partText = "Les moucherons culicoides sont des vampires infectieuses"
509 { partPicture = "Culicoides/Mosquito_(Ochlerotatus_annulipes)_and_Midge_(Culicoides_impunctatus)_biting_human_(me).avif"
510 , partPictureCSS = HTML.cssBlockObjectFitCover
511 , partLangue = LangueAnglais
512 , partText = "Culicoides midges are infectious vampires"
515 { partPicture = "Culicoides/CSIRO_ScienceImage_1791_SEM_of_a_biting_midge_Culicoides_brevitarsis.avif"
516 , partPictureCSS = HTML.cssBlockObjectFitCover
517 , partLangue = LangueMandarin
518 , partText = "库蠓属 具有 传染性 的 吸血鬼"
527 { partPicture = "Fraise/96caabc77f79887c4bbcb2383092707b.avif"
528 , partLangue = LangueFrançais
529 , partText = "Les fruits de la fraise sont les akènes"
532 { partPicture = "Fraise/OIP.avif"
533 , partPictureCSS = HTML.cssBlockObjectFitCover
534 , partLangue = LangueAnglais
535 , partText = "Strawberry's fruits are the achenes"
538 { partPicture = "Fraise/Coupe_d'une_fraise_dont_les_akènes_ont_germés.avif"
539 , partLangue = LangueMandarin
540 , partText = "草莓 的 果实 是 瘦果"
549 { partPicture = "ArielleLaPetiteSirène/3aff97d2a3c36b307c12e7ea36e2000b.avif"
550 , partLangue = LangueFrançais
551 , partText = "Arielle la poupée et Merlin le garçon"
554 { partPicture = "ArielleLaPetiteSirène/halle-bailey-as-ariel-in-the-little-mermaid-zk-1280x2120.small.avif"
555 , partLangue = LangueAnglais
556 , partText = "Ariel the doll and Merlin the boy"
559 { partPicture = "Poupée/IMG_20250613_111606.avif"
560 , partLangue = LangueMandarin
561 , partText = "娃娃 Arielle 和 男孩 梅林"
570 { partPicture = "LaBelleEtLaBête/batbjpg-fe2293_1280w.avif"
571 , partLangue = LangueFrançais
572 , partText = "Bella la poupée et Maya la fille"
575 { partPicture = "LaBelleEtLaBête/disney-live-action-02.avif"
576 , partPictureCSS = HTML.cssBlockObjectFitCover
577 , partLangue = LangueAnglais
578 , partText = "Bella the doll and Maya the girl"
581 { partPicture = "Poupée/IMG_20250613_111730.avif"
582 , partLangue = LangueMandarin
583 , partText = "娃娃 Bella 和 女孩 马雅" -- 玛雅
592 { partPicture = "Mûre/Bee-Feeding-on-Blackberry-Blossom.avif"
593 , partPictureCSS = HTML.cssBlockObjectFitCover
594 , partLangue = LangueFrançais
595 , partText = "Les fruits de la mûre sont des drupéoles"
598 { partPicture = "Mûre/blackberry-anatomy.avif"
599 , partLangue = LangueAnglais
600 , partText = "Blackberry's fruits are drupelets"
603 { partPicture = "Mûre/berryblack.avif"
604 , partPictureCSS = HTML.cssBlockObjectFitCover
605 , partLangue = LangueMandarin
606 , partText = "黑莓 的 果实 是 小 核果"
615 { partPicture = "Framboise/ghows-SR-6c5aadd8-13b2-7679-e053-0100007f79b5-ad44228b.avif"
617 HTML.cssBlockObjectFitCover
618 <> ["object-position" := "left center"]
619 , partLangue = LangueFrançais
620 , partText = "Le réceptacle de la framboise reste accroché au buisson"
623 { partPicture = "Framboise/framboise-schema-fr.avif"
624 , partLangue = LangueAnglais
625 , partText = "Raspberry's receptacle clings to the bush"
628 { partPicture = "Framboise/OIP.avif"
630 HTML.cssBlockObjectFitCover
631 <> ["object-position" := "right bottom"]
632 , partLangue = LangueMandarin
633 , partText = "山莓 的 花托 紧贴 灌木丛"
642 { partPicture = "Cheval/Mustang/2.avif"
644 HTML.cssBlockObjectFitCover
645 <> ["object-position" := "left center"]
646 , partLangue = LangueFrançais
647 , partText = "La plupart des chevaux mustangs sont sauvages"
650 { partPicture = "Cheval/Mustang/10.avif"
652 HTML.cssBlockObjectFitCover
653 <> ["object-position" := "left center"]
654 , partLangue = LangueAnglais
655 , partText = "Most mustang horses are wild"
658 { partPicture = "Cheval/Mustang/6.avif"
660 HTML.cssBlockObjectFitCover
661 , partLangue = LangueMandarin
662 , partText = "大多数 美洲野马 是 野马"
667 , "TortueDeMerMigration"
671 { partPicture = "Tortue/tumblr_mxnwydKTfm1qm9k25o1_1280.avif"
673 HTML.cssBlockObjectFitCover
674 <> ["object-position" := "left center"]
675 , partLangue = LangueFrançais
676 , partText = "Les tortues de mer peuvent traverser un océan à la nage"
679 { partPicture = "Tortue/SWOT_XV_Global_Loggerhead_V3_20200220.crop.avif"
681 [ "object-fit" := "contain"
682 , "object-position" := "center center"
684 , partLangue = LangueAnglais
685 , partText = "Sea turtles can swim across an ocean"
688 { partPicture = "Tortue/sea-turtle8.avif"
689 , partPictureCSS = HTML.cssBlockObjectFitCover
690 , partLangue = LangueMandarin
691 , partText = "海龟 可以 游泳 横穿 海洋"
700 { partPicture = "Loup/197922.avif"
702 HTML.cssBlockObjectFitCover
703 , partLangue = LangueFrançais
704 , partText = "Les loups hurlent pour se rassembler ou pour alerter"
707 { partPicture = "Loup/portrait-of-arctic-wolf-free-photo.avif"
709 HTML.cssBlockObjectFitCover
710 , partLangue = LangueAnglais
711 , partText = "Wolves howl to reassemble or to alert"
714 { partPicture = "Loup/R.avif"
716 HTML.cssBlockObjectFitCover
717 , partLangue = LangueMandarin
718 , partText = "狼 嚎 以 团结 在一起 或 警告"
727 { partPicture = "Papillon/Brimstone/t0109e2365f058fa5bb.avif"
729 [ "object-fit" := "cover"
730 , "object-position" := "left center"
732 , partLangue = LangueFrançais
733 , partText = "Le papillon citron peut survivre à l'hiver"
736 { partPicture = "Papillon/Brimstone/brimstone_life_cycle_l.avif"
738 [ "object-fit" := "contain"
740 , partLangue = LangueAnglais
741 , partText = "The brimstone butterfly can survive the winter"
744 { partPicture = "Papillon/Brimstone/brimstone_characteristics_l.avif"
746 [ "object-fit" := "contain"
748 , partLangue = LangueMandarin
749 , partText = "钩粉蝶 可以 度过 冬天"
758 { partPicture = "Seasons/canadian-seasons-mircea-costina.jpg"
760 [ "object-fit" := "cover"
761 , "object-position" := "center center"
763 , partLangue = LangueFrançais
764 , partText = "L'été, le soleil chauffe longtemps et frontalement"
767 { partPicture = "Seasons/summer.avif"
769 [ "object-fit" := "cover"
771 , partLangue = LangueAnglais
772 , partText = "In summer, sun's warming is longest and most frontal"
775 { partPicture = "Seasons/winter.avif"
777 [ "object-fit" := "cover"
779 , partLangue = LangueMandarin
780 , partText = "夏季, 太阳 的 加热 最 长 且 最 正面"
789 { partPicture = "Christmas/Cici-Fang-Christmas-Consumerism-1-pdf.avif"
791 [ "object-fit" := "cover"
792 --, "object-position" := "center center"
794 , partLangue = LangueFrançais
795 , partText = "Noël est une fête de la consommation et de la fantaisie"
798 { partPicture = "Christmas/l_etrange_noel_de_monsieur_jack.avif"
800 [ "object-fit" := "cover"
802 , partLangue = LangueAnglais
803 , partText = "Christmas celebrates consumption and fantasy"
806 { partPicture = "Christmas/Olafs.Frozen.Adventure.2017.720p.BluRay.x264.AAC-[YTS.MX].mp4.00-09-29-527.avif"
808 [ "object-fit" := "cover"
809 , "object-position" := "-1.75cm center"
811 , partLangue = LangueMandarin
812 , partText = "圣诞节 庆祝会 消费量 和 幻想"
821 { partPicture = "Loup/wolf-raven.avif"
823 HTML.cssBlockObjectFitCover
824 , partLangue = LangueFrançais
825 , partText = [Right "Loups et Corbeaux jouent et chassent souvent ensemble"]
828 { partPicture = "Loup/Screen Shot 2013-08-19 at 10.38.26 PM.avif"
830 HTML.cssBlockObjectFitCover
831 , partLangue = LangueAnglais
832 , partText = [Right "Wolves and ravens often play and hunt together"]
835 { partPicture = "Loup/NPS_WolfMagpiesRavens_NOV16_HerbertNeal.avif"
837 HTML.cssBlockObjectFitCover
838 , partLangue = LangueMandarin
839 , partText = [Right "狼 和 乌鸦 经常 玩耍 和 狩猎 一起"]
848 { partPicture = "Crocodile/1562781.avif"
850 HTML.cssBlockObjectFitCover
851 , partLangue = LangueFrançais
852 , partText = "Les crocodiles versent des larmes en mangeant"
855 { partPicture = "Crocodile/Morelet's_Crocodile_(Crocodylus_moreletii)_big_male_attracting_Julia_Butterflies_(Dryas_iulia)_-_Rio_Usumacintla_Chiapas_2020.avif"
857 HTML.cssBlockObjectFitCover
858 , partLangue = LangueAnglais
859 , partText = "Crocodiles shed tears when eating"
862 { partPicture = "Crocodile/sn-crocodiletears.avif"
864 HTML.cssBlockObjectFitCover
865 , partLangue = LangueMandarin
866 , partText = "鳄鱼 流泪 吃 时"
872 -- https://www.nationalgeographic.com/animals/article/european-red-wood-ants-impact
876 { partPicture = "Fourmi/Ingo_Arndt_MM10190_045-1.avif"
878 HTML.cssBlockObjectFitCover
879 , partLangue = LangueFrançais
880 , partText = "Les fourmis rousses des bois sont des ingénieures"
883 { partPicture = "Fourmi/STOCKPKG_MM10190_230605_206.avif"
885 HTML.cssBlockObjectFitCover
886 , partLangue = LangueAnglais
887 , partText = "Red wood ants are forest engineers"
890 { partPicture = "Fourmi/STOCKPKG_MM10190_230515_192.avif"
892 HTML.cssBlockObjectFitCover
893 , partLangue = LangueMandarin
895 , partText = "红木 蚂蚁 是 森林 工程师"
904 { partPicture = "HayBales/30-33-Lead-Image.avif"
906 [ "object-fit" := "cover"
908 , partLangue = LangueFrançais
909 , partText = "Les balles de foin sont plastifiées pour fermenter"
912 { partPicture = "HayBales/_DSC3737_0.avif"
914 [ "object-fit" := "cover"
915 , "object-position" := "-0.7cm center"
917 , partLangue = LangueAnglais
918 , partText = "Hay bales are wrapped in plastic to ferment"
921 { partPicture = "HayBales/Figure-2-200-Heifers-feeding-from-multiple-bags.avif"
923 [ "object-fit" := "cover"
925 , partLangue = LangueMandarin
926 , partText = "干草 包裹 塑料 以便 发酵"
935 { partPicture = "Étoiles/SavudrijaSTARTRAILS_Nadj1024.avif"
937 [ "object-fit" := "cover"
938 , "object-position" := "left top"
940 , partLangue = LangueFrançais
941 , partText = "La Terre tourne chaque jour autour d'un axe stable"
944 { partPicture = "Étoiles/trails-geminids.avif"
946 [ "object-fit" := "cover"
947 , "object-position" := "left top"
949 , partLangue = LangueAnglais
950 , partText = "Earth spins each day around a stable axis"
953 { partPicture = "Étoiles/Earth_precession.svg.avif"
955 [ "object-fit" := "contain"
956 , "object-position" := "right center"
958 , partLangue = LangueMandarin
959 , partText = "地球 围绕 每天 稳定 轴旋转"
968 { partPicture = "Étoiles/Iotw2246a_-_Beginning_to_End_of_a_Total_Lunar_Eclipse.avif"
970 [ "object-fit" := "cover"
971 , "object-position" := "left top"
973 , partLangue = LangueFrançais
974 , partText = "La Terre tourne chaque jour autour d'un axe stable"
977 { partPicture = "Étoiles/Star-trail-of-planets1067.avif"
979 [ "object-fit" := "cover"
980 , "object-position" := "left top"
982 , partLangue = LangueAnglais
983 , partText = "Earth spins each day around a stable axis"
986 { partPicture = "Étoiles/shows-precession-of-earth-which-cause-repetitions-of-climate-patterns-for-a-period-of.avif"
988 [ "object-fit" := "contain"
989 , "object-position" := "center center"
991 , partLangue = LangueMandarin
993 , partText = "地球 围绕 每天 稳定 轴旋转"
1002 { partPicture = "Arrosoir/OIP.avif"
1004 [ "object-fit" := "cover"
1006 , partLangue = LangueFrançais
1007 , partText = "Utiliser un arrosoir est une corvée technique"
1010 { partPicture = "Arrosoir/sub-buzz-1301-1687548112-1.avif"
1012 [ "object-fit" := "contain"
1014 , partLangue = LangueAnglais
1015 , partText = "Using a watering can is a technical chore"
1018 { partPicture = "Arrosoir/Watering-seedlings-with-a-pop-bottle-watering-can-1024x768.avif"
1020 [ "object-fit" := "cover"
1022 , partLangue = LangueMandarin
1023 , partText = "使用 浇水 壶 是 技术 例行 工作"
1032 { partPicture = "Fireworks/brian_titone_53841_1_262503.avif"
1034 [ "object-fit" := "cover"
1035 , "object-position" := "center top"
1037 , partLangue = LangueFrançais
1038 , partText = "Un feu d'artifice pollue l'air, l'eau et le sol"
1041 { partPicture = "Fireworks/The+Hidden+Science+of+Fireworks+-+Veritasium.avif"
1043 [ "object-fit" := "contain"
1044 , "object-position" := "center center"
1046 , partLangue = LangueAnglais
1047 , partText = "Fireworks are bombs polluting the air, water and soil"
1050 { partPicture = "Fireworks/2023-07-07 - The Hidden Science of Fireworks.lfkjm2YRG-Q.398+251.webm.00-20-58-624.avif"
1052 [ "object-fit" := "cover"
1053 , "object-position" := "center center"
1055 , partLangue = LangueMandarin
1056 , partText = "烟花 是 炸弹 污染 空气、水 和 土壤"
1067 { partPicture = "Renard/ArticFox/200512612-001-56a006345f9b58eba4ae8b10.avif"
1069 [ "object-fit" := "cover"
1071 , partDescription = "Artic Fox"
1072 , partLangue = LangueFrançais
1073 , partText = [Right "Il y a 12 espèces et 45 sous-espèces de renards"]
1076 { partPicture = "Renard/SwiftFox/shutterstock-46600522.avif"
1077 , partDescription = "Swift Fox"
1078 , partPictureCSS = [ "object-fit" := "cover" ]
1079 , partLangue = LangueAnglais
1080 , partText = [Right "There are at least 12 species and 45 subspecies of foxes"]
1083 { partPicture = "Renard/RedFox/v2.avif"
1084 , partDescription = "Red Fox"
1086 [ "object-fit" := "cover"
1088 , partLangue = LangueMandarin
1089 , partText = [Right "有 至少 12 种 和 45 亚种 狐狸"]
1097 { partPicture = "Renard/CorsacFox/029f945789fcc419f8f637a93917278b.avif"
1099 [ "object-fit" := "cover"
1100 , "object-position" := "0 -0.1cm"
1102 , partDescription = "Corsac Fox"
1103 , partLangue = LangueFrançais
1104 , partText = [Right "Il y a 12 espèces et 45 sous-espèces de renards"]
1107 { partPicture = "Renard/BlandfordFox/2-blanfords-fox-vulpes-cana-eyal-bartov.avif"
1109 [ "object-fit" := "cover"
1111 , partDescription = "Blandford's Fox"
1112 , partLangue = LangueAnglais
1113 , partText = [Right "There are at least 12 species and 45 subspecies of foxes"]
1116 { partPicture = "Renard/CapeFox/shutterstock-220059658.avif"
1118 [ "object-fit" := "cover"
1120 , partDescription = "Cape Fox"
1121 , partLangue = LangueMandarin
1122 , partText = [Right "有 至少 12 种 和 45 亚种 狐狸"]
1133 { partPicture = "Fireworks/skyrocket-collage-background-571127103-8430996ece5d423da30046df82620b4f.avif"
1135 [ "object-fit" := "cover"
1136 , "object-position" := "center top"
1138 , partLangue = LangueFrançais
1139 , partText = [Right "Un feu d'artifice pollue l'air, l'eau et le sol"]
1142 { partPicture = "Fireworks/The+Hidden+Science+of+Fireworks+-+Veritasium.avif"
1144 [ "object-fit" := "contain"
1145 , "object-position" := "center center"
1147 , partLangue = LangueAnglais
1148 , partText = [Right "Fireworks are bombs polluting", Left (" the ", LexemePron "ðiː" []), Right "air, water and soil"]
1151 { partPicture = "Fireworks/2023-07-07 - The Hidden Science of Fireworks.lfkjm2YRG-Q.398+251.webm.00-21-12-705.avif"
1153 [ "object-fit" := "cover"
1154 , "object-position" := "center center"
1156 , partLangue = LangueMandarin
1157 , partText = [Right "烟花 是 炸弹 污染 空气、水 和 土壤"]
1166 { partPicture = "Arbre/R3.avif"
1168 [ "object-fit" := "cover"
1169 , "object-position" := "center bottom"
1171 , partLangue = LangueFrançais
1172 , partText = [Right "Un pommier contre-attaque en changeant d'odeur"]
1175 { partPicture = "Arbre/_14250.avif"
1177 [ "object-fit" := "cover"
1178 , "object-position" := "center center"
1180 , partLangue = LangueAnglais
1181 , partText = [Right "An apple tree strikes back by changing its smell"]
1184 { partPicture = "Arbre/5485248248_7e7244f769_b.crop.avif"
1186 [ "object-fit" := "cover"
1187 , "object-position" := "left center"
1189 , partLangue = LangueMandarin
1190 , partText = [Right "苹果 树 变 味 为了 反击"]
1201 [ "object-fit" := "cover"
1202 , "object-position" := "center bottom"
1204 , partLangue = LangueFrançais
1205 , partText = [Right ""]
1210 [ "object-fit" := "cover"
1211 , "object-position" := "center center"
1213 , partLangue = LangueAnglais
1214 , partText = [Right ""]
1219 [ "object-fit" := "cover"
1220 , "object-position" := "left center"
1222 , partLangue = LangueMandarin
1223 , partText = [Right ""]
1234 { partPicture = "LOTR/TheHobbit/bilbo-baggins-dwarves-gandalf.avif"
1236 [ "object-fit" := "cover"
1237 , "object-position" := "center -5.3cm"
1239 , partLangue = LangueAnglais
1240 , partText = [Right "Far over the Misty Mountains cold"]
1243 { partPicture = "LOTR/TheHobbit/Una_tertulia_inesperada_3.avif"
1245 [ "object-fit" := "cover"
1246 , "object-position" := "center -0.4cm"
1248 , partLangue = LangueAnglais
1249 , partText = [Right "To dungeons deep and caverns old"]
1252 { partPicture = "LOTR/TheHobbit/bilbo-baggins11.avif"
1254 [ "object-fit" := "cover"
1255 , "object-position" := "center center"
1257 , partLangue = LangueAnglais
1258 , partText = [Right "We must away, ere break of day"]
1261 { partPicture = "LOTR/TheHobbit/b8e91bf011890c7602faa4d6c2e00275.avif"
1263 [ "object-fit" := "cover"
1264 , "object-position" := "center center"
1266 , partLangue = LangueAnglais
1267 , partText = [Right "To seek our pale enchanted gold"]