Read a leaflet in another language or currency
A leaflet check reads what the chain prints: the big price, the pack size, the small unit price line, the discount badge. Czech leaflets print 129,90 Kč and 1 kg = 259,80 Kč. A Slovak chain prints 1,69 € and jednotková cena 2,25 EUR/l. A Polish one will print something else again. None of that is a different product — it is a different recipe, and every one of those conventions is a setting on it.
It is not only language and money. Two Czech chains a mile apart print the same koruna in two different ways: one sets 129 large with a raised 90 beside it, the next sets the whole 19,90 as one figure with the comma inside it. One quotes every unit price per kilogram, the next quotes crisps per 100 g and beer per litre on facing pages. Those are recipe settings too, and they are in this guide.
This guide is for the moment a chain arrives whose leaflet Routario has never seen: what to look at on the page, which recipe setting each thing maps to, and what happens when you leave a setting blank. You will not touch code, and you do not need a source table — a leaflet on its own is enough to check its own arithmetic.
Where the settings live
Section titled “Where the settings live”Open the recipe under the gear on the Match home. The Reading the sources section, in the recipe’s Sources area, lists every reading decision with the reason it is set the way it is. A recipe maintained by Routario is tuned in place — change what you need and save; your workspace keeps only what you changed, and our later fixes still reach the rest — as described in Recipes.
Below, each setting is named the way it appears in the recipe. Blank means the default.
| Setting | What it says | Default |
|---|---|---|
currency | The currency the leaflet prints, as a code: EUR, CZK, PLN. | Your workspace’s main currency; if none is marked, Czech koruna. |
currency_marks | How that currency is written on the page: € and EUR, or Kč, Kc (a font without the č) and CZK. The first one is what findings quote. | Derived from the currency, with your workspace’s own symbol first. |
unit_price_min_gap | How far apart a printed and a recomputed unit price may be before it is a finding rather than rounding. | 0,50 for koruna-sized currencies, 0,02 for euro-sized ones. |
money_decimals | How many decimal places this chain’s money is printed to. Set it and a reference price typeset with any other number of them is reported in its own right. | off |
Why unit_price_min_gap matters: half a koruna absorbs rounding on a per-kilogram price in the hundreds. Half a euro on a 2,41 €/l unit price would swallow the very mistake the check exists for — 2,41 printed where 2,25 is right is only 0,16 apart. The same is true of a chain quoting per 100 g: those figures are small, so its recipe sets one haler.
And why money_decimals is worth setting: a decimal place too many is invisible on the page and loud in the arithmetic. One leaflet printed běžná cena 65,990 beside a 29,90, and the badge over it read -95 % — which is what you get from 659,90, and nothing like the -55 % the tile actually offers. Without this setting the reference is not read at all, and the tile loses its badge check along with the typo.
How the price itself is set
Section titled “How the price itself is set”| Setting | What it says | Default |
|---|---|---|
price_comma_single_span | The whole price is one figure with the decimal comma inside it — 19,90 — rather than a large integer with raised halere beside it. | off |
price_font_markers | Substrings of the font names the price figures are set in. | Bold |
price_min_size | The type size at which a figure is a headline price rather than a struck one. | 17 pt |
Leave the first one off and a chain that sets its price this way reads as having no prices at all — no tiles, no findings, and nothing on screen to say why. It is off by default rather than always on because the same shape is what a caption’s 0,7 l looks like, and on a chain with raised halere that would mint prices out of pack sizes.
The unit-price line
Section titled “The unit-price line”| Setting | What it says | Default |
|---|---|---|
unit_line_pattern | The exact wording of the unit-price line, as a pattern with two named parts: the figure (val) and the unit (unit); optionally a “from” word (od) and the currency mark (cur). One pattern, or a list when the chain prints the line more than one way. | The Czech shape, 1 kg = 89,80 Kč, in your currency’s marks. |
unit_line_alt_pattern | Whether a bare figure with the currency mark on the caption is a second unit price — the Czech club / non-club twin, 1 kg = 186,00 Kč s klubem / 212,67 Kč bez klubu. Set it to an empty value to switch this off. | On, in your currency’s marks. |
count_units | The words a pack is counted in — ks (pieces), a washing dose PD, a bag bal. — so a unit price quoted per dose is checked against the 54 PD the caption states, never against the litres beside it. | ks |
unit_aliases | Other spellings of those words, in whatever grammatical case the leaflet uses: pracia dávka, pracích dávok → PD; or the plain g and ml of a 100 g = … line, which mean the kilograms and litres the pack is measured in. | none |
unit_price_scales | Which quantities the reader tries when it recomputes a unit price, as multiples of the base unit: 1 for per kilogram or per litre, 0.1 for per 100 g or per 100 ml. On a recipe with a unit-price house rule (below) this is only how the tile is read; which bases are allowed is the rule’s. Without one, the first scale is what the chain normally quotes. | 1 |
If the chain states the basis on the line — 100 g = 24,91 Kč on one tile and 1 l = 399,80 Kč on the next — give unit_line_pattern a third named part, basis, holding the 100 or the 1. Then which quantity the figure is per is read rather than guessed, and a tile quoting per 100 g on a chain that mostly quotes per kilogram is no longer noted as unusual. That matters more than it sounds: one chain mixes the two by product class, and without the basis part the check produced a note on every one of its 1 200 tiles and buried the seventeen real errors among them.
Three things the reader does for you whatever the pattern: it reads the line off the caption as a whole, so a label on one line and its 2,41 EUR/l on the next still count; it keeps up to three decimals, so 1,999 €/kg is not rounded to 2,00 before it is compared; and it never takes a quantity equated to money for the tile’s pack. A 100 g = 24,91 Kč on a chain whose pattern only knows 1 kg = … is not read as a unit price, but its 100 g is not read as the pack either.
That guard needs the =. A line such as 100 g od 7,93, a from-price printed with no =, has to be in unit_line_pattern, or it is read as caption text and its 100 g as a pack. One chain’s reader missed exactly that shape, and the line’s 100 g became the pack of a correct 50 g bar printed below it, which was then reported. The reader cannot guess this shape because the caption is read as its separate pieces of text joined together, and there a pack is often followed by an od figure that has nothing to do with it.
Switch the alt pattern off when a bare figure under the caption means something else on your chain. On a Slovak leaflet, 1,19 € under the unit line is the lowest price of the last 30 days, and + záloh za obal 0,15 € is a bottle deposit — read as unit prices, both produced findings on tiles that were right.
Packs, and prices printed more than once
Section titled “Packs, and prices printed more than once”A tile often states more than one quantity, or more than one price, and which of them a unit price belongs to is a chain convention.
| Setting | What it says | Default |
|---|---|---|
multipack_single_item | A multipack tile may quote its unit price per one item of the pack — 6× 0,5 l with 1 l = 31,97 Kč over a figure labelled price per piece when buying the pack. | off |
pack_pair_readings | The chain writes two quantities as one slash pair — 340/285 g (gross and drained), 270/180 g. Only the second carries the unit, so without this the first is invisible. | off |
pack_in_name | The chain prints the pack inside the product name — Mila 50 g, Pringles 165 g — with no line for it under the name. Without this those tiles have no pack and nothing on them is checked. The name is read last, so a pack line, where one is printed, still wins. Off because a wholesale catalogue’s names state a gross and a drained weight (S3500g / PP1700g) that would outrank the 1 KS the product is sold by. | off |
caption_price_pattern | A further price the tile states in words rather than as a figure — při koupi 1 ks 49,90, the price for buying one where the headline is the price from two. Its own unit line is printed under it and is checked against it. | none |
pack_unit_glyphs | Letters the chain’s font puts where a unit belongs, as printed → meant. One chain sets its wine as 0,75 I — a capital i, not the litre’s lowercase l. Only a letter directly after a number is rewritten. | none |
unit_line_for_regular | The tile prints a unit price for the struck price as well as for the offer: 100 g = 22,17 Kč s Klubem/ 27,72 Kč bez Klubu over a 39,90 with a struck 49,90. | off |
Reach for pack_unit_glyphs when a tile shows a unit price but Routario says nothing about it — a pack nobody can read is the quiet failure, because the tile then states a figure with nothing to check it against and passes in silence rather than being reported. It is a recipe setting and not a rule on purpose: “a capital I after a digit is a litre” is true of one chain’s typesetting, not of typesetting. Somewhere else that position holds a Roman numeral or a size code, and a reader that rewrote it quietly would invent a pack the leaflet never printed — which is worse than not checking.
unit_line_for_regular is deliberately narrow in the same spirit: it applies only where a tile prints more unit lines than figures. “The unit price was computed from the struck price” is one of the commonest real printing mistakes there is, and a setting that explained it away on ordinary tiles would cost far more than it buys.
Two products under one price
Section titled “Two products under one price”| Setting | What it says | Default |
|---|---|---|
combo_words | The words printed beside a figure that is the price of a bundle — cena za KOMBO over a caption listing a whisky and a cola, each with its own pack and its own unit price. | none |
Each unit price on such a tile is that product’s own, computed from a price the tile never shows, so nothing on the page reproduces either of them. Naming the words tells Routario to read and name the tile and leave its unit lines unchecked. Accusing a correctly printed bundle is worse than saying nothing about it.
The discount badge
Section titled “The discount badge”A -20 % badge is a claim the leaflet makes about itself, and arithmetic settles it — but only once you know which figure it is measured against.
| Setting | What it says | Default |
|---|---|---|
discount_reference | struck — the struck-through old price beside the figure. lowest_30d — the lowest-price-in-30-days line the tile prints (what EU price-reduction rules ask for), falling back to the struck price when a tile prints none. either — the badge passes if any printed reference explains it. | struck |
reference_price_pattern | The shape of that 30-day line, with the figure as val — for example a bare 1,19 € set small under the unit line. | none |
The worked example below shows why this is a setting and not a rule: the same salmon tile is correct under one reference and a finding under the other.
What a unit price may be quoted per — your house rule
Section titled “What a unit price may be quoted per — your house rule”Czech law makes 1 kg, 1 l or 1 m the base for a unit price and allows other units where custom or the nature of the product warrants — per piece, per 100 g, per 100 ml, per washing dose. So there is no single right answer: which bases are fine is the chain’s own decision, and its house rule may be stricter than the law. A recipe states it as the settings of the rule Unit price follows from the price and the pack, edited in the recipe’s Unit prices area, under Unit price — what it may be quoted per:
| Setting | What it says |
|---|---|
| Usually quoted per | The base the chain normally prints. A tile on it passes. |
| Bases you allow | Every base a tile may be quoted per. Untick one and a tile quoted on it becomes an error — per 100 g, say, if you quote only per kilogram. |
| Another allowed base is reported as | A note on consistency (never an error), an error, or not at all. |
| By kind of product | A kind can have its own usual base: toilet paper per metre or per roll, tissues per piece, paint per litre. Not chosen means any allowed base passes for that kind. |
A kind of product is recognised one of two ways. By words in the name — toaletní papír, but not vlhčený — which Routario judges itself. Or by a description where the goods cannot be listed — counter goods weighed out at a deli: salami, cheese from the block, fresh meat. A model then decides from the printed name whether a tile is one of them, and that decision may only ever let a tile pass: a described kind can allow per 100 g on deli goods, but it can never be the reason a tile is reported. A recipe that tried to give a described kind a usual base is refused when it is saved.
Routario ships defaults for Czech retail, which a recipe names as its starting point and changes only where the chain says otherwise. Until the chain has told us its rule, the recipe says so — the setting is shown as our assumption both in the editor and on the page the client reads.
A pack with no unit price
Section titled “A pack with no unit price”Under a unit-pricing statute a tile that states a pack size must print a unit price too. Routario can report the ones that do not — off by default, because not every chain and not every trade is under such a rule.
| Setting | What it says | Default |
|---|---|---|
unit_line_required | Report a tile that states a pack size but prints no unit price. | off |
unit_line_exempt | Which packs need none: max_g / max_ml — packs at or under this weight or volume (the Slovak statute says 50 g / 50 ml); unit_packs — a pack of exactly 1 kg, 1 l or 1 piece, whose price is its unit price. | 50, 50, on |
A multi-variant tile (one priced “from …”) is never reported this way, and neither is a figure the reader could not caption at all — that is Routario’s gap, not the chain’s.
Finding the caption
Section titled “Finding the caption”The Czech chains set every caption directly under its price bubble, so a line of text belongs to the nearest bubble whose window it falls in. Some layouts put the price beside the caption, or above it, or a third of the page away — with the next product’s figure nearer than its own. For those there is a second way of binding.
| Setting | What it says | Default |
|---|---|---|
caption_binding | windows — text belongs to the nearest figure whose under- or beside-window admits it. nearest_consistent — each caption is bound to the figure its own numbers agree with: price ÷ pack size = the printed unit price. Only a caption that agrees with no nearby figure is bound to the nearest one still free, and that is the tile its finding is reported on. | windows |
caption_radius_ratio | How far a caption may look for its figure under nearest_consistent, as a fraction of the page width. | 0 |
caption_column_gap | The horizontal gap at which one block of text is two captions set side by side. PDFs group text by baseline, so a pair of captions the studio placed across the page arrives as one block with their lines interleaved. | off |
caption_meta_max_size | The largest type a caption may be set in — high enough to clear the chain’s product names and bigger tiles, low enough to stay under the strapline printed over every figure. Set below the names, no tile is named and a pack printed in a name is never read. | 10 pt |
caption_meta_min_size | The smallest. A leaflet that advertises the chain’s other catalogues reproduces their covers as artwork, and a reproduced cover carries a live text layer: a whole tile, name, pack and unit price, set at less than a point. | off |
The second mode is the rule that makes a finding trustworthy on such a layout: a tile whose numbers fit some nearby price is clean, and Routario only accuses when nothing fits. Measured on the leaflet that motivated it, every correct tile found a figure within 0.37 of the page width, so its recipe says 0.4.
The two size settings are worth checking whenever a tile is read but comes back unnamed, or a caption’s numbers turn up on the tile next door. Both were measured the same way on the chain that needed them: over 2 290 caption blocks, 2 185 had no internal gap at all and the smallest genuine second caption began 12 pt away, so its recipe says 10.
Text the page does not show
Section titled “Text the page does not show”A print file can carry text that never reaches paper. The commonest reason is a template: the studio starts from last month’s layout, draws a fresh white card over the old caption, and sets the new one on top. The old line is still in the file, at the position the template put it — so a reader working from the text layer can bind it as the tile’s own figure, and then report arithmetic against a line nobody printed.
One chain’s cover does exactly this on every issue: a leftover 100 g = 25,80 sits 19 pt above each tile’s real unit line, the same figure on every tile, buried under the caption card. Read as printed, it put a unit price on four tiles that contradicted their own price and pack — a finding that would have sent the studio to correct a page that was already right.
Routario drops such text before it binds anything, and this needs no setting: whether a span is covered is decidable from the file, because a PDF records the order things are drawn in. A span is treated as invisible when something drawn afterwards paints over it — an opaque fill, in a rectangle, covering most of the span’s own area. A half-transparent panel over a price is a scrim and the price still reads; a card that clips a descender covers nothing that matters; and a studio that buries a heading and sets it again on top keeps the copy that prints. Only the same text counts as set again: a new caption that runs across an old line leaves that line buried.
What was dropped is reported rather than discarded, so “the reader ignored this” is always answerable. On a leaflet with no buried text — which is most of them — the list is empty.
| Setting | What it says | Default |
|---|---|---|
hidden_text_cover_frac | How much of a span a later opaque fill must cover before the span counts as painted over. Set it to 0 to switch the pass off and read the file as written. | 0.7 |
This is on by default, unlike most of the settings in this guide, because text the page does not show is never the chain’s data — it is wrong to read it on any leaflet, not a matter of house style.
Typefaces
Section titled “Typefaces”Two settings you only need when the reader finds no prices, or loses the pack size:
price_font_markers— substrings of the font names the price figures are set in. The default isBold; a chain whose display face is calledAllerDisplayorAptly-Boldlists them.brand_font_marker— the face of the brand line above the product name,Mediumby default. Set it to an empty value when the chain prints no brand line and sets its pack size and unit line in a Medium face, or the reader files both under “brand” and the tile loses them.
A worked example
Section titled “A worked example”A Slovak grocery chain publishes four leaflets a week: one for the whole network, two regional ones, one image-only. Its recipe reads, in the settings above:
currency / currency_marks | EUR — €, EUR (the regional leaflets print €, the network one EUR) |
unit_line_pattern | two shapes: jednotková cena:? 4,19 EUR/kg (two or three decimals, od aware) and 1 pracia dávka 0,22 EUR on detergents |
unit_line_alt_pattern | off — a bare 1,19 € is the 30-day price |
count_units / unit_aliases | ks, PD, bal. — pracia dávka, pracích dávok → PD |
discount_reference | lowest_30d, with 1,19 € as the line’s shape |
unit_line_required | on, exempt at or under 50 g / 50 ml and for 1 kg / 1 l / 1 piece packs |
caption_binding | nearest_consistent, radius 0.4 |
price_font_markers / brand_font_marker | Aptly-Bold, AllerDisplay — no brand line |
Run on the three leaflets that carry a text layer — 471 tiles, no source table — the check reports three tiles and nothing else:
přepočet nesedí: 0,79 / 0,33 l je 2,394 €, uvedeno 1,580 € — uvedená cena odpovídá balení 0,5 l A 0,33 l beer at 0,79 € prints the unit price of the half-litre bottle.
přepočet nesedí: 11,99 / 10 kg je 1,199 €, uvedeno 1,999 € — uvedená cena odpovídá balení 6 kg A 10 kg bag of dog food at 11,99 € prints the unit price computed from 19,99 €.
přepočet nesedí: 1,69 / 0,75 l je 2,25 €, uvedeno 2,41 € — uvedená cena odpovídá balení 0,7 l A 0,75 l mineral water at 1,69 € prints a unit price computed from 1,81 €. Its caption touches the neighbouring tile’s 4,99 € figure and sits 73 pt from its own — under
windowsbinding it would have been checked against the wrong price.
And one tile that is not reported, because of the discount setting: salmon at 3,99 €, struck 5,99 €, badge -20 %, 30-day line 4,99 €. Against the struck price that is 33 % off and the badge is wrong; against the 30-day line it is exactly 20 %. With discount_reference: lowest_30d the tile is clean. Switch the recipe to struck and the same tile reads:
sleva nesedí: z 5,99 na 3,99 je 33 %, uvedeno 20 %
A tile with a pack size and no unit price reads chybí měrná cena (balení 75 g). The finding texts are written in Czech today whatever the recipe’s language; a Slovak wording per recipe is on the list.
A second worked example: same language, same money
Section titled “A second worked example: same language, same money”A Czech grocery chain publishes two leaflets a week plus a loyalty edition. It prints korunas, like every chain Routario already read — and the reader found nothing at all on it, because it sets the whole price as one figure with the comma inside. Its recipe fills in:
price_comma_single_span / price_font_markers | on — the display face carries no Bold in its name |
unit_line_pattern | one shape with a basis part: 100 g = 24,91 Kč, 1 l = 399,80 Kč, 1 m = 0,21 Kč, 1 ks = 2,99 Kč |
unit_price_scales / unit_aliases | 1 and 0.1; g → kilograms, ml → litres |
unit_price_min_gap | one haler — the figures are small on a per-100 g basis |
multipack_single_item / pack_pair_readings | on — 6× 0,5 l priced per can, 340/285 g gross and drained |
caption_price_pattern / unit_line_for_regular | při koupi 1 ks 49,90; the bez Klubu line is the struck price ÷ the pack |
combo_words | cena za KOMBO |
caption_binding | nearest_consistent, radius 0.3, columns cut at 10 pt, caption type between 3 and 11 pt |
money_decimals | 2 |
Across ten editions — 217 pages, 2 012 tiles, no source table — it recomputes 1 213 unit prices and reports seventeen tiles. Two families cover all of them. A decimal slip:
přepočet nesedí: 39,90 / 0,5 l je 79,80 Kč, uvedeno 7,98 Kč A half-litre of goat’s milk at 39,90 prints a tenth of its unit price.
And a unit price carried over from a different price — an earlier one, the struck one, or a neighbour’s:
přepočet nesedí: 24,90 / 10 ks je 2,49 Kč, uvedeno 2,99 Kč Sanitary towels at 24,90 print the unit price of the 29,90 pack.
Plus one the badge check caught on its own, where the reference price is typeset with a decimal too many:
referenční cena je vysázená na 3 desetinná místa: 65,990 Kč sleva nesedí: z 65,99 na 29,90 je 55 %, uvedeno 95 %
Nothing else is reported. The bundle tiles, the multipacks priced per can, the club/non-club twins, the reproduced covers of the chain’s other catalogues and a toilet roll whose 1 m = 0,21 Kč is truncated rather than rounded all come back clean — and each of them is a setting above.
Where to go next
Section titled “Where to go next”- Proof a catalogue against your source table — the whole check, from files to the annotated PDF.
- Recipes: how a check knows what to compare — where these settings sit and how a Routario-maintained recipe is tuned without leaving our updates behind.
- Check that extracted numbers add up — the same idea for numbers pulled out of a single document.