@@ -19,6 +19,7 @@ import { sessionStore } from '@/utils/sessionStore';
1919import { VoicePrepareOverlay } from '@/components/VoicePrepareOverlay' ;
2020import { useFocusEffect } from '@react-navigation/native' ;
2121import { useLocalSearchParams } from 'expo-router' ;
22+ import { useTranslation } from 'react-i18next' ;
2223import { useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
2324import {
2425 ActivityIndicator ,
@@ -56,6 +57,7 @@ function generateMessageId(counter: number): string {
5657}
5758
5859const MainUIScreen : React . FC < MainUIScreenProps > = ( ) => {
60+ const { t } = useTranslation ( ) ;
5961
6062 const [ isPageFocused , setIsPageFocused ] = useState ( true ) ;
6163
@@ -179,7 +181,7 @@ const MainUIScreen: React.FC<MainUIScreenProps> = () => {
179181
180182 applyQrRaw ( raw ) . then ( ( res ) => {
181183 if ( ! res . ok ) {
182- Alert . alert ( '二维码内容不可用' , res . error ) ;
184+ Alert . alert ( t ( 'qrScanner.invalidCode' ) , res . error ) ;
183185 }
184186 } ) ;
185187 } , [ applyQrRaw , params . characterName , params . host , params . name , params . port , params . qr ] ) ;
@@ -315,7 +317,7 @@ const MainUIScreen: React.FC<MainUIScreenProps> = () => {
315317 const { agent, onAgentChange, refreshAgentState } = useLive2DAgentBackend ( {
316318 apiBase : `http://${ config . host } :${ config . port } ` ,
317319 showToast : ( message , duration ) => {
318- Alert . alert ( '提示' , message ) ;
320+ Alert . alert ( t ( 'common.alert' ) , message ) ;
319321 } ,
320322 openPanel : toolbarOpenPanel === 'agent' ? 'agent' : null ,
321323 } ) ;
@@ -913,7 +915,7 @@ const MainUIScreen: React.FC<MainUIScreenProps> = () => {
913915
914916 const names = Object . keys ( data . 猫娘 || { } ) ;
915917 if ( names . length === 0 ) {
916- Alert . alert ( '角色管理' , '暂无可用角色' ) ;
918+ Alert . alert ( t ( 'characterManager.title' ) , t ( 'characterManager.empty' ) ) ;
917919 return ;
918920 }
919921
@@ -922,7 +924,7 @@ const MainUIScreen: React.FC<MainUIScreenProps> = () => {
922924 setToolbarOpenPanel ( null ) ;
923925 setCharacterModalVisible ( true ) ;
924926 } catch ( err : any ) {
925- Alert . alert ( '获取角色列表失败' , err . message || '网络错误' ) ;
927+ Alert . alert ( t ( 'characterManager.title' ) , err . message || t ( 'connection.errors.networkError' ) ) ;
926928 } finally {
927929 setCharacterLoading ( false ) ;
928930 }
@@ -981,7 +983,7 @@ const MainUIScreen: React.FC<MainUIScreenProps> = () => {
981983 return ;
982984 }
983985
984- Alert . alert ( '功能提示' , `即将打开: ${ id } ` ) ;
986+ Alert . alert ( t ( 'common.alert' ) , `即将打开: ${ id } ` ) ;
985987 } , [ config , toolbarMicEnabled , mainManager , chat , audio , syncLive2dModel ] ) ;
986988
987989 const handleSwitchCharacter = useCallback ( async ( name : string ) => {
@@ -1015,11 +1017,11 @@ const MainUIScreen: React.FC<MainUIScreenProps> = () => {
10151017 } , 15000 ) ;
10161018 } else {
10171019 setCharacterLoading ( false ) ;
1018- Alert . alert ( '切换失败' , res . error || '未知错误' ) ;
1020+ Alert . alert ( t ( 'main.character.switchError' ) , res . error || t ( 'common.error' ) ) ;
10191021 }
10201022 } catch ( err : any ) {
10211023 setCharacterLoading ( false ) ;
1022- Alert . alert ( '切换失败' , err . message || '网络错误' ) ;
1024+ Alert . alert ( t ( 'main.character.switchError' ) , err . message || t ( 'connection.errors.networkError' ) ) ;
10231025 }
10241026 } , [ config , toolbarMicEnabled ] ) ;
10251027
@@ -1096,14 +1098,14 @@ const MainUIScreen: React.FC<MainUIScreenProps> = () => {
10961098 // 使用 stream_data action 和 clientMessageId 与 N.E.K.O 协议一致
10971099 const handleSendMessage = useCallback ( async ( text : string , images ?: string [ ] ) => {
10981100 if ( ! audio . isConnected ) {
1099- Alert . alert ( '提示' , '未连接到服务器' ) ;
1101+ Alert . alert ( t ( 'common.alert' ) , t ( 'connection.status.disconnected' ) ) ;
11001102 return ;
11011103 }
11021104
11031105 // 确保 text session 已启动(与 Web 端一致)
11041106 const sessionOk = await ensureTextSession ( ) ;
11051107 if ( ! sessionOk ) {
1106- Alert . alert ( '提示' , '会话初始化失败,请重试' ) ;
1108+ Alert . alert ( t ( 'common.alert' ) , t ( 'connection.status.reconnecting' ) ) ;
11071109 return ;
11081110 }
11091111
@@ -1392,7 +1394,7 @@ const MainUIScreen: React.FC<MainUIScreenProps> = () => {
13921394 < View style = { styles . characterModalContent } >
13931395 { /* Header — 对应 neko-header 蓝色背景 */ }
13941396 < View style = { styles . characterModalHeader } >
1395- < Text style = { styles . characterModalTitle } > 角色管理 </ Text >
1397+ < Text style = { styles . characterModalTitle } > { t ( 'characterManager.title' ) } </ Text >
13961398 < TouchableOpacity
13971399 style = { styles . characterModalCloseBtn }
13981400 onPress = { ( ) => setCharacterModalVisible ( false ) }
@@ -1402,7 +1404,7 @@ const MainUIScreen: React.FC<MainUIScreenProps> = () => {
14021404 </ TouchableOpacity >
14031405 </ View >
14041406 < Text style = { styles . characterModalSubtitle } >
1405- < Text style = { styles . characterModalSubtitleLabel } > 当前 : </ Text > < Text style = { styles . characterModalSubtitleHighlight } > { currentCatgirl || '未设置' } </ Text >
1407+ < Text style = { styles . characterModalSubtitleLabel } > { t ( 'settings.language.current' ) } : </ Text > < Text style = { styles . characterModalSubtitleHighlight } > { currentCatgirl || t ( 'main.character.noCharacters' ) } </ Text >
14061408 </ Text >
14071409 < ScrollView style = { styles . characterModalList } showsVerticalScrollIndicator = { false } >
14081410 { characterList . map ( ( name ) => {
@@ -1430,7 +1432,7 @@ const MainUIScreen: React.FC<MainUIScreenProps> = () => {
14301432 </ Text >
14311433 { isCurrent ? (
14321434 < View style = { styles . characterModalBadgeWrap } >
1433- < Text style = { styles . characterModalBadge } > 当前 </ Text >
1435+ < Text style = { styles . characterModalBadge } > { t ( 'main.character.current' ) } </ Text >
14341436 </ View >
14351437 ) : (
14361438 < View style = { styles . characterModalBadgePlaceholder } />
@@ -1457,7 +1459,7 @@ const MainUIScreen: React.FC<MainUIScreenProps> = () => {
14571459 < TouchableWithoutFeedback >
14581460 < View style = { [ styles . characterModalContent , styles . voiceBlockModalContent ] } >
14591461 < View style = { [ styles . characterModalHeader , styles . voiceBlockModalHeader ] } >
1460- < Text style = { styles . characterModalTitle } > 无法切换角色 </ Text >
1462+ < Text style = { styles . characterModalTitle } > { t ( 'main.character.voiceBlockTitle' ) } </ Text >
14611463 < TouchableOpacity
14621464 style = { styles . characterModalCloseBtn }
14631465 onPress = { ( ) => setVoiceBlockModalVisible ( false ) }
@@ -1467,13 +1469,13 @@ const MainUIScreen: React.FC<MainUIScreenProps> = () => {
14671469 </ TouchableOpacity >
14681470 </ View >
14691471 < Text style = { styles . voiceBlockModalBody } >
1470- 语音模式下无法切换角色,请先停止语音对话后再切换。
1472+ { t ( 'main.voice.cannotSwitchCharacter' ) }
14711473 </ Text >
14721474 < TouchableOpacity
14731475 style = { styles . voiceBlockModalBtn }
14741476 onPress = { ( ) => setVoiceBlockModalVisible ( false ) }
14751477 >
1476- < Text style = { styles . voiceBlockModalBtnText } > 好的 </ Text >
1478+ < Text style = { styles . voiceBlockModalBtnText } > { t ( 'common.ok' ) } </ Text >
14771479 </ TouchableOpacity >
14781480 </ View >
14791481 </ TouchableWithoutFeedback >
@@ -1485,14 +1487,14 @@ const MainUIScreen: React.FC<MainUIScreenProps> = () => {
14851487 { characterLoading && (
14861488 < View style = { styles . switchingOverlay } >
14871489 < ActivityIndicator size = "large" color = "#40c5f1" />
1488- < Text style = { styles . switchingText } > 正在切换角色... </ Text >
1490+ < Text style = { styles . switchingText } > { t ( 'main.character.switching' ) } </ Text >
14891491 </ View >
14901492 ) }
14911493
14921494 { /* 切换成功提示条 */ }
14931495 { switchedCharacterName !== null && (
14941496 < View style = { styles . switchingSuccessBanner } pointerEvents = "none" >
1495- < Text style = { styles . switchingSuccessText } > 已切换为 { switchedCharacterName } </ Text >
1497+ < Text style = { styles . switchingSuccessText } > { t ( 'main.character.switched' , { name : switchedCharacterName } ) } </ Text >
14961498 </ View >
14971499 ) }
14981500
@@ -1554,24 +1556,24 @@ const MainUIScreen: React.FC<MainUIScreenProps> = () => {
15541556 onStartShouldSetResponder = { ( ) => true }
15551557 >
15561558 < Text style = { { color : '#40c5f1' , fontSize : 18 , fontWeight : 'bold' , marginBottom : 15 } } >
1557- 🔧 调试信息
1559+ 🔧 { t ( 'main.debug.title' ) }
15581560 </ Text >
15591561 < ScrollView >
15601562 < Text style = { { color : '#fff' , fontSize : 12 , fontFamily : 'monospace' , marginBottom : 10 } } >
1561- { `连接状态 : ${ udpConnection . status }
1562- 层级 : ${ udpConnection . layer || '未连接' }
1563- 端点 : ${ udpConnection . endpoint ? `${ udpConnection . endpoint . ip } :${ udpConnection . endpoint . port } ` : '无' }
1563+ { `${ t ( 'connection.status.connected' ) } : ${ udpConnection . status }
1564+ ${ t ( 'main.debug.p2pLayer' ) } : ${ udpConnection . layer || t ( 'connection.status.disconnected' ) }
1565+ ${ t ( 'serverInfo.host' ) } : ${ udpConnection . endpoint ? `${ udpConnection . endpoint . ip } :${ udpConnection . endpoint . port } ` : t ( 'common.unavailable' ) }
15641566
1565- 当前配置 :
1566- Host : ${ config . host } :${ config . port }
1567- Character : ${ config . characterName || '未设置' }
1567+ ${ t ( 'settings.sections.serverInfo' ) } :
1568+ ${ t ( 'serverInfo.host' ) } : ${ config . host } :${ config . port }
1569+ ${ t ( 'serverInfo.character' ) } : ${ config . characterName || t ( 'main.character.noCharacters' ) }
15681570` }
15691571 </ Text >
15701572 < Text style = { { color : '#40c5f1' , fontSize : 12 , fontWeight : 'bold' , marginBottom : 4 } } >
1571- 连接日志 :
1573+ { t ( 'main.debug.connection' ) } :
15721574 </ Text >
15731575 < Text style = { { color : '#ccc' , fontSize : 11 , fontFamily : 'monospace' } } >
1574- { udpConnection . logs . length > 0 ? udpConnection . logs . join ( '\n' ) : '(暂无日志)' }
1576+ { udpConnection . logs . length > 0 ? udpConnection . logs . join ( '\n' ) : t ( 'common.warning' ) }
15751577 </ Text >
15761578 </ ScrollView >
15771579 < TouchableOpacity
@@ -1584,7 +1586,7 @@ Character: ${config.characterName || '未设置'}
15841586 } }
15851587 onPress = { ( ) => setDebugPanelVisible ( false ) }
15861588 >
1587- < Text style = { { color : '#fff' , fontWeight : 'bold' } } > 关闭 </ Text >
1589+ < Text style = { { color : '#fff' , fontWeight : 'bold' } } > { t ( 'common.close' ) } </ Text >
15881590 </ TouchableOpacity >
15891591 </ View >
15901592 </ TouchableOpacity >
0 commit comments