Suprnova v1.0.0
Added
-
Localization. Message catalogs in
lang/<locale>/*.ftl
(Fluent), aLangfacade with the
__!("key", name: value)macro, per-request locale detection
(LocaleMiddleware: session → cookie →Accept-Language→
APP_LOCALE), and locale-aware formatting for numbers, currency,
dates, times, lists, and relative times over ICU4X.manual/localization.md
is the chapter.The built-in validation rules stop hardcoding English. Each returns a
keyed message (validation-minplus its arguments and an English
fallback), translated once at the serialization boundary — so a Spanish
app gets Spanish validation errors by dropping in
lang/es/validation.ftl, with no rule wrapping and no forked copy of
the framework's messages. Field names humanize through afield-<name>
lookup.Rule::passes(andContextualRule/AsyncRule) now return
Result<(), ValidationMessage>; a custom rule'sErr("…".into())body
still compiles and still renders verbatim, but the signature in your
implneeds the new type.The browser gets the same bytes the server resolved: the merged catalog
is served at/_suprnova/lang/<locale>.ftlwith an ETag and an
immutable?v=<hash>form, the three starter kits parse it with
@fluent/bundle, andsuprnova generate-typesemits aMessageKey
union so renaming a message points the TypeScript compiler at every
call site.Fluent rather than Laravel-style PHP arrays because one format has to
serve both the server and the browser, and because CLDR plural
categories are what gets Russian, Polish, and Arabic right —
trans_choice's integer ranges cannot, which is why there is no
trans_choicehere. Behind a default-onlocalizationfeature;
--no-default-featuresstill compiles and still validates, using the
embedded English fallbacks. -
IntoInertiaScrollforPaginator. The trait was implemented for
LengthAwarePaginatorandCursorPaginatorbut not for the simple
paginator, sosimple_paginateresults could not feed
Inertia::paginateat all — despitesimple.rs's own module docs
pointing at it as the URL-generation path. That left offset-paginated
Inertia collections with a choice between aCOUNT(*)per request and
hand-rolling the scroll metadata.next_pagecomes from the
LIMIT n+1overflow probe rather than a computed last page, there
being no total to compute one from.
Fixed
-
suprnova generate-typesemitted a different file on every run.
The topological sort seeded its work queue by iterating aHashMap,
and Rust randomises hash iteration order per process, so consecutive
runs ordered the same interfaces differently. The output is a
checked-in artifact, so every run produced a diff — and a generated
file that churns for no reason is one people stop regenerating, after
which it quietly stops describing the Rust it claims to. The directory
walk is sorted too, so the output no longer depends on filesystem
order either. Two runs of the same source are now byte-identical. -
topological_sortdid the opposite of its doc comment, emitting
dependents before dependencies. Harmless — a TypeScript interface may
reference one declared later in the same file — so the comment is
corrected rather than the order, which would have reshuffled a tracked
file for no benefit.