Skip to content

🚀 Release 2026-03-26#221

Merged
tnkshuuhei merged 18 commits intomainfrom
dev
Mar 26, 2026
Merged

🚀 Release 2026-03-26#221
tnkshuuhei merged 18 commits intomainfrom
dev

Conversation

@github-actions
Copy link

@github-actions github-actions bot commented Mar 26, 2026

🚀 Release 2026-03-26

Changes

feat: i18n support (#217)

  • Add locale routing (en, ja) with next-intl
  • Translate Semantic Scholar switcher, tooltips, Evidence Dialog, and more
  • ICU MessageFormat for pluralization
  • Improve translation key naming and extract shared modules
  • Improve UX wording (intent → goal, Hypercerts translations)

fix: workflow error messages (#219)

  • Show detailed error messages in workflow dialog instead of generic ones

fix: export image quality (#223)

  • Remove branding and improve canvas export image quality

docs

  • Update CLAUDE.md and README.md for i18n support and directory structure

tnkshuuhei and others added 14 commits March 25, 2026 20:52
Replace middleware with Next.js 16 proxy convention for locale detection.
Use @formatjs/intl-localematcher + negotiator for Accept-Language header
negotiation, supporting en/ja locales with sub-path routing (/en/*, /ja/*).
All pages moved under app/[lang]/ with next-intl for translations.
# Conflicts:
#	components/canvas/EvidenceDialog.tsx
#	components/canvas/EvidenceEdge.tsx
#	components/canvas/GenerateLogicModelDialog.tsx
#	components/canvas/ImagePreview.tsx
Use next-intl's built-in createMiddleware(routing) instead of manual
Negotiator + intl-localematcher implementation. This adds cookie-based
locale persistence, SEO alternate link headers, and efficient rewrites.
Remove unused dependencies: @formatjs/intl-localematcher, negotiator.
…ic 'Workflow failed'

Fix error extraction path in SSE streaming route - Mastra places the
Error object at event.payload.error, not event.payload.output.error.
Add error categorization (high demand, rate limit, timeout, etc.) with
i18n-aware user-friendly messages in both English and Japanese.

Closes #218
Fix workflow error dialog showing generic 'Workflow failed'
…ercert to インパクト証明書, simplify strength levels

- Rename `intent` to `goal` across codebase (variable names, API schema, workflow, prompts, docs)
- Update UI labels: "What do you want to achieve?" / "何を実現したいですか?"
- Translate "ハイパーサート" to "インパクト証明書" in Japanese locale
- Remove "Level X -" prefix from strength level dropdown (star rating is sufficient)
- Update button text and placeholder with EBP-aligned example
Remove duplicate effectTranslationKeys definitions from effect-filter.tsx
and effects/page.tsx, consolidating into effect-icons.tsx as the single
source of truth.
Replace manual ternary-based plural branching with ICU plural syntax
in translation keys (itemCount, metricCount, filterActive). Removes
duplicate singular/plural keys.
Rename effects.no → effects.noEffect, effects.noDescription →
effects.noEffectDescription, hypercerts.noFound → hypercerts.notFound
for clarity.
Hide specific API/service names (Semantic Scholar) from user-facing
text, using generic terms like "external academic papers" instead.
feat: add i18n support with proxy-based locale routing
@vercel
Copy link

vercel bot commented Mar 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
muse Ready Ready Preview, Comment Mar 26, 2026 7:22am

@github-actions
Copy link
Author

🔄 Release PR Updated

New changes have been pushed to dev branch since this PR was created.

🤖 Updated by GitHub Actions

@claude
Copy link

claude bot commented Mar 26, 2026

PR Review: i18n + Goal Rename + Error Categorization

Great work overall. This is a substantial PR that adds next-intl internationalization, renames intent to goal throughout, and improves workflow error handling. The architecture is sound and translation key coverage is thorough.

Critical Bug

Middleware in wrong file — locale routing will not work

The next-intl middleware is written to proxy.ts instead of middleware.ts. Next.js only recognizes middleware.ts at the project root. With proxy.ts, the middleware is dead code — users visiting / will hit a 404 (since app/page.tsx was deleted and replaced with app/[lang]/page.tsx), and locale detection/redirects will not function.

Fix: rename proxy.ts to middleware.ts.

Issues

1. hypercert.tsx unnecessarily converted to a client component

app/[lang]/hypercerts/hypercert.tsx was changed to "use client" solely to call useTranslations. This adds to JS bundle size and removes server rendering benefits for display-only content. Use getTranslations from next-intl/server and keep it as a server component, or pass translated strings as props from the parent HypercertsList server component.

2. Zod validation error messages not translated

In GenerateLogicModelDialog.tsx, the schema still uses hardcoded English strings that surface as visible form validation errors:

goal: z.string()
  .min(1, "Please enter your goal")
  .max(1000, "Goal must be 1000 characters or less"),

Either add translation keys for these or build the schema inside the component where t is in scope.

3. rawError exposed in API response

app/api/compact/route.ts now returns rawError: errorMessage in 500 responses. Raw internal error messages (which may contain model names, service details, or stack traces) should not be returned in production API responses. errorCategory is sufficient for the frontend. Consider omitting rawError or gating it on a non-production env check.

Minor Notes

4. buildProgressSteps moved inside component body - re-created on every render. Since it only closes over the stable t reference, it could stay at module scope with t passed as a parameter. Not a correctness issue but slightly less efficient.

What is done well

  • Consistent useTranslations (client) vs getTranslations (server) usage throughout - correct pattern everywhere except the hypercert.tsx case above.
  • i18n/routing.ts cleanly centralizes locale config and re-exports typed navigation helpers.
  • lib/workflow-errors.ts is well-structured with clean separation of error extraction and categorization, and correct error cause chain walking.
  • en.json and ja.json appear to be kept in sync with comprehensive key coverage.
  • The intent to goal rename is applied consistently across workflow schema, API routes, hooks, and UI with no orphaned references.
  • generateStaticParams in the locale layout correctly pre-renders both en and ja routes at build time.

The middleware filename issue is the blocker to merge - everything else is functional with varying degrees of importance.

tnkshuuhei and others added 2 commits March 26, 2026 15:25
Export images were too small with unreadable text due to OGP compositing
(1200×630 with header/footer/padding). Export mode now uses high-res
capture (pixelRatio: 2) directly without branding overlay, while IPFS
save retains the existing OGP format.
fix(canvas): remove branding and improve export image quality
@github-actions
Copy link
Author

🔄 Release PR Updated

New changes have been pushed to dev branch since this PR was created.

🤖 Updated by GitHub Actions

@claude
Copy link

claude bot commented Mar 26, 2026

PR Review for Release 2026-03-26 - please see detailed review below

@claude
Copy link

claude bot commented Mar 26, 2026

CRITICAL proxy.ts must be middleware.ts: Next.js only recognizes middleware at middleware.ts in the root. Without this fix, visiting / will 404 since app/page.tsx was deleted, and locale routing will not work at all. This is a blocker.

@claude
Copy link

claude bot commented Mar 26, 2026

SECURITY rawError in API responses: app/api/compact/route.ts and the SSE stream route return rawError in the HTTP response body, which can expose internal error details, stack traces, and model names to clients. Remove rawError from client responses and keep it server-side (logs only). errorCategory is fine to return.

@claude
Copy link

claude bot commented Mar 26, 2026

PERFORMANCE hypercert.tsx client component: Added use client + useTranslations to access 4 strings (unknown, untitled, noDescription, viewDetails), opting the Hypercert card out of server rendering unnecessarily. Use getTranslations from next-intl/server in the parent HypercertsList (already a server component) and pass translated strings as props to keep SSR. Also minor: buildProgressSteps moved into component body recreates the array on every render - move it back outside with t as a param. Also minor: Zod validation error messages in GenerateLogicModelDialog are still hardcoded English strings and will not be translated for Japanese users.

@claude
Copy link

claude bot commented Mar 26, 2026

Overall the i18n integration and error categorization work is solid. Highlights: error categorization in lib/workflow-errors.ts is clean with good cause-chain walking; key={item.href} in the navigation list is a correct fix (translated titles as keys was fragile); the intent-to-goal rename is thorough and consistent across workflow, API routes, hooks, and UI; generateStaticParams in the locale layout is correct; next-intl routing helpers are used consistently throughout. Two things to fix before merging: proxy.ts to middleware.ts rename (blocker), and removing rawError from API responses (security).

Replace static PR body with dynamic changelog that lists merged PRs
with nested sub-PRs. Update existing release PRs by editing the body
instead of adding comments.
@claude
Copy link

claude bot commented Mar 26, 2026

PR Review: Release 2026-03-26

Great release — the i18n architecture is solid and the error categorization work is a meaningful improvement for UX. A few issues worth addressing before merge:

Critical

Middleware file is misnamed (proxy.ts instead of middleware.ts)

The Next.js middleware for locale routing lives in proxy.ts instead of middleware.ts. Next.js only auto-loads middleware from a file named middleware.ts at the project root. As-is, locale detection and redirects (e.g. / to /en/, /canvas to /en/canvas) will silently not work — users hitting root-path routes will get a 404 or land on a non-locale-prefixed page.

Fix: rename proxy.ts to middleware.ts.

Medium

rawError exposed in HTTP 500 responses (app/api/compact/route.ts)

The raw Mastra/LLM error message returned as rawError in the 500 response body may include internal hostnames, API key references, stack frames, or model provider internals. Consider logging it server-side only and omitting from the API response, or restricting to authenticated/admin consumers.

Zod validation messages not translated (components/canvas/GenerateLogicModelDialog.tsx)

The schema still has hardcoded English strings for .min(1) and .max(1000) error messages. Japanese users will see English validation errors. These can be translated by constructing the schema inside the component after calling useTranslations, or by using a Zod custom error map seeded with locale strings.

Minor

buildProgressSteps moved inside component body

Before this PR it was a module-level function; now it is a nested function inside GenerateLogicModelDialog (recreated each render). It is only called in handleSubmit so there is no observable perf issue, but wrapping it in useCallback would make the intent clearer.

Hypercert component unnecessarily converted to a client component (app/[lang]/hypercerts/hypercert.tsx)

The component was given "use client" solely to call useTranslations. Since HypercertsList is already a server component using getTranslations, it could pass translated strings as props to Hypercert, avoiding the client boundary and preserving server-side rendering.

What looks good

  • lib/workflow-errors.ts is clean and well-structured — extracting error categorization to a shared utility used by both routes is the right call.
  • useCanvasImage mode split ("export" vs "ogp") is a clean separation of concerns; using pixelRatio: 2 for exports without OGP compositing overhead directly addresses the image quality issue.
  • The locale layout in app/[lang]/layout.tsx correctly renders the html lang attribute and validates the locale before rendering.
  • Translation key naming is well-organized across namespaces.
  • The CI workflow update to auto-generate the PR body from merged PR titles is a nice improvement over the generic placeholder text.

@tnkshuuhei tnkshuuhei merged commit 5e4a918 into main Mar 26, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant