Browse Source

上传ios 支付测试代码

newdev_shunjiawei
liwei1dao 11 months ago
parent
commit
e600573b2c
  1. 109
      lib/core/translations/language/ar_sa.dart
  2. 78
      lib/core/translations/language/de_de.dart
  3. 161
      lib/core/translations/language/en_us.dart
  4. 34
      lib/core/translations/language/es_es.dart
  5. 33
      lib/core/translations/language/fr_fr.dart
  6. 106
      lib/core/translations/language/hi_in.dart
  7. 78
      lib/core/translations/language/it_it.dart
  8. 34
      lib/core/translations/language/ja_jp.dart
  9. 78
      lib/core/translations/language/ko_kr.dart
  10. 78
      lib/core/translations/language/pt_pt.dart
  11. 78
      lib/core/translations/language/ru_ru.dart
  12. 146
      lib/core/translations/language/zh_cn.dart
  13. 116
      lib/core/translations/language/zh_hk.dart
  14. 17
      lib/core/widgets/intro_overlay_builder.dart
  15. 12
      lib/data/models/user_Info.dart
  16. 13
      lib/data/services/network/api.dart
  17. 48
      lib/data/services/novice_guide_service.dart
  18. 176
      lib/data/services/pay_service.dart
  19. 59
      lib/modules/agent/views/agent_view.dart
  20. 68
      lib/modules/goods/controllers/goods_base_controller.dart
  21. 63
      lib/modules/goods/utils/goods_i18n.dart
  22. 136
      lib/modules/goods/views/goodsai_view.dart
  23. 51
      lib/modules/goods/views/goodsmeet_view.dart
  24. 54
      lib/modules/goods/views/goodstrade_view.dart
  25. 91
      lib/modules/goods/views/goodsvip_view.dart
  26. 4
      lib/modules/home/views/home_view.dart
  27. 8
      lib/modules/settings/views/settings_view.dart
  28. 2
      pubspec.yaml

109
lib/core/translations/language/ar_sa.dart

@ -1159,4 +1159,113 @@ const Map<String, String> arSA = {
"justNow": "الآن",
"minutesAgo": "منذ @minutes دقيقة",
"yesterday": "أمس",
// Guide overlay keys (placeholders in English)
"sayXiaoYanHint": "Say \"Xiaoyan Xiaoyan\" to the mic",
"imHere": "I’m here~",
"guideWelcomeWakeAI": "Welcome to Voitrans! First, wake your AI “Xiaoyan”.",
"aiReplyCompleted": "Xiaoyan has finished the reply!",
"aiThinking": "Xiaoyan is thinking…",
"guideAwakenSuccess": "Great! Xiaoyan is awake—ask it to help.",
"confirmInput": "Confirm Input",
"guideClickSendPrefix": "Tap send, ",
"guideWeatherStart": "Tell Xiaoyan: “What’s the weather today?”",
"guideWeatherInput": "What’s the weather today?",
"guideWeatherSend": "Xiaoyan will report the weather in real time",
"guideWeatherEnd": "Xiaoyan can report weather live—try other commands",
"guideMusicStart": "Tell Xiaoyan: “Play some rock music”",
"guideMusicInput": "Play some rock music",
"guideMusicSend": "Xiaoyan will find music for you",
"guideMusicEnd": "Xiaoyan found music—try other commands",
"guideNavStart": "Tell Xiaoyan: “Navigate to Shenzhen Airport”",
"guideNavInput": "Navigate to Shenzhen Airport",
"guideNavSend": "Xiaoyan will plan the route",
"guideNavEnd": "Navigation set—try other commands",
"guideMeetingStart":
"Tell Xiaoyan: “Create a meeting reminder for 3pm tomorrow”",
"guideMeetingInput": "Create a meeting reminder for 3pm tomorrow",
"guideMeetingSend": "Xiaoyan will create a meeting reminder",
"guideMeetingEnd": "Reminder created—try other commands",
"guidePhoneStart": "Tell Xiaoyan: “Call Mom”",
"guidePhoneInput": "Call Mom",
"guidePhoneSend": "Xiaoyan will make the call",
"guidePhoneEnd": "Call placed—try other commands",
"guideSmsStart": "Tell Xiaoyan: “Send Dad a text: I’ll be home for dinner”",
"guideSmsInput": "Text Dad: I’ll be home for dinner",
"guideSmsSend": "Xiaoyan will send the message",
"guideSmsEnd": "Message sent—voice control is convenient",
// Goods pages common footer (placeholders)
'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans',
'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About',
'copyrightVoiTrans': '© 2025 VoiTrans',
// Meeting goods page (placeholders)
'meetingHeaderDesc1':
'Audio recording, transcription, keyword search, and auto summary.',
'meetingHeaderDesc2':
'Suitable for business meetings, class notes, and interview minutes.',
'meetingAutoRecording': 'Auto recording and segmentation',
'meetingSpeakerTagging': 'Speaker labeling',
'meetingLongAudioTranscription': 'Long audio transcription',
'meetingKeyPointSummary': 'Key point extraction',
'meetingTopicNameSearch': 'Search by topic/name',
'meetingTimelineJump': 'Timeline jump',
'meetingExportSummary': 'Export minutes',
'meetingMultiPlatformShare': 'Share across platforms',
'meetingDisclaimer':
'Use in quiet environments; performance depends on microphone and network.',
// Translation goods page (placeholders)
'tradeHeaderDesc1':
'Real-time simultaneous interpretation and text translation with low-latency voice.',
'tradeHeaderDesc2': 'Suitable for travel, business, speeches, and teaching.',
'translateZhEn': 'Chinese-English translation',
'lowLatencyVoiceBroadcast': 'Low-latency voice broadcast',
'multiLangTextTranslation': 'Multilingual text translation',
'termOptimizationContextPreserve':
'Terminology optimization and context preservation',
'lexiconTourBusinessLife': 'Travel/Business/Life lexicons',
'personalVocabularyMemory': 'Personal vocabulary memory',
'conversationSubtitleLargeText': 'Conversation subtitles / Large-text mode',
'colorHighContrast': 'High color contrast',
'tradeDisclaimer':
'Translation performance depends on microphone, network latency, and ambient noise.',
// VIP goods page (placeholders)
'benefitsOverview': 'Benefits overview',
'higherQuota': 'Higher usage quota',
'lowerUnitPrice': 'Lower unit price',
'priorityService': 'Priority service',
'exclusiveSupportChannel': 'Dedicated support channel',
'fastResponse': 'Fast issue response',
'eventsAndDiscounts': 'Events and discounts',
'memberExclusiveEvents': 'Member-exclusive events',
'longTermDiscountPlan': 'Long-term discount plan',
'generalPrivileges': 'General privileges',
'earlyAccessNewFeatures': 'Early access to new features',
'crossDeviceSync': 'Cross-device sync',
'vipDisclaimer':
'Actual benefits depend on the package details and may change with versions.',
// Goods names by id
'ai_001_name': 'الذكاء الاصطناعي الأساسي 100',
'ai_002_name': 'الذكاء الاصطناعي الأساسي 500',
'ai_003_name': 'الذكاء الاصطناعي الأساسي 1000',
'meet_001_name': 'اجتماع أساسي 100',
'meet_002_name': 'اجتماع أساسي 500',
'meet_003_name': 'اجتماع أساسي 1000',
'trade_001_name': 'ترجمة أساسية 100',
'trade_002_name': 'ترجمة أساسية 500',
'trade_003_name': 'ترجمة أساسية 1000',
// Goods descriptions by id
'ai_001_desc':
'يشمل 100 استخدام. الوصول إلى ميزات الذكاء الاصطناعي الأساسية.',
'ai_002_desc':
'يشمل 500 استخدام. الوصول إلى ميزات الذكاء الاصطناعي الأساسية.',
'ai_003_desc':
'يشمل 1000 استخدام. الوصول إلى ميزات الذكاء الاصطناعي الأساسية.',
'meet_001_desc': 'يشمل 100 تسجيل/نسخ لاجتماعات.',
'meet_002_desc': 'يشمل 500 تسجيل/نسخ لاجتماعات.',
'meet_003_desc': 'يشمل 1000 تسجيل/نسخ لاجتماعات.',
'trade_001_desc': 'يشمل 100 ترجمة (صوت/نص).',
'trade_002_desc': 'يشمل 500 ترجمة (صوت/نص).',
'trade_003_desc': 'يشمل 1000 ترجمة (صوت/نص).',
};

78
lib/core/translations/language/de_de.dart

@ -880,4 +880,82 @@ const Map<String, String> deDE = {
"乌尔都语": "Urdu",
"波斯语": "Persisch",
"斯瓦希里语": "Swahili",
// Guide overlay keys (placeholders in English)
"sayXiaoYanHint": "Say \"Xiaoyan Xiaoyan\" to the mic",
"imHere": "I’m here~",
"guideWelcomeWakeAI": "Welcome to Voitrans! First, wake your AI “Xiaoyan”.",
"aiReplyCompleted": "Xiaoyan has finished the reply!",
"aiThinking": "Xiaoyan is thinking…",
"guideAwakenSuccess": "Great! Xiaoyan is awake—ask it to help.",
"confirmInput": "Confirm Input",
"guideClickSendPrefix": "Tap send, ",
"guideWeatherStart": "Tell Xiaoyan: “What’s the weather today?”",
"guideWeatherInput": "What’s the weather today?",
"guideWeatherSend": "Xiaoyan will report the weather in real time",
"guideWeatherEnd": "Xiaoyan can report weather live—try other commands",
"guideMusicStart": "Tell Xiaoyan: “Play some rock music”",
"guideMusicInput": "Play some rock music",
"guideMusicSend": "Xiaoyan will find music for you",
"guideMusicEnd": "Xiaoyan found music—try other commands",
"guideNavStart": "Tell Xiaoyan: “Navigate to Shenzhen Airport”",
"guideNavInput": "Navigate to Shenzhen Airport",
"guideNavSend": "Xiaoyan will plan the route",
"guideNavEnd": "Navigation set—try other commands",
"guideMeetingStart": "Tell Xiaoyan: “Create a meeting reminder for 3pm tomorrow”",
"guideMeetingInput": "Create a meeting reminder for 3pm tomorrow",
"guideMeetingSend": "Xiaoyan will create a meeting reminder",
"guideMeetingEnd": "Reminder created—try other commands",
"guidePhoneStart": "Tell Xiaoyan: “Call Mom”",
"guidePhoneInput": "Call Mom",
"guidePhoneSend": "Xiaoyan will make the call",
"guidePhoneEnd": "Call placed—try other commands",
"guideSmsStart": "Tell Xiaoyan: “Send Dad a text: I’ll be home for dinner”",
"guideSmsInput": "Text Dad: I’ll be home for dinner",
"guideSmsSend": "Xiaoyan will send the message",
"guideSmsEnd": "Message sent—voice control is convenient",
// Goods pages common footer (placeholders)
'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans',
'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About',
'copyrightVoiTrans': '© 2025 VoiTrans',
// Meeting goods page (placeholders)
'meetingHeaderDesc1': 'Audio recording, transcription, keyword search, and auto summary.',
'meetingHeaderDesc2': 'Suitable for business meetings, class notes, and interview minutes.',
'meetingAutoRecording': 'Auto recording and segmentation',
'meetingSpeakerTagging': 'Speaker labeling',
'meetingLongAudioTranscription': 'Long audio transcription',
'meetingKeyPointSummary': 'Key point extraction',
'meetingTopicNameSearch': 'Search by topic/name',
'meetingTimelineJump': 'Timeline jump',
'meetingExportSummary': 'Export minutes',
'meetingMultiPlatformShare': 'Share across platforms',
'meetingDisclaimer': 'Use in quiet environments; performance depends on microphone and network.',
// Translation goods page (placeholders)
'tradeHeaderDesc1': 'Real-time simultaneous interpretation and text translation with low-latency voice.',
'tradeHeaderDesc2': 'Suitable for travel, business, speeches, and teaching.',
'translateZhEn': 'Chinese-English translation',
'lowLatencyVoiceBroadcast': 'Low-latency voice broadcast',
'multiLangTextTranslation': 'Multilingual text translation',
'termOptimizationContextPreserve': 'Terminology optimization and context preservation',
'lexiconTourBusinessLife': 'Travel/Business/Life lexicons',
'personalVocabularyMemory': 'Personal vocabulary memory',
'conversationSubtitleLargeText': 'Conversation subtitles / Large-text mode',
'colorHighContrast': 'High color contrast',
'tradeDisclaimer': 'Translation performance depends on microphone, network latency, and ambient noise.',
// VIP goods page (placeholders)
'benefitsOverview': 'Benefits overview',
'higherQuota': 'Higher usage quota',
'lowerUnitPrice': 'Lower unit price',
'priorityService': 'Priority service',
'exclusiveSupportChannel': 'Dedicated support channel',
'fastResponse': 'Fast issue response',
'eventsAndDiscounts': 'Events and discounts',
'memberExclusiveEvents': 'Member-exclusive events',
'longTermDiscountPlan': 'Long-term discount plan',
'generalPrivileges': 'General privileges',
'earlyAccessNewFeatures': 'Early access to new features',
'crossDeviceSync': 'Cross-device sync',
'vipDisclaimer': 'Actual benefits depend on the package details and may change with versions.',
};

161
lib/core/translations/language/en_us.dart

@ -197,6 +197,165 @@ const Map<String, String> enUS = {
"popularFunction": "Popular Features",
"tryNow": "Try Now",
// Goods screens (AI/Translation/Meeting)
'availablePackages': 'Available Packages',
'remainingQuota': 'Remaining Quota',
'totalCount': 'Total Count',
'remaining': 'Remaining',
'featureDescription': 'Feature Description',
// AI feature cards
'musicAndRecommendation': 'Music & Recommendation',
'navigationAndRoutes': 'Navigation & Routes',
'nearbySearch': 'Nearby Search',
'newsInformation': 'News',
'communicationAssistant': 'Communication Assistant',
// Translation feature cards
'realtimeTranscription': 'Real-time Transcription',
// 'textTranslation' exists
'sceneLexicon': 'Scenario Glossary',
'subtitleDisplay': 'Subtitles',
// Meeting feature cards
'meetingRecording': 'Meeting Recording',
'transcriptionAndSummary': 'Transcription & Summary',
'keywordSearch': 'Keyword Search',
'collaborationSharing': 'Collaboration & Sharing',
// Goods names by id
'ai_001_name': 'AI Basic 100',
'ai_002_name': 'AI Basic 500',
'ai_003_name': 'AI Basic 1000',
'meet_001_name': 'Meeting Basic 100',
'meet_002_name': 'Meeting Basic 500',
'meet_003_name': 'Meeting Basic 1000',
'trade_001_name': 'Translation Basic 100',
'trade_002_name': 'Translation Basic 500',
'trade_003_name': 'Translation Basic 1000',
// Goods descriptions by id
'ai_001_desc': 'Includes 100 uses. Access core AI features.',
'ai_002_desc': 'Includes 500 uses. Access core AI features.',
'ai_003_desc': 'Includes 1000 uses. Access core AI features.',
'meet_001_desc': 'Includes 100 meeting recordings/transcriptions.',
'meet_002_desc': 'Includes 500 meeting recordings/transcriptions.',
'meet_003_desc': 'Includes 1000 meeting recordings/transcriptions.',
'trade_001_desc': 'Includes 100 translations (voice/text).',
'trade_002_desc': 'Includes 500 translations (voice/text).',
'trade_003_desc': 'Includes 1000 translations (voice/text).',
// Goods pages common footer
'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans',
'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About',
'copyrightVoiTrans': '© 2025 VoiTrans',
// Meeting goods page descriptions
'meetingHeaderDesc1':
'Audio recording, transcription, keyword search, and auto summary to boost meeting efficiency.',
'meetingHeaderDesc2':
'Suitable for business meetings, class notes, and interview minutes.',
'meetingAutoRecording': 'Auto recording and segmentation',
'meetingSpeakerTagging': 'Speaker labeling',
'meetingLongAudioTranscription': 'Long audio transcription',
'meetingKeyPointSummary': 'Key point extraction',
'meetingTopicNameSearch': 'Search by topic/name',
'meetingTimelineJump': 'Timeline jump',
'meetingExportSummary': 'Export minutes',
'meetingMultiPlatformShare': 'Share across platforms',
'meetingDisclaimer':
'Use in quiet environments; performance depends on microphone and network.',
// Translation goods page descriptions
'tradeHeaderDesc1':
'Real-time simultaneous interpretation and text translation with low-latency voice.',
'tradeHeaderDesc2':
'Suitable for travel, business, speeches, and teaching.',
'translateZhEn': 'Chinese-English translation',
'lowLatencyVoiceBroadcast': 'Low-latency voice broadcast',
'multiLangTextTranslation': 'Multilingual text translation',
'termOptimizationContextPreserve': 'Terminology optimization and context preservation',
'lexiconTourBusinessLife': 'Travel/Business/Life lexicons',
'personalVocabularyMemory': 'Personal vocabulary memory',
'conversationSubtitleLargeText': 'Conversation subtitles / Large-text mode',
'colorHighContrast': 'High color contrast',
'tradeDisclaimer':
'Translation performance depends on microphone, network latency, and ambient noise.',
// AI goods page descriptions
'aiHeaderDesc1':
'Longer conversation quota, more tool calls, extended context length.',
'aiHeaderDesc2':
'Suitable for agent Q&A, summarization, analysis, and task execution.',
'musicSearchPlaybackControl': 'Music library search and playback control',
'smartPlaylistAndSimilarRecommendations':
'Smart playlist and similar song recommendations',
'routePlanningAndCongestionAvoidance':
'Route planning and congestion avoidance',
'voiceBroadcastAndWaypoints': 'Voice broadcast and waypoint settings',
'realTimeWeatherForecast': 'Real-time weather and forecast',
'clothingAdviceAndTravelReminders': 'Clothing advice and travel reminders',
'poiSearchFoodGasParking': 'POI search: dining / gas / parking',
'ratingsHoursAndDirectRoutes':
'Ratings, business hours, and direct routing',
'hotNewsAndTopicOverview': 'Hot news and topic overview',
'longArticleSummariesAndKeyPoints':
'Long-article summaries and key points',
'helpCallAndSMS': 'Help with calls and SMS',
'templatedMessagesAndScheduleReminders':
'Template messages and schedule reminders',
'aiDisclaimer':
'Features depend on device permissions, service availability, and network conditions.',
// VIP goods page
'benefitsOverview': 'Benefits overview',
'higherQuota': 'Higher usage quota',
'lowerUnitPrice': 'Lower unit price',
'priorityService': 'Priority service',
'exclusiveSupportChannel': 'Dedicated support channel',
'fastResponse': 'Fast issue response',
'eventsAndDiscounts': 'Events and discounts',
'memberExclusiveEvents': 'Member-exclusive events',
'longTermDiscountPlan': 'Long-term discount plan',
'generalPrivileges': 'General privileges',
'earlyAccessNewFeatures': 'Early access to new features',
'crossDeviceSync': 'Cross-device sync',
'vipDisclaimer':
'Actual benefits depend on the package details and may change with versions.',
// Onboarding / Guide
'skip': 'Skip',
'next': 'Next',
'sayXiaoYanHint': 'Say "Xiaoyan Xiaoyan" to the mic',
'imHere': 'I’m here~',
'guideWelcomeWakeAI': 'Welcome to Voitrans! First, wake your AI “Xiaoyan”.',
'aiReplyCompleted': 'Xiaoyan has finished the reply!',
'aiThinking': 'Xiaoyan is thinking…',
'guideAwakenSuccess': 'Great! Xiaoyan is awake—ask it to help.',
'confirmInput': 'Confirm Input',
'guideClickSendPrefix': 'Tap send, ',
// AI steps
'guideWeatherStart': 'Tell Xiaoyan: “What’s the weather today?”',
'guideWeatherInput': 'What’s the weather today?',
'guideWeatherSend': 'Xiaoyan will report the weather in real time',
'guideWeatherEnd': 'Xiaoyan can report weather live—try other commands',
'guideMusicStart': 'Tell Xiaoyan: “Play some rock music”',
'guideMusicInput': 'Play some rock music',
'guideMusicSend': 'Xiaoyan will find music for you',
'guideMusicEnd': 'Xiaoyan found music—try other commands',
'guideNavStart': 'Tell Xiaoyan: “Navigate to Shenzhen Airport”',
'guideNavInput': 'Navigate to Shenzhen Airport',
'guideNavSend': 'Xiaoyan will plan the route',
'guideNavEnd': 'Navigation set—try other commands',
'guideMeetingStart': 'Tell Xiaoyan: “Create a meeting reminder for 3pm tomorrow”',
'guideMeetingInput': 'Create a meeting reminder for 3pm tomorrow',
'guideMeetingSend': 'Xiaoyan will create a meeting reminder',
'guideMeetingEnd': 'Reminder created—try other commands',
'guidePhoneStart': 'Tell Xiaoyan: “Call Mom”',
'guidePhoneInput': 'Call Mom',
'guidePhoneSend': 'Xiaoyan will make the call',
'guidePhoneEnd': 'Call placed—try other commands',
'guideSmsStart': 'Tell Xiaoyan: “Send Dad a text: I’ll be home for dinner”',
'guideSmsInput': 'Text Dad: I’ll be home for dinner',
'guideSmsSend': 'Xiaoyan will send the message',
'guideSmsEnd': 'Message sent—voice control is convenient',
// 商务会议助手页
"startMeeting": "Start Meeting",
'edit': 'Edit',
@ -1053,7 +1212,7 @@ const Map<String, String> enUS = {
"autoInputCode": "Auto Input Code",
"skipBinding": "Skip Binding",
"rescan": "Rescan",
"skip": "Skip",
"verifyingDevice": "Verifying device...",
"confirmBinding": "Confirm Binding",
"associatingDevice": "Associating device...",

34
lib/core/translations/language/es_es.dart

@ -874,4 +874,38 @@ const Map<String, String> esES = {
"乌尔都语": "Urdu",
"波斯语": "Persa",
"斯瓦希里语": "Suajili",
// Guide overlay keys (placeholders in English)
"sayXiaoYanHint": "Say \"Xiaoyan Xiaoyan\" to the mic",
"imHere": "I’m here~",
"guideWelcomeWakeAI": "Welcome to Voitrans! First, wake your AI “Xiaoyan”.",
"aiReplyCompleted": "Xiaoyan has finished the reply!",
"aiThinking": "Xiaoyan is thinking…",
"guideAwakenSuccess": "Great! Xiaoyan is awake—ask it to help.",
"confirmInput": "Confirm Input",
"guideClickSendPrefix": "Tap send, ",
"guideWeatherStart": "Tell Xiaoyan: “What’s the weather today?”",
"guideWeatherInput": "What’s the weather today?",
"guideWeatherSend": "Xiaoyan will report the weather in real time",
"guideWeatherEnd": "Xiaoyan can report weather live—try other commands",
"guideMusicStart": "Tell Xiaoyan: “Play some rock music”",
"guideMusicInput": "Play some rock music",
"guideMusicSend": "Xiaoyan will find music for you",
"guideMusicEnd": "Xiaoyan found music—try other commands",
"guideNavStart": "Tell Xiaoyan: “Navigate to Shenzhen Airport”",
"guideNavInput": "Navigate to Shenzhen Airport",
"guideNavSend": "Xiaoyan will plan the route",
"guideNavEnd": "Navigation set—try other commands",
"guideMeetingStart":
"Tell Xiaoyan: “Create a meeting reminder for 3pm tomorrow”",
"guideMeetingInput": "Create a meeting reminder for 3pm tomorrow",
"guideMeetingSend": "Xiaoyan will create a meeting reminder",
"guideMeetingEnd": "Reminder created—try other commands",
"guidePhoneStart": "Tell Xiaoyan: “Call Mom”",
"guidePhoneInput": "Call Mom",
"guidePhoneSend": "Xiaoyan will make the call",
"guidePhoneEnd": "Call placed—try other commands",
"guideSmsStart": "Tell Xiaoyan: “Send Dad a text: I’ll be home for dinner”",
"guideSmsInput": "Text Dad: I’ll be home for dinner",
"guideSmsSend": "Xiaoyan will send the message",
"guideSmsEnd": "Message sent—voice control is convenient",
};

33
lib/core/translations/language/fr_fr.dart

@ -883,4 +883,37 @@ const Map<String, String> frFR = {
"乌尔都语": "Ourdou",
"波斯语": "Persan",
"斯瓦希里语": "Swahili",
// Guide overlay keys (placeholders in English)
"sayXiaoYanHint": "Say \"Xiaoyan Xiaoyan\" to the mic",
"imHere": "I’m here~",
"guideWelcomeWakeAI": "Welcome to Voitrans! First, wake your AI “Xiaoyan”.",
"aiReplyCompleted": "Xiaoyan has finished the reply!",
"aiThinking": "Xiaoyan is thinking…",
"guideAwakenSuccess": "Great! Xiaoyan is awake—ask it to help.",
"confirmInput": "Confirm Input",
"guideClickSendPrefix": "Tap send, ",
"guideWeatherStart": "Tell Xiaoyan: “What’s the weather today?”",
"guideWeatherInput": "What’s the weather today?",
"guideWeatherSend": "Xiaoyan will report the weather in real time",
"guideWeatherEnd": "Xiaoyan can report weather live—try other commands",
"guideMusicStart": "Tell Xiaoyan: “Play some rock music”",
"guideMusicInput": "Play some rock music",
"guideMusicSend": "Xiaoyan will find music for you",
"guideMusicEnd": "Xiaoyan found music—try other commands",
"guideNavStart": "Tell Xiaoyan: “Navigate to Shenzhen Airport”",
"guideNavInput": "Navigate to Shenzhen Airport",
"guideNavSend": "Xiaoyan will plan the route",
"guideNavEnd": "Navigation set—try other commands",
"guideMeetingStart": "Tell Xiaoyan: “Create a meeting reminder for 3pm tomorrow”",
"guideMeetingInput": "Create a meeting reminder for 3pm tomorrow",
"guideMeetingSend": "Xiaoyan will create a meeting reminder",
"guideMeetingEnd": "Reminder created—try other commands",
"guidePhoneStart": "Tell Xiaoyan: “Call Mom”",
"guidePhoneInput": "Call Mom",
"guidePhoneSend": "Xiaoyan will make the call",
"guidePhoneEnd": "Call placed—try other commands",
"guideSmsStart": "Tell Xiaoyan: “Send Dad a text: I’ll be home for dinner”",
"guideSmsInput": "Text Dad: I’ll be home for dinner",
"guideSmsSend": "Xiaoyan will send the message",
"guideSmsEnd": "Message sent—voice control is convenient",
};

106
lib/core/translations/language/hi_in.dart

@ -848,4 +848,110 @@ const Map<String, String> hiIN = {
"乌尔都语": "उर्दू",
"波斯语": "फारसी",
"斯瓦希里语": "स्वाहिली",
// Guide overlay keys (placeholders in English)
"sayXiaoYanHint": "Say \"Xiaoyan Xiaoyan\" to the mic",
"imHere": "I’m here~",
"guideWelcomeWakeAI": "Welcome to Voitrans! First, wake your AI “Xiaoyan”.",
"aiReplyCompleted": "Xiaoyan has finished the reply!",
"aiThinking": "Xiaoyan is thinking…",
"guideAwakenSuccess": "Great! Xiaoyan is awake—ask it to help.",
"confirmInput": "Confirm Input",
"guideClickSendPrefix": "Tap send, ",
"guideWeatherStart": "Tell Xiaoyan: “What’s the weather today?”",
"guideWeatherInput": "What’s the weather today?",
"guideWeatherSend": "Xiaoyan will report the weather in real time",
"guideWeatherEnd": "Xiaoyan can report weather live—try other commands",
"guideMusicStart": "Tell Xiaoyan: “Play some rock music”",
"guideMusicInput": "Play some rock music",
"guideMusicSend": "Xiaoyan will find music for you",
"guideMusicEnd": "Xiaoyan found music—try other commands",
"guideNavStart": "Tell Xiaoyan: “Navigate to Shenzhen Airport”",
"guideNavInput": "Navigate to Shenzhen Airport",
"guideNavSend": "Xiaoyan will plan the route",
"guideNavEnd": "Navigation set—try other commands",
"guideMeetingStart":
"Tell Xiaoyan: “Create a meeting reminder for 3pm tomorrow”",
"guideMeetingInput": "Create a meeting reminder for 3pm tomorrow",
"guideMeetingSend": "Xiaoyan will create a meeting reminder",
"guideMeetingEnd": "Reminder created—try other commands",
"guidePhoneStart": "Tell Xiaoyan: “Call Mom”",
"guidePhoneInput": "Call Mom",
"guidePhoneSend": "Xiaoyan will make the call",
"guidePhoneEnd": "Call placed—try other commands",
"guideSmsStart": "Tell Xiaoyan: “Send Dad a text: I’ll be home for dinner”",
"guideSmsInput": "Text Dad: I’ll be home for dinner",
"guideSmsSend": "Xiaoyan will send the message",
"guideSmsEnd": "Message sent—voice control is convenient",
// Goods pages common footer (placeholders)
'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans',
'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About',
'copyrightVoiTrans': '© 2025 VoiTrans',
// Meeting goods page (placeholders)
'meetingHeaderDesc1':
'Audio recording, transcription, keyword search, and auto summary.',
'meetingHeaderDesc2':
'Suitable for business meetings, class notes, and interview minutes.',
'meetingAutoRecording': 'Auto recording and segmentation',
'meetingSpeakerTagging': 'Speaker labeling',
'meetingLongAudioTranscription': 'Long audio transcription',
'meetingKeyPointSummary': 'Key point extraction',
'meetingTopicNameSearch': 'Search by topic/name',
'meetingTimelineJump': 'Timeline jump',
'meetingExportSummary': 'Export minutes',
'meetingMultiPlatformShare': 'Share across platforms',
'meetingDisclaimer':
'Use in quiet environments; performance depends on microphone and network.',
// Translation goods page (placeholders)
'tradeHeaderDesc1':
'Real-time simultaneous interpretation and text translation with low-latency voice.',
'tradeHeaderDesc2': 'Suitable for travel, business, speeches, and teaching.',
'translateZhEn': 'Chinese-English translation',
'lowLatencyVoiceBroadcast': 'Low-latency voice broadcast',
'multiLangTextTranslation': 'Multilingual text translation',
'termOptimizationContextPreserve':
'Terminology optimization and context preservation',
'lexiconTourBusinessLife': 'Travel/Business/Life lexicons',
'personalVocabularyMemory': 'Personal vocabulary memory',
'conversationSubtitleLargeText': 'Conversation subtitles / Large-text mode',
'colorHighContrast': 'High color contrast',
'tradeDisclaimer':
'Translation performance depends on microphone, network latency, and ambient noise.',
// VIP goods page (placeholders)
'benefitsOverview': 'Benefits overview',
'higherQuota': 'Higher usage quota',
'lowerUnitPrice': 'Lower unit price',
'priorityService': 'Priority service',
'exclusiveSupportChannel': 'Dedicated support channel',
'fastResponse': 'Fast issue response',
'eventsAndDiscounts': 'Events and discounts',
'memberExclusiveEvents': 'Member-exclusive events',
'longTermDiscountPlan': 'Long-term discount plan',
'generalPrivileges': 'General privileges',
'earlyAccessNewFeatures': 'Early access to new features',
'crossDeviceSync': 'Cross-device sync',
'vipDisclaimer':
'Actual benefits depend on the package details and may change with versions.',
// Goods names by id
'ai_001_name': 'एआई बेसिक 100',
'ai_002_name': 'एआई बेसिक 500',
'ai_003_name': 'एआई बेसिक 1000',
'meet_001_name': 'मीटिंग बेसिक 100',
'meet_002_name': 'मीटिंग बेसिक 500',
'meet_003_name': 'मीटिंग बेसिक 1000',
'trade_001_name': 'अनुवाद बेसिक 100',
'trade_002_name': 'अनुवाद बेसिक 500',
'trade_003_name': 'अनुवाद बेसिक 1000',
// Goods descriptions by id
'ai_001_desc': '100 उपयोग शामिल। मुख्य AI सुविधाओं की पहुँच।',
'ai_002_desc': '500 उपयोग शामिल। मुख्य AI सुविधाओं की पहुँच।',
'ai_003_desc': '1000 उपयोग शामिल। मुख्य AI सुविधाओं की पहुँच।',
'meet_001_desc': '100 बैठक रिकॉर्डिंग/ट्रांसक्रिप्शन शामिल।',
'meet_002_desc': '500 बैठक रिकॉर्डिंग/ट्रांसक्रिप्शन शामिल।',
'meet_003_desc': '1000 बैठक रिकॉर्डिंग/ट्रांसक्रिप्शन शामिल।',
'trade_001_desc': '100 अनुवाद (वॉयस/टेक्स्ट) शामिल।',
'trade_002_desc': '500 अनुवाद (वॉयस/टेक्स्ट) शामिल।',
'trade_003_desc': '1000 अनुवाद (वॉयस/टेक्स्ट) शामिल।',
};

78
lib/core/translations/language/it_it.dart

@ -869,4 +869,82 @@ const Map<String, String> itIT = {
"乌尔都语": "Urdu",
"波斯语": "Persiano",
"斯瓦希里语": "Swahili",
// Guide overlay keys (placeholders in English)
"sayXiaoYanHint": "Say \"Xiaoyan Xiaoyan\" to the mic",
"imHere": "I’m here~",
"guideWelcomeWakeAI": "Welcome to Voitrans! First, wake your AI “Xiaoyan”.",
"aiReplyCompleted": "Xiaoyan has finished the reply!",
"aiThinking": "Xiaoyan is thinking…",
"guideAwakenSuccess": "Great! Xiaoyan is awake—ask it to help.",
"confirmInput": "Confirm Input",
"guideClickSendPrefix": "Tap send, ",
"guideWeatherStart": "Tell Xiaoyan: “What’s the weather today?”",
"guideWeatherInput": "What’s the weather today?",
"guideWeatherSend": "Xiaoyan will report the weather in real time",
"guideWeatherEnd": "Xiaoyan can report weather live—try other commands",
"guideMusicStart": "Tell Xiaoyan: “Play some rock music”",
"guideMusicInput": "Play some rock music",
"guideMusicSend": "Xiaoyan will find music for you",
"guideMusicEnd": "Xiaoyan found music—try other commands",
"guideNavStart": "Tell Xiaoyan: “Navigate to Shenzhen Airport”",
"guideNavInput": "Navigate to Shenzhen Airport",
"guideNavSend": "Xiaoyan will plan the route",
"guideNavEnd": "Navigation set—try other commands",
"guideMeetingStart": "Tell Xiaoyan: “Create a meeting reminder for 3pm tomorrow”",
"guideMeetingInput": "Create a meeting reminder for 3pm tomorrow",
"guideMeetingSend": "Xiaoyan will create a meeting reminder",
"guideMeetingEnd": "Reminder created—try other commands",
"guidePhoneStart": "Tell Xiaoyan: “Call Mom”",
"guidePhoneInput": "Call Mom",
"guidePhoneSend": "Xiaoyan will make the call",
"guidePhoneEnd": "Call placed—try other commands",
"guideSmsStart": "Tell Xiaoyan: “Send Dad a text: I’ll be home for dinner”",
"guideSmsInput": "Text Dad: I’ll be home for dinner",
"guideSmsSend": "Xiaoyan will send the message",
"guideSmsEnd": "Message sent—voice control is convenient",
// Goods pages common footer (placeholders)
'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans',
'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About',
'copyrightVoiTrans': '© 2025 VoiTrans',
// Meeting goods page (placeholders)
'meetingHeaderDesc1': 'Audio recording, transcription, keyword search, and auto summary.',
'meetingHeaderDesc2': 'Suitable for business meetings, class notes, and interview minutes.',
'meetingAutoRecording': 'Auto recording and segmentation',
'meetingSpeakerTagging': 'Speaker labeling',
'meetingLongAudioTranscription': 'Long audio transcription',
'meetingKeyPointSummary': 'Key point extraction',
'meetingTopicNameSearch': 'Search by topic/name',
'meetingTimelineJump': 'Timeline jump',
'meetingExportSummary': 'Export minutes',
'meetingMultiPlatformShare': 'Share across platforms',
'meetingDisclaimer': 'Use in quiet environments; performance depends on microphone and network.',
// Translation goods page (placeholders)
'tradeHeaderDesc1': 'Real-time simultaneous interpretation and text translation with low-latency voice.',
'tradeHeaderDesc2': 'Suitable for travel, business, speeches, and teaching.',
'translateZhEn': 'Chinese-English translation',
'lowLatencyVoiceBroadcast': 'Low-latency voice broadcast',
'multiLangTextTranslation': 'Multilingual text translation',
'termOptimizationContextPreserve': 'Terminology optimization and context preservation',
'lexiconTourBusinessLife': 'Travel/Business/Life lexicons',
'personalVocabularyMemory': 'Personal vocabulary memory',
'conversationSubtitleLargeText': 'Conversation subtitles / Large-text mode',
'colorHighContrast': 'High color contrast',
'tradeDisclaimer': 'Translation performance depends on microphone, network latency, and ambient noise.',
// VIP goods page (placeholders)
'benefitsOverview': 'Benefits overview',
'higherQuota': 'Higher usage quota',
'lowerUnitPrice': 'Lower unit price',
'priorityService': 'Priority service',
'exclusiveSupportChannel': 'Dedicated support channel',
'fastResponse': 'Fast issue response',
'eventsAndDiscounts': 'Events and discounts',
'memberExclusiveEvents': 'Member-exclusive events',
'longTermDiscountPlan': 'Long-term discount plan',
'generalPrivileges': 'General privileges',
'earlyAccessNewFeatures': 'Early access to new features',
'crossDeviceSync': 'Cross-device sync',
'vipDisclaimer': 'Actual benefits depend on the package details and may change with versions.',
};

34
lib/core/translations/language/ja_jp.dart

@ -797,4 +797,38 @@ const Map<String, String> jaJP = {
"乌尔都语": "ウルドゥー語",
"波斯语": "ペルシャ語",
"斯瓦希里语": "スワヒリ語",
// Guide overlay keys (placeholders in English)
"sayXiaoYanHint": "Say \"Xiaoyan Xiaoyan\" to the mic",
"imHere": "I’m here~",
"guideWelcomeWakeAI": "Welcome to Voitrans! First, wake your AI “Xiaoyan”.",
"aiReplyCompleted": "Xiaoyan has finished the reply!",
"aiThinking": "Xiaoyan is thinking…",
"guideAwakenSuccess": "Great! Xiaoyan is awake—ask it to help.",
"confirmInput": "Confirm Input",
"guideClickSendPrefix": "Tap send, ",
"guideWeatherStart": "Tell Xiaoyan: “What’s the weather today?”",
"guideWeatherInput": "What’s the weather today?",
"guideWeatherSend": "Xiaoyan will report the weather in real time",
"guideWeatherEnd": "Xiaoyan can report weather live—try other commands",
"guideMusicStart": "Tell Xiaoyan: “Play some rock music”",
"guideMusicInput": "Play some rock music",
"guideMusicSend": "Xiaoyan will find music for you",
"guideMusicEnd": "Xiaoyan found music—try other commands",
"guideNavStart": "Tell Xiaoyan: “Navigate to Shenzhen Airport”",
"guideNavInput": "Navigate to Shenzhen Airport",
"guideNavSend": "Xiaoyan will plan the route",
"guideNavEnd": "Navigation set—try other commands",
"guideMeetingStart":
"Tell Xiaoyan: “Create a meeting reminder for 3pm tomorrow”",
"guideMeetingInput": "Create a meeting reminder for 3pm tomorrow",
"guideMeetingSend": "Xiaoyan will create a meeting reminder",
"guideMeetingEnd": "Reminder created—try other commands",
"guidePhoneStart": "Tell Xiaoyan: “Call Mom”",
"guidePhoneInput": "Call Mom",
"guidePhoneSend": "Xiaoyan will make the call",
"guidePhoneEnd": "Call placed—try other commands",
"guideSmsStart": "Tell Xiaoyan: “Send Dad a text: I’ll be home for dinner”",
"guideSmsInput": "Text Dad: I’ll be home for dinner",
"guideSmsSend": "Xiaoyan will send the message",
"guideSmsEnd": "Message sent—voice control is convenient",
};

78
lib/core/translations/language/ko_kr.dart

@ -784,4 +784,82 @@ const Map<String, String> koKR = {
"乌尔都语": "우르두어",
"波斯语": "페르시아어",
"斯瓦希里语": "스와힐리어",
// Guide overlay keys (placeholders in English)
"sayXiaoYanHint": "Say \"Xiaoyan Xiaoyan\" to the mic",
"imHere": "I’m here~",
"guideWelcomeWakeAI": "Welcome to Voitrans! First, wake your AI “Xiaoyan”.",
"aiReplyCompleted": "Xiaoyan has finished the reply!",
"aiThinking": "Xiaoyan is thinking…",
"guideAwakenSuccess": "Great! Xiaoyan is awake—ask it to help.",
"confirmInput": "Confirm Input",
"guideClickSendPrefix": "Tap send, ",
"guideWeatherStart": "Tell Xiaoyan: “What’s the weather today?”",
"guideWeatherInput": "What’s the weather today?",
"guideWeatherSend": "Xiaoyan will report the weather in real time",
"guideWeatherEnd": "Xiaoyan can report weather live—try other commands",
"guideMusicStart": "Tell Xiaoyan: “Play some rock music”",
"guideMusicInput": "Play some rock music",
"guideMusicSend": "Xiaoyan will find music for you",
"guideMusicEnd": "Xiaoyan found music—try other commands",
"guideNavStart": "Tell Xiaoyan: “Navigate to Shenzhen Airport”",
"guideNavInput": "Navigate to Shenzhen Airport",
"guideNavSend": "Xiaoyan will plan the route",
"guideNavEnd": "Navigation set—try other commands",
"guideMeetingStart": "Tell Xiaoyan: “Create a meeting reminder for 3pm tomorrow”",
"guideMeetingInput": "Create a meeting reminder for 3pm tomorrow",
"guideMeetingSend": "Xiaoyan will create a meeting reminder",
"guideMeetingEnd": "Reminder created—try other commands",
"guidePhoneStart": "Tell Xiaoyan: “Call Mom”",
"guidePhoneInput": "Call Mom",
"guidePhoneSend": "Xiaoyan will make the call",
"guidePhoneEnd": "Call placed—try other commands",
"guideSmsStart": "Tell Xiaoyan: “Send Dad a text: I’ll be home for dinner”",
"guideSmsInput": "Text Dad: I’ll be home for dinner",
"guideSmsSend": "Xiaoyan will send the message",
"guideSmsEnd": "Message sent—voice control is convenient",
// Goods pages common footer (placeholders)
'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans',
'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About',
'copyrightVoiTrans': '© 2025 VoiTrans',
// Meeting goods page (placeholders)
'meetingHeaderDesc1': 'Audio recording, transcription, keyword search, and auto summary.',
'meetingHeaderDesc2': 'Suitable for business meetings, class notes, and interview minutes.',
'meetingAutoRecording': 'Auto recording and segmentation',
'meetingSpeakerTagging': 'Speaker labeling',
'meetingLongAudioTranscription': 'Long audio transcription',
'meetingKeyPointSummary': 'Key point extraction',
'meetingTopicNameSearch': 'Search by topic/name',
'meetingTimelineJump': 'Timeline jump',
'meetingExportSummary': 'Export minutes',
'meetingMultiPlatformShare': 'Share across platforms',
'meetingDisclaimer': 'Use in quiet environments; performance depends on microphone and network.',
// Translation goods page (placeholders)
'tradeHeaderDesc1': 'Real-time simultaneous interpretation and text translation with low-latency voice.',
'tradeHeaderDesc2': 'Suitable for travel, business, speeches, and teaching.',
'translateZhEn': 'Chinese-English translation',
'lowLatencyVoiceBroadcast': 'Low-latency voice broadcast',
'multiLangTextTranslation': 'Multilingual text translation',
'termOptimizationContextPreserve': 'Terminology optimization and context preservation',
'lexiconTourBusinessLife': 'Travel/Business/Life lexicons',
'personalVocabularyMemory': 'Personal vocabulary memory',
'conversationSubtitleLargeText': 'Conversation subtitles / Large-text mode',
'colorHighContrast': 'High color contrast',
'tradeDisclaimer': 'Translation performance depends on microphone, network latency, and ambient noise.',
// VIP goods page (placeholders)
'benefitsOverview': 'Benefits overview',
'higherQuota': 'Higher usage quota',
'lowerUnitPrice': 'Lower unit price',
'priorityService': 'Priority service',
'exclusiveSupportChannel': 'Dedicated support channel',
'fastResponse': 'Fast issue response',
'eventsAndDiscounts': 'Events and discounts',
'memberExclusiveEvents': 'Member-exclusive events',
'longTermDiscountPlan': 'Long-term discount plan',
'generalPrivileges': 'General privileges',
'earlyAccessNewFeatures': 'Early access to new features',
'crossDeviceSync': 'Cross-device sync',
'vipDisclaimer': 'Actual benefits depend on the package details and may change with versions.',
};

78
lib/core/translations/language/pt_pt.dart

@ -863,4 +863,82 @@ const Map<String, String> ptPT = {
"乌尔都语": "Urdu",
"波斯语": "Persa",
"斯瓦希里语": "Suaíli",
// Guide overlay keys (placeholders in English)
"sayXiaoYanHint": "Say \"Xiaoyan Xiaoyan\" to the mic",
"imHere": "I’m here~",
"guideWelcomeWakeAI": "Welcome to Voitrans! First, wake your AI “Xiaoyan”.",
"aiReplyCompleted": "Xiaoyan has finished the reply!",
"aiThinking": "Xiaoyan is thinking…",
"guideAwakenSuccess": "Great! Xiaoyan is awake—ask it to help.",
"confirmInput": "Confirm Input",
"guideClickSendPrefix": "Tap send, ",
"guideWeatherStart": "Tell Xiaoyan: “What’s the weather today?”",
"guideWeatherInput": "What’s the weather today?",
"guideWeatherSend": "Xiaoyan will report the weather in real time",
"guideWeatherEnd": "Xiaoyan can report weather live—try other commands",
"guideMusicStart": "Tell Xiaoyan: “Play some rock music”",
"guideMusicInput": "Play some rock music",
"guideMusicSend": "Xiaoyan will find music for you",
"guideMusicEnd": "Xiaoyan found music—try other commands",
"guideNavStart": "Tell Xiaoyan: “Navigate to Shenzhen Airport”",
"guideNavInput": "Navigate to Shenzhen Airport",
"guideNavSend": "Xiaoyan will plan the route",
"guideNavEnd": "Navigation set—try other commands",
"guideMeetingStart": "Tell Xiaoyan: “Create a meeting reminder for 3pm tomorrow”",
"guideMeetingInput": "Create a meeting reminder for 3pm tomorrow",
"guideMeetingSend": "Xiaoyan will create a meeting reminder",
"guideMeetingEnd": "Reminder created—try other commands",
"guidePhoneStart": "Tell Xiaoyan: “Call Mom”",
"guidePhoneInput": "Call Mom",
"guidePhoneSend": "Xiaoyan will make the call",
"guidePhoneEnd": "Call placed—try other commands",
"guideSmsStart": "Tell Xiaoyan: “Send Dad a text: I’ll be home for dinner”",
"guideSmsInput": "Text Dad: I’ll be home for dinner",
"guideSmsSend": "Xiaoyan will send the message",
"guideSmsEnd": "Message sent—voice control is convenient",
// Goods pages common footer (placeholders)
'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans',
'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About',
'copyrightVoiTrans': '© 2025 VoiTrans',
// Meeting goods page (placeholders)
'meetingHeaderDesc1': 'Audio recording, transcription, keyword search, and auto summary.',
'meetingHeaderDesc2': 'Suitable for business meetings, class notes, and interview minutes.',
'meetingAutoRecording': 'Auto recording and segmentation',
'meetingSpeakerTagging': 'Speaker labeling',
'meetingLongAudioTranscription': 'Long audio transcription',
'meetingKeyPointSummary': 'Key point extraction',
'meetingTopicNameSearch': 'Search by topic/name',
'meetingTimelineJump': 'Timeline jump',
'meetingExportSummary': 'Export minutes',
'meetingMultiPlatformShare': 'Share across platforms',
'meetingDisclaimer': 'Use in quiet environments; performance depends on microphone and network.',
// Translation goods page (placeholders)
'tradeHeaderDesc1': 'Real-time simultaneous interpretation and text translation with low-latency voice.',
'tradeHeaderDesc2': 'Suitable for travel, business, speeches, and teaching.',
'translateZhEn': 'Chinese-English translation',
'lowLatencyVoiceBroadcast': 'Low-latency voice broadcast',
'multiLangTextTranslation': 'Multilingual text translation',
'termOptimizationContextPreserve': 'Terminology optimization and context preservation',
'lexiconTourBusinessLife': 'Travel/Business/Life lexicons',
'personalVocabularyMemory': 'Personal vocabulary memory',
'conversationSubtitleLargeText': 'Conversation subtitles / Large-text mode',
'colorHighContrast': 'High color contrast',
'tradeDisclaimer': 'Translation performance depends on microphone, network latency, and ambient noise.',
// VIP goods page (placeholders)
'benefitsOverview': 'Benefits overview',
'higherQuota': 'Higher usage quota',
'lowerUnitPrice': 'Lower unit price',
'priorityService': 'Priority service',
'exclusiveSupportChannel': 'Dedicated support channel',
'fastResponse': 'Fast issue response',
'eventsAndDiscounts': 'Events and discounts',
'memberExclusiveEvents': 'Member-exclusive events',
'longTermDiscountPlan': 'Long-term discount plan',
'generalPrivileges': 'General privileges',
'earlyAccessNewFeatures': 'Early access to new features',
'crossDeviceSync': 'Cross-device sync',
'vipDisclaimer': 'Actual benefits depend on the package details and may change with versions.',
};

78
lib/core/translations/language/ru_ru.dart

@ -856,4 +856,82 @@ const Map<String, String> ruRU = {
"乌尔都语": "Урду",
"波斯语": "Персидский",
"斯瓦希里语": "Суахили",
// Guide overlay keys (placeholders in English)
"sayXiaoYanHint": "Say \"Xiaoyan Xiaoyan\" to the mic",
"imHere": "I’m here~",
"guideWelcomeWakeAI": "Welcome to Voitrans! First, wake your AI “Xiaoyan”.",
"aiReplyCompleted": "Xiaoyan has finished the reply!",
"aiThinking": "Xiaoyan is thinking…",
"guideAwakenSuccess": "Great! Xiaoyan is awake—ask it to help.",
"confirmInput": "Confirm Input",
"guideClickSendPrefix": "Tap send, ",
"guideWeatherStart": "Tell Xiaoyan: “What’s the weather today?”",
"guideWeatherInput": "What’s the weather today?",
"guideWeatherSend": "Xiaoyan will report the weather in real time",
"guideWeatherEnd": "Xiaoyan can report weather live—try other commands",
"guideMusicStart": "Tell Xiaoyan: “Play some rock music”",
"guideMusicInput": "Play some rock music",
"guideMusicSend": "Xiaoyan will find music for you",
"guideMusicEnd": "Xiaoyan found music—try other commands",
"guideNavStart": "Tell Xiaoyan: “Navigate to Shenzhen Airport”",
"guideNavInput": "Navigate to Shenzhen Airport",
"guideNavSend": "Xiaoyan will plan the route",
"guideNavEnd": "Navigation set—try other commands",
"guideMeetingStart": "Tell Xiaoyan: “Create a meeting reminder for 3pm tomorrow”",
"guideMeetingInput": "Create a meeting reminder for 3pm tomorrow",
"guideMeetingSend": "Xiaoyan will create a meeting reminder",
"guideMeetingEnd": "Reminder created—try other commands",
"guidePhoneStart": "Tell Xiaoyan: “Call Mom”",
"guidePhoneInput": "Call Mom",
"guidePhoneSend": "Xiaoyan will make the call",
"guidePhoneEnd": "Call placed—try other commands",
"guideSmsStart": "Tell Xiaoyan: “Send Dad a text: I’ll be home for dinner”",
"guideSmsInput": "Text Dad: I’ll be home for dinner",
"guideSmsSend": "Xiaoyan will send the message",
"guideSmsEnd": "Message sent—voice control is convenient",
// Goods pages common footer (placeholders)
'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans',
'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About',
'copyrightVoiTrans': '© 2025 VoiTrans',
// Meeting goods page (placeholders)
'meetingHeaderDesc1': 'Audio recording, transcription, keyword search, and auto summary.',
'meetingHeaderDesc2': 'Suitable for business meetings, class notes, and interview minutes.',
'meetingAutoRecording': 'Auto recording and segmentation',
'meetingSpeakerTagging': 'Speaker labeling',
'meetingLongAudioTranscription': 'Long audio transcription',
'meetingKeyPointSummary': 'Key point extraction',
'meetingTopicNameSearch': 'Search by topic/name',
'meetingTimelineJump': 'Timeline jump',
'meetingExportSummary': 'Export minutes',
'meetingMultiPlatformShare': 'Share across platforms',
'meetingDisclaimer': 'Use in quiet environments; performance depends on microphone and network.',
// Translation goods page (placeholders)
'tradeHeaderDesc1': 'Real-time simultaneous interpretation and text translation with low-latency voice.',
'tradeHeaderDesc2': 'Suitable for travel, business, speeches, and teaching.',
'translateZhEn': 'Chinese-English translation',
'lowLatencyVoiceBroadcast': 'Low-latency voice broadcast',
'multiLangTextTranslation': 'Multilingual text translation',
'termOptimizationContextPreserve': 'Terminology optimization and context preservation',
'lexiconTourBusinessLife': 'Travel/Business/Life lexicons',
'personalVocabularyMemory': 'Personal vocabulary memory',
'conversationSubtitleLargeText': 'Conversation subtitles / Large-text mode',
'colorHighContrast': 'High color contrast',
'tradeDisclaimer': 'Translation performance depends on microphone, network latency, and ambient noise.',
// VIP goods page (placeholders)
'benefitsOverview': 'Benefits overview',
'higherQuota': 'Higher usage quota',
'lowerUnitPrice': 'Lower unit price',
'priorityService': 'Priority service',
'exclusiveSupportChannel': 'Dedicated support channel',
'fastResponse': 'Fast issue response',
'eventsAndDiscounts': 'Events and discounts',
'memberExclusiveEvents': 'Member-exclusive events',
'longTermDiscountPlan': 'Long-term discount plan',
'generalPrivileges': 'General privileges',
'earlyAccessNewFeatures': 'Early access to new features',
'crossDeviceSync': 'Cross-device sync',
'vipDisclaimer': 'Actual benefits depend on the package details and may change with versions.',
};

146
lib/core/translations/language/zh_cn.dart

@ -191,6 +191,87 @@ const Map<String, String> zhCN = {
"popularFunction": "热门功能场景",
"tryNow": "立即尝试",
// 商品页面(AI/翻译/会议)
'availablePackages': '可购买套餐',
'remainingQuota': '剩余额度',
'totalCount': '总次数',
'remaining': '剩余',
'featureDescription': '功能说明',
// AI 功能卡片
'musicAndRecommendation': '听歌与推荐',
'navigationAndRoutes': '导航与路线',
'nearbySearch': '附近搜索',
'newsInformation': '新闻资讯',
'communicationAssistant': '通讯助手',
// 翻译功能卡片
'realtimeTranscription': '实时同传',
// 'textTranslation' 已存在
'sceneLexicon': '场景词库',
'subtitleDisplay': '字幕显示',
// 会议功能卡片
'meetingRecording': '会议记录',
'transcriptionAndSummary': '转写与总结',
'keywordSearch': '关键词检索',
'collaborationSharing': '协同分享',
// 商品名称(按ID)
'ai_001_name': 'AI基础 100 次',
'ai_002_name': 'AI基础 500 次',
'ai_003_name': 'AI基础 1000 次',
'meet_001_name': '会议基础 100 次',
'meet_002_name': '会议基础 500 次',
'meet_003_name': '会议基础 1000 次',
'trade_001_name': '翻译基础 100 次',
'trade_002_name': '翻译基础 500 次',
'trade_003_name': '翻译基础 1000 次',
// 商品描述(按ID)
'ai_001_desc': '含 100 次使用,覆盖核心 AI 功能',
'ai_002_desc': '含 500 次使用,覆盖核心 AI 功能',
'ai_003_desc': '含 1000 次使用,覆盖核心 AI 功能',
'meet_001_desc': '含 100 次会议录音/转写',
'meet_002_desc': '含 500 次会议录音/转写',
'meet_003_desc': '含 1000 次会议录音/转写',
'trade_001_desc': '含 100 次翻译(语音/文本)',
'trade_002_desc': '含 500 次翻译(语音/文本)',
'trade_003_desc': '含 1000 次翻译(语音/文本)',
// 新手引导 / Onboarding
'skip': '跳过',
'next': '下一步',
'sayXiaoYanHint': '对着麦克风说:“小言小言”',
'imHere': '我在呢~',
'guideWelcomeWakeAI': '欢迎使用Voitrans!首先,让我们唤醒你的专属 AI—— 小言',
'aiReplyCompleted': '小言已经完成了回答!',
'aiThinking': '小言正在思考中~',
'guideAwakenSuccess': '太棒了!你已成功唤醒小言,接下来试试让它帮你做件事吧',
'confirmInput': '确定输入',
'guideClickSendPrefix': '点击发送,',
// AI 引导步骤
'guideWeatherStart': '对小言说:“今天天气怎么样”',
'guideWeatherInput': '今天天气怎么样',
'guideWeatherSend': '小言会为你实时为你播报天气',
'guideWeatherEnd': '小言能实时为你播报天气,试试其他指令吧',
'guideMusicStart': '对小言说:“请播放一组摇滚乐”',
'guideMusicInput': '请播放一组摇滚乐',
'guideMusicSend': '小言会为你搜寻到一组音乐',
'guideMusicEnd': '小言已成功为您搜寻到一组音乐,试试其他指令吧',
'guideNavStart': '对小言说:“导航到深圳机场”',
'guideNavInput': '导航到深圳机场',
'guideNavSend': '小言会为你规划路线',
'guideNavEnd': '小言已成功为您导航到深圳机场,试试其他指令吧',
'guideMeetingStart': '对小言说:“明天下午3点创建会议提醒”',
'guideMeetingInput': '明天下午3点创建会议提醒',
'guideMeetingSend': '小言会为你创建会议提醒',
'guideMeetingEnd': '小言已成功为您创建会议提醒,试试其他指令吧',
'guidePhoneStart': '对小言说:“拨打妈妈的电话”',
'guidePhoneInput': '拨打妈妈的电话',
'guidePhoneSend': '小言会为你拨打电话',
'guidePhoneEnd': '小言已成功为您拨打电话,试试其他指令吧',
'guideSmsStart': '对小言说:“给爸爸发短信说晚上回家吃饭”',
'guideSmsInput': '给爸爸发短信说晚上回家吃饭',
'guideSmsSend': '小言会为你发送短信',
'guideSmsEnd': '短信已发送,语音操控更便捷',
// 商务会议助手页
"startMeeting": "开始会议",
'edit': '编辑',
@ -968,7 +1049,7 @@ const Map<String, String> zhCN = {
"autoInputCode": "自动输入代码",
"skipBinding": "跳过绑定",
"rescan": "重新扫描",
"skip": "跳过",
"verifyingDevice": "正在验证设备...",
"confirmBinding": "确认绑定",
"associatingDevice": "正在关联设备...",
@ -1118,4 +1199,67 @@ const Map<String, String> zhCN = {
//补充
"insufficientIntegral": "积分不足",
// 商品页通用页脚
'appNameProvider': '应用名称:VoiTrans · 服务提供:VoiTrans',
'moreInfoViewInSettingsAbout': '更多信息请前往 设置 > 关于 查看',
'copyrightVoiTrans': '© 2025 VoiTrans',
// 会议商品页描述
'meetingHeaderDesc1': '录音转写、关键词检索与自动总结,提升会议效率。',
'meetingHeaderDesc2': '适用于商务会议、课堂笔记、访谈纪要等场景。',
'meetingAutoRecording': '自动录音与分段',
'meetingSpeakerTagging': '讲话人标注',
'meetingLongAudioTranscription': '长音频转写',
'meetingKeyPointSummary': '关键要点提炼',
'meetingTopicNameSearch': '按主题/人名检索',
'meetingTimelineJump': '时间线跳转',
'meetingExportSummary': '导出纪要',
'meetingMultiPlatformShare': '多平台分享',
'meetingDisclaimer': '建议在安静环境使用,效果受麦克风与网络影响,具体以实际表现为准。',
// 同传/翻译商品页描述
'tradeHeaderDesc1': '多语种实时同传与文本翻译,低延时语音播报。',
'tradeHeaderDesc2': '适用于出行、商务、演讲与教学等场景。',
'translateZhEn': '中英互译',
'lowLatencyVoiceBroadcast': '低延时语音播报',
'multiLangTextTranslation': '多语种文本翻译',
'termOptimizationContextPreserve': '术语优化与语境保持',
'lexiconTourBusinessLife': '旅游/商务/生活词库',
'personalVocabularyMemory': '专属词汇记忆',
'conversationSubtitleLargeText': '对话字幕/大字模式',
'colorHighContrast': '颜色高对比度',
'tradeDisclaimer': '翻译效果受麦克风、网络时延与环境噪声影响,具体以实际表现为准。',
// AI 商品页描述
'aiHeaderDesc1': '更长对话额度、更多工具调用、更强上下文长度支持。',
'aiHeaderDesc2': '适用于智能体问答、总结分析、任务执行等场景。',
'musicSearchPlaybackControl': '检索曲库、播放控制',
'smartPlaylistAndSimilarRecommendations': '智能推荐歌单与相似歌曲',
'routePlanningAndCongestionAvoidance': '路线规划与拥堵规避',
'voiceBroadcastAndWaypoints': '语音播报与途径点设置',
'realTimeWeatherForecast': '实时天气与预报',
'clothingAdviceAndTravelReminders': '穿衣建议与出行提醒',
'poiSearchFoodGasParking': '餐饮/加油/停车等地点检索',
'ratingsHoursAndDirectRoutes': '评分、营业时间与路线直达',
'hotNewsAndTopicOverview': '热点快讯与专题速览',
'longArticleSummariesAndKeyPoints': '长文总结与要点提炼',
'helpCallAndSMS': '帮忙拨打电话与发短信',
'templatedMessagesAndScheduleReminders': '模板消息与日程提醒',
'aiDisclaimer': '以上功能受设备权限、服务可用性与网络状况影响,具体以实际表现为准。',
// 会员商品页
'benefitsOverview': '权益总览',
'higherQuota': '更高使用额度',
'lowerUnitPrice': '更低单价',
'priorityService': '优先服务',
'exclusiveSupportChannel': '专属客服通道',
'fastResponse': '问题快速响应',
'eventsAndDiscounts': '活动与折扣',
'memberExclusiveEvents': '会员专属活动',
'longTermDiscountPlan': '长期优惠计划',
'generalPrivileges': '通用特权',
'earlyAccessNewFeatures': '新功能优先体验',
'crossDeviceSync': '跨设备同步',
'vipDisclaimer': '具体权益以实际套餐说明为准,可能随版本迭代调整。',
};

116
lib/core/translations/language/zh_hk.dart

@ -189,6 +189,27 @@ const Map<String, String> zhHK = {
"aiSingerInfo": "用你喜歡的歌手聲音演唱任何歌曲,甚至是你自己創作的歌曲",
"popularFunction": "熱門功能場景",
"tryNow": "立即嘗試",
// 商品名稱(按ID)
'ai_001_name': 'AI基礎 100 次',
'ai_002_name': 'AI基礎 500 次',
'ai_003_name': 'AI基礎 1000 次',
'meet_001_name': '會議基礎 100 次',
'meet_002_name': '會議基礎 500 次',
'meet_003_name': '會議基礎 1000 次',
'trade_001_name': '翻譯基礎 100 次',
'trade_002_name': '翻譯基礎 500 次',
'trade_003_name': '翻譯基礎 1000 次',
// 商品描述(按ID)
'ai_001_desc': '含 100 次使用,涵蓋核心 AI 功能',
'ai_002_desc': '含 500 次使用,涵蓋核心 AI 功能',
'ai_003_desc': '含 1000 次使用,涵蓋核心 AI 功能',
'meet_001_desc': '含 100 次會議錄音/轉寫',
'meet_002_desc': '含 500 次會議錄音/轉寫',
'meet_003_desc': '含 1000 次會議錄音/轉寫',
'trade_001_desc': '含 100 次翻譯(語音/文本)',
'trade_002_desc': '含 500 次翻譯(語音/文本)',
'trade_003_desc': '含 1000 次翻譯(語音/文本)',
// 商務會議助手頁
"startMeeting": "開始會議",
@ -787,4 +808,99 @@ const Map<String, String> zhHK = {
"乌尔都语": "烏爾都語",
"波斯语": "波斯語",
"斯瓦希里语": "斯瓦希里語",
// Guide overlay keys (placeholders in English)
"sayXiaoYanHint": "Say \"Xiaoyan Xiaoyan\" to the mic",
"imHere": "I’m here~",
"guideWelcomeWakeAI": "Welcome to Voitrans! First, wake your AI “Xiaoyan”.",
"aiReplyCompleted": "Xiaoyan has finished the reply!",
"aiThinking": "Xiaoyan is thinking…",
"guideAwakenSuccess": "Great! Xiaoyan is awake—ask it to help.",
"confirmInput": "Confirm Input",
"guideClickSendPrefix": "Tap send, ",
"guideWeatherStart": "Tell Xiaoyan: “What’s the weather today?”",
"guideWeatherInput": "What’s the weather today?",
"guideWeatherSend": "Xiaoyan will report the weather in real time",
"guideWeatherEnd": "Xiaoyan can report weather live—try other commands",
"guideMusicStart": "Tell Xiaoyan: “Play some rock music”",
"guideMusicInput": "Play some rock music",
"guideMusicSend": "Xiaoyan will find music for you",
"guideMusicEnd": "Xiaoyan found music—try other commands",
"guideNavStart": "Tell Xiaoyan: “Navigate to Shenzhen Airport”",
"guideNavInput": "Navigate to Shenzhen Airport",
"guideNavSend": "Xiaoyan will plan the route",
"guideNavEnd": "Navigation set—try other commands",
"guideMeetingStart": "Tell Xiaoyan: “Create a meeting reminder for 3pm tomorrow”",
"guideMeetingInput": "Create a meeting reminder for 3pm tomorrow",
"guideMeetingSend": "Xiaoyan will create a meeting reminder",
"guideMeetingEnd": "Reminder created—try other commands",
"guidePhoneStart": "Tell Xiaoyan: “Call Mom”",
"guidePhoneInput": "Call Mom",
"guidePhoneSend": "Xiaoyan will make the call",
"guidePhoneEnd": "Call placed—try other commands",
"guideSmsStart": "Tell Xiaoyan: “Send Dad a text: I’ll be home for dinner”",
"guideSmsInput": "Text Dad: I’ll be home for dinner",
"guideSmsSend": "Xiaoyan will send the message",
"guideSmsEnd": "Message sent—voice control is convenient",
// Goods pages common footer (placeholders)
'appNameProvider': '應用名稱:VoiTrans · 服務提供:VoiTrans',
'moreInfoViewInSettingsAbout': '更多信息請前往 設置 > 關於 查看',
'copyrightVoiTrans': '© 2025 VoiTrans',
// Meeting goods page (placeholders)
'meetingHeaderDesc1': '錄音轉寫、關鍵詞檢索與自動總結,提升會議效率。',
'meetingHeaderDesc2': '適用於商務會議、課堂筆記、訪談紀要等場景。',
'meetingAutoRecording': '自動錄音與分段',
'meetingSpeakerTagging': '講話人標注',
'meetingLongAudioTranscription': '長音頻轉寫',
'meetingKeyPointSummary': '關鍵要點提煉',
'meetingTopicNameSearch': '按主題/人名檢索',
'meetingTimelineJump': '時間線跳轉',
'meetingExportSummary': '導出紀要',
'meetingMultiPlatformShare': '多平台分享',
'meetingDisclaimer': '建議在安靜環境使用,效果受麥克風與網絡影響,具體以實際表現為準。',
// Translation goods page (placeholders)
'tradeHeaderDesc1': '多語種實時同傳與文本翻譯,低延時語音播報。',
'tradeHeaderDesc2': '適用於出行、商務、演講與教學等場景。',
'translateZhEn': '中英互譯',
'lowLatencyVoiceBroadcast': '低延時語音播報',
'multiLangTextTranslation': '多語種文本翻譯',
'termOptimizationContextPreserve': '術語優化與語境保持',
'lexiconTourBusinessLife': '旅遊/商務/生活詞庫',
'personalVocabularyMemory': '專屬詞彙記憶',
'conversationSubtitleLargeText': '對話字幕/大字模式',
'colorHighContrast': '顏色高對比度',
'tradeDisclaimer': '翻譯效果受麥克風、網絡時延與環境噪聲影響,具體以實際表現為準。',
// AI 商品頁描述(佔位)
'aiHeaderDesc1': '更長對話額度、更多工具調用、更強上下文長度支持。',
'aiHeaderDesc2': '適用於智能體問答、總結分析、任務執行等場景。',
'musicSearchPlaybackControl': '檢索曲庫、播放控制',
'smartPlaylistAndSimilarRecommendations': '智能推薦歌單與相似歌曲',
'routePlanningAndCongestionAvoidance': '路線規劃與擁堵規避',
'voiceBroadcastAndWaypoints': '語音播報與途徑點設置',
'realTimeWeatherForecast': '實時天氣與預報',
'clothingAdviceAndTravelReminders': '穿衣建議與出行提醒',
'poiSearchFoodGasParking': '餐飲/加油/停車等地點檢索',
'ratingsHoursAndDirectRoutes': '評分、營業時間與路線直達',
'hotNewsAndTopicOverview': '熱點快訊與專題速覽',
'longArticleSummariesAndKeyPoints': '長文總結與要點提煉',
'helpCallAndSMS': '幫忙撥打電話與發短信',
'templatedMessagesAndScheduleReminders': '模板消息與日程提醒',
'aiDisclaimer': '以上功能受設備權限、服務可用性與網絡狀況影響,具體以實際表現為準。',
// VIP goods page (placeholders)
'benefitsOverview': '權益總覽',
'higherQuota': '更高使用額度',
'lowerUnitPrice': '更低單價',
'priorityService': '優先服務',
'exclusiveSupportChannel': '專屬客服通道',
'fastResponse': '問題快速響應',
'eventsAndDiscounts': '活動與折扣',
'memberExclusiveEvents': '會員專屬活動',
'longTermDiscountPlan': '長期優惠計劃',
'generalPrivileges': '通用特權',
'earlyAccessNewFeatures': '新功能優先體驗',
'crossDeviceSync': '跨設備同步',
'vipDisclaimer': '具體權益以實際套餐說明為準,可能隨版本迭代調整。',
};

17
lib/core/widgets/intro_overlay_builder.dart

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_intro/flutter_intro.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:lottie/lottie.dart';
class IntroOverlayBuilder {
@ -19,7 +20,7 @@ class IntroOverlayBuilder {
static Widget homeBuilder(
StepWidgetParams params,
bool isWakeup, {
String title = '对着麦克风说:“小言小言”',
String title = 'sayXiaoYanHint',
Function? onNext,
}) {
return Column(
@ -29,7 +30,7 @@ class IntroOverlayBuilder {
margin: EdgeInsets.only(top: ScreenUtil().statusBarHeight),
alignment: Alignment.centerRight,
child: _button(
'跳过',
'skip'.tr,
() {
params.onFinish();
},
@ -47,7 +48,7 @@ class IntroOverlayBuilder {
Padding(
padding: EdgeInsets.only(bottom: 10.w),
child: Text(
isWakeup ? '我在呢~' : title,
isWakeup ? 'imHere'.tr : title.tr,
style: TextStyle(
fontSize: 15.sp,
color: Colors.white,
@ -57,7 +58,7 @@ class IntroOverlayBuilder {
),
if (onNext != null)
_button(
'下一步',
'next'.tr,
() {
params.onNext!();
onNext();
@ -70,7 +71,7 @@ class IntroOverlayBuilder {
static Widget aiBuilder(
StepWidgetParams params,
String text, {
String buttonText = '下一步',
String buttonText = 'next',
bool alignment = true,
Function? onNext,
Function? onFinish,
@ -92,7 +93,7 @@ class IntroOverlayBuilder {
margin: EdgeInsets.only(top: ScreenUtil().statusBarHeight),
alignment: Alignment.centerRight,
child: _button(
'跳过',
'skip'.tr,
() {
params.onFinish();
},
@ -125,7 +126,7 @@ class IntroOverlayBuilder {
Padding(
padding: EdgeInsets.only(top: 10.w, left: 3, right: 3),
child: _button(
buttonText,
buttonText.tr,
() {
params.onNext!();
onNext();
@ -136,7 +137,7 @@ class IntroOverlayBuilder {
Padding(
padding: EdgeInsets.only(top: 10.w, left: 3, right: 3),
child: _button(
buttonText,
buttonText.tr,
() {
params.onFinish();
onFinish();

12
lib/data/models/user_Info.dart

@ -45,7 +45,7 @@ class User {
String phonemac;
String password;
int viplv = 0; //添加会员等级字段,0表示普通用户
int viptime = 0; // 会员到期/剩余时间(秒/毫秒,按后端定义)
int vipexptime = 0; // 会员到期/剩余时间(秒/毫秒,按后端定义)
int aichatintegral = 0; // ai聊天积分
int aichattotalintegral = 0; // ai聊天总积分
int tradeintegral = 0; // 翻译积分
@ -67,7 +67,7 @@ class User {
required this.phonemac,
required this.password,
required this.viplv,
required this.viptime,
required this.vipexptime,
required this.aichatintegral,
required this.aichattotalintegral,
required this.tradeintegral,
@ -96,7 +96,7 @@ class User {
phonemac: (userData?['phonemac'] as String?) ?? '',
password: (userData?['password'] as String?) ?? '',
viplv: (userData?['viplv'] as int?) ?? 0, // 提供默认值
viptime: (userData?['viptime'] as int?) ?? 0, // 提供默认值
vipexptime: (userData?['vipexptime'] as int?) ?? 0, // 提供默认值
aichatintegral: (userData?['aichatintegral'] as int?) ?? 0,
aichattotalintegral: (userData?['aichattotalintegral'] as int?) ?? 0,
@ -130,7 +130,7 @@ class User {
phonemac: (userData?['phonemac'] as String?) ?? '',
password: (userData?['password'] as String?) ?? '',
viplv: (userData?['viplv'] as int?) ?? 0, // 提供默认值
viptime: (userData?['viptime'] as int?) ?? 0, // 提供默认值
vipexptime: (userData?['vipexptime'] as int?) ?? 0, // 提供默认值
aichatintegral: (userData?['aichatintegral'] as int?) ?? 0,
aichattotalintegral: (userData?['aichattotalintegral'] as int?) ?? 0,
tradeintegral: (userData?['tradeintegral'] as int?) ?? 0,
@ -156,7 +156,7 @@ class User {
phonemac = user['phonemac'] as String? ?? phonemac;
password = user['password'] as String? ?? password;
viplv = user['viplv'] as int? ?? viplv;
viptime = user['viptime'] as int? ?? viptime;
vipexptime = user['vipexptime'] as int? ?? vipexptime;
aichatintegral = user['aichatintegral'] as int? ?? aichatintegral;
aichattotalintegral =
user['aichattotalintegral'] as int? ?? aichattotalintegral;
@ -183,7 +183,7 @@ class User {
'phonemac': phonemac,
'password': password,
'viplv': viplv,
'viptime': viptime,
'vipexptime': vipexptime,
'aichatintegral': aichatintegral,
'aichattotalintegral': aichattotalintegral,
'tradeintegral': tradeintegral,

13
lib/data/services/network/api.dart

@ -182,19 +182,10 @@ class Api {
}
//询问订单
static payaskorder([params]) {
static payverifyorder([params]) {
return DioManager().request(
NWMethod.post,
'/api/home/pay_askorder',
params: params,
);
}
//内购收据验证
static payiapverify([params]) {
return DioManager().request(
NWMethod.post,
'/api/home/pay_iapverify',
'/api/home/pay_verifyorder',
params: params,
);
}

48
lib/data/services/novice_guide_service.dart

@ -23,10 +23,10 @@ class NoviceGuideService extends GetxService {
List aiStepsList = [
{
'start': '对小言说:“今天天气怎么样”',
'input': '今天天气怎么样',
'send': '小言会为你实时为你播报天气',
'end': '小言能实时为你播报天气,试试其他指令吧',
'startKey': 'guideWeatherStart',
'inputKey': 'guideWeatherInput',
'sendKey': 'guideWeatherSend',
'endKey': 'guideWeatherEnd',
'method': () async {
// 天气查询需要位置权限
await PermissionUtil.instance.requestPermission(
@ -39,17 +39,17 @@ class NoviceGuideService extends GetxService {
},
},
{
'start': '对小言说:“请播放一组摇滚乐”',
'input': '请播放一组摇滚乐',
'send': '小言会为你搜寻到一组音乐',
'end': '小言已成功为您搜寻到一组音乐,试试其他指令吧',
'startKey': 'guideMusicStart',
'inputKey': 'guideMusicInput',
'sendKey': 'guideMusicSend',
'endKey': 'guideMusicEnd',
'method': () async {},
},
{
'start': '对小言说:“导航到深圳机场”',
'input': '导航到深圳机场',
'send': '小言会为你规划路线',
'end': '小言已成功为您导航到深圳机场,试试其他指令吧',
'startKey': 'guideNavStart',
'inputKey': 'guideNavInput',
'sendKey': 'guideNavSend',
'endKey': 'guideNavEnd',
'method': () async {
// 导航功能需要位置权限
await PermissionUtil.instance.requestPermission(
@ -62,10 +62,10 @@ class NoviceGuideService extends GetxService {
},
},
{
'start': '对小言说:“明天下午3点创建会议提醒”',
'input': '明天下午3点创建会议提醒',
'send': '小言会为你创建会议提醒',
'end': '小言已成功为您创建会议提醒,试试其他指令吧',
'startKey': 'guideMeetingStart',
'inputKey': 'guideMeetingInput',
'sendKey': 'guideMeetingSend',
'endKey': 'guideMeetingEnd',
'method': () async {
//创建会议提醒需要日历权限
await PermissionUtil.instance.requestPermission(
@ -78,10 +78,10 @@ class NoviceGuideService extends GetxService {
},
},
{
'start': '对小言说:“拨打妈妈的电话”',
'input': '拨打妈妈的电话',
'send': '小言会为你拨打电话',
'end': '小言已成功为您拨打电话,试试其他指令吧',
'startKey': 'guidePhoneStart',
'inputKey': 'guidePhoneInput',
'sendKey': 'guidePhoneSend',
'endKey': 'guidePhoneEnd',
'method': () async {
if (Platform.isAndroid) {
// 拨打电话需要电话权限
@ -103,10 +103,10 @@ class NoviceGuideService extends GetxService {
},
},
{
'start': '对小言说:“给爸爸发短信说晚上回家吃饭’”',
'input': '给爸爸发短信说晚上回家吃饭’',
'send': '小言会为你发送短信',
'end': '短信已发送,语音操控更便捷',
'startKey': 'guideSmsStart',
'inputKey': 'guideSmsInput',
'sendKey': 'guideSmsSend',
'endKey': 'guideSmsEnd',
'method': () async {
if (Platform.isAndroid) {
// 发送短信需要短信权限

176
lib/data/services/pay_service.dart

@ -54,7 +54,7 @@ class PayService extends GetxService {
/// 初始化支付宝SDK
Future<void> _initAlipay() async {
try {
// 检查支付宝是否安装 - 修复用法
// 检查支付宝是否安x装 - 修复用法
final isInstalled = await _tobias.isAliPayInstalled;
print('支付宝是否安装: $isInstalled');
} catch (e) {
@ -99,8 +99,11 @@ class PayService extends GetxService {
print('[IAP] 待查询商品ID: $id');
}
// 仅在非 Web 平台执行;平台信息用于日志
await _initIAP();
final platform = _platformString();
if (!iapAvailable.value) {
final available = await _inAppPurchase.isAvailable();
iapAvailable.value = available;
}
if (!iapAvailable.value) {
print('[IAP-$platform] 当前平台内购不可用,无法查询商品。');
return;
@ -108,7 +111,9 @@ class PayService extends GetxService {
print('[IAP-$platform] 开始查询商品,IDs=${productIds.join(', ')}');
final resp = await _inAppPurchase.queryProductDetails(productIds);
if (resp.error != null) {
print('[IAP-$platform] 查询错误: ${resp.error}');
final err = resp.error!;
print(
'[IAP-$platform] 查询错误: code=${err.code}, source=${err.source}, message=${err.message}, details=${err.details}');
}
if (resp.productDetails.isEmpty) {
print('[IAP-$platform] 未返回任何商品。notFound=${resp.notFoundIDs}');
@ -132,7 +137,9 @@ class PayService extends GetxService {
print('[IAP] 开始查询单个商品: id="$pid"');
final resp = await _inAppPurchase.queryProductDetails({pid});
if (resp.error != null) {
print('[IAP] 查询商品失败: ${resp.error}');
final err = resp.error!;
print(
'[IAP] 查询商品失败: code=${err.code}, source=${err.source}, message=${err.message}, details=${err.details}');
}
if (resp.productDetails.isEmpty) {
print('[IAP] 查询结果为空。notFound=${resp.notFoundIDs}');
@ -187,31 +194,43 @@ class PayService extends GetxService {
if (isSubscription) {
print('[IAP-android] 订阅商品(ENV),使用 buyNonConsumable');
final gpParam = GooglePlayPurchaseParam(productDetails: product);
print(
'[IAP-android] 调用 buyNonConsumable 参数: productId=${product.id}');
ok = await _inAppPurchase.buyNonConsumable(purchaseParam: gpParam);
print('[IAP-android] buyNonConsumable 返回: $ok');
} else {
// 普通一次性/消耗型商品,使用 buyConsumable
final purchaseParam = PurchaseParam(productDetails: product);
print(
'[IAP-android] 调用 buyConsumable 参数: productId=${product.id} autoConsume=true');
ok = await _inAppPurchase.buyConsumable(
purchaseParam: purchaseParam,
autoConsume: true,
);
print('[IAP-android] buyConsumable 返回: $ok');
}
} else {
// iOS 或非订阅商品,按消耗型处理(如需支持 iOS 订阅,可通过 ENV 切换调用 buyNonConsumable)
final purchaseParam = PurchaseParam(productDetails: product);
print(
'[IAP-ios] 调用 buyConsumable 参数: productId=${product.id} autoConsume=true');
ok = await _inAppPurchase.buyConsumable(
purchaseParam: purchaseParam,
autoConsume: true,
);
print('[IAP-ios] buyConsumable 返回: $ok');
}
if (!ok) {
onResult?.call(false, '无法发起内购');
print('[IAP] 发起内购失败:平台=${_platformString()} productId=${product.id}');
} else {
onResult?.call(true, '已发起内购,请完成支付');
print('[IAP] 已发起内购:等待购买流回调(可能受旧交易阻塞或商店限制)');
}
return ok;
} catch (e) {
onResult?.call(false, '发起内购失败: $e');
print('[IAP] 发起内购异常: $e');
return false;
}
}
@ -232,41 +251,59 @@ class PayService extends GetxService {
_iapOnResult?.call(false, details.error?.message ?? '支付错误');
break;
case PurchaseStatus.purchased:
final txId = details.purchaseID ?? '';
final ok = await _verifyIapWithServer(details);
if (!ok) {
print(
'[IAP] 验证失败 purchased txId=${details.purchaseID} product=${details.productID}');
_iapOnResult?.call(false, details.error?.message ?? '支付错误');
}
if (ok) {
try {
await _inAppPurchase.completePurchase(details);
print('[IAP] 完成交易 purchased txId=${details.purchaseID}');
_iapOnResult?.call(true, details.error?.message ?? '支付成功');
} catch (e, st) {
print('[IAP] 完成交易异常 purchased txId=${details.purchaseID} err=$e');
print('[IAP] 完成交易异常堆栈 purchased $st');
}
}
break;
case PurchaseStatus.restored:
// 完成购买并进行服务端收据验证
try {
await _verifyIapWithServer(details);
} catch (e) {
_iapOnResult?.call(false, '收据验证失败: $e');
final txId = details.purchaseID ?? '';
final ok = await _verifyIapWithServer(details);
if (!ok) {
print(
'[IAP] 验证失败 restored(silent) txId=${details.purchaseID} product=${details.productID}');
_iapOnResult?.call(false, details.error?.message ?? '支付错误');
}
if (ok) {
try {
await _inAppPurchase.completePurchase(details);
_iapOnResult?.call(true, details.error?.message ?? '支付成功');
print('[IAP] 完成交易 restored(silent) txId=${details.purchaseID}');
} catch (e, st) {
print(
'[IAP] 完成交易异常 restored(silent) txId=${details.purchaseID} err=$e');
print('[IAP] 完成交易异常堆栈 restored(silent) $st');
}
}
break;
case PurchaseStatus.canceled:
_iapOnResult?.call(false, '已取消支付');
print('[IAP] 用户取消支付 product=${details.productID}');
break;
}
if (details.pendingCompletePurchase) {
try {
await _inAppPurchase.completePurchase(details);
} catch (_) {}
}
}
}
Future<void> _verifyIapWithServer(PurchaseDetails details) async {
final platform = _platformString();
final verificationData =
details.verificationData.serverVerificationData ?? '';
final transactionId = details.purchaseID ?? '';
final params = {
'platform': platform,
'product_id': details.productID,
'transaction_id': transactionId,
'server_verification_data': verificationData,
};
Future<bool> _verifyIapWithServer(PurchaseDetails details) async {
try {
final resp = await Api.payiapverify(params);
// 兼容多种返回结构,优先拿到用户信息
final params = await buildIapAskParams();
final resp = await Api.payverifyorder(params);
Map<String, dynamic>? user;
Map<String, dynamic>? order;
if (resp is Map) {
if (resp['user'] is Map<String, dynamic>) {
user = resp['user'] as Map<String, dynamic>;
@ -274,15 +311,32 @@ class PayService extends GetxService {
(resp['data']['user'] is Map<String, dynamic>)) {
user = resp['data']['user'] as Map<String, dynamic>;
}
if (resp['order'] is Map<String, dynamic>) {
order = resp['order'] as Map<String, dynamic>;
} else if (resp['data'] is Map &&
(resp['data']['order'] is Map<String, dynamic>)) {
order = resp['data']['order'] as Map<String, dynamic>;
}
}
if (user != null) {
final int? status = order != null
? (order['status'] is int
? order['status'] as int
: int.tryParse('${order['status']}'))
: null;
final bool ok = status == 1 || user != null;
if (ok && user != null) {
User.instance.updateUserInfo(user);
_iapOnResult?.call(true, '支付成功');
} else {
_iapOnResult?.call(true, '支付成功,额度将稍后刷新');
}
if (!ok) {
final code = (resp is Map) ? resp['code'] : null;
final msg = (resp is Map) ? (resp['message'] ?? resp['msg']) : null;
print(
'[IAP] 验证失败详情 status=$status code=$code msg=$msg order_id=${params['order_id']}');
}
return ok;
} catch (e) {
_iapOnResult?.call(false, '服务器验证异常: $e');
print('[IAP] 服务器验证异常: $e');
return false;
}
}
@ -360,6 +414,41 @@ class PayService extends GetxService {
}
}
/// 解析 Apple 的真实商品ID(支持环境前缀/后缀或显式映射)
/// 优先级:显式映射(APP_IOS_IAP_ID_MAP JSON) > 前缀(APP_IOS_IAP_PREFIX) > 后缀(APP_IOS_IAP_SUFFIX) > 原始ID
/// 示例:
/// - APP_IOS_IAP_PREFIX=com.voitrans.
/// - APP_IOS_IAP_ID_MAP={"ai_001":"com.voitrans.ai001","ai_002":"com.voitrans.ai002"}
String resolveAppleProductId(String backendId) {
final raw = backendId.trim();
Map<String, dynamic>? mapped;
try {
final jsonStr = dotenv.env['APP_IOS_IAP_ID_MAP'];
if (jsonStr != null && jsonStr.isNotEmpty) {
mapped = json.decode(jsonStr) as Map<String, dynamic>;
}
} catch (e) {
print('[IAP-ios] 解析 APP_IOS_IAP_ID_MAP 失败: $e');
}
if (mapped != null) {
final m = mapped[raw];
if (m is String && m.trim().isNotEmpty) {
final resolved = m.trim();
print('[IAP-ios] 使用映射ID: $raw -> $resolved');
return resolved;
}
}
final prefix = dotenv.env['APP_IOS_IAP_PREFIX'] ?? '';
final suffix = dotenv.env['APP_IOS_IAP_SUFFIX'] ?? '';
final resolved = '${prefix}${raw}${suffix}';
if (resolved != raw) {
print('[IAP-ios] 使用前后缀ID: $raw -> $resolved');
} else {
print('[IAP-ios] 未配置映射/前缀,使用原始ID: $raw');
}
return resolved;
}
/// 发起 Apple 内购
Future<bool> processApplePayment({
required String productId,
@ -369,9 +458,17 @@ class PayService extends GetxService {
onResult?.call(false, '当前平台不支持 Apple 内购');
return false;
}
// 重新初始化内购,避免早期可用性判断为 false
await _initIAP();
return _processIapPayment(productId: productId, onResult: onResult);
if (!iapAvailable.value) {
await _initIAP();
if (!iapAvailable.value) {
onResult?.call(false, '内购不可用');
return false;
}
}
// 解析为 App Store 的真实商品ID
final iosId = resolveAppleProductId(productId);
print('[IAP-ios] 准备使用商品ID购买: backend="$productId" -> store="$iosId"');
return _processIapPayment(productId: iosId, onResult: onResult);
}
/// 发起 Google Play 内购
@ -383,8 +480,13 @@ class PayService extends GetxService {
onResult?.call(false, '当前平台不支持 Google 内购');
return false;
}
// 重新初始化内购,避免早期可用性判断为 false
await _initIAP();
if (!iapAvailable.value) {
await _initIAP();
if (!iapAvailable.value) {
onResult?.call(false, '内购不可用');
return false;
}
}
return _processIapPayment(productId: productId, onResult: onResult);
}

59
lib/modules/agent/views/agent_view.dart

@ -276,8 +276,8 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
params,
false,
title: controller.newAIReplyCompleted.value
? '小言已经完成了回答!'
: '小言正在思考中~',
? 'aiReplyCompleted'.tr
: 'aiThinking'.tr,
onNext: controller.newAIReplyCompleted.value ? () {} : null,
),
);
@ -326,15 +326,18 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
getOverlayPosition:
IntroOverlayBuilder.overlayPosition,
overlayBuilder: (params) {
return IntroOverlayBuilder.aiBuilder(
params,
controller.noviceGuideService.aiStepsList[
controller.noviceGuideService
.aiStep]['end'],
onFinish: () async {
if (controller
.noviceGuideService.aiStep <
5) {
return IntroOverlayBuilder.aiBuilder(
params,
controller
.noviceGuideService
.aiStepsList[controller
.noviceGuideService.aiStep]
['endKey']
.tr,
onFinish: () async {
if (controller
.noviceGuideService.aiStep <
5) {
await Future.delayed(const Duration(
milliseconds: 300));
controller
@ -622,23 +625,29 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
return IntroOverlayBuilder.aiBuilder(
params,
controller
.noviceGuideService.aiStepsList[
controller.noviceGuideService
.aiStep]['start'],
buttonText: '确定输入',
.noviceGuideService
.aiStepsList[controller
.noviceGuideService.aiStep]
['startKey']
.tr,
buttonText: 'confirmInput'.tr,
onNext: () {
controller.textController.text =
controller.noviceGuideService
.aiStepsList[
controller.noviceGuideService
.aiStep]['input'];
controller
.noviceGuideService
.aiStepsList[controller
.noviceGuideService
.aiStep]['inputKey']
.tr;
},
onTap: () {
controller.textController.text =
controller.noviceGuideService
.aiStepsList[
controller.noviceGuideService
.aiStep]['input'];
controller
.noviceGuideService
.aiStepsList[controller
.noviceGuideService
.aiStep]['inputKey']
.tr;
params.onNext!();
},
);
@ -862,13 +871,13 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
overlayBuilder: (params) {
return IntroOverlayBuilder.aiBuilder(
params,
'点击发送,${controller.noviceGuideService.aiStepsList[controller.noviceGuideService.aiStep]['send']}',
'${'guideClickSendPrefix'.tr}${controller.noviceGuideService.aiStepsList[controller.noviceGuideService.aiStep]['sendKey'].tr}',
alignment: false,
onTap: () async {
await controller
.noviceGuideService.aiStepsList[
controller.noviceGuideService
.aiStep]['method']();
.aiStep]['method']();
params.onNext!();
controller.sendMessage();
},

68
lib/modules/goods/controllers/goods_base_controller.dart

@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:voitrans/data/models/user_Info.dart';
import '../../../routes/app_routes.dart';
import '../../../data/services/pay_service.dart';
import '../../../data/services/version_update_service.dart';
import '../../../data/models/goods.dart';
@ -17,6 +16,8 @@ abstract class GoodsBaseController extends GetxController {
final RxList<DBGoods> items = <DBGoods>[].obs;
final RxBool loading = false.obs;
final RxString error = ''.obs;
final RxBool isPaying = false.obs;
Timer? _payingTimeoutTimer;
late final PayService _payService = Get.find<PayService>();
StreamSubscription<Uri?>? _deeplinkSub;
@ -34,6 +35,8 @@ abstract class GoodsBaseController extends GetxController {
void onClose() {
_deeplinkSub?.cancel();
_deeplinkSub = null;
_payingTimeoutTimer?.cancel();
_payingTimeoutTimer = null;
super.onClose();
}
@ -43,6 +46,8 @@ abstract class GoodsBaseController extends GetxController {
try {
final list = await fetchProducts();
items.assignAll(list);
// iOS 环境下,在页面加载后批量查询当前商品的 IAP 详情,便于排查 StoreKit 可用商品
await _debugQueryIapProductsIfIos();
} catch (e) {
error.value = e.toString();
} finally {
@ -53,6 +58,30 @@ abstract class GoodsBaseController extends GetxController {
/// 子类实现:返回商品列表(统一使用 DBGoods)
Future<List<DBGoods>> fetchProducts();
/// iOS 批量查询当前页面商品的 IAP 详情(仅真机 iOS 生效,Web/Android 跳过)
Future<void> _debugQueryIapProductsIfIos() async {
try {
final isIOS = GetPlatform.isIOS && !kIsWeb;
if (!isIOS) return;
// 收集页面商品ID;若为空,使用预设的基础套餐ID进行测试
final ids = items
.map((e) => (e.id ?? '').trim())
.where((id) => id.isNotEmpty)
.toSet();
if (ids.isEmpty) {
ids.addAll({
'ai_001',
});
}
print('[IAP-ios] 批量查询页面商品IDs: ${ids.join(', ')}');
await _payService.debugQueryProducts(ids);
} catch (e) {
print('[IAP-ios] 批量查询异常: $e');
}
}
/// 统一入口:根据后端配置决定是否弹出支付方式选择面板
Future<void> purchase(DBGoods item) async {
// 读取渠道配置
@ -480,9 +509,15 @@ abstract class GoodsBaseController extends GetxController {
onResult?.call(false, '创建 Apple 订单失败');
return false;
}
isPaying.value = true;
_startPayingTimeout();
// 使用商品id作为内购的 productId(与后台保持一致)
final productId = item.id;
// 解析为 App Store 的真实商品ID(支持前缀/映射)
final iosProductId = _payService.resolveAppleProductId(productId);
// 调试:在发起购买前先查询并打印该商品的内购详情/错误,便于定位问题
await _payService.debugQueryProducts({iosProductId});
return _payService.processApplePayment(
productId: productId,
onResult: (success, msg) {
@ -490,6 +525,8 @@ abstract class GoodsBaseController extends GetxController {
onResult?.call(success, msg);
if (!success) {
_showPayResultDialog(false, msg);
isPaying.value = false;
_cancelPayingTimeout();
} else {
// 支付成功或额度待刷新时弹窗,其余阶段用轻提示
final showDialog = msg.contains('支付成功');
@ -497,6 +534,8 @@ abstract class GoodsBaseController extends GetxController {
_showPayResultDialog(true, msg);
// 仅在支付成功阶段,携带校验参数主动查询订单
_askOrderWithIapVerification();
isPaying.value = false;
_cancelPayingTimeout();
} else {
Get.snackbar('提示', msg,
snackPosition: SnackPosition.BOTTOM,
@ -507,6 +546,8 @@ abstract class GoodsBaseController extends GetxController {
);
} catch (e) {
onResult?.call(false, 'Apple 内购异常: $e');
isPaying.value = false;
_cancelPayingTimeout();
return false;
}
}
@ -526,6 +567,8 @@ abstract class GoodsBaseController extends GetxController {
onResult?.call(false, '创建 Google 订单失败');
return false;
}
isPaying.value = true;
_startPayingTimeout();
// 使用商品id作为内购的 productId(与后台保持一致)
final productId = item.id;
@ -537,12 +580,16 @@ abstract class GoodsBaseController extends GetxController {
onResult?.call(success, msg);
if (!success) {
_showPayResultDialog(false, msg);
isPaying.value = false;
_cancelPayingTimeout();
} else {
final showDialog = msg.contains('支付成功');
if (showDialog) {
_showPayResultDialog(true, msg);
// 仅在支付成功阶段,携带校验参数主动查询订单
_askOrderWithIapVerification();
isPaying.value = false;
_cancelPayingTimeout();
} else {
Get.snackbar('提示', msg,
snackPosition: SnackPosition.BOTTOM,
@ -553,6 +600,8 @@ abstract class GoodsBaseController extends GetxController {
);
} catch (e) {
onResult?.call(false, 'Google 内购异常: $e');
isPaying.value = false;
_cancelPayingTimeout();
return false;
}
}
@ -590,7 +639,7 @@ abstract class GoodsBaseController extends GetxController {
try {
// 简单轮询回查,避免回调延迟
for (int i = 0; i < retries; i++) {
final resp = await Api.payaskorder({'order_id': orderId});
final resp = await Api.payverifyorder({'order_id': orderId});
print("查询订单 resp: $resp");
final order = resp?['order'] as Map<String, dynamic>?;
final user = resp?['user'] as Map<String, dynamic>?;
@ -625,7 +674,7 @@ abstract class GoodsBaseController extends GetxController {
Future<void> _askOrderWithIapVerification() async {
try {
final params = await _payService.buildIapAskParams();
final resp = await Api.payaskorder(params);
final resp = await Api.payverifyorder(params);
print('[IAP] 主动查询订单 resp: $resp');
final order = resp?['order'] as Map<String, dynamic>?;
final user = resp?['user'] as Map<String, dynamic>?;
@ -731,6 +780,19 @@ abstract class GoodsBaseController extends GetxController {
);
}
void _startPayingTimeout({int seconds = 30}) {
_payingTimeoutTimer?.cancel();
_payingTimeoutTimer = Timer(Duration(seconds: seconds), () {
isPaying.value = false;
_payingTimeoutTimer = null;
});
}
void _cancelPayingTimeout() {
_payingTimeoutTimer?.cancel();
_payingTimeoutTimer = null;
}
/// 指定 PayPal 支付(创建订单并打开授权链接)
Future<bool> payPaypal(DBGoods item,
{PaymentResultCallback? onResult}) async {

63
lib/modules/goods/utils/goods_i18n.dart

@ -0,0 +1,63 @@
import 'package:get/get.dart';
import 'package:voitrans/data/models/goods.dart';
/// 商品名称本地化
/// 优先根据商品ID映射到本地化名称;若无映射,则回退到后端提供的名称
String localizedGoodsName(DBGoods item) {
final id = (item.id ?? '').trim();
switch (id) {
case 'ai_001':
return 'ai_001_name'.tr;
case 'ai_002':
return 'ai_002_name'.tr;
case 'ai_003':
return 'ai_003_name'.tr;
case 'meet_001':
return 'meet_001_name'.tr;
case 'meet_002':
return 'meet_002_name'.tr;
case 'meet_003':
return 'meet_003_name'.tr;
case 'trade_001':
return 'trade_001_name'.tr;
case 'trade_002':
return 'trade_002_name'.tr;
case 'trade_003':
return 'trade_003_name'.tr;
// 可在此补充其他商品ID的映射,如:translate_001、meet_001 等
default:
final name = (item.name ?? '').trim();
return name.isNotEmpty ? name : 'unknown'.tr;
}
}
/// 商品描述本地化
/// 优先根据商品ID映射到本地化描述;若无映射,则回退到后端提供的描述
String localizedGoodsDesc(DBGoods item) {
final id = (item.id ?? '').trim();
switch (id) {
case 'ai_001':
return 'ai_001_desc'.tr;
case 'ai_002':
return 'ai_002_desc'.tr;
case 'ai_003':
return 'ai_003_desc'.tr;
case 'meet_001':
return 'meet_001_desc'.tr;
case 'meet_002':
return 'meet_002_desc'.tr;
case 'meet_003':
return 'meet_003_desc'.tr;
case 'trade_001':
return 'trade_001_desc'.tr;
case 'trade_002':
return 'trade_002_desc'.tr;
case 'trade_003':
return 'trade_003_desc'.tr;
default:
final desc = (item.desc ?? '').trim();
return desc.isNotEmpty ? desc : '';
}
}

136
lib/modules/goods/views/goodsai_view.dart

@ -5,6 +5,7 @@ import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import '../../../data/models/goods.dart';
import '../../../data/models/user_Info.dart';
import '../controllers/goodsai_controller.dart';
import '../utils/goods_i18n.dart';
class GoodsaiView extends GetView<GoodsaiController> {
const GoodsaiView({super.key});
@ -31,37 +32,54 @@ class GoodsaiView extends GetView<GoodsaiController> {
body: Obx(() {
// 访问刷新信号以建立依赖关系:用户信息变化时触发重建
final _ = User.refreshTick.value;
Widget content;
if (controller.loading.value) {
return const Center(child: CircularProgressIndicator());
}
if (controller.error.isNotEmpty) {
return Center(child: Text(controller.error.value));
content = const Center(child: CircularProgressIndicator());
} else if (controller.error.isNotEmpty) {
content = Center(child: Text(controller.error.value));
} else {
content = ListView(
padding: EdgeInsets.all(16.w),
children: [
_buildHeader(isDarkMode),
SizedBox(height: 12.h),
_buildUsageCard(isDarkMode),
SizedBox(height: 16.h),
Text(
'availablePackages'.tr,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black,
),
),
SizedBox(height: 8.h),
...controller.items.map((item) => Padding(
padding: EdgeInsets.only(bottom: 12.h),
child: _buildCard(item, isDarkMode),
)),
SizedBox(height: 16.h),
_buildFeaturesSection(isDarkMode),
SizedBox(height: 16.h),
_buildFooterSection(isDarkMode),
],
);
}
return ListView(
padding: EdgeInsets.all(16.w),
return Stack(
children: [
_buildHeader(isDarkMode),
SizedBox(height: 12.h),
_buildUsageCard(isDarkMode),
SizedBox(height: 16.h),
Text(
'可购买套餐',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black,
content,
if (controller.isPaying.value)
Positioned.fill(
child: AbsorbPointer(
absorbing: true,
child: Container(
color: Colors.black.withOpacity(0.35),
child: const Center(
child: CircularProgressIndicator(),
),
),
),
),
),
SizedBox(height: 8.h),
...controller.items.map((item) => Padding(
padding: EdgeInsets.only(bottom: 12.h),
child: _buildCard(item, isDarkMode),
)),
SizedBox(height: 16.h),
_buildFeaturesSection(isDarkMode),
SizedBox(height: 16.h),
_buildFooterSection(isDarkMode),
],
);
}),
@ -105,7 +123,7 @@ class GoodsaiView extends GetView<GoodsaiController> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'AI 功能',
'aiFunction'.tr,
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w700,
@ -114,7 +132,7 @@ class GoodsaiView extends GetView<GoodsaiController> {
),
SizedBox(height: 6.h),
Text(
'更长对话额度、更多工具调用、更强上下文长度支持。',
'aiHeaderDesc1'.tr,
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[700],
@ -122,7 +140,7 @@ class GoodsaiView extends GetView<GoodsaiController> {
),
SizedBox(height: 4.h),
Text(
'适用于智能体问答、总结分析、任务执行等场景。',
'aiHeaderDesc2'.tr,
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[700],
@ -172,7 +190,7 @@ class GoodsaiView extends GetView<GoodsaiController> {
color: isDarkMode ? Colors.blue[300]! : Colors.blue[600]!),
SizedBox(width: 8.w),
Text(
'剩余额度',
'remainingQuota'.tr,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
@ -194,14 +212,14 @@ class GoodsaiView extends GetView<GoodsaiController> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'总次数:$totalAi',
'${'totalCount'.tr}:$totalAi',
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[700],
),
),
Text(
'剩余:$remainAi',
'${'remaining'.tr}:$remainAi',
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[700],
@ -221,7 +239,7 @@ class GoodsaiView extends GetView<GoodsaiController> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'功能说明',
'featureDescription'.tr,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
@ -242,10 +260,10 @@ class GoodsaiView extends GetView<GoodsaiController> {
return _buildFeatureCard(
isDarkMode,
icon: Icons.music_note,
title: '听歌与推荐',
title: 'musicAndRecommendation'.tr,
lines: [
'检索曲库、播放控制',
'智能推荐歌单与相似歌曲',
'musicSearchPlaybackControl'.tr,
'smartPlaylistAndSimilarRecommendations'.tr,
],
colorSeed: Colors.purple,
);
@ -253,10 +271,10 @@ class GoodsaiView extends GetView<GoodsaiController> {
return _buildFeatureCard(
isDarkMode,
icon: Icons.navigation,
title: '导航与路线',
title: 'navigationAndRoutes'.tr,
lines: [
'路线规划与拥堵规避',
'语音播报与途径点设置',
'routePlanningAndCongestionAvoidance'.tr,
'voiceBroadcastAndWaypoints'.tr,
],
colorSeed: Colors.orange,
);
@ -264,10 +282,10 @@ class GoodsaiView extends GetView<GoodsaiController> {
return _buildFeatureCard(
isDarkMode,
icon: Icons.wb_sunny,
title: '天气查询',
title: 'weatherQuery'.tr,
lines: [
'实时天气与预报',
'穿衣建议与出行提醒',
'realTimeWeatherForecast'.tr,
'clothingAdviceAndTravelReminders'.tr,
],
colorSeed: Colors.blue,
);
@ -275,10 +293,10 @@ class GoodsaiView extends GetView<GoodsaiController> {
return _buildFeatureCard(
isDarkMode,
icon: Icons.place,
title: '附近搜索',
title: 'nearbySearch'.tr,
lines: [
'餐饮/加油/停车等地点检索',
'评分、营业时间与路线直达',
'poiSearchFoodGasParking'.tr,
'ratingsHoursAndDirectRoutes'.tr,
],
colorSeed: Colors.green,
);
@ -286,10 +304,10 @@ class GoodsaiView extends GetView<GoodsaiController> {
return _buildFeatureCard(
isDarkMode,
icon: Icons.newspaper,
title: '新闻资讯',
title: 'newsInformation'.tr,
lines: [
'热点快讯与专题速览',
'长文总结与要点提炼',
'hotNewsAndTopicOverview'.tr,
'longArticleSummariesAndKeyPoints'.tr,
],
colorSeed: Colors.indigo,
);
@ -297,10 +315,10 @@ class GoodsaiView extends GetView<GoodsaiController> {
return _buildFeatureCard(
isDarkMode,
icon: Icons.call,
title: '通讯助手',
title: 'communicationAssistant'.tr,
lines: [
'帮忙拨打电话与发短信',
'模板消息与日程提醒',
'helpCallAndSMS'.tr,
'templatedMessagesAndScheduleReminders'.tr,
],
colorSeed: Colors.teal,
);
@ -309,7 +327,7 @@ class GoodsaiView extends GetView<GoodsaiController> {
),
SizedBox(height: 12.h),
Text(
'以上功能受设备权限、服务可用性与网络状况影响,具体以实际表现为准。',
'aiDisclaimer'.tr,
style: TextStyle(fontSize: 12.sp, color: subColor),
),
],
@ -329,19 +347,19 @@ class GoodsaiView extends GetView<GoodsaiController> {
),
SizedBox(height: 8.h),
Text(
'应用名称:VoiTrans · 服务提供:VoiTrans',
'appNameProvider'.tr,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 11.sp, color: subColor),
),
SizedBox(height: 4.h),
Text(
'更多信息请前往 设置 > 关于 查看',
'moreInfoViewInSettingsAbout'.tr,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 11.sp, color: subColor),
),
SizedBox(height: 4.h),
Text(
'© 2025 VoiTrans',
'copyrightVoiTrans'.tr,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 11.sp, color: subColor),
),
@ -460,14 +478,14 @@ class GoodsaiView extends GetView<GoodsaiController> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(item.name,
Text(localizedGoodsName(item),
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black,
)),
SizedBox(height: 4.h),
Text(item.desc,
Text(localizedGoodsDesc(item),
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[600],
@ -495,7 +513,7 @@ class GoodsaiView extends GetView<GoodsaiController> {
borderRadius: BorderRadius.circular(20.r),
),
child: Text(
'购买',
'purchase'.tr,
style: TextStyle(fontSize: 12.sp, color: Colors.white),
),
),

51
lib/modules/goods/views/goodsmeet_view.dart

@ -4,6 +4,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:voitrans/data/models/goods.dart';
import '../../../data/models/user_Info.dart';
import '../controllers/goodsmeet_controller.dart';
import '../utils/goods_i18n.dart';
class GoodsmeetView extends GetView<GoodsmeetController> {
const GoodsmeetView({super.key});
@ -99,7 +100,7 @@ class GoodsmeetView extends GetView<GoodsmeetController> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'会议助手',
'conferenceAssistant'.tr,
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w700,
@ -108,7 +109,7 @@ class GoodsmeetView extends GetView<GoodsmeetController> {
),
SizedBox(height: 6.h),
Text(
'录音转写、关键词检索与自动总结,提升会议效率。',
'meetingHeaderDesc1'.tr,
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[700],
@ -116,7 +117,7 @@ class GoodsmeetView extends GetView<GoodsmeetController> {
),
SizedBox(height: 4.h),
Text(
'适用于商务会议、课堂笔记、访谈纪要等场景。',
'meetingHeaderDesc2'.tr,
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[700],
@ -164,7 +165,7 @@ class GoodsmeetView extends GetView<GoodsmeetController> {
color: isDarkMode ? Colors.blue[300]! : Colors.blue[600]!),
SizedBox(width: 8.w),
Text(
'剩余额度',
'remainingQuota'.tr,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
@ -186,14 +187,14 @@ class GoodsmeetView extends GetView<GoodsmeetController> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'总次数:$totalAi',
'${'totalCount'.tr}:$totalAi',
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[700],
),
),
Text(
'剩余:$remainAi',
'${'remaining'.tr}:$remainAi',
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[700],
@ -241,14 +242,14 @@ class GoodsmeetView extends GetView<GoodsmeetController> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(item.name,
Text(localizedGoodsName(item),
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black,
)),
SizedBox(height: 4.h),
Text(item.desc,
Text(localizedGoodsDesc(item),
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[600],
@ -276,7 +277,7 @@ class GoodsmeetView extends GetView<GoodsmeetController> {
borderRadius: BorderRadius.circular(20.r),
),
child: Text(
'购买',
'purchase'.tr,
style: TextStyle(fontSize: 12.sp, color: Colors.white),
),
),
@ -295,7 +296,7 @@ class GoodsmeetView extends GetView<GoodsmeetController> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'功能说明',
'featureDescription'.tr,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
@ -312,36 +313,42 @@ class GoodsmeetView extends GetView<GoodsmeetController> {
_buildFeatureCard(
isDarkMode,
icon: Icons.mic,
title: '会议记录',
lines: ['自动录音与分段', '讲话人标注'],
title: 'meetingRecording'.tr,
lines: ['meetingAutoRecording'.tr, 'meetingSpeakerTagging'.tr],
colorSeed: Colors.pink,
),
_buildFeatureCard(
isDarkMode,
icon: Icons.summarize,
title: '转写与总结',
lines: ['长音频转写', '关键要点提炼'],
title: 'transcriptionAndSummary'.tr,
lines: [
'meetingLongAudioTranscription'.tr,
'meetingKeyPointSummary'.tr
],
colorSeed: Colors.blue,
),
_buildFeatureCard(
isDarkMode,
icon: Icons.search,
title: '关键词检索',
lines: ['按主题/人名检索', '时间线跳转'],
title: 'keywordSearch'.tr,
lines: ['meetingTopicNameSearch'.tr, 'meetingTimelineJump'.tr],
colorSeed: Colors.indigo,
),
_buildFeatureCard(
isDarkMode,
icon: Icons.share,
title: '协同分享',
lines: ['导出纪要', '多平台分享'],
title: 'collaborationSharing'.tr,
lines: [
'meetingExportSummary'.tr,
'meetingMultiPlatformShare'.tr
],
colorSeed: Colors.teal,
),
],
),
SizedBox(height: 12.h),
Text(
'建议在安静环境使用,效果受麦克风与网络影响,具体以实际表现为准。',
'meetingDisclaimer'.tr,
style: TextStyle(fontSize: 12.sp, color: subColor),
),
],
@ -428,19 +435,19 @@ class GoodsmeetView extends GetView<GoodsmeetController> {
),
SizedBox(height: 8.h),
Text(
'应用名称:VoiTrans · 服务提供:VoiTrans',
'appNameProvider'.tr,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 11.sp, color: subColor),
),
SizedBox(height: 4.h),
Text(
'更多信息请前往 设置 > 关于 查看',
'moreInfoViewInSettingsAbout'.tr,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 11.sp, color: subColor),
),
SizedBox(height: 4.h),
Text(
'© 2025 VoiTrans',
'copyrightVoiTrans'.tr,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 11.sp, color: subColor),
),

54
lib/modules/goods/views/goodstrade_view.dart

@ -4,6 +4,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:voitrans/data/models/goods.dart';
import '../../../data/models/user_Info.dart';
import '../controllers/goodstrade_controller.dart';
import '../utils/goods_i18n.dart';
class GoodstradeView extends GetView<GoodstradeController> {
const GoodstradeView({super.key});
@ -99,7 +100,7 @@ class GoodstradeView extends GetView<GoodstradeController> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'翻译功能',
'simultaneousTranslation'.tr,
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w700,
@ -108,7 +109,7 @@ class GoodstradeView extends GetView<GoodstradeController> {
),
SizedBox(height: 6.h),
Text(
'多语种实时同传与文本翻译,低延时语音播报。',
'tradeHeaderDesc1'.tr,
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[700],
@ -116,7 +117,7 @@ class GoodstradeView extends GetView<GoodstradeController> {
),
SizedBox(height: 4.h),
Text(
'适用于出行、商务、演讲与教学等场景。',
'tradeHeaderDesc2'.tr,
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[700],
@ -164,7 +165,7 @@ class GoodstradeView extends GetView<GoodstradeController> {
color: isDarkMode ? Colors.blue[300]! : Colors.blue[600]!),
SizedBox(width: 8.w),
Text(
'剩余额度',
'remainingQuota'.tr,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
@ -186,14 +187,14 @@ class GoodstradeView extends GetView<GoodstradeController> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'总次数:$totalAi',
'${'totalCount'.tr}:$totalAi',
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[700],
),
),
Text(
'剩余:$remainAi',
'${'remaining'.tr}:$remainAi',
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[700],
@ -241,14 +242,14 @@ class GoodstradeView extends GetView<GoodstradeController> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(item.name,
Text(localizedGoodsName(item),
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black,
)),
SizedBox(height: 4.h),
Text(item.desc,
Text(localizedGoodsDesc(item),
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[600],
@ -276,7 +277,7 @@ class GoodstradeView extends GetView<GoodstradeController> {
borderRadius: BorderRadius.circular(20.r),
),
child: Text(
'购买',
'purchase'.tr,
style: TextStyle(fontSize: 12.sp, color: Colors.white),
),
),
@ -295,7 +296,7 @@ class GoodstradeView extends GetView<GoodstradeController> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'功能说明',
'featureDescription'.tr,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
@ -312,36 +313,45 @@ class GoodstradeView extends GetView<GoodstradeController> {
_buildFeatureCard(
isDarkMode,
icon: Icons.translate,
title: '实时同传',
lines: ['中英互译', '低延时语音播报'],
title: 'realtimeTranscription'.tr,
lines: ['translateZhEn'.tr, 'lowLatencyVoiceBroadcast'.tr],
colorSeed: Colors.indigo,
),
_buildFeatureCard(
isDarkMode,
icon: Icons.text_snippet,
title: '文本翻译',
lines: ['多语种文本翻译', '术语优化与语境保持'],
title: 'textTranslation'.tr,
lines: [
'multiLangTextTranslation'.tr,
'termOptimizationContextPreserve'.tr
],
colorSeed: Colors.blue,
),
_buildFeatureCard(
isDarkMode,
icon: Icons.library_books,
title: '场景词库',
lines: ['旅游/商务/生活词库', '专属词汇记忆'],
title: 'sceneLexicon'.tr,
lines: [
'lexiconTourBusinessLife'.tr,
'personalVocabularyMemory'.tr
],
colorSeed: Colors.teal,
),
_buildFeatureCard(
isDarkMode,
icon: Icons.subtitles,
title: '字幕显示',
lines: ['对话字幕/大字模式', '颜色高对比度'],
title: 'subtitleDisplay'.tr,
lines: [
'conversationSubtitleLargeText'.tr,
'colorHighContrast'.tr
],
colorSeed: Colors.purple,
),
],
),
SizedBox(height: 12.h),
Text(
'翻译效果受麦克风、网络时延与环境噪声影响,具体以实际表现为准。',
'tradeDisclaimer'.tr,
style: TextStyle(fontSize: 12.sp, color: subColor),
),
],
@ -428,19 +438,19 @@ class GoodstradeView extends GetView<GoodstradeController> {
),
SizedBox(height: 8.h),
Text(
'应用名称:VoiTrans · 服务提供:VoiTrans',
'appNameProvider'.tr,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 11.sp, color: subColor),
),
SizedBox(height: 4.h),
Text(
'更多信息请前往 设置 > 关于 查看',
'moreInfoViewInSettingsAbout'.tr,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 11.sp, color: subColor),
),
SizedBox(height: 4.h),
Text(
'© 2025 VoiTrans',
'copyrightVoiTrans'.tr,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 11.sp, color: subColor),
),

91
lib/modules/goods/views/goodsvip_view.dart

@ -3,6 +3,7 @@ import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:voitrans/data/models/goods.dart';
import '../controllers/goodsvip_controller.dart';
import '../utils/goods_i18n.dart';
class GoodsvipView extends GetView<GoodsvipController> {
const GoodsvipView({super.key});
@ -27,26 +28,44 @@ class GoodsvipView extends GetView<GoodsvipController> {
centerTitle: true,
),
body: Obx(() {
Widget content;
if (controller.loading.value) {
return const Center(child: CircularProgressIndicator());
content = const Center(child: CircularProgressIndicator());
} else if (controller.error.isNotEmpty) {
content = Center(child: Text(controller.error.value));
} else {
content = ListView.separated(
padding: EdgeInsets.all(16.w),
itemCount: controller.items.length + 2,
separatorBuilder: (_, __) => SizedBox(height: 12.h),
itemBuilder: (_, index) {
if (index < controller.items.length) {
final item = controller.items[index];
return _buildGoodsCard(item, isDarkMode);
}
if (index == controller.items.length) {
return _buildFeaturesSection(isDarkMode);
}
return _buildFooterSection(isDarkMode);
},
);
}
if (controller.error.isNotEmpty) {
return Center(child: Text(controller.error.value));
}
return ListView.separated(
padding: EdgeInsets.all(16.w),
itemCount: controller.items.length + 2,
separatorBuilder: (_, __) => SizedBox(height: 12.h),
itemBuilder: (_, index) {
if (index < controller.items.length) {
final item = controller.items[index];
return _buildGoodsCard(item, isDarkMode);
}
if (index == controller.items.length) {
return _buildFeaturesSection(isDarkMode);
}
return _buildFooterSection(isDarkMode);
},
return Stack(
children: [
content,
if (controller.isPaying.value)
Positioned.fill(
child: AbsorbPointer(
absorbing: true,
child: Container(
color: Colors.black.withOpacity(0.35),
child: const Center(
child: CircularProgressIndicator(),
),
),
),
),
],
);
}),
);
@ -94,7 +113,7 @@ class GoodsvipView extends GetView<GoodsvipController> {
color: isDarkMode ? Colors.white : Colors.black,
)),
SizedBox(height: 4.h),
Text(item.desc,
Text(localizedGoodsDesc(item),
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[600],
@ -123,7 +142,7 @@ class GoodsvipView extends GetView<GoodsvipController> {
borderRadius: BorderRadius.circular(20.r),
),
child: Text(
'购买',
'purchase'.tr,
style: TextStyle(
fontSize: 12.sp,
color: Colors.white,
@ -145,7 +164,7 @@ class GoodsvipView extends GetView<GoodsvipController> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'功能说明',
'featureDescription'.tr,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
@ -162,36 +181,36 @@ class GoodsvipView extends GetView<GoodsvipController> {
_buildFeatureCard(
isDarkMode,
icon: Icons.workspace_premium,
title: '权益总览',
lines: ['更高使用额度', '更低单价'],
title: 'benefitsOverview'.tr,
lines: ['higherQuota'.tr, 'lowerUnitPrice'.tr],
colorSeed: Colors.amber,
),
_buildFeatureCard(
isDarkMode,
icon: Icons.support_agent,
title: '优先服务',
lines: ['专属客服通道', '问题快速响应'],
title: 'priorityService'.tr,
lines: ['exclusiveSupportChannel'.tr, 'fastResponse'.tr],
colorSeed: Colors.purple,
),
_buildFeatureCard(
isDarkMode,
icon: Icons.local_offer,
title: '活动与折扣',
lines: ['会员专属活动', '长期优惠计划'],
title: 'eventsAndDiscounts'.tr,
lines: ['memberExclusiveEvents'.tr, 'longTermDiscountPlan'.tr],
colorSeed: Colors.indigo,
),
_buildFeatureCard(
isDarkMode,
icon: Icons.auto_awesome,
title: '通用特权',
lines: ['新功能优先体验', '跨设备同步'],
title: 'generalPrivileges'.tr,
lines: ['earlyAccessNewFeatures'.tr, 'crossDeviceSync'.tr],
colorSeed: Colors.teal,
),
],
),
SizedBox(height: 12.h),
Text(
'具体权益以实际套餐说明为准,可能随版本迭代调整。',
'vipDisclaimer'.tr,
style: TextStyle(fontSize: 12.sp, color: subColor),
),
],
@ -257,7 +276,8 @@ class GoodsvipView extends GetView<GoodsvipController> {
SizedBox(height: 8.h),
...lines.map((l) => Padding(
padding: EdgeInsets.only(bottom: 4.h),
child: Text(l, style: TextStyle(fontSize: 12.sp, color: subColor)),
child:
Text(l, style: TextStyle(fontSize: 12.sp, color: subColor)),
)),
],
),
@ -273,24 +293,23 @@ class GoodsvipView extends GetView<GoodsvipController> {
children: [
SizedBox(
width: double.infinity,
child:
Divider(color: isDarkMode ? Colors.white24 : Colors.black12),
child: Divider(color: isDarkMode ? Colors.white24 : Colors.black12),
),
SizedBox(height: 8.h),
Text(
'应用名称:VoiTrans · 服务提供:VoiTrans',
'appNameProvider'.tr,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 11.sp, color: subColor),
),
SizedBox(height: 4.h),
Text(
'更多信息请前往 设置 > 关于 查看',
'moreInfoViewInSettingsAbout'.tr,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 11.sp, color: subColor),
),
SizedBox(height: 4.h),
Text(
'© 2025 VoiTrans',
'copyrightVoiTrans'.tr,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 11.sp, color: subColor),
),

4
lib/modules/home/views/home_view.dart

@ -101,7 +101,7 @@ class HomeView extends GetView<HomeController> {
overlayBuilder: (params) {
return IntroOverlayBuilder.aiBuilder(
params,
'欢迎使用Voitrans!首先,让我们唤醒你的专属 AI—— 小言',
'guideWelcomeWakeAI'.tr,
onNext: () {
controller.noviceGuideService.startWakeupListen();
},
@ -812,7 +812,7 @@ class HomeView extends GetView<HomeController> {
overlayBuilder: (params) {
return IntroOverlayBuilder.aiBuilder(
params,
'太棒了!你已成功唤醒小言,接下来试试让它帮你做件事吧',
'guideAwakenSuccess'.tr,
onTap: () {
params.onFinish();
controller.exploreAIFeatures();

8
lib/modules/settings/views/settings_view.dart

@ -248,7 +248,7 @@ class SettingsView extends GetView<SettingsController> {
children: [
_buildCategoryItem(
icon: Icons.workspace_premium,
label: 'Vip',
label: 'premiumMember'.tr,
iconBg: isDarkMode
? Colors.amber[900]!.withOpacity(0.3)
: Colors.amber[100]!,
@ -257,7 +257,7 @@ class SettingsView extends GetView<SettingsController> {
),
_buildCategoryItem(
icon: Icons.translate,
label: 'Translation',
label: 'interpretation'.tr,
iconBg: isDarkMode
? Colors.indigo[900]!.withOpacity(0.3)
: Colors.indigo[100]!,
@ -266,7 +266,7 @@ class SettingsView extends GetView<SettingsController> {
),
_buildCategoryItem(
icon: Icons.file_open,
label: "Meet",
label: 'conferenceAssistant'.tr,
iconBg: isDarkMode
? Colors.pink[900]!.withOpacity(0.3)
: Colors.pink[100]!,
@ -275,7 +275,7 @@ class SettingsView extends GetView<SettingsController> {
),
_buildCategoryItem(
icon: Icons.smart_toy,
label: "AI",
label: 'aiFunction'.tr,
iconBg: isDarkMode
? Colors.teal[900]!.withOpacity(0.3)
: Colors.teal[100]!,

2
pubspec.yaml

@ -1,7 +1,7 @@
name: voitrans
description: "Voitrans - AI Voice Assistant."
publish_to: "none"
version: 1.0.18+57
version: 1.0.20+62
environment:
sdk: ">=3.3.0 <4.0.0"

Loading…
Cancel
Save