fix(desktop): render the reader's own group lines in the active language
The GroupRow preview and the group transcript spelled the reader as the English literal 'You' under every locale, so a zh roster read "You: …" beside otherwise Chinese chrome. Add `group.you` to all four Bot Mode bundles and use it at the three RENDER sites (bot-row preview, group-chat-view speaker display and clicked label). The persisted author marker written into the room log (group-chat-parts.tsx, group-rounds.ts) stays the English sentinel: group-activity.ts compares it by value, so translating it in place would corrupt existing logs and break the comparison. The i18n.ts header now documents that split.
This commit is contained in:
@@ -248,4 +248,20 @@ describe('a group row', () => {
|
||||
expect(japanese.getByText('ボット3体')).toBeTruthy()
|
||||
expect(japanese.getByRole('button', { name: 'crew, ボット3体, 3体中3体が利用可能' })).toBeTruthy()
|
||||
})
|
||||
|
||||
it('names the reader in the active language when their line is the latest, without touching the log marker', () => {
|
||||
// 'You' is the persisted author sentinel on the log entry; only its rendering localizes.
|
||||
act(() =>
|
||||
$groupChats.set({ crew: { log: [{ at: 1, from: { kind: 'user', name: 'You' }, text: 'ship it' }], running: false, watermarks: {} } })
|
||||
)
|
||||
locale.current = 'zh'
|
||||
|
||||
const chinese = render(row)
|
||||
|
||||
expect(chinese.getByText('你: ship it')).toBeTruthy()
|
||||
expect(chinese.queryByText(/^You:/)).toBeNull()
|
||||
expect($groupChats.get().crew.log[0].from.name).toBe('You')
|
||||
|
||||
act(() => $groupChats.set({}))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -500,7 +500,7 @@ export function GroupRow({ active, group, members, needsYou, onOpen, onDisband,
|
||||
)
|
||||
|
||||
const preview = last
|
||||
? `${last.from?.kind === 'user' ? 'You' : `@${lastHandle}`}: ${stripPreviewMarkdown(last.text) || '…'}`
|
||||
? `${last.from?.kind === 'user' ? b.group.you : `@${lastHandle}`}: ${stripPreviewMarkdown(last.text) || '…'}`
|
||||
: b.group.memberCount(members.length)
|
||||
|
||||
const availableMembers = members.filter(member => botSourceStatus(member).available).length
|
||||
|
||||
@@ -991,7 +991,7 @@ export function GroupChatWorkspace({ group, members, onBack, visible = true }: G
|
||||
) || null
|
||||
|
||||
const display = isUser
|
||||
? 'You'
|
||||
? b.group.you
|
||||
: displayName(
|
||||
member || {
|
||||
name: entry.from.name
|
||||
@@ -1005,7 +1005,7 @@ export function GroupChatWorkspace({ group, members, onBack, visible = true }: G
|
||||
// Clicked: append the gateway name so same-named agents on
|
||||
// two connections are tellable apart on demand.
|
||||
const label = isUser
|
||||
? 'You'
|
||||
? b.group.you
|
||||
: revealed
|
||||
? `${display}${entry.from.source ? `-${entry.from.source}` : ''} (@${botHandle(entry.from.name, member || undefined)})`
|
||||
: display
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
* - **Syntax and identifiers**: cron expressions and their examples, React
|
||||
* keys, workspace ids.
|
||||
* - **`'You'`**, the author marker on room-log entries. It is persisted into
|
||||
* the log and compared as a sentinel (`group-activity.ts`), so translating
|
||||
* it in place would break both. Localizing it needs the marker and its
|
||||
* rendering split apart — worth doing, not doable as a rename.
|
||||
* the log and compared as a sentinel (`group-activity.ts`), so it stays
|
||||
* English where it is WRITTEN (`group-chat-parts.tsx`, `group-rounds.ts`);
|
||||
* the places that RENDER the reader's own lines use `group.you` instead.
|
||||
*
|
||||
* Locales follow kanban: `en` / `ja` / `zh` / `zh-hant`. Arabic falls through
|
||||
* the resolution chain (active locale → this plugin's `en` → the key) the
|
||||
@@ -216,6 +216,8 @@ type BotsMessages = {
|
||||
pictureGenerationFailed: string
|
||||
nameTaken: (name: string) => string
|
||||
memberCount: (count: number) => string
|
||||
/** The reader's own lines in a room: the transcript speaker and the roster preview. */
|
||||
you: string
|
||||
/** How many of a room's members are reachable right now. */
|
||||
availableCount: (available: number, total: number) => string
|
||||
settingsHint: (group: string) => string
|
||||
@@ -471,6 +473,7 @@ const en: BotsMessages = {
|
||||
pictureGenerationFailed: 'Group picture generation failed',
|
||||
nameTaken: name => `A group named “${name}” already exists.`,
|
||||
memberCount: count => `${count} bots`,
|
||||
you: 'You',
|
||||
availableCount: (available, total) => `${available} of ${total} available`,
|
||||
settingsHint: group => `Group settings — rename ${group} or set a room picture`,
|
||||
settingsLabel: group => `Group settings for ${group}`,
|
||||
@@ -718,6 +721,7 @@ const ja: BotsMessages = {
|
||||
pictureGenerationFailed: 'グループ画像の生成に失敗しました',
|
||||
nameTaken: name => `「${name}」という名前のグループはすでに存在します。`,
|
||||
memberCount: count => `ボット${count}体`,
|
||||
you: 'あなた',
|
||||
availableCount: (available, total) => `${total}体中${available}体が利用可能`,
|
||||
settingsHint: group => `グループ設定 — ${group}の名前変更やルーム画像の設定`,
|
||||
settingsLabel: group => `${group}のグループ設定`,
|
||||
@@ -960,6 +964,7 @@ const zh: BotsMessages = {
|
||||
pictureGenerationFailed: '群组图片生成失败',
|
||||
nameTaken: name => `已存在名为“${name}”的群聊。`,
|
||||
memberCount: count => `${count} 个机器人`,
|
||||
you: '你',
|
||||
availableCount: (available, total) => `${total} 个中 ${available} 个可用`,
|
||||
settingsHint: group => `群聊设置 — 重命名 ${group} 或设置房间图片`,
|
||||
settingsLabel: group => `${group} 的群聊设置`,
|
||||
@@ -1202,6 +1207,7 @@ const zhHant: BotsMessages = {
|
||||
pictureGenerationFailed: '群組圖片產生失敗',
|
||||
nameTaken: name => `已存在名為「${name}」的群組聊天。`,
|
||||
memberCount: count => `${count} 個機器人`,
|
||||
you: '您',
|
||||
availableCount: (available, total) => `${total} 個中 ${available} 個可用`,
|
||||
settingsHint: group => `群組設定 — 重新命名 ${group} 或設定房間圖片`,
|
||||
settingsLabel: group => `${group} 的群組設定`,
|
||||
|
||||
Reference in New Issue
Block a user