Skip to content

fix(flows): localize node-summary and cron descriptions (i18n ×14) - #5289

Merged
graycyrus merged 1 commit into
tinyhumansai:mainfrom
graycyrus:fix/flows-i18n-node-cron-summaries
Jul 31, 2026
Merged

fix(flows): localize node-summary and cron descriptions (i18n ×14)#5289
graycyrus merged 1 commit into
tinyhumansai:mainfrom
graycyrus:fix/flows-i18n-node-cron-summaries

Conversation

@graycyrus

@graycyrus graycyrus commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Localizes the flows canvas: node summaries and cron/schedule descriptions were hardcoded English rendered in the UI, violating the project's rule that all UI text goes through useT().
  • Covers all 14 node kinds (including the newly-landed dedup) and every schedule shape.
  • Replaces two hand-maintained English weekday arrays with Intl.DateTimeFormat, so weekday names are correct per locale with no translation surface.
  • Adds 63 keys to en.ts plus real translations in all 13 other locales.

Problem

Two pure modules returned English string literals that render directly in the UI:

  • app/src/lib/flows/nodeSummary.tsdescribeNode returned 'Runs on demand', 'Branches to true / false', 'Merges parallel branches', 'Recalls memory', `Sets ${n} field${n > 1 ? 's' : ''} on each item` … shown on every canvas node card via FlowNodeComponent.tsx.
  • app/src/lib/flows/cron.tsdescribeCron / describeEveryMs / describeSchedule returned 'Every day at …', 'weekdays', 'weekends', 'No schedule set', `Custom schedule (${expr})`, 'Once at …', plus English WEEKDAY_SHORT / WEEKDAY_INITIAL arrays — shown in ScheduleField.tsx's live summary and weekday toggles, and in trigger node summaries.

So a non-English user saw English on every node card and every schedule field. This is drift rather than policy: the sibling runStepSummary.ts already takes t as a parameter precisely to stay localized.

Solution

  • Threaded t (and locale, for weekday names) as parameters through the pure functions, mirroring runStepSummary.ts, rather than importing a React hook into them — keeps the modules pure and unit-testable.
  • Weekday names now derive from Intl.DateTimeFormat against a fixed Sunday reference date, so they are correct per locale and need no translated arrays.
  • Pluralization uses separate singular/plural keys rather than string concatenation, since several target locales have plural rules English lacks.
  • Two pure-placeholder keys carrying no translatable prose ('{method} {url}', the quoted-prompt/model line) are allowlisted in scripts/i18n-find-english.ts, matching the existing channels.activeRouteValue precedent.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy
  • Diff coverage ≥ 80% — pure functions with direct unit tests; 436 tests passed across src/lib/flows, src/components/flows, src/lib/i18n
  • Coverage matrix updated — N/A: localization of existing UI strings, no feature rows added/removed/renamed
  • All affected feature IDs from the matrix are listed under ## RelatedN/A: no matrix feature rows affected
  • No new external network dependencies introduced
  • Manual smoke checklist updated if this touches release-cut surfaces — N/A: string-rendering change only; the canvas smoke path is unchanged
  • Linked issue closed via Closes #NNNN/A: found by code review, no tracking issue filed yet

Impact

  • Runtime/platform: desktop frontend only (app/src). No Rust, no Tauri.
  • Behaviour: node cards and schedule fields render in the user's language. English output is unchanged for en.
  • i18n gates: pnpm i18n:check reports 0 missing / 0 extra across all 13 locales; the coverage test's no-em-dash assertion passes; pnpm i18n:english:check measured 0 on this branch and 0 on the stashed base — no regression.
  • Compatibility: describeNode / describeCron / describeSchedule signatures changed. All in-repo call sites are updated; these are internal helpers with no external consumers.

Related

  • Closes: N/A
  • Follow-up PR(s)/TODOs: the cron builder silently clamps an out-of-range custom step (e.g. */90*/59) on the next edit — fixed in the stacked residual-minors PR.
  • Merge order: independent of the Rust PRs in this batch (frontend-only, no file overlap). The residual-minors PR stacks on this one because it also edits cron.ts.

AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: fix/flows-i18n-node-cron-summaries
  • Commit SHA: 3a39433df

Validation Run

  • pnpm --filter openhuman-app format:check — prettier clean on touched files (one auto-fix applied to ScheduleField.tsx)
  • pnpm typecheck — clean, exit 0
  • Focused tests: vitest run src/lib/flows src/components/flows src/lib/i18n436 passed across 34 files; i18n coverage suite 67/67
  • Rust fmt/check (if changed): N/A, no Rust changed
  • Tauri fmt/check (if changed): N/A, app/src-tauri untouched

Validation Blocked

  • command: N/A
  • error: N/A
  • impact: N/A

Behavior Changes

  • Intended behavior change: flows node summaries and schedule descriptions are localized instead of always English.
  • User-visible effect: non-English users see translated node cards and schedule fields; weekday labels follow locale conventions.

Parity Contract

  • Legacy behavior preserved: English (en) output is unchanged, including the wording of every summary and schedule description; the describeSchedule fallback chain is intact.
  • Guard/fallback/dispatch parity checks: existing nodeSummary / cron unit tests are preserved with a t stub, so the same behavioural assertions still hold.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): none
  • Canonical PR: this one
  • Resolution: N/A

Summary by CodeRabbit

  • New Features

    • Localized workflow node summaries and schedule descriptions across supported languages.
    • Schedule weekday labels, dates, intervals, and validation messages now respect the active locale.
    • Added translations for Arabic, Bengali, German, English, Spanish, French, Hindi, Indonesian, Italian, Korean, Polish, Portuguese, Russian, and Simplified Chinese.
  • Bug Fixes

    • Added fallback handling for unsupported locales and invalid schedules.
  • Tests

    • Expanded coverage for localized node summaries, schedules, weekday labels, and locale fallback behavior.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 8 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a9cff215-70eb-48f9-85a1-ff93d0528096

📥 Commits

Reviewing files that changed from the base of the PR and between f536313 and 520e50d.

📒 Files selected for processing (23)
  • app/src/components/flows/canvas/FlowNodeComponent.tsx
  • app/src/components/flows/canvas/nodeConfig/NodeConfigDrawer.tsx
  • app/src/components/flows/canvas/nodeConfig/ScheduleField.tsx
  • app/src/components/flows/canvas/nodeConfig/nodeConfigForms.tsx
  • app/src/lib/flows/cron.test.ts
  • app/src/lib/flows/cron.ts
  • app/src/lib/flows/nodeSummary.test.ts
  • app/src/lib/flows/nodeSummary.ts
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/zh-CN.ts
  • scripts/i18n-find-english.ts
📝 Walkthrough

Walkthrough

Workflow node and schedule summaries now use injected translations and locale-aware formatting. Schedule controls display localized weekday labels. Translation catalogs add node and cron description keys across multiple locales. Tests cover localized labels, fallbacks, and summary variants.

Changes

Localized flow summaries

Layer / File(s) Summary
Locale-aware schedule descriptions and controls
app/src/lib/flows/cron.ts, app/src/lib/flows/cron.test.ts, app/src/components/flows/canvas/nodeConfig/ScheduleField.tsx, app/src/components/flows/canvas/nodeConfig/nodeConfigForms.tsx
Cron and schedule descriptions accept translation and locale inputs. Weekday formatting uses locale-aware Intl.DateTimeFormat with English fallback. Schedule controls render localized labels.
Localized node summaries
app/src/lib/flows/nodeSummary.ts, app/src/lib/flows/nodeSummary.test.ts, app/src/components/flows/canvas/FlowNodeComponent.tsx, app/src/components/flows/canvas/nodeConfig/NodeConfigDrawer.tsx
Node summaries use translation keys and interpolated configuration values. Callers pass the active translation function and locale.
Translation catalogs and scan exceptions
app/src/lib/i18n/*.ts, scripts/i18n-find-english.ts
Locale catalogs add workflow node and cron schedule translations. Intentional dynamic English values are allowlisted.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant FlowCanvas
  participant useT
  participant describeNode
  participant describeSchedule
  participant TranslationCatalog
  FlowCanvas->>useT: read translation function and locale
  FlowCanvas->>describeNode: pass node data, t, and locale
  describeNode->>describeSchedule: pass schedule data, t, and locale
  describeNode->>TranslationCatalog: resolve node-summary keys
  describeNode-->>FlowCanvas: return localized summary
Loading

Possibly related PRs

Suggested labels: bug

Suggested reviewers: senamakel, m3ga-mind

Poem

I hop through nodes where bright words grow,
In every tongue, the summaries flow.
Weekdays wear labels fresh and neat,
Cron ticks softly to translated beat.
Tests guard each phrase with care—
A rabbit’s localized trail is there!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: localizing flow node summaries and cron descriptions.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@graycyrus

Copy link
Copy Markdown
Contributor Author

Review follow-up: clean, no changes applied. Independently verified — 204/204 tests, i18n:check 0 missing/0 extra, all 63 new keys genuinely translated in every locale (only the two allowlisted pure-placeholder keys are byte-identical to English), zero em dashes, all 14 node kinds covered including dedup, and both modules confirmed still pure (no React import; t/locale threaded as parameters).

One real finding, recommended as a follow-up rather than a blocker: the two-form singular/plural split is not sufficient for Russian, Polish, or Arabic.

Concretely, with the strings as shipped:

  • ru'Каждые {n} минут' renders "Каждые 2 минут" at n=2; correct is "минуты" (few-form). Same for часов/дней/полей.
  • pl'Co {n} minut' renders "Co 2 minut" at n=2; correct is "minuty". (dni happens to be invariant, so that one is fine.)
  • ar — bare singular for all n≥2: wrong at 2 (needs dual) and 3–10 (needs plural).

n ∈ {2,3,4} are extremely common cron intervals, so this is not an edge case. The abbreviated short forms (ч, min, س) and all n=1 singulars are correct — only the spelled-out N>1 forms are affected.

Not this PR's fault, and that's why it's a follow-up: there is no Intl.PluralRules usage anywhere in the codebase; t() is a flat key→string map with manual placeholder replacement, and the Singular/Plural two-key shape is the established project convention this PR correctly followed (Sets N field(s) already had it pre-PR). Fixing it properly means adding a CLDR-category-aware tPlural(key, n) helper to I18nContext and re-keying every counted string app-wide — a framework change, correctly out of scope here.

Recommend shipping this PR and filing the pluralization gap separately; it already affects every other counted-plural string in the app, this PR just adds three more instances of a pre-existing limitation.

(Cosmetic, optional: fr.ts's agent.withPrompt keeps English " " quotes while the same file uses « » elsewhere, e.g. memory.flavourWith. Stylistic only — " " is broadly accepted in modern French UI.)

@graycyrus
graycyrus force-pushed the fix/flows-i18n-node-cron-summaries branch from 3a39433 to f536313 Compare July 31, 2026 06:23
@graycyrus
graycyrus marked this pull request as ready for review July 31, 2026 09:59
@graycyrus
graycyrus requested a review from a team July 31, 2026 09:59

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

graycyrus has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
app/src/lib/flows/cron.test.ts (1)

118-132: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a test for a real non-English locale.

The current tests exercise weekdayShortLabel/weekdayNarrowLabel only with 'en' and with an intentionally invalid tag ('not-a-real-locale'). No test confirms that Intl.DateTimeFormat actually produces correctly localized weekday names for a real non-English locale. This is the core new behavior this cohort introduces, so add at least one assertion against a known locale, for example French or German, to confirm real localization output.

✅ Suggested additional test
   it('falls back to English for an unsupported locale tag rather than throwing', () => {
     expect(() => weekdayShortLabel(0, 'not-a-real-locale')).not.toThrow();
   });
+
+  it('localizes weekday names for a real non-English locale', () => {
+    expect(weekdayShortLabel(3, 'fr')).toBe('mer.');
+  });
 });

As per path instructions, **/*.{ts,tsx,rs}: "Untested code is incomplete; add tests for new or changed behavior."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/lib/flows/cron.test.ts` around lines 118 - 132, Extend the
weekdayShortLabel/weekdayNarrowLabel tests with a real non-English locale, such
as French or German, and assert a known localized weekday value returned by
Intl.DateTimeFormat. Keep the existing English and invalid-locale coverage
unchanged.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/lib/i18n/es.ts`:
- Around line 4304-4305: Update the Spanish translation values for the memory
recall node summaries to use the verb "Recupera" instead of "Recuerda". Change
the value for the 'flows.nodeSummary.memory.recallScoped' key from "Recuerda de
la memoria ({scope})" to "Recupera de la memoria ({scope})", and update the
'flows.nodeSummary.memory.recall' key from "Recuerda de la memoria" to "Recupera
de la memoria". This ensures the translations properly reflect the retrieval
operation rather than a remembering action.

In `@app/src/lib/i18n/pt.ts`:
- Line 4360: Update the translation value for flows.cron.everyMinuteOnDays to
use a gender-neutral phrase such as “nos dias {days}” instead of “aos {days}”,
preserving correct wording for mixed weekday abbreviations.
- Around line 4293-4294: Update the Portuguese translations for
flows.nodeSummary.memory.recall and flows.nodeSummary.memory.recallScoped from
“Recorda da memória” to “Recupera da memória”, preserving the existing ({scope})
placeholder in the scoped variant.

---

Nitpick comments:
In `@app/src/lib/flows/cron.test.ts`:
- Around line 118-132: Extend the weekdayShortLabel/weekdayNarrowLabel tests
with a real non-English locale, such as French or German, and assert a known
localized weekday value returned by Intl.DateTimeFormat. Keep the existing
English and invalid-locale coverage unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 86aac8d3-5a6f-4267-988d-e5ff2c782a25

📥 Commits

Reviewing files that changed from the base of the PR and between 6c0381a and f536313.

📒 Files selected for processing (23)
  • app/src/components/flows/canvas/FlowNodeComponent.tsx
  • app/src/components/flows/canvas/nodeConfig/NodeConfigDrawer.tsx
  • app/src/components/flows/canvas/nodeConfig/ScheduleField.tsx
  • app/src/components/flows/canvas/nodeConfig/nodeConfigForms.tsx
  • app/src/lib/flows/cron.test.ts
  • app/src/lib/flows/cron.ts
  • app/src/lib/flows/nodeSummary.test.ts
  • app/src/lib/flows/nodeSummary.ts
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/zh-CN.ts
  • scripts/i18n-find-english.ts

Comment thread app/src/lib/i18n/es.ts Outdated
Comment thread app/src/lib/i18n/pt.ts Outdated
Comment thread app/src/lib/i18n/pt.ts Outdated
@graycyrus
graycyrus force-pushed the fix/flows-i18n-node-cron-summaries branch from f536313 to 163c0fd Compare July 31, 2026 10:41

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

graycyrus has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

describeNode/describeCron/describeEveryMs/describeSchedule returned
hardcoded English literals rendered on every canvas node card and in
the schedule field, violating the project's useT() rule. Thread `t`
(and `locale`, for weekday names) through these pure modules mirroring
the existing runStepSummary.ts pattern, add flows.nodeSummary.*/
flows.cron.* keys to en.ts plus real translations across all 14
locales, and derive weekday names from Intl.DateTimeFormat against the
active locale instead of hand-translated WEEKDAY_SHORT/WEEKDAY_INITIAL
arrays.

Allowlist two pure-placeholder strings (HTTP method+URL, quoted
prompt+model) in the i18n-find-english leftover-English checker, same
as existing entries like channels.activeRouteValue.
@graycyrus
graycyrus force-pushed the fix/flows-i18n-node-cron-summaries branch from 163c0fd to 520e50d Compare July 31, 2026 10:51

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

graycyrus has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@graycyrus
graycyrus merged commit fe08b05 into tinyhumansai:main Jul 31, 2026
20 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in Team Openhuman Jul 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

1 participant