Minor Changes
-
#916
71f4e7dThanks @Rimander! - Adds i18n support to menus and taxonomies (categories, tags, custom
definitions), mirroring the per-locale model already in place for content.
Each row carrieslocaleandtranslation_group; translations of the
same menu/term/def share atranslation_group._emdash_menu_items.reference_id
andcontent_taxonomies.taxonomy_idare remapped to store the referenced
row's translation_group, so a single association survives content
translations and is resolved against the active locale at runtime.- Runtime helpers (
getMenu,getTaxonomyTerms,getTerm,getEntryTerms,
getAllTermsForEntries, …) accept an optional{ locale }and honour the
i18n fallback chain; when no locale is given they fall back to the
request context anddefaultLocale, matchinggetEmDashCollection/
getEmDashEntry. - REST API: GET endpoints accept
?locale=xx; POST endpoints accept
localeandtranslationOfin their bodies. New endpoints:
GET/POST /_emdash/api/menus/:name/translationsand
GET/POST /_emdash/api/taxonomies/:name/terms/:slug/translations. - Creating a content translation now auto-copies the source's taxonomy
assignments (the pivot is locale-agnostic, so the copied rows apply to
the whole translation group). - MCP:
taxonomy_list,taxonomy_list_terms,taxonomy_create_term,
menu_list,menu_getacceptlocale. New tools:
taxonomy_term_translations,menu_translations. - Admin:
TaxonomyManagerandMenuListsurface aLocaleSwitcherwhen
multiple locales are configured and thread the active locale through
all API calls.TaxonomyManagerexposes a "Translate" action per term
that creates the translation and switches to the new locale.
No breaking changes for new installs or single-locale upgrades — defaults
are additive (locale defaults to'en'when omitted, reproducing pre-i18n
behaviour).⚠️ Rolling back migration
036_i18n_menus_and_taxonomiesis blocked
on multi-locale installs. Dropping thelocalecolumn would collapse
translated rows onto an ambiguous(name, slug)unique key, silently
deleting content. The migration'sdown()now refuses to run when any
row uses a non-default locale and prints the affected table in the
error. If you need to revert, export translations first (or delete
them), then re-run the rollback. Single-locale installs revert cleanly. - Runtime helpers (
-
#902
7e32092Thanks @ascorbic! -emdash plugin initnow prompts for the plugin format (sandboxed or native) when run interactively, and the scaffolded boilerplate matches the canonical patterns from the docs. Both formats now ship adist/build via tsdown, declare a samplestoragecollection, and demonstrate a hook plus an API route. The sandboxed entry uses an explicitly typedContentSaveEvent; the native entry forwards options throughcreatePlugin. The descriptoridis now derived from the slug instead of the full scoped package name, so scoped names like@org/my-pluginproduce a runtime-valid id. Pass--format=sandboxed,--format=native, or--nativeto skip the prompt; non-TTY runs continue to default to sandboxed.
Patch Changes
-
#701
a2d3658Thanks @lsngmin! - Fixes MediaValue.src returning bare media ID instead of a usable URL for local media -
#912
c8a3a2cThanks @lsngmin! - Permanent-delete API now refuses to remove live (non-trashed) rows and uses a content-domaincontent:delete_permanentpermission instead of the unrelatedimport:execute. Existing audience (ADMIN-only) is unchanged. -
#896
699e1b3Thanks @cristianuibar! - Fixes 500 error onGET /_emdash/api/dashboardwhen running on Cloudflare D1 with many title-bearing collections.fetchRecentItemsnow issues one query per collection in parallel and merges results in JS instead of building a single chainedUNION ALL, which trips D1'sSQLITE_LIMIT_COMPOUND_SELECTcap once enough collections are present (#895). -
#719
2e2b8e9Thanks @ascorbic! - Fixes thefilefield type rendering as a plain text input in the content editor. Adds aFileFieldRendererthat opens the media picker (with mime filter disabled) so any file type can be attached. Also adds ahideUrlInputprop toMediaPickerModalso non-image pickers can hide the image-specific "Insert from URL" input.Aligns the Zod schema and generated TypeScript types for
imageandfilefields with the shape the admin actually stores:provider?,meta?(for both), andpreviewUrl?(for image). Previously these fields were stripped on validation and missing from generated types, so site code could not reliably resolve local media URLs frommeta.storageKey. -
#911
9146931Thanks @masonjames! - Fixes WordPress media URL rewriting for imported image URLs that use generated size suffixes. -
Updated dependencies [
c8a3a2c,2e2b8e9]:- @emdash-cms/auth@0.10.0
- @emdash-cms/admin@0.10.0
- @emdash-cms/auth-atproto@0.2.2
- @emdash-cms/gutenberg-to-portable-text@0.10.0