Skip to content

feat(landing): three languages, asset-tokenisation positioning, on-chain receipts - #60

Merged
temrjan merged 5 commits into
mainfrom
feat/landing-i18n
Aug 14, 2026
Merged

feat(landing): three languages, asset-tokenisation positioning, on-chain receipts#60
temrjan merged 5 commits into
mainfrom
feat/landing-i18n

Conversation

@temrjan

@temrjan temrjan commented Aug 14, 2026

Copy link
Copy Markdown
Owner

The landing was four hand-written HTML files in Russian. It is now twelve pages in three
languages, printed from one template set, with English as the source text.

What changes

Generation. public/ is printed from src/templates (markup, one set for every language)
and src/strings/<lang>.json (text only), then committed. deploy.sh and the server are
untouched — they still copy public/ as it is. The generator is standard library and the
substitution is deliberately dumb: {{key}} becomes a string, no conditionals, no loops, no
pluralisation. A placeholder no dictionary answers, and a key no template uses, both fail the
build rather than shipping a page with a hole in it.

Positioning. The page now leads with the mechanism: the issuer posts a coverage ceiling
on-chain, the network refuses issuance beyond it, the customer's key stays on their device. Gold
is presented as the first case carried through to the end rather than as the whole product, and
the page states plainly that another underlying asset needs its own set of contracts — the price
source and the unit of measure are fixed at deployment and never change afterwards.

Receipts instead of assurances. Three transactions on the home page and one beside each
load-bearing invariant, every hash resolved against the chain and every abbreviation checked
against the full hash it links to. The attestation is labelled as an example with its own date
and points at the full history, so the page cannot age into a false claim.

Routing. English at /, Russian at /ru, Uzbek at /uz, cross-linked by hreflang. Six
redirects were added to Caddyfile: the existing clean-URL rules match exact paths, so each
translated page would otherwise have answered on two URLs at once.

How it was verified

  • generator reproduced the previous Russian site byte for byte before any text changed;
  • 20 routes exercised against a real Caddy: pages 200, .html forms 301, unknown paths 404;
  • every displayed transaction hash resolved on-chain (status 0x1);
  • all 14 external links answer 200 with no redirect hop;
  • 28 tests, each guard proven by mutation — including removal of the testnet disclosure from a
    single language, which turns the suite red;
  • build.py --check reprints and diffs both ways; this now runs as a gate on pull requests.

Notes

Merging does not publish: the landing deploys by running deploy.sh on the server, and it must
be done in one step so the three language trees appear together.

Uzbek has not yet been proof-read by a native speaker; the legal section is deliberately compact
and does not interpret the licensing regime.

The landing is four hand-written HTML files. Adding two more languages would
have made twelve, with nothing to keep them structurally in step — and no CI on
this subproject at all, so a divergence would only ever be caught by eye.

Pages are now printed from src/templates (one markup set) and
src/strings/<lang>.json (text only). The generator is standard library, and the
substitution is dumb by design: {{key}} becomes a string, no conditionals, no
loops, no pluralisation. A placeholder no dictionary answers, and a key no
template uses, both fail the build rather than shipping a page with a hole.

public/ stays committed and is byte-for-byte unchanged by this commit, so
deploy.sh and the server keep working exactly as before — they still copy
public/ as it is. `build.py --check` reprints and diffs both ways, and now runs
as a gate on pull requests together with the page guards (language attribute,
testnet disclosures, legal note, no unsubstituted placeholders).

Caddyfile gains six redirects: the existing clean-URL rules match exact paths,
so /ru/index.html and /uz/how-it-works.html would each have answered on two URLs
at once — verified against a real Caddy before and after.
…on-chain receipts

English becomes the source text rather than a translation, and the page now leads
with what the machinery does: the issuer posts a coverage ceiling on-chain, the
network refuses issuance beyond it, the customer's key stays on their device.
Gold is presented as the first case carried through to the end, not as the whole
product — and the page says plainly that another underlying asset needs its own
set of contracts, because the price source and the unit of measure are fixed at
deployment and never change afterwards.

Claims now settle in transactions instead of inviting the reader to take our word:
three receipts on the home page and one beside each of the load-bearing
invariants, every hash checked against the chain (eth_getTransactionReceipt,
status 0x1) and every abbreviation checked against the full hash it links to.
The attestation receipt is labelled as an example with its own date and points at
the full attestation history, so the page cannot go stale into a false claim.

Language switch, hreflang and a 404 that offers all three languages are in place;
/ru and /uz answer 404 until those dictionaries land. The Russian dictionary moved
to src/strings/pending/ for now: its wording describes the previous positioning,
and building it alongside the new English text would ship a site that contradicts
itself.
…uages

English stays at the root, Russian moves to /ru and Uzbek to /uz, each declaring
its own lang attribute and cross-linked by hreflang.

The Russian text is rebuilt from the verified original rather than retyped: every
string that already existed was carried across untouched, and only the positioning
copy was rewritten from the approved English. The legal block is byte-identical to
what it was before this branch started — checked key by key, not by eye.

Uzbek is Latin script, and the phone mockup takes its wording from the Mini App's
own dictionary so the showcase and the product do not name the same thing
differently. The thirteen mockup strings with no entry in that dictionary were
translated here and listed for approval rather than decided silently.

Verified on a real Caddy: all twelve pages answer 200, all six .html forms redirect
301 to their clean address, and unknown paths under every language still fall
through to an honest 404. All fourteen external links answer 200, including the
per-language register pages of the regulator.
It was a holding place while English was written on its own. Now that ru.json
carries that text — the legal block key-for-key identical — keeping the copy
would leave two Russian dictionaries where only one is built, and the unused one
is the kind that silently drifts. The original remains in history.
…d for the class

hiw_inv4_h read "tegа": the third letter is U+0430, Cyrillic small a, sitting
inside a Latin word. It renders identically and no reader — reviewer or native
proof-reader — would have caught it. Review found it with a script, which is the
only way this class is ever found.

The fix is one character. The guard is the point: every Latin-script dictionary is
now checked for Cyrillic characters, with a positive control asserting the Russian
dictionary still contains some — without that control the check could pass simply
by being broken.
@temrjan
temrjan merged commit 30910f4 into main Aug 14, 2026
1 check passed
@temrjan
temrjan deleted the feat/landing-i18n branch August 14, 2026 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant