mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-05 07:10:55 +00:00
feat(i18n): Add Internationalization Support for UI and LLM Output (#1058)
This commit is contained in:
parent
640f30655d
commit
48b77541c3
98 changed files with 4740 additions and 636 deletions
|
|
@ -7,7 +7,6 @@
|
|||
import * as fsPromises from 'node:fs/promises';
|
||||
import React from 'react';
|
||||
import { Text } from 'ink';
|
||||
import { theme } from '../semantic-colors.js';
|
||||
import type {
|
||||
CommandContext,
|
||||
SlashCommand,
|
||||
|
|
@ -20,6 +19,7 @@ import path from 'node:path';
|
|||
import type { HistoryItemWithoutId } from '../types.js';
|
||||
import { MessageType } from '../types.js';
|
||||
import type { Content } from '@google/genai';
|
||||
import { t } from '../../i18n/index.js';
|
||||
|
||||
interface ChatDetail {
|
||||
name: string;
|
||||
|
|
@ -67,7 +67,9 @@ const getSavedChatTags = async (
|
|||
|
||||
const listCommand: SlashCommand = {
|
||||
name: 'list',
|
||||
description: 'List saved conversation checkpoints',
|
||||
get description() {
|
||||
return t('List saved conversation checkpoints');
|
||||
},
|
||||
kind: CommandKind.BUILT_IN,
|
||||
action: async (context): Promise<MessageActionReturn> => {
|
||||
const chatDetails = await getSavedChatTags(context, false);
|
||||
|
|
@ -75,7 +77,7 @@ const listCommand: SlashCommand = {
|
|||
return {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content: 'No saved conversation checkpoints found.',
|
||||
content: t('No saved conversation checkpoints found.'),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -83,7 +85,7 @@ const listCommand: SlashCommand = {
|
|||
...chatDetails.map((chat) => chat.name.length),
|
||||
);
|
||||
|
||||
let message = 'List of saved conversations:\n\n';
|
||||
let message = t('List of saved conversations:') + '\n\n';
|
||||
for (const chat of chatDetails) {
|
||||
const paddedName = chat.name.padEnd(maxNameLength, ' ');
|
||||
const isoString = chat.mtime.toISOString();
|
||||
|
|
@ -91,7 +93,7 @@ const listCommand: SlashCommand = {
|
|||
const formattedDate = match ? `${match[1]} ${match[2]}` : 'Invalid Date';
|
||||
message += ` - ${paddedName} (saved on ${formattedDate})\n`;
|
||||
}
|
||||
message += `\nNote: Newest last, oldest first`;
|
||||
message += `\n${t('Note: Newest last, oldest first')}`;
|
||||
return {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
|
|
@ -102,8 +104,11 @@ const listCommand: SlashCommand = {
|
|||
|
||||
const saveCommand: SlashCommand = {
|
||||
name: 'save',
|
||||
description:
|
||||
'Save the current conversation as a checkpoint. Usage: /chat save <tag>',
|
||||
get description() {
|
||||
return t(
|
||||
'Save the current conversation as a checkpoint. Usage: /chat save <tag>',
|
||||
);
|
||||
},
|
||||
kind: CommandKind.BUILT_IN,
|
||||
action: async (context, args): Promise<SlashCommandActionReturn | void> => {
|
||||
const tag = args.trim();
|
||||
|
|
@ -111,7 +116,7 @@ const saveCommand: SlashCommand = {
|
|||
return {
|
||||
type: 'message',
|
||||
messageType: 'error',
|
||||
content: 'Missing tag. Usage: /chat save <tag>',
|
||||
content: t('Missing tag. Usage: /chat save <tag>'),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -126,9 +131,12 @@ const saveCommand: SlashCommand = {
|
|||
prompt: React.createElement(
|
||||
Text,
|
||||
null,
|
||||
'A checkpoint with the tag ',
|
||||
React.createElement(Text, { color: theme.text.accent }, tag),
|
||||
' already exists. Do you want to overwrite it?',
|
||||
t(
|
||||
'A checkpoint with the tag {{tag}} already exists. Do you want to overwrite it?',
|
||||
{
|
||||
tag,
|
||||
},
|
||||
),
|
||||
),
|
||||
originalInvocation: {
|
||||
raw: context.invocation?.raw || `/chat save ${tag}`,
|
||||
|
|
@ -142,7 +150,7 @@ const saveCommand: SlashCommand = {
|
|||
return {
|
||||
type: 'message',
|
||||
messageType: 'error',
|
||||
content: 'No chat client available to save conversation.',
|
||||
content: t('No chat client available to save conversation.'),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -152,13 +160,15 @@ const saveCommand: SlashCommand = {
|
|||
return {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content: `Conversation checkpoint saved with tag: ${decodeTagName(tag)}.`,
|
||||
content: t('Conversation checkpoint saved with tag: {{tag}}.', {
|
||||
tag: decodeTagName(tag),
|
||||
}),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content: 'No conversation found to save.',
|
||||
content: t('No conversation found to save.'),
|
||||
};
|
||||
}
|
||||
},
|
||||
|
|
@ -167,8 +177,11 @@ const saveCommand: SlashCommand = {
|
|||
const resumeCommand: SlashCommand = {
|
||||
name: 'resume',
|
||||
altNames: ['load'],
|
||||
description:
|
||||
'Resume a conversation from a checkpoint. Usage: /chat resume <tag>',
|
||||
get description() {
|
||||
return t(
|
||||
'Resume a conversation from a checkpoint. Usage: /chat resume <tag>',
|
||||
);
|
||||
},
|
||||
kind: CommandKind.BUILT_IN,
|
||||
action: async (context, args) => {
|
||||
const tag = args.trim();
|
||||
|
|
@ -176,7 +189,7 @@ const resumeCommand: SlashCommand = {
|
|||
return {
|
||||
type: 'message',
|
||||
messageType: 'error',
|
||||
content: 'Missing tag. Usage: /chat resume <tag>',
|
||||
content: t('Missing tag. Usage: /chat resume <tag>'),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -188,7 +201,9 @@ const resumeCommand: SlashCommand = {
|
|||
return {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content: `No saved checkpoint found with tag: ${decodeTagName(tag)}.`,
|
||||
content: t('No saved checkpoint found with tag: {{tag}}.', {
|
||||
tag: decodeTagName(tag),
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -237,7 +252,9 @@ const resumeCommand: SlashCommand = {
|
|||
|
||||
const deleteCommand: SlashCommand = {
|
||||
name: 'delete',
|
||||
description: 'Delete a conversation checkpoint. Usage: /chat delete <tag>',
|
||||
get description() {
|
||||
return t('Delete a conversation checkpoint. Usage: /chat delete <tag>');
|
||||
},
|
||||
kind: CommandKind.BUILT_IN,
|
||||
action: async (context, args): Promise<MessageActionReturn> => {
|
||||
const tag = args.trim();
|
||||
|
|
@ -245,7 +262,7 @@ const deleteCommand: SlashCommand = {
|
|||
return {
|
||||
type: 'message',
|
||||
messageType: 'error',
|
||||
content: 'Missing tag. Usage: /chat delete <tag>',
|
||||
content: t('Missing tag. Usage: /chat delete <tag>'),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -257,13 +274,17 @@ const deleteCommand: SlashCommand = {
|
|||
return {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content: `Conversation checkpoint '${decodeTagName(tag)}' has been deleted.`,
|
||||
content: t("Conversation checkpoint '{{tag}}' has been deleted.", {
|
||||
tag: decodeTagName(tag),
|
||||
}),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: 'message',
|
||||
messageType: 'error',
|
||||
content: `Error: No checkpoint found with tag '${decodeTagName(tag)}'.`,
|
||||
content: t("Error: No checkpoint found with tag '{{tag}}'.", {
|
||||
tag: decodeTagName(tag),
|
||||
}),
|
||||
};
|
||||
}
|
||||
},
|
||||
|
|
@ -309,8 +330,11 @@ export function serializeHistoryToMarkdown(history: Content[]): string {
|
|||
|
||||
const shareCommand: SlashCommand = {
|
||||
name: 'share',
|
||||
description:
|
||||
'Share the current conversation to a markdown or json file. Usage: /chat share <file>',
|
||||
get description() {
|
||||
return t(
|
||||
'Share the current conversation to a markdown or json file. Usage: /chat share <file>',
|
||||
);
|
||||
},
|
||||
kind: CommandKind.BUILT_IN,
|
||||
action: async (context, args): Promise<MessageActionReturn> => {
|
||||
let filePathArg = args.trim();
|
||||
|
|
@ -324,7 +348,7 @@ const shareCommand: SlashCommand = {
|
|||
return {
|
||||
type: 'message',
|
||||
messageType: 'error',
|
||||
content: 'Invalid file format. Only .md and .json are supported.',
|
||||
content: t('Invalid file format. Only .md and .json are supported.'),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -333,7 +357,7 @@ const shareCommand: SlashCommand = {
|
|||
return {
|
||||
type: 'message',
|
||||
messageType: 'error',
|
||||
content: 'No chat client available to share conversation.',
|
||||
content: t('No chat client available to share conversation.'),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -346,7 +370,7 @@ const shareCommand: SlashCommand = {
|
|||
return {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content: 'No conversation found to share.',
|
||||
content: t('No conversation found to share.'),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -362,14 +386,18 @@ const shareCommand: SlashCommand = {
|
|||
return {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content: `Conversation shared to ${filePath}`,
|
||||
content: t('Conversation shared to {{filePath}}', {
|
||||
filePath,
|
||||
}),
|
||||
};
|
||||
} catch (err) {
|
||||
const errorMessage = err instanceof Error ? err.message : String(err);
|
||||
return {
|
||||
type: 'message',
|
||||
messageType: 'error',
|
||||
content: `Error sharing conversation: ${errorMessage}`,
|
||||
content: t('Error sharing conversation: {{error}}', {
|
||||
error: errorMessage,
|
||||
}),
|
||||
};
|
||||
}
|
||||
},
|
||||
|
|
@ -377,7 +405,9 @@ const shareCommand: SlashCommand = {
|
|||
|
||||
export const chatCommand: SlashCommand = {
|
||||
name: 'chat',
|
||||
description: 'Manage conversation history.',
|
||||
get description() {
|
||||
return t('Manage conversation history.');
|
||||
},
|
||||
kind: CommandKind.BUILT_IN,
|
||||
subCommands: [
|
||||
listCommand,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue