From 47e6537ddef6a2852896ef7d03b510c6506e5f70 Mon Sep 17 00:00:00 2001 From: michilis Date: Fri, 21 Aug 2026 05:06:58 +0200 Subject: [PATCH] Expand i18n locales and improve reviews UI Add many new language packs with RTL support, refresh brand assets, and harden review rendering with tests. Co-authored-by: Cursor --- web/package.json | 1 + web/public/apple-touch-icon.png | Bin 2004 -> 6438 bytes web/public/favicon-32.png | Bin 888 -> 1515 bytes web/public/favicon.ico | Bin 910 -> 1537 bytes web/public/favicon.svg | 2 +- web/public/icon-192.png | Bin 2168 -> 6312 bytes web/public/icon-512.png | Bin 2745 -> 10634 bytes web/scripts/make-assets.mjs | 107 ++-- web/src/assets/cashu-logo.png | Bin 0 -> 8087 bytes web/src/components/CopyableId.astro | 4 +- web/src/components/LanguageSwitcher.astro | 131 +++- web/src/components/LoginDialog.astro | 8 + web/src/components/Reviews.astro | 164 ++++- web/src/i18n/GLOSSARY.md | 1 + web/src/i18n/ar-eg.json | 658 ++++++++++++++++++++ web/src/i18n/ar.json | 658 ++++++++++++++++++++ web/src/i18n/config.ts | 23 + web/src/i18n/cs.json | 700 ++++++++++++++++++++++ web/src/i18n/da.json | 658 ++++++++++++++++++++ web/src/i18n/de.json | 658 ++++++++++++++++++++ web/src/i18n/el.json | 658 ++++++++++++++++++++ web/src/i18n/en.json | 23 +- web/src/i18n/es.json | 23 +- web/src/i18n/format.ts | 7 +- web/src/i18n/fr.json | 658 ++++++++++++++++++++ web/src/i18n/hi.json | 658 ++++++++++++++++++++ web/src/i18n/id.json | 658 ++++++++++++++++++++ web/src/i18n/it.json | 658 ++++++++++++++++++++ web/src/i18n/ja.json | 658 ++++++++++++++++++++ web/src/i18n/locales.mjs | 27 +- web/src/i18n/nl.json | 23 +- web/src/i18n/pl.json | 700 ++++++++++++++++++++++ web/src/i18n/pt.json | 658 ++++++++++++++++++++ web/src/i18n/ro.json | 679 +++++++++++++++++++++ web/src/i18n/ru.json | 700 ++++++++++++++++++++++ web/src/i18n/sv.json | 658 ++++++++++++++++++++ web/src/i18n/tr.json | 658 ++++++++++++++++++++ web/src/i18n/uk.json | 700 ++++++++++++++++++++++ web/src/i18n/ur.json | 658 ++++++++++++++++++++ web/src/i18n/vi.json | 658 ++++++++++++++++++++ web/src/i18n/zh.json | 658 ++++++++++++++++++++ web/src/layouts/Base.astro | 4 +- web/src/lib/auth-ui.ts | 13 + web/src/lib/client.ts | 20 +- web/src/lib/review-body.ts | 117 ++++ web/src/lib/review-cards.ts | 342 ++++++++++- web/src/pages/[...locale]/index.astro | 104 +--- web/src/pages/[...locale]/reviews.astro | 172 +++++- web/src/styles/global.css | 117 +++- web/test/hostile-review.mjs | 20 + web/test/review-body.test.mjs | 77 +++ 51 files changed, 15291 insertions(+), 246 deletions(-) create mode 100644 web/src/assets/cashu-logo.png create mode 100644 web/src/i18n/ar-eg.json create mode 100644 web/src/i18n/ar.json create mode 100644 web/src/i18n/cs.json create mode 100644 web/src/i18n/da.json create mode 100644 web/src/i18n/de.json create mode 100644 web/src/i18n/el.json create mode 100644 web/src/i18n/fr.json create mode 100644 web/src/i18n/hi.json create mode 100644 web/src/i18n/id.json create mode 100644 web/src/i18n/it.json create mode 100644 web/src/i18n/ja.json create mode 100644 web/src/i18n/pl.json create mode 100644 web/src/i18n/pt.json create mode 100644 web/src/i18n/ro.json create mode 100644 web/src/i18n/ru.json create mode 100644 web/src/i18n/sv.json create mode 100644 web/src/i18n/tr.json create mode 100644 web/src/i18n/uk.json create mode 100644 web/src/i18n/ur.json create mode 100644 web/src/i18n/vi.json create mode 100644 web/src/i18n/zh.json create mode 100644 web/src/lib/review-body.ts create mode 100644 web/test/hostile-review.mjs create mode 100644 web/test/review-body.test.mjs diff --git a/web/package.json b/web/package.json index 4185ce0..aa595ca 100644 --- a/web/package.json +++ b/web/package.json @@ -13,6 +13,7 @@ "bones": "node --env-file-if-exists=../.env scripts/bones.mjs", "check:links": "node scripts/check-links.mjs dist", "check:i18n": "node scripts/check-i18n.mjs", + "test": "node --experimental-strip-types --test test/*.test.mjs", "check:hreflang": "node scripts/check-hreflang.mjs dist" }, "dependencies": { diff --git a/web/public/apple-touch-icon.png b/web/public/apple-touch-icon.png index 40ddcc39b7ec99208d8827eeb36c6a55bf53691d..25ef08cd9083b3de3d83471117aa28afdca30109 100644 GIT binary patch literal 6438 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 literal 2004 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 KMNUMnLSTaX+Q|z5 delta 876 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 U@9&R3qyPW_07*qoM6N<$g1Bpz0RR91 diff --git a/web/public/favicon.svg b/web/public/favicon.svg index c38e8ef..3512f50 100644 --- a/web/public/favicon.svg +++ b/web/public/favicon.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/web/public/icon-192.png b/web/public/icon-192.png index 3b07de349492c8872cf3bbb8e6a350c6fa31e47f..98d6d83db70d2963f47ddcc818b97046f96a1bcd 100644 GIT binary patch literal 6312 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 Jq!YfE{|yGVrP%-g diff --git a/web/public/icon-512.png b/web/public/icon-512.png index 4487fc4f2fec626538c2fe54da07b5648c929282..1c0b13d9b1ce254f3ff58d1949d85bc4738bef84 100644 GIT binary patch literal 10634 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 literal 2745 zcmcguK}Z`>5S`s_=o$$u1ZnY}s|m`v03h^JeDF|G2L*{SRZ& z)+hkP(kc5ffR0-oOj=&H_PocXDVG|`12o6!SA%zpw*jK#X}f!H;_&34BPKGIz4aqr zoV_``^mF!&ervz5t$iQJK3{m0+c_EE>x4`uuY(3j01Lo?D{UJM&qc0~R(vh}7Hd;) zAps`nB7{W%vFJo*5@&)q$%uPGXe0-8ag2nNxwB)%7A=XQ8mOygfd+^S{K36N#w0F5 zjTl977*0_b$Haa{gFMOoqq3zy#*03c&DS@YBvXR)A+3C~{pma2h;$5O$FMmI&hM&a zb+tx9W@Y`u0X%RXFjBj~A$L<#UPPO1`iFb@`9gZPYyG%|W`lF$f%AZC0J;nEoc$Te zC?t@m(c?gL^=e$WG5=|$RD6AHUA0e@_@1Enth>&d6LMy(GRWgff5}2ugCogB4Tw-W zvkM~`c?a1?iD{H@z>TKv{&+gh&JdiJQjz$7Hr#b08_Ch z%;o}z91Y4s%Emx}C8Gg>-Mfz4l;q<{y^V4|o6o diff --git a/web/scripts/make-assets.mjs b/web/scripts/make-assets.mjs index 19589c2..bc4df0a 100644 --- a/web/scripts/make-assets.mjs +++ b/web/scripts/make-assets.mjs @@ -6,6 +6,7 @@ * files change roughly never. * * node scripts/make-assets.mjs + * node scripts/make-assets.mjs --no-card # icon set only, needs no browser * * Playwright and sharp are not dependencies of this workspace. Both arrive transitively * under `astro` (which ships sharp for its image pipeline) and are resolved through it, @@ -14,10 +15,12 @@ * * The card is drawn in a real browser rather than assembled by hand because it uses the * site's own fonts and tokens: a social card that does not look like the site is worth - * less than no card. The moai is the same rect geometry as `components/Moai.astro`. + * less than no card. The moai on the card is the same rect geometry as + * `components/Moai.astro`. The icon set is a different mark: the pixel cashu nut carried + * over from the old site (`src/assets/cashu-logo.png`), composed with sharp alone. */ import { createRequire } from 'node:module'; -import { mkdir, writeFile } from 'node:fs/promises'; +import { mkdir, readFile, writeFile } from 'node:fs/promises'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -100,14 +103,8 @@ p { margin-top: 28px; font-size: 27px; line-height: 1.45; color: #9A927E; max-wi
cashumints.space
`; -/* The icon master: the moai on the site's background, generous padding. */ -const iconHtml = `${moaiSvg(320)}`; +/* The icon source: the old site's pixel cashu nut, 1000x1000 with transparent margins. */ +const logoPath = path.join(root, 'src', 'assets', 'cashu-logo.png'); /** * A 32x32 ICO wrapping a PNG payload. @@ -138,46 +135,64 @@ function icoFromPng(png) { await mkdir(publicDir, { recursive: true }); -const browser = await chromium.launch(); -try { - const page = await browser.newPage({ - viewport: { width: 1200, height: 630 }, - deviceScaleFactor: 1, - }); +/* + * The icon master: the nut trimmed and centred on the brand ground, at the footprint the + * moai used to occupy (glyph ≈ 380px tall in the 512 tile). Content this size also stays + * inside the circle a maskable icon is cropped to. + */ +const glyph = await sharp(logoPath).trim().resize(384, 384, { fit: 'inside' }).png().toBuffer(); +const master = await sharp({ + create: { width: 512, height: 512, channels: 4, background: '#0E0D0B' }, +}) + .composite([{ input: glyph, gravity: 'centre' }]) + .png() + .toBuffer(); - await page.setContent(cardHtml, { waitUntil: 'load' }); - await page.evaluate(() => document.fonts.ready); - await page.screenshot({ path: path.join(publicDir, 'og.png') }); - console.log('og.png'); +for (const [name, size] of [ + ['icon-512.png', 512], + ['icon-192.png', 192], + ['favicon-32.png', 32], +]) { + await sharp(master).resize(size, size).png({ compressionLevel: 9 }).toFile(path.join(publicDir, name)); + console.log(name); +} - await page.setViewportSize({ width: 512, height: 512 }); - await page.setContent(iconHtml, { waitUntil: 'load' }); - const master = await page.screenshot({ type: 'png' }); +// iOS ignores transparency and composites on white; the master's ground is already opaque. +await sharp(master) + .resize(180, 180) + .png({ compressionLevel: 9 }) + .toFile(path.join(publicDir, 'apple-touch-icon.png')); +console.log('apple-touch-icon.png'); - for (const [name, size] of [ - ['icon-512.png', 512], - ['icon-192.png', 192], - ['favicon-32.png', 32], - ]) { - await sharp(master).resize(size, size).png({ compressionLevel: 9 }).toFile(path.join(publicDir, name)); - console.log(name); - } +const png32 = await sharp(master).resize(32, 32).png({ compressionLevel: 9 }).toBuffer(); +await writeFile(path.join(publicDir, 'favicon.ico'), icoFromPng(png32)); +console.log('favicon.ico'); - // iOS ignores transparency and composites on white, so flatten onto the brand ground. - await sharp(master) - .resize(180, 180) - .flatten({ background: '#0E0D0B' }) - .png({ compressionLevel: 9 }) - .toFile(path.join(publicDir, 'apple-touch-icon.png')); - console.log('apple-touch-icon.png'); +// The standalone SVG favicon: the nut itself, transparent like the old site served it. +// The PNG rides inside the SVG so one source file covers every size; `pixelated` keeps +// the pixel art crisp if anything scales it up. +const logoB64 = (await readFile(logoPath)).toString('base64'); +await writeFile( + path.join(publicDir, 'favicon.svg'), + `` + + ``, +); +console.log('favicon.svg'); - const png32 = await sharp(master).resize(32, 32).png({ compressionLevel: 9 }).toBuffer(); - await writeFile(path.join(publicDir, 'favicon.ico'), icoFromPng(png32)); - console.log('favicon.ico'); +if (!process.argv.includes('--no-card')) { + const browser = await chromium.launch(); + try { + const page = await browser.newPage({ + viewport: { width: 1200, height: 630 }, + deviceScaleFactor: 1, + }); - // The standalone SVG favicon: the same mark, at any size, for browsers that take it. - await writeFile(path.join(publicDir, 'favicon.svg'), moaiSvg(11)); - console.log('favicon.svg'); -} finally { - await browser.close(); + await page.setContent(cardHtml, { waitUntil: 'load' }); + await page.evaluate(() => document.fonts.ready); + await page.screenshot({ path: path.join(publicDir, 'og.png') }); + console.log('og.png'); + } finally { + await browser.close(); + } } diff --git a/web/src/assets/cashu-logo.png b/web/src/assets/cashu-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..150951123a7d9675cef19e812fe2cc29e8a4d013 GIT binary patch literal 8087 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 literal 0 HcmV?d00001 diff --git a/web/src/components/CopyableId.astro b/web/src/components/CopyableId.astro index 88a27c0..db0cee6 100644 --- a/web/src/components/CopyableId.astro +++ b/web/src/components/CopyableId.astro @@ -32,12 +32,14 @@ const t = useI18n(locale); const { value, label, kind = t('mint.kind.identifier'), class: className } = Astro.props; --- +{/* The accessible name repeats the visible text: a voice-control user says what + they see, and a name that omits it cannot be spoken at. */} diff --git a/web/src/components/LanguageSwitcher.astro b/web/src/components/LanguageSwitcher.astro index 4518c8d..9b35097 100644 --- a/web/src/components/LanguageSwitcher.astro +++ b/web/src/components/LanguageSwitcher.astro @@ -3,7 +3,7 @@ * The language switcher, in two shapes. * * `menu` is the header control: a compact button showing the current language's code, - * opening a list of the three. `inline` is the footer's plain row of three links. Both + * opening a searchable list. `inline` is the footer's plain row of links. Both * are built from the same list and the same hrefs, because they are the same control * and a reader who finds one and then the other should not have to work out whether * they do the same thing. @@ -67,25 +67,44 @@ const currentCode = locale.toUpperCase(); - +
+ + +
) : (