The samples speak the page's language, the money sample is formatted for it
Every frame, every HTML tab, the demo application and the bar's scheme
menu now speak the page's language. The walker is Rastrillo's
localMarkup, ported under its names into localise.go: text and the
spoken attributes (Rastrillo's five, and alt) are looked up by their
English in i18n/samples.<locale>.json; stand-ins (names, brands,
codes, addresses, numbers) stay as written by Rastrillo's rules; a
sentence with inline markup is one key. Three additions over
Rastrillo's walker: every data-rst-<key> attribute whose key the
framework's own i18n/<locale>.json has takes that value, so the
enhanced select and date fields speak the page's language without a
script table; an element carrying lang keeps its words (the language
menu's endonyms); and sampleSenses names the two words Fiesta's
examples use as verbs, the row menu's Archive and the bulk bar's
Export, which are looked up under Rastrillo's "(verb)" keys.
EnglishStrings collects the sample keys with the same walker, over
the same sources, so the exporter and the renderer ask for the same
phrases.
The Money sample is Rastrillo's moneySampleMarkup for each of the
twelve locales, written by the exporter into i18n/money.json, and
format-money's default frame and HTML tab are that markup, bypassing
the walker as Rastrillo's formatMarkup does. The English entry is the
seeded body byte for byte.
A layout's document is localised before it is framed, so the frame's
link rewrites come after the walker; the layouts' foot link is now
matched by its words in the page's language. A frame's <title> in a
translated locale is the frame's title from labels.*. A layout's HTML
tab is the localised document with lang and dir set.
The field-date and field-datetime note on the enhanced state now
reads as approved in copy review (prose.field-date-words, approved
unchanged): "The words it parses are on data-rst-date-words, here in
the page's language. i18n/<lang>.json has them in twelve languages,
so the field can parse whichever language the page is in." Applied
through the exporter's approvedProse table; examples/prose.json and
hack/seed/prose-review.json regenerated by run-prose.sh at
e14b745a7c08d0efa3bf221a8b6a5e75de15c46f, twice, byte-identical; the
README's checksums updated.
Translations. The exporter ran at
5bb38c0ab31b9e3f5a698c61d73161cd1246471f; a second run rewrote every
file in i18n/ byte for byte and left no todo list. Per locale, the
same in each of ar, bn, es, ga, hi, ja, pt-PT, ru, vi, yue, zh-Hans:
catalog (chrome, prose, labels): 396 ids, 298 carried, 98 drafted
samples: 383 keys, 338 carried, 45 drafted
money.json: Rastrillo's formatting, twelve locales, nothing drafted
The 45 sample drafts and the two re-drafted date notes are machine
drafts nobody has reviewed. Most are built from Rastrillo's own
approved pieces where the English differs only around them (Actions
for {name}, {agent} for {person}, Sign in to {name}, the job and
sign-in sentences, the shells' paragraph with Fiesta and components
for ui.Layout and partials). The drafted ids:
- (lowercase, no spaces)
- 1–4 of 24 requests
- <bdi><strong>Import</strong></bdi> failed: <bdi>row 91: no such column "published"</bdi>
- <bdi><strong>Import</strong></bdi> finished.
- Actions for Alan Turing
- Actions for Card declined on renewal
- Actions for Checkout, step 2
- Actions for Claude for Grace Hopper
- Actions for Export takes twenty minutes
- Actions for Harbour logo
- Actions for Invoice #4471 never arrived
- Actions for Pricing page
- Actions for Seat count is wrong on the invoice
- Actions for Spring banner
- Card declined on renewal<small><bdi>Otto Neurath</bdi> · 08:40</small>
- Card declined on renewal<small><bdi>Otto Neurath</bdi> · Billing</small>
- Claude for Grace Hopper
- Codex for Grace Hopper
- Continue as <bdi>grace@example.com</bdi>
- Export takes twenty minutes<small><bdi>Mary Sherman</bdi> · Data</small>
- Invoice #4471 never arrived<small><bdi>Fiona Reid</bdi> · 09:12</small>
- Invoice #4471 never arrived<small><bdi>Fiona Reid</bdi> · Billing</small>
- Made with Fiesta
- Nightly import for Grace Hopper
- Reference: k3f9tq
- Release notes, August<small>Published 2 August</small>
- Reported by Fiona Reid, and still waiting on us.
- Revoke all for this agent: Claude
- Seat count is wrong on the invoice<small><bdi>Hedy Lamarr</bdi> · 11 August</small>
- Seat count is wrong on the invoice<small><bdi>Hedy Lamarr</bdi> · Billing</small>
- Select Checkout, step 2
- Select Pricing page
- Sign in to Harbour
- This is the column shell, one of the shells Fiesta ships. A screen is a column: a page header, then a section heading and its card, then the next one. Everything you see here is the shell, tokens.css and two components.
- This is the console shell, one of the shells Fiesta ships. A screen is a column: a page header, then a section heading and its card, then the next one. Everything you see here is the shell, tokens.css and two components.
- This is the sidebar shell, one of the shells Fiesta ships. A screen is a column: a page header, then a section heading and its card, then the next one. Everything you see here is the shell, tokens.css and two components.
- This is the topbar shell, one of the shells Fiesta ships. A screen is a column: a page header, then a section heading and its card, then the next one. Everything you see here is the shell, tokens.css and two components.
- We sent a link to <bdi>grace@example.com</bdi>. The link works once and expires soon.
- We sent a link to <bdi>kay@example.org</bdi>. The link works once and expires soon.
- We sent a link to your inbox. The link works once and expires soon.
- Why we moved off the old runner<small>Draft</small>
- as <bdi>kay@example.org</bdi>
- is running:
- ← Order AB3PX
- ← Requests
- examples.field-date.states.enhanced-input-type-tomorrow-or-in-3-weeks
- examples.field-datetime.states.enhanced-input-type-tomorrow-or-in-3-weeks
Stand-ins added to Rastrillo's list, from the misses: Fiesta, Party
planner, Keymail, Claude, Codex, EUR (the money field's code, which
Rastrillo keeps as data), REQ-4471, k3f9tq.
The leak gate now sweeps every document: pages, frames, the demo's
four, the modal route, the lifted scheme menu and the HTML tab's
source, read as the markup it shows. It leaves alone what the walker
keeps as written (code, svg, bdi, the shell's brand and person,
anything carrying lang). A string a locale says the same way is not a
leak when every id saying it is carried from Rastrillo with that same
translation (Madrid in Spanish), or when it is the locale's own word
for another id (Vietnamese names the Tokens page "Token"); a draft
equal to its English still has to be in leakUnchanged. A new control:
"Sign out" put back to English in the ja sample catalog is reported
in the sidebar shell's frame.
Heights. The full sweep (FIESTA_SWEEP=full) ran over all twelve
locales at 1500px and 320px. The first sweep found 8 short boxes at 1500px
(api-tokens with its body open, in ga, ja, ru and vi) and 112 at
320px, all in es, ga, ja, pt-PT, ru, vi and one in bn; en and ar need
nothing new. Pasted: the 1500px printout (api-tokens 930 and 1060 to
990 and 1120; error-page 403 and 404 to 350, 500 to 400, 503 to 350,
the generic pair to 330; format-abbr to 170; layout-column to 590),
and the 320px raises as previewMobileLocaleHeights, per language.
The second sweep read 0 short at both widths over all twelve locales
and printed the Desktop and Mobile tables unchanged; its language
table dropped five 503 entries the raised Desktop height now covers
and named modal/default 350 in ga and ru, under the modal's 620
reserve. Pasted as printed; the render is byte-identical to the one
the second sweep measured, so a third prints the same. 96 language
entries: bn 1, es 15, ga 24, ja 7, pt-PT 16, ru 26, vi 7.
hack/test-weights.txt: the HTML-tab drive, now in two languages,
weighs 104s.
Tests.
New, seen red by assertion:
- TestSampleTranslationsKeepTheirStandIns, TestSampleMarkupSurvivesTranslation:
"the sample catalogs are empty; there is nothing to hold"
- TestNoEnglishSampleLabelReachesATranslatedPage: "plain/ar/frames/
layout-sidebar-page/default.html carries the English sample label
"Settings"", and "Colour scheme" on every translated page's bar
- TestEverySampleStringIsTranslated: "i18n/samples.ar.json has no
translation of "Select all 412 matching""
- TestMoneySampleIsFormattedPerLocale: "ja: the money frame lacks
"¥1,285"" against an English-only table
- TestTheMoneyTableStartsFromTheExample: "i18n/money.json has no en
sample" against an empty table
- TestAVerbAndItsNounAreTranslatedApart: "day/es's row-menu frame does
not show the button Archivar", "... shell-topbar frame does not show
the nav link Archivo"
- TestTheWalkersTranslateWordsAndKeepStandIns and
TestTheEnhancedControlsCarryThePagesStrings, against an identity
localMarkup: "the walker did not write data-rst-date-pick="カレンダーを開く"",
"field-select/...: data-rst-select-filter is "Type to filter", want
the ja catalog's "入力して絞り込む""
- browser, against an identity localMarkup and an English money table:
TestTheEnhancedControlsSpeakThePagesLanguage ("offers its filter as
"Type to filter", want "入力して絞り込む"", the calendar button and
the calendar named in English); TestMoneySamplesWithNoScript
("Spanish money sample with no script: "EUR\n€1,284.50...")
Already passing, labelled: TestLocalisingIntoEnglishChangesNothing
passes on an identity localMarkup; its mutation, a localText that
lowercases what it returns, turns it red ("page-header: localMarkup
changed English markup"). TestSampleMarkupSurvivesTranslation reads
the catalogs and stays green under that mutation.
Extended: TestTheHTMLTabRendersExactlyLikeThePreview runs on day/ja's
samples as well as English's; TestNoEnglishProseReachesATranslatedPage
sweeps every document, with the sample control.
Preservation, adapted to the samples being translated:
TestTheTextOnScreenIsTheTextCopied (its Arabic want goes through
localMarkup, the localised document, and the money table);
TestAShellDemosLinksAreLive (the foot link's words in the page's
language); TestEveryProseKeyIsTranslated (sample ids are the sample
gate's; i18n/ holds samples.<locale>.json and money.json).
Nobody reviewed the drafts; the English is unchanged but for the one approved note.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
46 files changed,
+6950
−139
examples/prose.json+2 −2hack/seed/README.md+2 −2hack/seed/_rastrillo/prose_fiestaseed_test.go+2 −2hack/seed/_rastrillo/translations_fiestaseed_test.go+74 −4hack/seed/prose-review.json+2 −2hack/test-weights.txt+1 −1internal/gallery/code_browser_test.go+35 −23internal/gallery/demo.go+43 −6internal/gallery/example_page.go+1 −11internal/gallery/frame.go+12 −2internal/gallery/frame_test.go+5 −1internal/gallery/gallery.go+29 −1internal/gallery/heights.go+125 −12internal/gallery/i18n.go+19 −4internal/gallery/i18n/ar.json+2 −2internal/gallery/i18n/bn.json+2 −2internal/gallery/i18n/drafts.json+722 −2internal/gallery/i18n/es.json+2 −2internal/gallery/i18n/ga.json+2 −2internal/gallery/i18n/hi.json+2 −2internal/gallery/i18n/ja.json+2 −2internal/gallery/i18n/money.json+14 −0internal/gallery/i18n/pt-PT.json+2 −2internal/gallery/i18n/ru.json+2 −2internal/gallery/i18n/samples.ar.json+385 −0internal/gallery/i18n/samples.bn.json+385 −0internal/gallery/i18n/samples.es.json+385 −0internal/gallery/i18n/samples.ga.json+385 −0internal/gallery/i18n/samples.hi.json+385 −0internal/gallery/i18n/samples.ja.json+385 −0internal/gallery/i18n/samples.pt-PT.json+385 −0internal/gallery/i18n/samples.ru.json+385 −0internal/gallery/i18n/samples.vi.json+385 −0internal/gallery/i18n/samples.yue.json+385 −0internal/gallery/i18n/samples.zh-Hans.json+385 −0internal/gallery/i18n/vi.json+2 −2internal/gallery/i18n/yue.json+2 −2internal/gallery/i18n/zh-Hans.json+2 −2internal/gallery/i18n_test.go+188 −32internal/gallery/localise.go+668 −0internal/gallery/localise_test.go+552 −0internal/gallery/money.go+47 −0internal/gallery/nav.go+1 −1internal/gallery/samples_browser_test.go+133 −0internal/gallery/view.go+1 −0internal/gallery/view_test.go+15 −9
CI passed — run details
CI log
=== gofmt ===
=== no-rastrillo ===
go test -run '^(TestFiestaNeverImportsRastrillo|TestThePublicPackagesLinkNoBrowser)$' -count=1 .
ok amadan.net/rastrillo/fiesta 0.113s
=== size ===
go test ./internal/build -run '^TestTheOneLinkIsUnder25KiBGzipped$' -count=1 -v
=== RUN TestTheOneLinkIsUnder25KiBGzipped
build_test.go:138: fiesta-plain.css: 152856 bytes, 22303 bytes gzipped (21.8 KiB of the 25.0 KiB limit)
build_test.go:138: fiesta-signal.css: 152951 bytes, 22414 bytes gzipped (21.9 KiB of the 25.0 KiB limit)
build_test.go:138: fiesta.css: 155770 bytes, 23018 bytes gzipped (22.5 KiB of the 25.0 KiB limit)
--- PASS: TestTheOneLinkIsUnder25KiBGzipped (0.02s)
PASS
ok amadan.net/rastrillo/fiesta/internal/build 0.020s
=== suite ===
--- shard 0 of 15 ---
==> shard 0 of 15: make root
go build ./...
go vet ./...
FIESTA_TEST_REQUIRE_NODE=1 FIESTA_TEST_REQUIRE_GIT=1 go test -count=1 ./...
ok amadan.net/rastrillo/fiesta 1.624s
ok amadan.net/rastrillo/fiesta/check 7.284s
ok amadan.net/rastrillo/fiesta/cmd/fiesta 106.941s
ok amadan.net/rastrillo/fiesta/example 0.244s
? amadan.net/rastrillo/fiesta/hack/seed/english [no test files]
ok amadan.net/rastrillo/fiesta/internal/axe 0.144s
ok amadan.net/rastrillo/fiesta/internal/build 1.288s
ok amadan.net/rastrillo/fiesta/internal/codeview 0.005s
ok amadan.net/rastrillo/fiesta/internal/gallery 142.714s
? amadan.net/rastrillo/fiesta/internal/harness [no test files]
ok amadan.net/rastrillo/fiesta/internal/markup 0.017s
ok amadan.net/rastrillo/fiesta/internal/nodetest 0.296s
ok amadan.net/rastrillo/fiesta/internal/site 3.893s
ok amadan.net/rastrillo/fiesta/internal/tokens 0.013s
ok amadan.net/rastrillo/fiesta/internal/www 89.624s
--- shard 1 of 15 ---
==> shard 1 of 15: make staticcheck
go run honnef.co/go/tools/cmd/staticcheck@v0.8.2 -tags browser ./...
--- shard 2 of 15 ---
==> shard 2 of 15: make govulncheck
go run golang.org/x/vuln/cmd/govulncheck@v1.8.0 ./...
=== Symbol Results ===
No vulnerabilities found.
Your code is affected by 0 vulnerabilities.
This scan also found 2 vulnerabilities in packages you import and 5
vulnerabilities in modules you require, but your code doesn't appear to call
these vulnerabilities.
Use '-show verbose' for more details.
--- shard 3 of 15 ---
==> shard 3 of 15: make gitleaks
go run github.com/zricethezav/gitleaks/v8@v8.30.1 git --no-banner --redact --log-opts='--full-history --diff-filter=tuxdb HEAD' .
[90m10:32AM[0m [32mINF[0m [1mUnknown SCM platform. Use --platform to include links in findings.[0m [36mhost=[0mamadan.net
[90m10:32AM[0m [32mINF[0m [1m1 commits scanned.[0m
[90m10:32AM[0m [32mINF[0m [1mscanned ~7571962 bytes (7.57 MB) in 6.33s[0m
[90m10:32AM[0m [32mINF[0m [1mno leaks found[0m
--- shard 4 of 15 ---
==> shard 4 of 15: make browser.internal.harness
./hack/gotest.sh browser 'internal.harness'
gotest: on DOCS-T1, driving the harness's own choice (/usr/bin/chromium)
ok amadan.net/rastrillo/fiesta/internal/harness 15.269s
--- shard 5 of 15 ---
==> shard 5 of 15: make browser.check~1of3
./hack/gotest.sh browser 'check~1of3'
gotest: on DOCS-T1, driving the harness's own choice (/usr/bin/chromium)
gotest: slice 1 of 3 of ./check/ runs 95 of 286 tests
ok amadan.net/rastrillo/fiesta/check 254.557s
--- shard 6 of 15 ---
==> shard 6 of 15: make browser.check~2of3
./hack/gotest.sh browser 'check~2of3'
gotest: on DOCS-T1, driving the harness's own choice (/usr/bin/chromium)
gotest: slice 2 of 3 of ./check/ runs 95 of 286 tests
ok amadan.net/rastrillo/fiesta/check 276.766s
--- shard 7 of 15 ---
==> shard 7 of 15: make browser.check~3of3
./hack/gotest.sh browser 'check~3of3'
gotest: on DOCS-T1, driving the harness's own choice (/usr/bin/chromium)
gotest: slice 3 of 3 of ./check/ runs 96 of 286 tests
ok amadan.net/rastrillo/fiesta/check 293.941s
--- shard 8 of 15 ---
==> shard 8 of 15: make browser.internal.gallery~1of4
./hack/gotest.sh browser 'internal.gallery~1of4'
gotest: on DOCS-T1, driving the harness's own choice (/usr/bin/chromium)
gotest: slice 1 of 4 of ./internal/gallery/ runs 1 of 163 tests
ok amadan.net/rastrillo/fiesta/internal/gallery 334.833s
--- shard 9 of 15 ---
==> shard 9 of 15: make browser.internal.gallery~2of4
./hack/gotest.sh browser 'internal.gallery~2of4'
gotest: on DOCS-T1, driving the harness's own choice (/usr/bin/chromium)
gotest: slice 2 of 4 of ./internal/gallery/ runs 53 of 163 tests
ok amadan.net/rastrillo/fiesta/internal/gallery 289.647s
--- shard 10 of 15 ---
==> shard 10 of 15: make browser.internal.gallery~3of4
./hack/gotest.sh browser 'internal.gallery~3of4'
gotest: on DOCS-T1, driving the harness's own choice (/usr/bin/chromium)
gotest: slice 3 of 4 of ./internal/gallery/ runs 55 of 163 tests
ok amadan.net/rastrillo/fiesta/internal/gallery 224.392s
--- shard 11 of 15 ---
==> shard 11 of 15: make browser.internal.gallery~4of4
./hack/gotest.sh browser 'internal.gallery~4of4'
gotest: on DOCS-T1, driving the harness's own choice (/usr/bin/chromium)
gotest: slice 4 of 4 of ./internal/gallery/ runs 54 of 163 tests
ok amadan.net/rastrillo/fiesta/internal/gallery 325.028s
--- shard 12 of 15 ---
==> shard 12 of 15: make browser.internal.gallery.history
./hack/gotest.sh browser 'internal.gallery.history'
gotest: on DOCS-T1, driving the harness's own choice (/usr/bin/chromium)
ok amadan.net/rastrillo/fiesta/internal/gallery/history 43.975s
--- shard 13 of 15 ---
==> shard 13 of 15: make browser.internal.www~1of2
./hack/gotest.sh browser 'internal.www~1of2'
gotest: on DOCS-T1, driving the harness's own choice (/usr/bin/chromium)
gotest: slice 1 of 2 of ./internal/www/ runs 17 of 34 tests
ok amadan.net/rastrillo/fiesta/internal/www 165.665s
--- shard 14 of 15 ---
==> shard 14 of 15: make browser.internal.www~2of2
./hack/gotest.sh browser 'internal.www~2of2'
gotest: on DOCS-T1, driving the harness's own choice (/usr/bin/chromium)
gotest: slice 2 of 2 of ./internal/www/ runs 17 of 34 tests
ok amadan.net/rastrillo/fiesta/internal/www 142.388s
Intent
examples/prose.jsonLoading diff…
hack/seed/README.mdLoading diff…
hack/seed/_rastrillo/prose_fiestaseed_test.goLoading diff…
hack/seed/_rastrillo/translations_fiestaseed_test.goLoading diff…
hack/seed/prose-review.jsonLoading diff…
hack/test-weights.txtLoading diff…
internal/gallery/code_browser_test.goLoading diff…
internal/gallery/demo.goLoading diff…
internal/gallery/example_page.goLoading diff…
internal/gallery/frame.goLoading diff…
internal/gallery/frame_test.goLoading diff…
internal/gallery/gallery.goLoading diff…
internal/gallery/heights.goLoading diff…
internal/gallery/i18n.goLoading diff…
internal/gallery/i18n/ar.jsonLoading diff…
internal/gallery/i18n/bn.jsonLoading diff…
internal/gallery/i18n/drafts.jsonLoading diff…
internal/gallery/i18n/es.jsonLoading diff…
internal/gallery/i18n/ga.jsonLoading diff…
internal/gallery/i18n/hi.jsonLoading diff…
internal/gallery/i18n/ja.jsonLoading diff…
internal/gallery/i18n/money.jsonLoading diff…
internal/gallery/i18n/pt-PT.jsonLoading diff…
internal/gallery/i18n/ru.jsonLoading diff…
internal/gallery/i18n/samples.ar.jsonLoading diff…
internal/gallery/i18n/samples.bn.jsonLoading diff…
internal/gallery/i18n/samples.es.jsonLoading diff…
internal/gallery/i18n/samples.ga.jsonLoading diff…
internal/gallery/i18n/samples.hi.jsonLoading diff…
internal/gallery/i18n/samples.ja.jsonLoading diff…
internal/gallery/i18n/samples.pt-PT.jsonLoading diff…
internal/gallery/i18n/samples.ru.jsonLoading diff…
internal/gallery/i18n/samples.vi.jsonLoading diff…
internal/gallery/i18n/samples.yue.jsonLoading diff…
internal/gallery/i18n/samples.zh-Hans.jsonLoading diff…
internal/gallery/i18n/vi.jsonLoading diff…
internal/gallery/i18n/yue.jsonLoading diff…
internal/gallery/i18n/zh-Hans.jsonLoading diff…
internal/gallery/i18n_test.goLoading diff…
internal/gallery/localise.goLoading diff…
internal/gallery/localise_test.goLoading diff…
internal/gallery/money.goLoading diff…
internal/gallery/nav.goLoading diff…
internal/gallery/samples_browser_test.goLoading diff…
internal/gallery/view.goLoading diff…
internal/gallery/view_test.goLoading diff…