feat(i18n): Add Internationalization Support for UI and LLM Output (#1058)

This commit is contained in:
pomelo 2025-11-21 15:44:37 +08:00 committed by GitHub
parent 640f30655d
commit 48b77541c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
98 changed files with 4740 additions and 636 deletions

View file

@ -15,6 +15,7 @@ import { RadioButtonSelect } from '../components/shared/RadioButtonSelect.js';
import { useUIState } from '../contexts/UIStateContext.js';
import { useUIActions } from '../contexts/UIActionsContext.js';
import { useSettings } from '../contexts/SettingsContext.js';
import { t } from '../../i18n/index.js';
function parseDefaultAuthType(
defaultAuthType: string | undefined,
@ -39,10 +40,14 @@ export function AuthDialog(): React.JSX.Element {
const items = [
{
key: AuthType.QWEN_OAUTH,
label: 'Qwen OAuth',
label: t('Qwen OAuth'),
value: AuthType.QWEN_OAUTH,
},
{ key: AuthType.USE_OPENAI, label: 'OpenAI', value: AuthType.USE_OPENAI },
{
key: AuthType.USE_OPENAI,
label: t('OpenAI'),
value: AuthType.USE_OPENAI,
},
];
const initialAuthIndex = Math.max(
@ -98,7 +103,9 @@ export function AuthDialog(): React.JSX.Element {
if (settings.merged.security?.auth?.selectedType === undefined) {
// Prevent exiting if no auth method is set
setErrorMessage(
'You must select an auth method to proceed. Press Ctrl+C again to exit.',
t(
'You must select an auth method to proceed. Press Ctrl+C again to exit.',
),
);
return;
}
@ -116,9 +123,9 @@ export function AuthDialog(): React.JSX.Element {
padding={1}
width="100%"
>
<Text bold>Get started</Text>
<Text bold>{t('Get started')}</Text>
<Box marginTop={1}>
<Text>How would you like to authenticate for this project?</Text>
<Text>{t('How would you like to authenticate for this project?')}</Text>
</Box>
<Box marginTop={1}>
<RadioButtonSelect
@ -134,19 +141,19 @@ export function AuthDialog(): React.JSX.Element {
</Box>
)}
<Box marginTop={1}>
<Text color={Colors.AccentPurple}>(Use Enter to Set Auth)</Text>
<Text color={Colors.AccentPurple}>{t('(Use Enter to Set Auth)')}</Text>
</Box>
{hasApiKey && currentSelectedAuthType === AuthType.QWEN_OAUTH && (
<Box marginTop={1}>
<Text color={Colors.Gray}>
Note: Your existing API key in settings.json will not be cleared
when using Qwen OAuth. You can switch back to OpenAI authentication
later if needed.
{t(
'Note: Your existing API key in settings.json will not be cleared when using Qwen OAuth. You can switch back to OpenAI authentication later if needed.',
)}
</Text>
</Box>
)}
<Box marginTop={1}>
<Text>Terms of Services and Privacy Notice for Qwen Code</Text>
<Text>{t('Terms of Services and Privacy Notice for Qwen Code')}</Text>
</Box>
<Box marginTop={1}>
<Text color={Colors.AccentBlue}>

View file

@ -10,6 +10,7 @@ import { Box, Text } from 'ink';
import Spinner from 'ink-spinner';
import { theme } from '../semantic-colors.js';
import { useKeypress } from '../hooks/useKeypress.js';
import { t } from '../../i18n/index.js';
interface AuthInProgressProps {
onTimeout: () => void;
@ -48,13 +49,13 @@ export function AuthInProgress({
>
{timedOut ? (
<Text color={theme.status.error}>
Authentication timed out. Please try again.
{t('Authentication timed out. Please try again.')}
</Text>
) : (
<Box>
<Text>
<Spinner type="dots" /> Waiting for auth... (Press ESC or CTRL+C to
cancel)
<Spinner type="dots" />{' '}
{t('Waiting for auth... (Press ESC or CTRL+C to cancel)')}
</Text>
</Box>
)}

View file

@ -18,6 +18,7 @@ import type { OpenAICredentials } from '../components/OpenAIKeyPrompt.js';
import { useQwenAuth } from '../hooks/useQwenAuth.js';
import { AuthState, MessageType } from '../types.js';
import type { HistoryItem } from '../types.js';
import { t } from '../../i18n/index.js';
export type { QwenAuthState } from '../hooks/useQwenAuth.js';
@ -60,7 +61,9 @@ export const useAuthCommand = (
const handleAuthFailure = useCallback(
(error: unknown) => {
setIsAuthenticating(false);
const errorMessage = `Failed to authenticate. Message: ${getErrorMessage(error)}`;
const errorMessage = t('Failed to authenticate. Message: {{message}}', {
message: getErrorMessage(error),
});
onAuthError(errorMessage);
// Log authentication failure
@ -127,7 +130,9 @@ export const useAuthCommand = (
addItem(
{
type: MessageType.INFO,
text: `Authenticated successfully with ${authType} credentials.`,
text: t('Authenticated successfully with {{authType}} credentials.', {
authType,
}),
},
Date.now(),
);
@ -225,7 +230,13 @@ export const useAuthCommand = (
)
) {
onAuthError(
`Invalid QWEN_DEFAULT_AUTH_TYPE value: "${defaultAuthType}". Valid values are: ${[AuthType.QWEN_OAUTH, AuthType.USE_OPENAI].join(', ')}`,
t(
'Invalid QWEN_DEFAULT_AUTH_TYPE value: "{{value}}". Valid values are: {{validValues}}',
{
value: defaultAuthType,
validValues: [AuthType.QWEN_OAUTH, AuthType.USE_OPENAI].join(', '),
},
),
);
}
}, [onAuthError]);