Aller au contenu principal
Recette numéro 169

Recettes · Chapitre 12 · Manuels scolaires

Une fiche d’exercices en dix traditions scolaires

Les sept mêmes blocs :::exercise en dix langues, chaque édition mise en page par un style d’exercice fidèle aux manuels scolaires de son pays.

Sur cette page
Sortie
Canvas · PDF
Postext
Testé avec Postext 1.59.0
Nécessite ≥ 1.59.0 · postext-pdf ≥ 1.59.0
Licence
Mis à jour le 24 oct. 2026
Code MIT · Texte CC BY 4.0
  • Format 210 × 297 mm
  • 1 colonne
  • Nunito 12/18
  • Baloo 2
  • 2 pages
  • Niveau
  • Postext 1.59.0
  • Mis en page en 90 ms
  • 154 lignes de code

En bref

Une fiche de sciences et de maths de deux pages sur le cycle de l’eau, faite dix fois. Les questions sont les mêmes ; les numéros, les cases, les lignes d’écriture et la division ressemblent à ceux des manuels de chaque pays.

Ce que vous allez composer

La fiche 7 d’un cours de sciences et de mathématiques de CM1, Le voyage de l’eau, en dix éditions. Les questions sont les mêmes dans toutes les langues : choisir une réponse, cocher vrai ou faux, compléter un texte à trous avec une liste de mots, relier des mots à leur définition, entourer un mot, partager l’eau d’une citerne, expliquer pourquoi il faut l’économiser. Chaque édition les imprime comme le font ses écoles. Les fiches espagnole et catalane mettent le numéro dans un disque, font cocher V ou F et posent la division avec le diviseur dans un L à droite du dividende. La française met ses numéros dans des carrés et utilise des cases à cocher, des pointillés pour les trous et une réglure Seyès pour la réponse. L’allemande écrit R et F, Lückentext et 864 : 4 = sur une ligne, avec un point pour la multiplication. La brésilienne demande V ou F entre parenthèses. L’anglaise divise sous le crochet ⟌. La chinoise numérote ses parties 一、二、, place ( ) après chaque énoncé avec A. B. C. sur une ligne, demande √ ou × et finit par 看拼音,写词语 dans des cases 田字格. La japonaise propose ア イ ウ et ○ ×, et l’arabe se lit de droite à gauche avec أ ب ج et صح ou خطأ.

Cette recette répond à

  • Comment composer la même fiche comme les manuels de chaque pays composent leurs exercices ?
  • Comment composer la division posée comme l'écrivent les écoles de chaque pays ?
  • Comment composer des questions d'examen chinois : des parenthèses ( ) après l'énoncé et les options A. B. C. D. sur une ligne ?

La réponse courte

script.js · lignes 36–69dans le code complet
// The Markdown of every edition has the same seven exercises. What changes is this table:
// how the number prints, how options are labelled and answered, how true/false reads, where
// a blank is written, the paper of the open answer and the layout of long division.
const disc = { shape: 'disc' };
const square = { shape: 'square' };
const bare = { shape: 'none', suffix: '.' };
const TRADITIONS = {
  es: { number: disc, options: { marker: 'none' }, trueFalse: { look: 'boxes' },
    blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'potence' } },
  fr: { number: square, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
    blank: { look: 'dots' }, area: { kind: 'seyes', spacing: mm(8) },
    arithmetic: { division: 'potence' } },
  de: { number: square, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
    blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'inline' } },
  it: { number: { shape: 'rounded' }, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
    blank: { look: 'dots' }, area: { kind: 'lines' }, arithmetic: { division: 'potence' } },
  pt: { number: bare, options: { marker: 'none' }, trueFalse: { look: 'bracket' },
    blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'potence' } },
  en: { number: bare, options: { marker: 'none' }, trueFalse: { look: 'boxes' },
    blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'bracket' } },
  // 一、二、 sections; ( ) after the stem and A. B. C. in a row; √ × in a bracket; 田字格.
  zh: { number: { shape: 'none', format: 'simp-chinese-informal', suffix: '、' },
    options: { labels: 'alpha-upper', suffix: '.', layout: 'row', bracket: true },
    trueFalse: { look: 'bracket' }, blank: { look: 'line' },
    area: { kind: 'tianzige', spacing: mm(13), lines: 1 }, arithmetic: { division: 'bracket' } },
  // ア イ ウ in a row with ( ), ○ × in a bracket, the number in a square.
  ja: { number: square, options: { labels: 'katakana', suffix: '', layout: 'row', bracket: true },
    trueFalse: { look: 'bracket' }, blank: { look: 'line' }, area: { kind: 'lines' },
    arithmetic: { division: 'bracket' } },
  ar: { number: disc, options: { marker: 'none', prefix: '(', suffix: ')' },
    trueFalse: { look: 'boxes' },
    blank: { look: 'dots' }, area: { kind: 'lines' }, arithmetic: { division: 'bracket' } },
};
TRADITIONS.ca = TRADITIONS.es; // Catalan schools set exercises as Spanish ones do

Ingrédients

Typographie
Nunito, Baloo 2, Noto Serif SC, Noto Sans SC, Klee One, Noto Sans JP, Noto Naskh Arabic, Baloo Bhaijaan 2 (SIL OFL 1.1)
Ressources
Aucune : chaque image est dessinée en code

Préparation

#1 · Mettre chaque tradition dans un tableau

script.js · lignes 36–69dans le code complet
// The Markdown of every edition has the same seven exercises. What changes is this table:
// how the number prints, how options are labelled and answered, how true/false reads, where
// a blank is written, the paper of the open answer and the layout of long division.
const disc = { shape: 'disc' };
const square = { shape: 'square' };
const bare = { shape: 'none', suffix: '.' };
const TRADITIONS = {
  es: { number: disc, options: { marker: 'none' }, trueFalse: { look: 'boxes' },
    blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'potence' } },
  fr: { number: square, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
    blank: { look: 'dots' }, area: { kind: 'seyes', spacing: mm(8) },
    arithmetic: { division: 'potence' } },
  de: { number: square, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
    blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'inline' } },
  it: { number: { shape: 'rounded' }, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
    blank: { look: 'dots' }, area: { kind: 'lines' }, arithmetic: { division: 'potence' } },
  pt: { number: bare, options: { marker: 'none' }, trueFalse: { look: 'bracket' },
    blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'potence' } },
  en: { number: bare, options: { marker: 'none' }, trueFalse: { look: 'boxes' },
    blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'bracket' } },
  // 一、二、 sections; ( ) after the stem and A. B. C. in a row; √ × in a bracket; 田字格.
  zh: { number: { shape: 'none', format: 'simp-chinese-informal', suffix: '、' },
    options: { labels: 'alpha-upper', suffix: '.', layout: 'row', bracket: true },
    trueFalse: { look: 'bracket' }, blank: { look: 'line' },
    area: { kind: 'tianzige', spacing: mm(13), lines: 1 }, arithmetic: { division: 'bracket' } },
  // ア イ ウ in a row with ( ), ○ × in a bracket, the number in a square.
  ja: { number: square, options: { labels: 'katakana', suffix: '', layout: 'row', bracket: true },
    trueFalse: { look: 'bracket' }, blank: { look: 'line' }, area: { kind: 'lines' },
    arithmetic: { division: 'bracket' } },
  ar: { number: disc, options: { marker: 'none', prefix: '(', suffix: ')' },
    trueFalse: { look: 'boxes' },
    blank: { look: 'dots' }, area: { kind: 'lines' }, arithmetic: { division: 'bracket' } },
};
TRADITIONS.ca = TRADITIONS.es; // Catalan schools set exercises as Spanish ones do

Toutes les éditions ont le même Markdown : sept blocs :::exercise dont les réponses sont dans le texte (- [x], [[vapeur]], - Évaporation -> L'eau devient vapeur, - 864 : 4). Ce qui change d’un pays à l’autre, c’est la forme, et elle vit dans ce tableau et nulle part ailleurs : la forme et les chiffres du numéro, les lettres des options et le geste de l’élève (cocher une case ou entourer une lettre), l’aspect du vrai ou faux, celui des trous, la zone d’écriture et la disposition de la division. Le catalan reprend telle quelle la ligne de l’espagnol.

#2 · Poser la tradition sur le style de la maison

script.js · lignes 73–87dans le code complet
const T = TRADITIONS[LANG];
const ficha = {
  id: 'ficha', ...T,
  number: { background: col('accent'), color: T.number.shape === 'none' ? col('accent')
    : col('paper'), fontFamily: LABEL, fontWeight: 700, ...T.number },
  // Chinese and Japanese sheets set the instructions in the gothic (黑体, ゴシック).
  instruction: { bold: true, color: col('ink'), ...(LANG === 'zh' || LANG === 'ja'
    ? { fontFamily: LABEL } : {}) },
  blank: { color: col('ink'), weight: pt(0.7), ...T.blank },
  match: { look: 'dots', gap: em(5), color: col('accent') },
  bank: { order: 'alpha' },
  area: { color: col('rule'), spacing: mm(9), weight: pt(0.6), ...T.area },
  grid: { cell: mm(8.5), fontFamily: TEXT, rule: col('rule'), color: col('ink') },
  marginTop: mm(7), marginBottom: mm(1), itemSpacing: em(0.4),
};

Un seul style d’exercice, ficha, porte ce que les dix fiches ont en commun (le bleu des numéros, les filets gris, l’espace entre les exercices), et la ligne de l’édition se pose par-dessus. Ce que la ligne ne précise pas vient de la langue : T F, V F, R F, √ ×, ○ × et صح خطأ sont des mots du moteur lui-même, comme a) b) c), A. B. C., ア イ ウ et أ ب ج, si bien qu’aucune édition ne les écrit.

#3 · Donner à chaque écriture ses polices

script.js · lignes 27–32dans le code complet
const FACES = {
  zh: { text: 'Noto Serif SC', label: 'Noto Sans SC' },
  ja: { text: 'Klee One', label: 'Noto Sans JP' },
  ar: { text: 'Noto Naskh Arabic', label: 'Baloo Bhaijaan 2' },
}[LANG] ?? { text: 'Nunito', label: 'Baloo 2' };
const [TEXT, LABEL] = [FACES.text, FACES.label];

Les éditions en alphabet latin partagent Nunito et Baloo 2. La fiche chinoise compose le texte en Song et les consignes en Hei ; la japonaise compose le texte en Klee One, une police de manuel scolaire, et les consignes dans une gothique ; l’arabe utilise Noto Naskh Arabic. La graisse la plus forte de Klee One est 600, donc l’édition japonaise règle son gras à 600 (boldFontWeight) : un 700 serait dessiné par le navigateur et ferait échouer la capture.

#4 · Mettre en tête de la fiche des lignes pour le nom

script.js · lignes 91–110dans le code complet
const at = (to, edge, x = 0, y = 0, size) => ({ anchor: { to, edge },
  offset: { x: mm(x), y: mm(y) }, ...(size && { size }) });
const field = (id, attr, x, width) => [
  { kind: 'text', id, content: `{attr.${attr}}`, fontFamily: LABEL, fontSize: pt(10),
    fontWeight: 700, color: col('muted'), align: 'left', placement: at('container', 'top-left',
      x, 28) },
  { kind: 'rule', id: `${id}-line`, direction: 'horizontal', thickness: pt(0.75),
    color: col('rule'), placement: at('container', 'top-left', x + 16, 33, { width: mm(width) }) },
];
const head = { enabled: true, minHeight: mm(38), slot: { elements: [
  { kind: 'box', id: 'band', style: { backgroundColor: col('accent'), borderRadius: mm(3) },
    placement: at('container', 'top-left', 0, 0, { width: 'fill', height: mm(21) }) },
  { kind: 'text', id: 'kicker', content: '{title} · {subtitle}', fontFamily: LABEL,
    fontSize: pt(8.5), fontWeight: 700, color: col('tint'), align: 'left',
    placement: at('container', 'top-left', 6, 3.5) },
  { kind: 'text', id: 'title', content: '{titleText}', fontFamily: LABEL, fontSize: pt(22),
    fontWeight: 700, color: col('paper'), align: 'left', lineHeight: 1.1,
    placement: at('container', 'top-left', 6, 9.5) },
  ...field('name', 'nombre', 0, 96), ...field('date', 'fecha', 120, 40),
] } };

Le titre de niveau 1 dessine le bandeau, le cours tiré du frontmatter et le titre, ainsi que deux champs sur une ligne dont les mots viennent des attributs du titre (nombre="Prénom" fecha="Date"). La fiche allemande dit donc Datum et la japonaise 名前 sans une seule chaîne dans le code.

La recette complète

Sandbox
// ═══ Postext Cookbook · Nº 169 · One worksheet in ten school traditions ═════════
// https://postext.dev/en/cookbook/school-traditions-worksheet
// Code: MIT · Text: original (CC BY 4.0) · Pictures: none
// Fonts: Nunito, Baloo 2, Klee One, Noto Naskh Arabic and others (SIL OFL) · Needs postext ≥ 1.59.0
import {
  buildDocument, withLoadedFonts, renderPageToCanvas,
} from 'https://esm.sh/postext';
import { renderToPdf, decompressWoff2 } from 'https://esm.sh/postext-pdf';

const LANG = 'fr'; // @lang: the language of the worksheet (en es ca fr de it pt zh ja ar)
const RECIPE = 'school-traditions-worksheet';

// ─── 1 · Design ─────────────────────────────────────────────────────────────
// #region palette: a blue-black ink, one blue accent, a pale tint, grey rules
const palette = {
  ink: '#1d2633', accent: '#2a5d9f', tint: '#e8f0fa', rule: '#a9b6c6', muted: '#5d6878',
  paper: '#ffffff',
};
const col = (id) => ({ hex: palette[id], model: 'hex', paletteId: id });
const colorPalette = [
  ...Object.entries(palette).map(([id, hex]) => ({ id, name: id, value: { hex, model: 'hex' } })),
  { id: 'main-color', name: 'accent (defaults)', value: { hex: palette.accent, model: 'hex' } },
];
// #endregion

// #region faces: Latin editions share two faces; Chinese, Japanese and Arabic their own
const FACES = {
  zh: { text: 'Noto Serif SC', label: 'Noto Sans SC' },
  ja: { text: 'Klee One', label: 'Noto Sans JP' },
  ar: { text: 'Noto Naskh Arabic', label: 'Baloo Bhaijaan 2' },
}[LANG] ?? { text: 'Nunito', label: 'Baloo 2' };
const [TEXT, LABEL] = [FACES.text, FACES.label];
// #endregion

// #region answer: the form of the exercises, as each country's school books set them
// The Markdown of every edition has the same seven exercises. What changes is this table:
// how the number prints, how options are labelled and answered, how true/false reads, where
// a blank is written, the paper of the open answer and the layout of long division.
const disc = { shape: 'disc' };
const square = { shape: 'square' };
const bare = { shape: 'none', suffix: '.' };
const TRADITIONS = {
  es: { number: disc, options: { marker: 'none' }, trueFalse: { look: 'boxes' },
    blank: { look: 'line' }, area: { kind: 'lines' }, arithmetic: { division: 'potence' } },
  fr: { number: square, options: { marker: 'box' }, trueFalse: { look: 'boxes' },
    blank: { look: 'dots' }, area: { kind: 'seyes', spacing: mm(8) },
    arithmetic: { division: 'potence' } },
  de: { number: square, options: { marker: 'box' }, trueFalse: { look: 'boxes' },

Le script.js composé s’exécute tel quel : collez-le dans le script de module de n’importe quelle page, ou ouvrez la recette sur CodePen. Dossier de la recette sur GitHub ↗ (s’ouvre dans un nouvel onglet)

Variantes

#Imprimer l’exemplaire du maître

Chaque réponse va à sa place en magenta : les parenthèses, les cases, les trous et le quotient.

   exerciseStyles: [ficha],
+  exercises: { edition: 'teacher' },

#Regrouper les réponses en bas de la fiche

placement: 'after' place le corrigé de chaque exercice sous celui-ci ; 'inverted' le retourne tête en bas, comme dans les pages de jeux.

+  exercises: { solutions: { placement: 'inverted', layout: 'key' } },

Erreurs fréquentes

  • Une police sans graisse 700 donne aux numéros des énoncés un gras synthétique. Donnez à une telle police de texte un boldFontWeight avec une graisse qu’elle possède.
  • Le ○ des consignes japonaises et le √ des consignes chinoises n’existent que dans les polices CJK : placez-les dans une phrase du texte CJK, pas dans une étiquette latine.

Crédits

Texte
Texte original, CC BY 4.0
Polices
Nunito (SIL OFL 1.1) · Baloo 2 (SIL OFL 1.1) · Noto Serif SC (SIL OFL 1.1) · Noto Sans SC (SIL OFL 1.1) · Klee One (SIL OFL 1.1) · Noto Sans JP (SIL OFL 1.1) · Noto Naskh Arabic (SIL OFL 1.1) · Baloo Bhaijaan 2 (SIL OFL 1.1)
SandboxPDF