本文へスキップ
レシピ番号169

レシピ集 · 第12章 · 教科書

1枚のプリントを10の国の学校の流儀で

同じ7つの :::exercise を10の言語で組みます。各版は、その国の教科書が問題を組むやり方にならった問題スタイルで印刷します。

このページの内容
出力
Canvas · PDF
レベル
中級
Postext
Postext 1.59.0で検証済み
1.59.0以上が必要 · postext-pdf ≥ 1.59.0
ライセンス
2026年10月24日更新
コードMIT · 本文CC BY 4.0

1ページ(全2ページ)

  • 仕上がり210 × 297 mm
  • 1段
  • Klee One 12/18
  • Noto Sans JP
  • 2ページ
  • レベル
  • Postext 1.59.0
  • 組版時間16 ms
  • コード154行

かんたんな説明

水のめぐりを扱う2ページの理科と算数のプリントを、10回作ります。問題はどれも同じで、番号、答えのわく、書く線、わり算の筆算が、それぞれの国の教科書と同じ見た目になります。

できあがり

小学4年の理科と算数の講座から、プリント7「水のたび」を10の版で組みます。問題はどの言語でも同じです。答えを選び、正しいかどうかを答え、語群のことばで穴をうめ、ことばと意味を線で結び、ことばを丸で囲み、水そうの水を分け、水を節約するわけを書きます。各版は、その国の学校のやり方で印刷します。スペイン語版とカタルーニャ語版は番号を丸に入れ、V か F に印をつけさせ、わる数をわられる数の右の L 字の中に置いてわり算をします。フランス語版は四角の番号、cases à cocher、点線の空らん、答えを書く Seyès の紙を使います。ドイツ語版は R と F、Lückentext、1行で書く 864 : 4 =、点で書くかけ算です。ブラジル版はかっこの中に V か F を書かせます。英語版は ⟌ の下でわり算をします。中国語版は大問を「一、二、」と数え、問題文のあとに( )を置いて A. B. C. を横に並べ、√ か × を書かせ、最後は田字格に書く「看拼音,写词语」です。日本語版はア イ ウと○×を使い、アラビア語版は右から左へ進んで、أ ب ج と صح か خطأ を使います。

このレシピが答える質問

  • 同じプリントを、国ごとの教科書の問題の組み方で組むには?
  • わり算の筆算を国ごとの学校の書き方で組むには?
  • 中国語の選択問題(問の後の( )と一行に並ぶ A. B. C. D.)はどう組む?

手短な答え

script.js · 36〜69行コード全体で見る
// 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

材料

種類
Nunito, Baloo 2, Noto Serif SC, Noto Sans SC, Klee One, Noto Sans JP, Noto Naskh Arabic, Baloo Bhaijaan 2 (SIL OFL 1.1)
素材
なし:画像はすべてコードで描画

作り方

#1 · 国ごとの流儀を表にまとめる

script.js · 36〜69行コード全体で見る
// 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

どの版も Markdown は同じです。7つの :::exercise があり、答えは本文に書いてあります(- [x]、[[水じょう気]]、- じょう発 -> 水が水じょう気になる、- 864 ÷ 4)。国によって違うのは形なので、形はこの表にだけ置きます。番号の形と数字、選択肢の記号、子どもがわくに印をつけるか記号を丸で囲むか、○×の見た目、空らんの見た目、書く場所、わり算の筆算の並べ方です。カタルーニャ語版はスペイン語版の行をそのまま使います。

#2 · 共通のスタイルに国の流儀を重ねる

script.js · 73〜87行コード全体で見る
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),
};

問題スタイルは ficha ひとつだけです。10枚に共通するもの(番号の青、灰色の罫線、問題と問題のあいだのあき)をこのスタイルが持ち、その上に版ごとの行を重ねます。行に書いていないことは言語が決めます。T F、V F、R F、√ ×、○ ×、صح خطأ はエンジンがもともと持っていることばで、a) b) c)、A. B. C.、ア イ ウ、أ ب ج も同じなので、どの版も自分では書きません。

#3 · 文字ごとに書体を決める

script.js · 27〜32行コード全体で見る
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];

ラテン文字の版は Nunito と Baloo 2 を共有します。中国語版は本文を宋体、問題文を黒体で組みます。日本語版は本文を教科書体の Klee One、問題文をゴシック体で組み、アラビア語版は Noto Naskh Arabic を使います。Klee One のいちばん太いウェイトは 600 なので、日本語版は太字を 600 にします(boldFontWeight)。700 にするとブラウザーが太字を描き足し、キャプチャーが失敗します。

#4 · プリントの頭に名前を書く線を置く

script.js · 91〜110行コード全体で見る
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),
] } };

レベル1の見出しが、帯、frontmatter から取った講座名、題、線のついた2つの欄を描きます。欄のことばは見出しの属性から取ります(nombre="名前" fecha="日付")。そのため、コードに文字列をひとつも書かなくても、ドイツ語版には Datum、日本語版には「名前」と出ます。

レシピの全体

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 = 'ja'; // @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' },

組み立てたscript.jsはそのまま動きます。任意のページのモジュールスクリプトに貼り付けるか、レシピをCodePenで開いてください。 GitHub上のレシピのフォルダー ↗ (新しいタブで開きます)

アレンジ

#先生用の答え入りを印刷する

答えはすべて、マゼンタでそれぞれの場所に入ります。かっこ、わく、空らん、わり算の商です。

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

#答えをプリントの下にまとめる

placement: 'after' は各問題の答えをその下に置きます。'inverted' はパズルのページのように、答えを上下さかさまにします。

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

よくあるつまずき

  • 700 のウェイトがない書体では、問題番号の太字が合成されたものになります。そのような本文の書体には、実際にあるウェイトを boldFontWeight で指定します。
  • 日本語の問題文の○と中国語の問題文の√は、CJK の書体にしかありません。ラテン文字のラベルではなく、CJK の本文の文の中に置きます。

クレジット

レシピ
Ignacio Ferro
本文
書き下ろしの文章, CC BY 4.0
フォント
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