Release v0.30 – v0.32
v0.30 – v0.32 Release: The Web Console Speaks Your Language
October 17, 2026 · The Smarter Project
v0.27 to v0.29 made Smarter extensible. v0.30 to v0.32, released on October 16 and 17, are about the people who use the web console. The console is now translated into Spanish, French and Brazilian Portuguese, and it picks your language from your browser. You can upload a profile image. List pages are much faster, and the dashboard’s last two widgets work as they should.
| Change | What it means for you |
|---|---|
| Four languages | The whole web console is in English, Spanish, French and Brazilian Portuguese, chosen from your browser or a language menu. |
| Translatable by design | Every template, view message, React app and script goes through gettext, so a new language is translation work, not code. |
| Profile images | Upload your own image from the user menu. Users without one get a default avatar instead of a broken image. |
| Faster list pages | The can this be deleted? check on every row is 20 to 70 times faster. |
| Service Health and Token Usage | Service Health is redesigned, and the Token Usage chart, which had never shown data, does now. |
The web console in four languages
The web console was English only. Its templates, view messages, React apps and scripts held hard-coded English text, and nobody could choose a language. Now the whole console is translated:
- English, the source language and the default.
- Spanish, in Latin American Spanish, with the informal tú.
- French, with vous and French typography.
- Brazilian Portuguese, with você and Brazilian vocabulary.
Each translation covers every message, about 1,580 of them, from sign-in and password reset to every list page, dialog, chart and error message.
How the console picks a language
- Your browser first. The console uses your browser’s preferred language when it can. Any variant of Spanish (
es-MX,es-AR,es-419,es-ES) gets Spanish, any variant of French (such asfr-CA) gets French, andpt,pt-BRandpt-PTget Brazilian Portuguese. Any other language gets English. - Or choose one. The language menu in your user menu lists each language in its own name, English, Español, Français and Português (Brasil), and remembers your choice in a cookie.
- Dates too. Relative times such as 1 day ago are shown in your language.
- Smarter Chat follows. The chat’s own buttons, labels and errors use the language of the page that hosts it, so the workbench chat matches the console.
Product names and resource kind names, such as LLMClient, MCPClient and AuthToken, stay in English, as do code samples and manifest keys. Your own resources and manifests aren’t translated, and neither are the API’s responses or the documentation at docs.smarter.sh. An LLM answers in the language it’s asked in, so write an LLMClient’s welcome message and example prompts in your users’ language.
Native speakers wanted
The translations were checked automatically against their English source: the same placeholders, the same escapes and the same inline HTML in every message, with both plural forms. They haven’t been reviewed by native speakers yet. If you find a phrase that reads wrong, open an issue or a pull request on GitHub. The catalogs are plain .po files under smarter/smarter/locale/.
Adding a language
Every piece of the console’s text goes through gettext. Templates use Django’s translate tags, Python uses gettext with named placeholders, and the React apps use gettext, ngettext and interpolate from @smarter/common. Messages that used to be put together from pieces, such as Successfully cloned plus a kind name, are now whole sentences, because translators can’t translate fragments.
Adding a language takes three steps:
- Add it to the
LANGUAGESsetting. - Run
make i18n-messages, which extracts every message from the templates, Python, TypeScript and scripts, and writes the new language’s catalogs. - Translate the two new
.pofiles.
The test suite rejects a catalog with an untranslated or fuzzy entry, and the message extractor refuses a React message that isn’t a plain string literal, so a change that can’t be translated fails before it ships.
📖 Web console languages · How the console is translated
Your profile image
The user menu was meant to show your profile image, but it never did. The image could only come from social sign-in, and when there was none, the console showed a broken image, and the menu showed your email address. GitHub sign-ins never supplied an image even when social sign-in was on, because GitHub sends it under a different name from Google and LinkedIn.
- Upload your own. Click your image in the user menu, or Change Profile Image, and pick a file. It uploads at once. Remove Profile Image goes back to your social sign-in image or the default.
- A clear order of precedence: your upload, then your social sign-in image (now including GitHub’s), then a neutral default avatar.
- Your image is the user menu’s button again, with your email address in its tooltip and its accessible name.
- Your sign-in won’t overwrite it. Uploads are stored separately from the social sign-in image, which is rewritten on every sign-in.
Security
Images are validated with Pillow, and the console accepts PNG, JPEG, GIF and WebP up to 2 MB. It checks the type that Pillow detects, not the one the browser claims. SVG is refused, because an SVG can carry a script. Uploads are stored under a random name, so the public URL says nothing about you or the original file.
Faster list pages
Every row of a list page shows whether you can delete it, and computing that was slow. For each row, Smarter built a full broker for the resource, then another full broker for every resource that depended on it. A 25-row Guardrail page spent about 1.9 seconds on that alone.
Now the check asks the database whether anything refers to the row, and builds no brokers at all:
| Row | Before | After |
|---|---|---|
| LLMClient | 23 ms, 4 queries | 0.9 ms, 2.1 queries |
| Guardrail | 74 ms, 15 queries | 1.1 ms, 2.0 queries |
| Secret | 50 ms, 21 queries | 3.0 ms, 5.8 queries |
Building a single broker is faster too, from 19 ms to 3.5 ms for a Guardrail, because waffle switch lookups are now cached in each process for 5 seconds, instead of a round trip to Redis for every gated log line. A deletion is still refused while anything depends on the resource: the delete check and the list pages now ask the same question in the same way.
Dashboard: Service Health and Token Usage
- Service Health is redesigned to match the rest of the dashboard. It shows the Smarter version and the runtime versions, a badge that says All systems operational or how many checks are failing, and a ring that is green, amber or red by score. Each backend check (database, cache, task broker, workers) is a tile that says Healthy or Down, with a tooltip that explains what it tests. A refresh button runs the checks again, and the page refreshes them every five minutes. If Redis is down, the Cache tile says so, instead of the whole widget failing.
- Token Usage shows data. The chart never had any, for four separate reasons, from a URL that answered 404 to a query that left out the current hour. It now charts 12 or 24 hours by the hour, 7 or 30 days by the day, or 12 months, and counts both aggregated charges and those not aggregated yet. Periods are labeled in your language.
- The N pending link works. My Resources’ pending deployments link opened the whole LLMClient list. It now opens the list filtered to pending LLMClients, with a chip that shows the filter and dismisses it. List APIs accept a named
filterparameter, and their pagination reports the filter that applied and those available. - The Extensions card links each official Extension to its GitHub repository.
Fixes and operations
- The LLM Tools page loaded no lists after the v0.29 upgrade. Smarter cached URL lookups in Redis for a year, under a key that didn’t change between releases, so production kept sending the page’s list requests to the old
/plugin/URL. The redirect turned them into GETs, which the list API didn’t accept. URL lookups are no longer cached across deployments, and every list API now also answers GET. - A missing template is a real error. A page whose template didn’t exist answered 200, with a description of a 500 response as its body. It now answers 500. That change turned up 21 hidden failures, which are fixed: list APIs without a GET handler, and six account pages and three dashboard pages whose templates were deleted in 2024, which are removed.
- Saving a user profile without a name raised an error, which affected every profile created by social sign-in.
- HTML entities such as
→showed literally in two dashboard labels. The message extractor now refuses an entity in a React message. - CI badges on the dashboard link to the platform’s own repository, read from
git remote, and hide any badge whose image doesn’t load. - Docker images compile the translations in the right build stage. Production image builds failed because the files were read-only by the time they were compiled.
Upgrading
- Migrations:
accountgains a migration for the profile image. Runmanage.py migrateas usual. - Translations are compiled when the image is built. The image build installs gettext and compiles the
.pocatalogs. If you build Smarter outside the Dockerfile, install gettext and runmanage.py compilemessages. - Profile images and storage. Uploads go to the platform’s default storage. On an install without AWS, files go to the local filesystem, which the platform doesn’t serve, so uploaded images won’t display there yet. Provider logos have the same limitation.
- Offering fewer languages. The languages the console offers are its
LANGUAGESsetting. With only one language, the language menu is hidden. - SDKs: the account profile’s new
profile_imagefield and the list APIs’ new pagination fields are additive. Update the Python, Node.js and Go SDKs to pick them up.
What’s next
That brings the announcements up to date with v0.32.
The full list of changes is in the v0.30 and v0.31 changelogs, and the v0.32 changelog. To try the release, start with the documentation, or browse the code on GitHub.
