Skip to content

Commit 47d3f5e

Browse files
committed
v2.28.0 — the app speaks eleven languages, and debug mode is everyone's
Added - Russian (#31) and Dutch (#32), contributed by @Ptitlouis6012 and merged as their own work: 1523 keys each, reviewed against en.json key by key and run in the app before shipping. Two fixes came out of that review -- Russian counts use the impersonal form because the engine has two plural forms where Russian has three, and the printer speed dropdown now sizes to its own widest option instead of a width tuned to the English "Standard". Changed - Debug mode is every account's switch, not the admins'. The gate bought no safety -- the panel reads the signed-in user's own documents, through the same Security Rules as the rest of the app -- and it meant the people reporting bugs could not produce what makes a report useful. - The Firebase Explorer reaches the devices (scales, racks, lists, tigerspools) and, in a new tab, the Realtime database: two services, only one of which was reachable. Reading tigerspools is how we found the deployed rules denied that path; fixed in the backend repo and deployed. - The What's New tooling knows about locales that arrived late: LOCALE_SINCE records the version a locale shipped in, so the 507 existing entries stay valid while everything from this release must carry all eleven.
1 parent 51af7be commit 47d3f5e

9 files changed

Lines changed: 103 additions & 12 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,20 @@ Versions follow [Semantic Versioning](https://semver.org/).
55

66
---
77

8+
## v2.28.0 — 2026-09-23
9+
10+
### Added
11+
12+
- **Two new locales, contributed: Russian (#31) and Dutch (#32).** `ru.json` and `nl.json`, 1523 keys each, merged as their author's own work and wired into the language picker, the onboarding language step, the renderer's locale loader and the i18n scripts. Both were reviewed against `en.json` before merging — identical key set, no empty value, every `{{param}}` preserved, the 19 plural objects and 6 arrays kept as such — and both were run in the app before shipping. Two fixes came out of that: the Russian translation's counts use the impersonal form its author already used elsewhere (`Материалов: {{n}}`) because the app's engine has two plural forms where Russian has three, and the printer speed dropdown now sizes to its own widest option — a width tuned to the English "Standard" clipped `Сбалансированная`. `scripts/check-docs-drift.mjs` also stopped holding the locale count as a constant and COUNTS the files, which is what makes the next locale cheap — `renderer/locales/{ru,nl}.json`, `renderer/inventory.{html,js}`, `scripts/{i18n-add,check-i18n-consistency,check-docs-drift}.mjs`, `renderer/css/57-elegoo.css`, `renderer/printers/anycubic/anycubic.css`.
13+
14+
### Changed
15+
16+
- **Debug mode is every account's switch, not the admins'.** The toggle in the account modal was rendered only for `roles: "admin"`, and `state.debugEnabled` was itself `isAdmin && !!Debug`, so a normal user could never turn on the one view that makes a bug report useful — their own raw Firestore documents, the last call to the API, the per-card "copy ref" helper. The gate bought no safety: the panel reads the SIGNED-IN user's own documents and every path goes through the same Security Rules as the rest of the app; the checkbox was never what stood between a user and someone else's data. The row is always rendered now and `Debug` is read as the plain user preference it is. `roles` still gates the Admin badge, and nothing else — `renderer/inventory.js`, `CLAUDE.md`.
17+
- **The Firebase Explorer reaches the devices, and the Realtime database.** Quick chips added for `scales`, `racks`, `lists` and `tigerspools` — the last being where a TigerSpool writes itself from firmware 1.65.0, keyed by its Wi-Fi MAC (`printers_active`, `printer_ids`, `last_used_at` beside the scale's own identity/liveness fields). Reading it is how we found the deployed rules denied that path entirely; fixed in the backend repo (`tigerspools`, plural — the rule had been written singular and matched nothing) and deployed. A **Realtime** tab joins Firestore: two services, and only the first was reachable, so a scale's command channel could not be looked at from the app at all. It is read over REST with the signed-in user's ID token, each node probed with `shallow=true` first — a branch of 25 children or fewer is then read whole, anything larger stays a list of names to drill into, so no stray click pulls a tree. Measured against the live database: its rules are per-NODE (`scales/{mac}/cmd` reads, `scales/{mac}` and `scales` do not), so the chips are built from the account's own scales and point at the readable node — `renderer/inventory.{html,js}`, `renderer/css/70-detail-misc.css`.
18+
- **The "What's New" tooling knows about locales that arrived late.** Adding a locale to the three `whatsnew-*.mjs` scripts alone would fail the whole back-catalogue: the check demands that an item carrying ANY non-English locale carries them all, and the 507 items written before Russian and Dutch existed carry neither. A `LOCALE_SINCE` map (`{ ru: "2.28.0", nl: "2.28.0" }`) records which version a locale shipped in, and each version block is held to the locales that existed then — history stays valid, everything from this release must be complete in all 11. `whatsnew:add` scaffolds 11 locales and `whatsnew:import` recognises an entry in either new locale as hand-localised — `scripts/whatsnew-{add,check,import-changelog}.mjs`.
19+
20+
---
21+
822
## v2.27.3 — 2026-09-18
923

1024
### Changed

‎CLAUDE.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ assets/db/tigertag/ — TigerTag reference data (unified in v1.7.0, se
398398
data/ — non-migrated static assets (loaded via direct fetch in renderer)
399399
container_spool/spools_filament.json
400400
rack-presets.json
401-
whatsnew.json — "What's New" modal content (register 3 — playful/Discord), keyed by version, 11 locales inline (full history, browsable via the in-modal version picker). `npm run whatsnew:import` seeds an EN baseline from CHANGELOG (register 1) — a **rough draft to rewrite into register 3**, never shipped verbatim; recent versions hand-localised. Scaffold `npm run whatsnew:add`, validate `npm run whatsnew:check` (EN mandatory; entries are EN-only or fully localised — a locale that shipped later, like `ru` and `nl` from v2.27.4, is not required on older entries)
401+
whatsnew.json — "What's New" modal content (register 3 — playful/Discord), keyed by version, 11 locales inline (full history, browsable via the in-modal version picker). `npm run whatsnew:import` seeds an EN baseline from CHANGELOG (register 1) — a **rough draft to rewrite into register 3**, never shipped verbatim; recent versions hand-localised. Scaffold `npm run whatsnew:add`, validate `npm run whatsnew:check` (EN mandatory; entries are EN-only or fully localised — a locale that shipped later, like `ru` and `nl` from v2.28.0, is not required on older entries)
402402
release-notes/ — one `vX.Y.Z.md` per version: the BambuLab-style **release note** (register 2), pushed verbatim to the GitHub Release page by `scripts/extract-changelog.mjs`. See *Three copy registers*.
403403
printers/ — per-brand printer model catalogs (bbl/cre/eleg/ffg/snap)
404404
assets/svg/

‎FEATURES.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Tiger Studio Manager — Feature Catalogue
22

3-
Tiger Studio Manager is the Electron desktop companion to the TigerTag ecosystem: a filament-inventory manager built around RFID/NFC-tagged spools ("TigerTag" chips), a fully-digital "TigerData" tier (and its catalogue-identified "TigerData+" rung), live 3D-printer integration across six brands, physical storage/rack management, a Firebase-backed social layer (friends, shareable wishlists, public profiles), and companion hardware (TD1S color sensor, TigerScale, TigerPOD dual-reader stand). This document catalogues every **shipped** feature, grouped by domain, current as of **v2.27.3**. Per-version release detail lives in `CHANGELOG.md`; forward-looking / in-progress work lives in `ROADMAP.md`.
3+
Tiger Studio Manager is the Electron desktop companion to the TigerTag ecosystem: a filament-inventory manager built around RFID/NFC-tagged spools ("TigerTag" chips), a fully-digital "TigerData" tier (and its catalogue-identified "TigerData+" rung), live 3D-printer integration across six brands, physical storage/rack management, a Firebase-backed social layer (friends, shareable wishlists, public profiles), and companion hardware (TD1S color sensor, TigerScale, TigerPOD dual-reader stand). This document catalogues every **shipped** feature, grouped by domain, current as of **v2.28.0**. Per-version release detail lives in `CHANGELOG.md`; forward-looking / in-progress work lives in `ROADMAP.md`.
44

55
---
66

@@ -261,7 +261,7 @@ Live integrations across six brands, each with real-time temperatures, per-slot
261261

262262
## Internationalization (i18n)
263263

264-
- **11 locales** shipped and kept in lock-step: English, French, German, Spanish, Italian, Chinese, Portuguese (Brasil), Portuguese (Portugal), Polish, Russian and Dutch (both contributed, v2.27.4).
264+
- **11 locales** shipped and kept in lock-step: English, French, German, Spanish, Italian, Chinese, Portuguese (Brasil), Portuguese (Portugal), Polish, Russian and Dutch (both contributed, v2.28.0).
265265
- Plural inflection (`{one, other}`) applied consistently to every duration key (v1.4.9).
266266
- `npm run i18n:add` — single command that writes a new/updated key across all 11 locale files at once (v1.4.9).
267267
- `npm run i18n:check` + a pre-commit hook blocking any commit that lets the 11 locale files drift apart (v1.4.9).

‎WORKLOG.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# Worklog — v2.27.4 (in progress)
1+
# Worklog — v2.28.0 (released)
22

33
## Added
44
- **Dutch, the 11th locale** — `nl.json`, 1523 keys, contributed by @Ptitlouis6012 in #32 and merged as theirs. Reviewed to the same bar as Russian before merging: key set identical to `en.json`, no empty value, every `{{param}}` preserved, the 19 plural objects and 6 arrays kept as such, and the tone held in the playful strings ("Zullen we," for "Let's go,"). The 92 strings identical to English are genuine cognates — Type, Model, Status, Details, Container, Diameter, Online — not untranslated leftovers. Verified by running the app in Dutch: the picker offers Nederlands, every view renders translated and nothing clips.
5-
- Finished on top, the same three gaps the Russian PR left: the whatsnew scripts learn `nl` (and `LOCALE_SINCE` gains `nl: "2.27.4"`, so the 507 items written before it stay valid while everything from this release must carry it), and the locale counts move 10 → 11 wherever a living doc or comment states one — `scripts/whatsnew-{add,check,import-changelog}.mjs`, `CLAUDE.md`, `README.md`, `FEATURES.md`, `ROADMAP.md`, `renderer/CODEMAP.md`, the four `docs/*-BRIEF.md`
5+
- Finished on top, the same three gaps the Russian PR left: the whatsnew scripts learn `nl` (and `LOCALE_SINCE` gains `nl: "2.28.0"`, so the 507 items written before it stay valid while everything from this release must carry it), and the locale counts move 10 → 11 wherever a living doc or comment states one — `scripts/whatsnew-{add,check,import-changelog}.mjs`, `CLAUDE.md`, `README.md`, `FEATURES.md`, `ROADMAP.md`, `renderer/CODEMAP.md`, the four `docs/*-BRIEF.md`
66

77
- **Russian, the 10th locale** — `ru.json`, 1523 keys, contributed by @Ptitlouis6012 in #31 and merged as theirs. Wired into the language picker, the onboarding step, the locale loader and the three i18n scripts; the doc-drift checker now COUNTS the locale files instead of holding "9" as a constant, which is the part that keeps the next locale cheap. Reviewed before merging: key set identical to `en.json`, no empty value, every `{{param}}` preserved, the 19 plural objects and 6 arrays kept as such, and the tone held — the translation avoids ты/вы entirely through impersonal forms, which is the safe register in Russian.
88

@@ -12,7 +12,7 @@
1212
- **The Firebase Explorer reaches the TigerSpools**, the collection a TigerSpool writes itself into from firmware 1.65.0 (`users/{uid}/tigerspools/{mac}`, keyed by the Wi-Fi MAC). Presence only, which is all the device publishes today; the app does not list the boxes yet. Reading it is also the fastest way to answer whether a box is declaring itself at all — and the first thing it answered here is that the rules deny the path entirely — `renderer/inventory.js`
1313
- **The Firebase Explorer reaches the scales, the racks and the lists.** Its quick chips covered the inventory, the printers and the products but stopped there, so a TigerScale's document — the one holding what the firmware reports about a physical device — could only be seen by typing its path by hand, which means knowing it. Three chips added: `scales`, `racks`, `lists`. A scale's live command channel (TARE) is in the REALTIME database rather than Firestore, so it stays out of reach of this explorer by nature, and the chip comment says so — `renderer/inventory.js`
1414
- **Debug mode is every account's switch, not the admins'.** The toggle in the account modal was shown only to `roles: "admin"`, and `state.debugEnabled` was itself `isAdmin && Debug` — so a normal user could never turn on the one view that makes a bug report useful (their own raw Firestore documents, the last call to the API, the per-card "copy ref" helper). The gate bought no safety: the panel reads the SIGNED-IN user's own documents and every path goes through the same Security Rules as the rest of the app — the checkbox was never what stood between a user and someone else's data. The row is always shown now and `Debug` is read as the plain user preference it is; `roles` still gates the Admin badge, and nothing else. The panel button itself was already unconditional — `renderer/inventory.js`, `CLAUDE.md`
15-
- **The "What's New" tooling knows about locales that arrived late.** Adding `ru` to the three whatsnew scripts alone would have failed the whole back-catalogue: the check demands that an item which carries ANY non-English locale carries them all, and 507 items written before Russian existed carry none. A `LOCALE_SINCE` map (`{ ru: "2.27.4" }`) now says which version a locale shipped in, and each version block is held to the locales that existed then — history stays valid, everything from v2.27.4 on must be complete in all 10. `whatsnew:add` scaffolds 10 locales, and `whatsnew:import` recognises a Russian entry as hand-localised so it is never overwritten — `scripts/whatsnew-{add,check,import-changelog}.mjs`
15+
- **The "What's New" tooling knows about locales that arrived late.** Adding `ru` to the three whatsnew scripts alone would have failed the whole back-catalogue: the check demands that an item which carries ANY non-English locale carries them all, and 507 items written before Russian existed carry none. A `LOCALE_SINCE` map (`{ ru: "2.28.0" }`) now says which version a locale shipped in, and each version block is held to the locales that existed then — history stays valid, everything from v2.28.0 on must be complete in all 11. `whatsnew:add` scaffolds 10 locales, and `whatsnew:import` recognises a Russian entry as hand-localised so it is never overwritten — `scripts/whatsnew-{add,check,import-changelog}.mjs`
1616
- **Seven Russian plurals corrected** (kept in the contributor's own style, which sidesteps the problem elsewhere in the file): Russian has three plural forms where the app's engine has two, so "{{n}} материалов" is wrong for 2-4. The counts now read "Материалов: {{n}}", "Друзей: {{n}}", "Подписчиков: {{n}}" — the impersonal form the translation already uses for loaded spools and hidden items — the durations use the invariant abbreviations "{{n}} сек" / "{{n}} мин", and the rack tile's label, which sits under its own number, is the plain plural "стеллажи" — `renderer/locales/ru.json`
1717
- **The printer speed dropdown sizes itself to its own label.** Found by running the app in Russian: a fixed 110 px (96 px on Anycubic) clipped "Сбалансированная" to "Сбалансирова…" — the width had been tuned to the English "Standard", and every locale is free to be longer. It now sizes to its widest option, floored at the old width so no other locale moves, and capped so a long label cannot push the card — `renderer/css/57-elegoo.css`, `renderer/printers/anycubic/anycubic.css`
1818
- Locale counts updated wherever a doc or a comment stated nine — `CLAUDE.md`, `README.md`, `FEATURES.md`, `ROADMAP.md`, `renderer/CODEMAP.md`, `renderer/inventory.js`, the four `docs/*-BRIEF.md`
@@ -23,4 +23,4 @@
2323
## Removed
2424

2525
## i18n
26-
- Pending cleanup, carried over from v2.23.1: `scaleNoActivity` and `scaleReader` are orphaned — still shipped in all 9 locales, no longer referenced anywhere in `renderer/`
26+
- Pending cleanup, carried over from v2.23.1: `scaleNoActivity` and `scaleReader` are orphaned — still shipped in all 11 locales, no longer referenced anywhere in `renderer/`

‎data/release-notes/v2.28.0.md‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Two new languages, contributed by the community.
2+
3+
## Added
4+
5+
- **Russian** and **Dutch** — the app is now available in 11 languages. Both were contributed by a community member and reviewed string by string before shipping. Pick yours in your account settings.
6+
7+
## Changed
8+
9+
- Debug mode can now be turned on by anyone, from the account settings. It shows what the app sees — your own data, the last call to the server — which is exactly what a useful bug report needs.
10+
- Fixed a case where a long translation was cut off in the printer speed selector.
11+
12+
---
13+
14+
📖 **[Full changelog](https://github.com/TigerTag-Project/TigerTag-Studio-Manager/blob/main/CHANGELOG.md)** · ⬇️ Grab the installer for your OS from the **Assets** below (macOS `.dmg`, Windows `Setup .exe` or `portable .exe`, Linux `.AppImage`).

0 commit comments

Comments
 (0)