Skip to content

i18n: localize pending-input preview messages#2929

Open
gordonlu wants to merge 2 commits into
Hmbown:mainfrom
gordonlu:feat/i18n-pending-inputs
Open

i18n: localize pending-input preview messages#2929
gordonlu wants to merge 2 commits into
Hmbown:mainfrom
gordonlu:feat/i18n-pending-inputs

Conversation

@gordonlu

@gordonlu gordonlu commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Localize the PendingInput preview widget (10 MessageIds) across all 7 shipped locales.

Section headers

  • PendingContextHeader"Context for next send"
  • PendingInputHeader"Pending inputs"

Delivery-mode labels

  • PendingSteerLabel"Steer pending: "
  • PendingRejectedLabel"Rejected steer: "
  • PendingQueuedLabel"Queued follow-up: "
  • PendingEditingLabel"Editing queued follow-up: "

Action hints

  • PendingRestoreHint"Esc restores queued follow-up"
  • PendingEditHint"{key} edit last queued message"
  • PendingDeleteHint"Backspace/Delete removes"
  • PendingRemovable"removable"

Infrastructure

  • Added locale: Locale field to PendingInputPreview widget
  • Converted const prefix strings (PENDING_STEER_PREFIX, etc.) into dynamic tr()-based helpers
  • Threaded locale from build_pending_input_preview(app) in ui.rs
  • Layout characters (, , indentation) remain hardcoded

Verification

  • 14 pending-input tests pass (including UI integration tests)
  • cargo clippy: clean
  • cargo fmt --all --check: clean

- Add 10 MessageIds for PendingInput surface (section headers,
  delivery-mode labels, action hints)
- Store locale on PendingInputPreview widget; thread through
  from build_pending_input_preview in ui.rs
- Replace hardcoded prefix constants with tr()-based helpers
- Keep layout characters (arrows, indentation) hardcoded

@greptile-apps greptile-apps 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.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces localization support for the pending input preview widget, adding new message IDs and translations across multiple languages, and updating the widget to render localized strings based on the active locale. The reviewer feedback focuses on performance optimizations in the rendering path, specifically avoiding unnecessary heap allocations and string formatting, as well as correcting a translation inconsistency in Traditional Chinese.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines 100 to 106
push_section_header(
&mut lines,
Line::from(vec![Span::raw("• "), Span::raw("Context for next send")]),
Line::from(vec![
Span::raw("• "),
Span::raw(tr(self.locale, MessageId::PendingContextHeader).to_string()),
]),
);

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.

medium

Unnecessary heap allocation. tr returns a &'static str, which can be coerced directly into Span::raw without calling .to_string(). This avoids a heap allocation in the rendering path.

Suggested change
push_section_header(
&mut lines,
Line::from(vec![Span::raw("• "), Span::raw("Context for next send")]),
Line::from(vec![
Span::raw("• "),
Span::raw(tr(self.locale, MessageId::PendingContextHeader).to_string()),
]),
);
push_section_header(
&mut lines,
Line::from(vec![
Span::raw("• "),
Span::raw(tr(self.locale, MessageId::PendingContextHeader)),
]),
);

Comment on lines 116 to 122
push_section_header(
&mut lines,
Line::from(vec![Span::raw("• "), Span::raw("Pending inputs")]),
Line::from(vec![
Span::raw("• "),
Span::raw(tr(self.locale, MessageId::PendingInputHeader).to_string()),
]),
);

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.

medium

Unnecessary heap allocation. tr returns a &'static str, which can be coerced directly into Span::raw without calling .to_string(). This avoids a heap allocation in the rendering path.

Suggested change
push_section_header(
&mut lines,
Line::from(vec![Span::raw("• "), Span::raw("Pending inputs")]),
Line::from(vec![
Span::raw("• "),
Span::raw(tr(self.locale, MessageId::PendingInputHeader).to_string()),
]),
);
push_section_header(
&mut lines,
Line::from(vec![
Span::raw("• "),
Span::raw(tr(self.locale, MessageId::PendingInputHeader)),
]),
);

Comment on lines 158 to 161
lines.push(Line::from(vec![Span::styled(
" Esc restores queued follow-up".to_string(),
format!(" {}", tr(self.locale, MessageId::PendingRestoreHint)),
dim,
)]));

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.

medium

Unnecessary heap allocation. Instead of using format! to prepend spaces to the translated hint, we can construct the Line with separate Spans. This avoids a heap allocation in the rendering path.

Suggested change
lines.push(Line::from(vec![Span::styled(
" Esc restores queued follow-up".to_string(),
format!(" {}", tr(self.locale, MessageId::PendingRestoreHint)),
dim,
)]));
lines.push(Line::from(vec![
Span::styled(" ", dim),
Span::styled(tr(self.locale, MessageId::PendingRestoreHint), dim),
]));

Comment on lines 176 to 183
lines.push(Line::from(vec![Span::styled(
format!(" {} edit last queued message", self.edit_binding.label),
format!(
" {}",
tr(self.locale, MessageId::PendingEditHint)
.replace("{key}", self.edit_binding.label)
),
dim,
)]));

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.

medium

Unnecessary heap allocation. Instead of using format! to prepend spaces to the translated hint, we can construct the Line with separate Spans. This avoids a heap allocation in the rendering path.

            if !self.queued_messages.is_empty() {
                lines.push(Line::from(vec![
                    Span::styled("    ", dim),
                    Span::styled(
                        tr(self.locale, MessageId::PendingEditHint)
                            .replace("{key}", self.edit_binding.label),
                        dim,
                    ),
                ]));
            }

Comment on lines 254 to 261
let action = if item.selected {
" · Backspace/Delete removes"
format!(" · {}", tr(locale, MessageId::PendingDeleteHint))
} else if item.removable {
" · removable"
format!(" · {}", tr(locale, MessageId::PendingRemovable))
} else {
""
String::new()
};
let body = format!("[{}] {}{}{}", item.kind, item.label, detail, action);

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.

medium

Unnecessary double formatting and heap allocations. Instead of formatting action as an intermediate String and then formatting it again into body, we can determine the action label first and perform a single formatting step. This is cleaner and more efficient.

    let action_label = if item.selected {
        Some(tr(locale, MessageId::PendingDeleteHint))
    } else if item.removable {
        Some(tr(locale, MessageId::PendingRemovable))
    } else {
        None
    };
    let body = if let Some(label) = action_label {
        format!("[{}] {}{} · {}", item.kind, item.label, detail, label)
    } else {
        format!("[{}] {}{}", item.kind, item.label, detail)
    };

Comment thread crates/tui/src/localization.rs Outdated
Comment on lines +2121 to +2124
MessageId::PendingQueuedLabel => "已排隊後續消息:",
MessageId::PendingEditingLabel => "正在編輯已排隊的後續消息:",
MessageId::PendingRestoreHint => "Esc 恢復已排隊的後續消息",
MessageId::PendingEditHint => "{key} 編輯最後一條已排隊消息",

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.

medium

In Traditional Chinese (especially Taiwan/Hong Kong), "訊息" is the standard translation for "message" (as in chat messages, API messages), which is already used elsewhere in this file (e.g., MessageId::CtxInspApiMessages => "API 訊息"). "消息" is more commonly used in Simplified Chinese. Let's use "訊息" consistently for Traditional Chinese.

Suggested change
MessageId::PendingQueuedLabel => "已排隊後續消息:",
MessageId::PendingEditingLabel => "正在編輯已排隊的後續消息:",
MessageId::PendingRestoreHint => "Esc 恢復已排隊的後續消息",
MessageId::PendingEditHint => "{key} 編輯最後一條已排隊消息",
MessageId::PendingQueuedLabel => "已排隊後續訊息:",
MessageId::PendingEditingLabel => "正在編輯已排隊的後續訊息:",
MessageId::PendingRestoreHint => "Esc 恢復已排隊的後續訊息",
MessageId::PendingEditHint => "{key} 編輯最後一條已排隊訊息",

- Remove unnecessary .to_string() on tr() results (2 spots)
- Use separate Span for indentation + hint text instead of format!
- Single-step action label formatting in push_context_item
- Fix Traditional Chinese: 消息 → 訊息 for consistency

@greptile-apps greptile-apps 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.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@gordonlu

gordonlu commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

All 6 review items addressed in dcded84:

1-2. Removed on results for section headers
3-4. Split indent + hint into separate s instead of
5. Single-step formatting in
6. Traditional Chinese: 消息 → 訊息

@Hmbown

Hmbown commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Thanks @gordonlu — we merged #2891 and #2896 from your i18n batch tonight, which moved localization.rs on main, so this slice now shows as conflicting. Could you rebase it onto current main when you get a chance?

Since the slices all touch localization.rs, the smoothest path is to rebase and push them one at a time, oldest-first (#2892#2901#2918#2919#2921#2926#2929#2932#2940) — we'll merge each promptly so the next rebase stays small. Sorry for the churn; the batch is exactly the right shape and we want all of it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants