🚀 Feature Request: Translate the chat's remaining hard-coded strings ("Thinking…", screen-reader labels) through `labels` · Issue #7864 · CopilotKit/CopilotKit · GitHub
Skip to content

🚀 Feature Request: Translate the chat's remaining hard-coded strings ("Thinking…", screen-reader labels) through labels #7864

Open

Description

@Mordris

Pre-flight Checklist

  • I have searched existing issues, and this hasn't been requested yet.

Problem or Motivation

The labels config translates most of the prebuilt chat, but some strings bypass it and stay in English whatever the app passes. In @copilotkit/react-core@1.79.1 (unchanged on main), with every label set to German:

  • The reasoning header shows "Thinking…" while the model reasons and "Thought for a few seconds" / "Thought for 12 seconds" / "Thought for 2m 5s" afterwards (CopilotChatReasoningMessage.tsx). The duration formatter is English-only.
  • Screen readers announce English names: "Remove attachment" and "Play video" (CopilotChatAttachmentQueue.tsx), "Close preview" (Lightbox.tsx), "Slash commands" plus the visible "No commands found" (CopilotChatInput.tsx), "Close" and "Open threads" (CopilotModalHeader.tsx), and "Copilot chat sidebar" (CopilotSidebarView.tsx).

Vue has the same strings. Angular hard-codes "Thinking…" / "Thought for …", "Remove attachment", "Close Copilot chat" and "Close Copilot sidebar".

The only way around it today is to replace slots. For the reasoning header even that falls short: the header slot gets label and isStreaming, but not the elapsed time, so a custom header can't say "Thought for 12 seconds" in another language without re-implementing the timer.

With German labels on 1.79.1 (repro: https://github.com/Mordris/copilotkit-ui-repro), the reasoning headers on the left and right stay English:

1.79.1 with German labels

🎤 Tell us your idea

Route these strings through labels, the way #6771 did for the add-menu tooltip:

Proposed key Default
reasoningMessageThinkingLabel "Thinking…"
attachmentRemoveButtonLabel "Remove attachment"
attachmentPlayVideoButtonLabel "Play video"
attachmentPreviewCloseButtonLabel "Close preview"
chatInputSlashMenuLabel "Slash commands"
chatInputSlashMenuEmptyText "No commands found"
modalHeaderCloseButtonLabel "Close"
modalHeaderThreadsButtonLabel "Open threads"
sidebarLabel "Copilot chat sidebar"

"Thought for N seconds" carries a number and plural rules, which a plain string label can't express. I'd keep its current English output as the default and pass elapsedSeconds to the reasoning header slot, so an app can render its own text with correct plurals:

<CopilotChat
  messageView={{
    reasoningMessage: {
      header: ({ isStreaming, elapsedSeconds, ...props }) => (
        <CopilotChatReasoningMessage.Header
          {...props}
          isStreaming={isStreaming}
          label={isStreaming ? "Denkt nach…" : `${Math.round(elapsedSeconds)} Sekunden nachgedacht`}
        />
      ),
    },
  }}
/>

Everything is additive: same English defaults, no visual change. Each framework keeps its own default text where it differs today, as it already does for chatInputToolbarAddButtonLabel. The A2UI renderer's own strings ("Building interface", "Retrying generation…", "Filter options...") are left out, since the A2UI catalog is being reworked in #7819 / #7829.

Icon-only buttons with no accessible name at all (send/stop, add, voice, scroll to bottom, branch navigation) are a separate bug: #7862.

Would you like to work on this?

  • Yes, I’d love to work on it!
  • I’m open to collaborating but need guidance.
  • No, I’m just sharing the idea.

Activity

  1. copilotkit-outpost-bot commented on Oct 18, 2026

    @copilotkit-outpost-bot

    ⚠️ This is an AI-generated response. A member of our team will review and follow up if needed.

    This is a well-scoped request and the code confirms the gap. Looking at CopilotChatReasoningMessage.tsx, the label string ("Thinking…" / "Thought for ${formatDuration(elapsed)}") is assembled inline and never touches labels. The CopilotChatLabels interface in packages/angular/src/lib/chat-config.ts shows the pattern for how keys are added — each framework maintains its own defaults object that mirrors the shared shape.

    A few notes on the proposed design that will help when you open the PR:

    The elapsedSeconds slot prop is the right call. The header slot already receives isOpen, label, hasContent, isStreaming, and onClick (source: CopilotChatReasoningMessage.tsx lines 113–119). Adding elapsed (the raw number already tracked in state at line 78) alongside the pre-formatted label lets apps do their own pluralisation without re-implementing the timer. The default label can stay English-formatted so nothing breaks for existing users.

    For the simple string keys, the Angular CopilotChatLabels interface and COPILOT_CHAT_DEFAULT_LABELS constant (packages/angular/src/lib/chat-config.ts) will need the same additions as the React side, or the frameworks will drift again. The existing keys like assistantMessageToolbarThumbsUpLabel show the naming convention to follow.

    reasoningMessageThinkingLabel can be a plain labels key (no interpolation needed — it's the static "Thinking…" string). The post-stream "Thought for …" string is the one that needs the slot approach you described, since it carries a number.

    The repro and the table of proposed keys are clear. Engineering will review the implementation details when the PR is up.


    🤖 Generated by CopilotKit AI Support · Documentation


    Was this helpful? React with 👍 or 👎

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions