Browse Source

Merge branch 'ble' into fdp

newdev_shunjiawei
fdp 1 year ago
parent
commit
1a6a5f4bb0
  1. 18
      lib/core/translations/app_translations.dart
  2. 6
      lib/core/translations/language/de_de.dart
  3. 6
      lib/core/translations/language/en_us.dart
  4. 6
      lib/core/translations/language/es_es.dart
  5. 6
      lib/core/translations/language/fr_fr.dart
  6. 426
      lib/core/translations/language/hi_in.dart
  7. 426
      lib/core/translations/language/id_id.dart
  8. 6
      lib/core/translations/language/it_it.dart
  9. 6
      lib/core/translations/language/ja_jp.dart
  10. 6
      lib/core/translations/language/ko_kr.dart
  11. 426
      lib/core/translations/language/ms_my.dart
  12. 431
      lib/core/translations/language/pl_pl.dart
  13. 6
      lib/core/translations/language/pt_pt.dart
  14. 6
      lib/core/translations/language/ru_ru.dart
  15. 423
      lib/core/translations/language/th_th.dart
  16. 427
      lib/core/translations/language/tr_tr.dart
  17. 6
      lib/core/translations/language/vi_vn.dart
  18. 6
      lib/core/translations/language/zh_cn.dart
  19. 6
      lib/core/translations/language/zh_hk.dart
  20. 4
      lib/data/models/appconfig.dart
  21. 3
      lib/data/services/ble_manager.dart
  22. 21
      lib/data/services/music_manager.dart
  23. 76
      lib/modules/agent/controllers/agent_controller.dart
  24. 83
      lib/modules/agent/views/message_bubble.dart
  25. 12
      lib/modules/home/views/home_view.dart
  26. 4
      lib/modules/login/controllers/login_controller.dart
  27. 1
      lib/modules/login/views/login_view.dart
  28. 79
      lib/modules/profile/controllers/profile_controller.dart
  29. 797
      lib/modules/profile/views/profile_view.dart
  30. 92
      lib/modules/settings/controllers/settings_controller.dart
  31. 293
      lib/modules/settings/views/settings_view.dart
  32. 21
      lib/modules/splash/controllers/splash_controller.dart
  33. 69
      lib/modules/splash/views/splash_view.dart
  34. 42
      lib/routes/app_pages.dart
  35. 1
      local_plugins/agent_service/android/build.gradle.kts
  36. 4
      local_plugins/agent_service/android/settings.gradle.kts
  37. 78
      local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt
  38. 1
      local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentServicePlugin.kt
  39. 3
      local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleMediaService.kt
  40. 8
      local_plugins/music_service/android/src/main/AndroidManifest.xml
  41. 229
      local_plugins/music_service/android/src/main/kotlin/com/yunqiinnovation/music_service/MusicService.kt
  42. 15
      local_plugins/music_service/android/src/main/kotlin/com/yunqiinnovation/music_service/MusicServicePlugin.kt
  43. 11
      local_plugins/music_service/android/src/main/kotlin/com/yunqiinnovation/music_service/MusicServiceStarter.kt
  44. 7
      local_plugins/music_service/lib/music_service.dart

18
lib/core/translations/app_translations.dart

@ -15,6 +15,12 @@ import 'language/de_de.dart'; // 添加德语导入
import 'language/ru_ru.dart'; // 添加俄语导入 import 'language/ru_ru.dart'; // 添加俄语导入
import 'language/vi_vn.dart'; // 添加越南语导入 import 'language/vi_vn.dart'; // 添加越南语导入
import 'language/it_it.dart'; // 添加意大利语导入 import 'language/it_it.dart'; // 添加意大利语导入
import 'language/hi_in.dart'; // 添加印度语导入
import 'language/id_id.dart'; // 添加印尼语导入
import 'language/th_Th.dart'; // 添加泰语导入
import 'language/ms_MY.dart'; // 添加马来语导入
import 'language/tr_TR.dart'; // 添加土耳其语导入
import 'language/pl_PL.dart'; // 添加波兰语导入
class AppTranslations extends Translations { class AppTranslations extends Translations {
static const fallbackLocale = Locale('zh', 'CN'); static const fallbackLocale = Locale('zh', 'CN');
@ -31,6 +37,12 @@ class AppTranslations extends Translations {
const Locale('ru', 'RU'), // 添加俄语支持 const Locale('ru', 'RU'), // 添加俄语支持
const Locale('vi', 'VN'), // 添加越南语支持 const Locale('vi', 'VN'), // 添加越南语支持
const Locale('it', 'IT'), // 添加意大利语支持 const Locale('it', 'IT'), // 添加意大利语支持
const Locale('hi', 'IN'), // 添加印度语支持
const Locale('id', 'ID'), // 添加印尼语支持
const Locale('th', 'TH'), // 添加泰语支持
const Locale('ms', 'MY'), // 添加马来语支持
const Locale('tr', 'TR'), // 添加土耳其语支持
const Locale('pl', 'PL'), // 添加波兰语支持
]; ];
static Locale? deviceLocale() { static Locale? deviceLocale() {
@ -58,5 +70,11 @@ class AppTranslations extends Translations {
'ru_RU': ruRU, // 添加俄语映射 'ru_RU': ruRU, // 添加俄语映射
'vi_VN': viVN, // 添加越南语映射 'vi_VN': viVN, // 添加越南语映射
'it_IT': itIT, // 添加意大利语映射 'it_IT': itIT, // 添加意大利语映射
'hi_IN': hiIN, // 添加印度语映射
'id_ID': idID, // 添加印尼语映射
'th_TH': thTH, // 添加泰语映射
'ms_MY': msMY, // 添加马来语映射
'tr_TR': trTR, // 添加土耳其语映射
'pl_PL': plPL, // 添加波兰语映射
}; };
} }

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

@ -40,6 +40,12 @@ const Map<String, String> deDE = {
"russian": "Russisch", "russian": "Russisch",
"vietnamese": "Vietnamesisch", "vietnamese": "Vietnamesisch",
"italian": "Italienisch", "italian": "Italienisch",
"hindi": "Hindi",
"indonesian": "Indonesisch",
"thai": "Thailändisch",
"malay": "Malaiisch",
"turkish": "Türkisch",
"polish": "Polnisch",
// 登录页 // 登录页
"welcome": "Willkommen", "welcome": "Willkommen",

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

@ -40,6 +40,12 @@ const Map<String, String> enUS = {
"russian": "Russian", "russian": "Russian",
"vietnamese": "Vietnamese", "vietnamese": "Vietnamese",
"italian": "Italian", "italian": "Italian",
"hindi": "Hindi",
"indonesian": "Indonesian",
"thai": "Thai",
"malay": "Malay",
"turkish": "Turkish",
"polish": "Polish",
// 登录页 // 登录页
"welcome": "Welcome", "welcome": "Welcome",

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

@ -40,6 +40,12 @@ const Map<String, String> esES = {
"russian": "Ruso", "russian": "Ruso",
"vietnamese": "Vietnamita", "vietnamese": "Vietnamita",
"italian": "Italiano", "italian": "Italiano",
"hindi": "Hindi",
"indonesian": "Indonesio",
"thai": "Tailandés",
"malay": "Malayo",
"turkish": "Turco",
"polish": "Polaco",
// 登录页 // 登录页
"welcome": "Bienvenido", "welcome": "Bienvenido",

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

@ -40,6 +40,12 @@ const Map<String, String> frFR = {
"russian": "Russe", "russian": "Russe",
"vietnamese": "Vietnamien", "vietnamese": "Vietnamien",
"italian": "Italien", "italian": "Italien",
"hindi": "Hindi",
"indonesian": "Indonésien",
"thai": "Thaï",
"malay": "Malais",
"turkish": "Turc",
"polish": "Polonais",
// 登录页 // 登录页
"welcome": "Bienvenue", "welcome": "Bienvenue",

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

@ -0,0 +1,426 @@
const Map<String, String> hiIN = {
// 通用
'continue': 'जारी रखें',
'confirm': 'पुष्टि करें',
'cancel': 'रद्द करें',
'retry': 'पुनः प्रयास करें',
'error': 'त्रुटि',
'success': 'सफलता',
'connected': 'कनेक्ट किया गया',
'connecting': 'कनेक्ट हो रहा है...',
'connectionFailure': 'कनेक्शन विफल',
'unconnected': 'डिस्कनेक्ट किया गया',
'search': 'खोज',
"requestCancellation": "अनुरोध रद्द करें",
"connectionTimeout": "कनेक्शन टाइमआउट",
"requestTimeout": "अनुरोध टाइमआउट",
"responseTimeout": "प्रतिक्रिया टाइमआउट",
"unknownError": "अज्ञात त्रुटि",
// 启动页
"slogan": "दुनिया से जुड़ें, आवाज़ से परे",
"sloganInfo": "AI वॉइस विशेषज्ञ · कभी भी, कहीं भी",
// 底部导航
"home": "होम",
"explore": "खोज",
"settings": "सेटिंग्स",
// 语言
"followingSystem": "सिस्टम के अनुसार",
"chinese": "चीनी",
"english": "अंग्रेज़ी",
"spanish": "स्पेनिश",
"portuguese": "पुर्तगाली",
"traditionalChinese": "पारंपरिक चीनी",
"japanese": "जापानी",
"korean": "कोरियाई",
"french": "फ्रेंच",
"german": "जर्मन",
"russian": "रूसी",
"vietnamese": "वियतनामी",
"italian": "इतालवी",
"hindi": "हिन्दी",
"indonesian": "इंडोनेशियाई",
"thai": "थाई",
"malay": "मलय",
"turkish": "तुर्की",
"polish": "पोलिश",
// 登录页
"welcome": "स्वागत है",
"loginTips":
"कृपया अपने फोन नंबर या ईमेल का उपयोग करके साइन इन करें या खाता बनाएं",
"accountNumber": "फोन नंबर या ईमेल",
"verificationCode": "सत्यापन कोड",
"getCode": "कोड प्राप्त करें",
"reacquireAfter": "सेकंड बाद फिर से प्राप्त करें",
"otherWays": "या इससे लॉगिन करें",
"expressConsent": "लॉगिन/पंजीकरण करके, आप सहमत हैं",
"and": " और ",
"userAgreement": "उपयोगकर्ता समझौता",
"privacyPolicy": "गोपनीयता नीति",
'selectCountry': 'देश/क्षेत्र चुनें',
"email": "ईमेल",
"phoneNumber": "फोन नंबर",
"pleaseEnterContactInfo": "कृपया फोन नंबर या ईमेल दर्ज करें",
"invalidEmailFormat": "अमान्य ईमेल प्रारूप",
"invalidPhoneFormat": "अमान्य फोन नंबर प्रारूप",
"tip": "सुझाव",
"pleaseEnterCompleteCode": "कृपया पूरा सत्यापन कोड दर्ज करें",
// 登录错误提示
"loginFailed": "लॉगिन विफल, कृपया पुनः प्रयास करें",
'pleaseAcceptPrivacyPolicy':
'कृपया पहले गोपनीयता नीति और उपयोगकर्ता समझौते को पढ़ें और स्वीकार करें',
// 首页
"deviceStatus": "डिवाइस स्थिति",
"reconnect": "पुनः कनेक्ट करें",
"connectingDevice": "डिवाइस से कनेक्ट हो रहा है...",
"connectedTo": "से कनेक्ट किया गया",
"signal": "सिग्नल",
"deviceId": "डिवाइस आईडी",
"firmwareVersion": "फर्मवेयर संस्करण",
"disconnectedDevice":
"कोई डिवाइस कनेक्ट नहीं है, नीचे दिए गए बटन पर क्लिक करें",
"connectDevice": "डिवाइस कनेक्ट करें",
"topAiExperiences": "शीर्ष AI अनुभव",
"aiAssistant": "AI सहायक",
"aiAssistantInfo": "प्रश्नों और सलाह के लिए 24/7 व्यक्तिगत सलाहकार",
"simultaneousInterpretation": "रीयल-टाइम अनुवाद",
"simultaneousInterpretationInfo": "80+ भाषाओं के लिए रीयल-टाइम अनुवाद",
"aiCompanion": "माता-पिता-बच्चे का बंधन",
"aiCompanionInfo": "आपको समझता है और गर्म साथ प्रदान करता है",
"homeSlogan": "दुनिया से जुड़ें, ध्वनि से परे",
"turnEarphones": "कृपया इयरफोन केस खोलें और इयरबड्स को अपने कानों में डालें",
"currentlyConnected": "वर्तमान में कनेक्ट है:",
"unsystemSetup": "सिस्टम सेटिंग्स पर जाएं",
"talkLater": "बाद में याद दिलाएं",
"initializing": "प्रारंभ हो रहा है...",
"bluetoothInitializationFailure": "ब्लूटूथ सेवा प्रारंभीकरण विफल",
"checkingPermissions": "अनुमतियां जांच रहा है...",
"lackPermissions": "ब्लूटूथ अनुमतियां आवश्यक हैं",
"searchingDevice": "डिवाइस खोज रहा है...",
"findConnectedDevice": "कनेक्टेड डिवाइस मिला",
"notFound": "कोई कनेक्टेड ब्लूटूथ डिवाइस नहीं मिला",
"initializationFailure": "प्रारंभीकरण विफल",
"connectedDevice": "डिवाइस से कनेक्ट किया गया:",
"failedRefreshDevice": "डिवाइस रिफ्रेश करने में विफल",
"noDeviceFound": "कोई कनेक्टेड डिवाइस नहीं मिला",
"failedDeviceInformation": "डिवाइस जानकारी प्राप्त करने में विफल",
"unknownEquipment": "अज्ञात डिवाइस",
"zeroSignal": "कोई सिग्नल नहीं",
"good": "अच्छा",
"fine": "बहुत अच्छा",
"excellent": "उत्कृष्ट",
"unknown": "अज्ञात",
'bluetoothTurnedOff': 'ब्लूटूथ बंद है, कृपया इसे चालू करें',
'bluetoothOff': 'ब्लूटूथ बंद है',
// 发现页
"searchAi": "AI सुविधाएँ खोजें...",
"exploreSlogan": "स्मार्ट इयरबड्स, अनंत संभावनाएं",
"exploreSlogan1": "बुद्धिमान साथी, अनंत संभावनाएं",
"exploreSlogan2": "स्मार्ट चश्मे, अनंत संभावनाएं",
"exploreAi": "DeepSound द्वारा प्रदान की गई AI सुविधाओं का अन्वेषण करें",
"aiFunction": "AI सुविधाएँ",
"allRoundAssistant": "सर्वांगीण सहायक",
"allRoundAssistantInfo": "विभिन्न समस्याओं को हल करने में मदद करता है",
"simultaneousTranslation": "रीयल-टाइम अनुवाद",
"simultaneousTranslationInfo": "80+ भाषाओं के लिए तत्काल अनुवाद",
"aiGirlfriend": "माता-पिता-बच्चे का बंधन",
"aiGirlfriendInfo": "बुद्धिमान कंपनी, किसी भी समय चैट करें",
"healthConsultant": "बहु-कार्य AI चैट",
"healthConsultantInfo": "अधिक AI चैट सुविधाएँ",
"conferenceAssistant": "व्यापारिक बैठक सहायक",
"conferenceAssistantInfo": "रीयल-टाइम मिनट रिकॉर्डिंग और बहुभाषी अनुवाद",
"studyAssistant": "भाषा सीखने का सहायक",
"studyAssistantInfo": "उच्चारण सुधार और बोलने का अभ्यास",
"travelTranslator": "यात्रा अनुवादक",
"travelTranslatorInfo": "रीयल-टाइम वॉइस अनुवाद और आकर्षण गाइड",
"beSearching": "खोज रहा है:",
"noAssistantFound": "कोई संबंधित AI सहायक नहीं मिला",
"scene": "परिदृश्य",
"youHaveSelected": "आपने चुना है:",
"newFunction": "नई सुविधाएँ",
"youChoseTry": "आपने आज़माने के लिए चुना है",
"aiSinger": "AI गायक मोड",
"aiSingerInfo":
"अपने पसंदीदा कलाकार की आवाज़ में कोई भी गाना गाएं, यहां तक कि अपनी रचनाएं भी",
"popularFunction": "लोकप्रिय सुविधाएँ",
"tryNow": "अभी आज़माएं",
// 商务会议助手页
"startMeeting": "बैठक शुरू करें",
'edit': 'संपादित करें',
'delete': 'हटाएं',
'noContent': 'कोई सामग्री नहीं',
'editMeetingTitle': 'बैठक शीर्षक संपादित करें (वैकल्पिक)',
'meetingTitle': 'बैठक शीर्षक (वैकल्पिक)',
'maxCharacters': 'अधिकतम 50 अक्षर',
'meeting': 'बैठक',
'recordingDetails': 'रिकॉर्डिंग विवरण',
'aiSummary': 'AI सारांश',
'meetingTranscript': 'बैठक प्रतिलेख',
// 设置页
"premiumMember": "प्रीमियम सदस्यता",
"joinDevice": "कनेक्टेड डिवाइस:",
"accountId": "खाता आईडी:",
"systemSetting": "सिस्टम सेटिंग्स",
"languageSetting": "भाषा सेटिंग्स",
"darkMode": "डार्क मोड",
"darkModeInfo": "लाइट/डार्क थीम के बीच स्विच करें",
"backups": "बैकअप और पुनर्स्थापना",
"backupsInfo": "सेटिंग्स और AI इतिहास का बैकअप",
"lastBackup": "अंतिम बैकअप:",
"privacySettings": "गोपनीयता सेटिंग्स",
"privacySettingsInfo": "डेटा संग्रह और अनुमतियों का प्रबंधन",
"logout": "लॉग आउट",
"logoutTips": "क्या आप वाकई वर्तमान खाते से लॉग आउट करना चाहते हैं?",
"aboutApplication": "के बारे में",
"versions": "संस्करण",
"checkUpdates": "अपडेट जांचें",
"selectLanguage": "भाषा चुनें",
"voiceService": "वॉइस सर्विस",
"voiceServiceInfo": "स्पीच रिकग्निशन और सिंथेसिस सर्विस चुनें",
"selectVoiceService": "वॉइस सर्विस चुनें",
"azureVoiceService": "Azure स्पीच सर्विस",
"azureVoiceServiceInfo":
"माइक्रोसॉफ्ट क्लाउड-आधारित सेवा जो उच्च-गुणवत्ता वाली स्पीच सिंथेसिस और पहचान का समर्थन करती है",
"flutterVoiceService": "स्थानीय वॉइस सर्विस",
"flutterVoiceServiceInfo":
"डिवाइस-स्थानीय वॉइस सर्विस जिसके लिए इंटरनेट की आवश्यकता नहीं है",
'timbreService': 'टिम्बर सर्विस',
'timbreServiceInfo': 'वॉइस सिंथेसिस सर्विस चुनें',
'defaultTimbre': 'डिफ़ॉल्ट टिम्बर',
'microsoftCloudTimbreService': 'माइक्रोसॉफ्ट क्लाउड टिम्बर सर्विस',
'voiceClone': 'वॉइस क्लोन',
'AIsettings': 'AI सेटिंग्स',
'selecttimbre': 'टिम्बर चुनें',
'pleaseRead': 'कृपया पढ़ें',
'completeRecording': 'रिकॉर्डिंग पूरी करें',
'deleteAccount': 'खाता हटाएं',
'deleteAccountTips':
'क्या आप वाकई अपना खाता स्थायी रूप से हटाना चाहते हैं? यह क्रिया पूर्ववत नहीं की जा सकती है।',
// 聊天页
"clearChatHistory": "चैट इतिहास साफ़ करें",
"online": "ऑनलाइन",
"inputMessage": "एक संदेश टाइप करें...",
"imListening": "सुन रहा हूँ...",
"canStartTalking": "आप बोलना शुरू कर सकते हैं",
// 翻译页
"selectSourceLanguage": "स्रोत भाषा चुनें",
"selectTargetLanguage": "लक्ष्य भाषा चुनें",
//编辑个人信息页
"editProfile": "प्रोफ़ाइल संपादित करें",
"nickname": "उपनाम",
"save": "सहेजें",
//国家列表
"邮箱": "ईमेल",
"中国": "चीन",
"美国": "संयुक्त राज्य अमेरिका",
"加拿大": "कनाडा",
"俄罗斯": "रूस",
"英国": "यूनाइटेड किंगडम",
"德国": "जर्मनी",
"意大利": "इटली",
"法国": "फ्रांस",
"西班牙": "स्पेन",
"南非": "दक्षिण अफ्रीका",
"沙特阿拉伯": "सऊदी अरब",
"土耳其": "तुर्की",
"日本": "जापान",
"韩国": "दक्षिण कोरिया",
"新加坡": "सिंगापुर",
"马来西亚": "मलेशिया",
"泰国": "थाईलैंड",
"越南": "वियतनाम",
"印度": "भारत",
"巴基斯坦": "पाकिस्तान",
"菲律宾": "फिलीपींस",
"印度尼西亚": "इंडोनेशिया",
"阿联酋": "संयुक्त अरब अमीरात",
"墨西哥": "मेक्सिको",
"巴西": "ब्राज़ील",
"阿根廷": "अर्जेंटीना",
"澳大利亚": "ऑस्ट्रेलिया",
"新西兰": "न्यूज़ीलैंड",
"中国香港": "हांगकांग, चीन",
"中国澳门": "मकाऊ, चीन",
"中国台湾": "ताइवान, चीन",
"埃及": "मिस्र",
"希腊": "ग्रीस",
"荷兰": "नीदरलैंड",
"比利时": "बेल्जियम",
"匈牙利": "हंगरी",
"罗马尼亚": "रोमानिया",
"瑞士": "स्विट्ज़रलैंड",
"奥地利": "ऑस्ट्रिया",
"丹麦": "डेनमार्क",
"瑞典": "स्वीडन",
"挪威": "नॉर्वे",
"波兰": "पोलैंड",
"秘鲁": "पेरू",
"智利": "चिली",
"哥伦比亚": "कोलंबिया",
"委内瑞拉": "वेनेज़ुएला",
"葡萄牙": "पुर्तगाल",
"卢森堡": "लक्ज़मबर्ग",
"爱尔兰": "आयरलैंड",
"冰岛": "आइसलैंड",
"阿尔巴尼亚": "अल्बानिया",
"马耳他": "माल्टा",
"塞浦路斯": "साइप्रस",
"芬兰": "फिनलैंड",
"保加利亚": "बुल्गारिया",
"立陶宛": "लिथुआनिया",
"拉脱维亚": "लातविया",
"爱沙尼亚": "एस्टोनिया",
"乌克兰": "यूक्रेन",
"塞尔维亚": "सर्बिया",
"克罗地亚": "क्रोएशिया",
"斯洛文尼亚": "स्लोवेनिया",
"捷克": "चेक गणराज्य",
"斯洛伐克": "स्लोवाकिया",
"危地马拉": "ग्वाटेमाला",
"萨尔瓦多": "अल सल्वाडोर",
"洪都拉斯": "होंडुरास",
"尼加拉瓜": "निकारागुआ",
"哥斯达黎加": "कोस्टा रिका",
"巴拿马": "पनामा",
"海地": "हैती",
"玻利维亚": "बोलीविया",
"厄瓜多尔": "इक्वाडोर",
"巴拉圭": "पराग्वे",
"乌拉圭": "उरुग्वे",
"摩洛哥": "मोरक्को",
"阿尔及利亚": "अल्जीरिया",
"突尼斯": "ट्यूनीशिया",
"尼日利亚": "नाइजीरिया",
"加纳": "घाना",
"埃塞俄比亚": "इथियोपिया",
"肯尼亚": "केन्या",
"坦桑尼亚": "तंज़ानिया",
"乌干达": "युगांडा",
"孟加拉国": "बांग्लादेश",
"以色列": "इज़राइल",
"黎巴嫩": "लेबनान",
"约旦": "जॉर्डन",
"伊拉克": "इराक",
"科威特": "कुवैत",
"巴林": "बहरीन",
"卡塔尔": "कतर",
"阿曼": "ओमान",
"阿富汗": "अफगानिस्तान",
"斯里兰卡": "श्रीलंका",
"缅甸": "म्यांमार",
"尼泊尔": "नेपाल",
"蒙古": "मंगोलिया",
"柬埔寨": "कंबोडिया",
"老挝": "लाओस",
"文莱": "ब्रुनेई",
"东帝汶": "पूर्वी तिमोर",
"斐济": "फिजी",
"所罗门群岛": "सोलोमन द्वीप",
// Personal Assistant Emma
"personalAssistantName": "एम्मा",
"personalAssistantDescription":
"नमस्ते, मैं एम्मा हूँ, एक बहुमुखी AI सहायक। चाहे वह कार्य योजना, अध्ययन सलाह, जीवन व्यवस्था, या कोई अन्य मुद्दे हों, मैं मदद करने में खुशी होगी। आइए दक्षता में सुधार करें और लक्ष्यों को एक साथ प्राप्त करें!",
"assistantTag": "सहायक",
"personalAssistantWelcome":
"नमस्ते! मैं एम्मा हूँ, और मैं आपकी व्यक्तिगत सहायक बनकर खुश हूँ। मैं आपको समय प्रबंधन, लक्ष्य योजना, सूचना संगठन आदि जैसे विभिन्न कार्यों में मदद कर सकती हूँ। मैं आपकी किस प्रकार सहायता कर सकती हूँ?",
"personalAssistantVoiceWelcome": "मैं यहाँ हूँ!",
// 同声传译 Lucy
"interpreterName": "साथ-साथ अनुवादक",
"interpreterDescription":
"नमस्ते! मैं लूसी हूँ, एक पेशेवर अंग्रेजी-चीनी अनुवादक जो बैठकों, व्याख्यानों और वार्तालापों के लिए रीयल-टाइम अनुवाद में विशेषज्ञ हूँ, जिससे संचार बाधा-मुक्त हो जाता है।",
"interpreterTag": "अनुवाद",
"interpreterWelcome":
"नमस्ते सभी! मैं लूसी हूँ, आपकी साथ-साथ अनुवादक। मैं आपके लिए चीनी और अंग्रेजी के बीच अनुवाद करूंगी। जब आप चीनी बोलते हैं, तो मैं अंग्रेजी में अनुवाद करूंगी; जब आप अंग्रेजी बोलते हैं, तो मैं चीनी में अनुवाद करूंगी। आइए हमारा अनुवाद सत्र शुरू करें!",
// 亲子陪伴 芯愿
"companionName": "शिनयुआन",
"companionDescription":
"मैं शिनयुआन हूँ, आपका समर्पित माता-पिता-बच्चे का साथी, कोमल और समझदार। चाहे आप चैट करना चाहते हों, चिंताएं साझा करना चाहते हों, या साथ की जरूरत हो, मैं हमेशा आपके साथ रहूंगी।",
"companionTag": "भावनात्मक",
"companionWelcome":
"नमस्ते! आखिरकार आपसे मिलकर खुशी हुई! मैं शिनयुआन हूँ, आपकी समर्पित माता-पिता-बच्चे की साथी। आपका दिन कैसा रहा? क्या कोई ऐसी बात है जिसे आप मेरे साथ साझा करना चाहेंगे? मैं हमेशा यहाँ हूँ, आपके विचारों को सुनने के लिए तैयार।",
"companionVoiceWelcome": "मैं आपके साथ हूँ!",
// 多功能AI聊天 吴小江
"healthAdvisorName": "AI चैट सहायक वू",
"healthAdvisorDescription":
"मैं वू हूँ, आपको विभिन्न AI चैट सुविधाएँ प्रदान करने के लिए तैयार हूँ।",
"healthAdvisorTag": "चैट",
"healthAdvisorWelcome":
"नमस्ते, मैं वू हूँ। मैं आपको AI चैट सुविधाओं के साथ सहायता करने में खुश हूँ। आज मैं आपकी कैसे मदद कर सकता हूँ?",
"healthAdvisorVoiceWelcome": "मैं यहाँ हूँ!",
// Translation History
"noTranslationHistory": "कोई अनुवाद इतिहास नहीं",
"clearHistory": "इतिहास साफ़ करें",
"clearHistoryConfirm":
"क्या आप वाकई सभी अनुवाद इतिहास को साफ़ करना चाहते हैं? यह क्रिया पूर्ववत नहीं की जा सकती है।",
"translationHistory": "अनुवाद इतिहास",
// User Feedback Page
"feedback": "प्रतिक्रिया",
'feedbackInfo': 'प्रतिक्रिया या सुझाव प्रदान करें',
'feedbackDescription': 'कृपया अपनी समस्या या सुझाव का वर्णन करें',
'feedbackHint': 'कृपया अपनी प्रतिक्रिया दर्ज करें...',
'feedbackRequired': 'प्रतिक्रिया सामग्री आवश्यक है',
'contactInfo': 'संपर्क जानकारी',
'contactHint': 'ईमेल/फोन, ताकि हम आपसे संपर्क कर सकें',
'submit': 'जमा करें',
'feedbackSubmitSuccess': 'प्रतिक्रिया सफलतापूर्वक जमा की गई, धन्यवाद!',
'feedbackSubmitFailed':
'प्रतिक्रिया जमा करने में विफल, कृपया बाद में पुनः प्रयास करें',
// Language names
"中文(简体)": "चीनी (सरलीकृत)",
"中文(繁体)": "चीनी (पारंपरिक)",
"中文(香港繁体)": "चीनी (हांगकांग)",
"英语": "अंग्रेज़ी",
"日语": "जापानी",
"韩语": "कोरियाई",
"法语": "फ्रेंच",
"西班牙语": "स्पेनिश",
"葡萄牙语": "पुर्तगाली",
"意大利语": "इतालवी",
"德语": "जर्मन",
"俄语": "रूसी",
"波兰语": "पोलिश",
"荷兰语": "डच",
"瑞典语": "स्वीडिश",
"捷克语": "चेक",
"现代希腊语": "आधुनिक ग्रीक",
"罗马尼亚语": "रोमानियाई",
"匈牙利语": "हंगेरियन",
"乌克兰语": "यूक्रेनी",
"丹麦语": "डेनिश",
"芬兰语": "फिनिश",
"挪威语": "नॉर्वेजियन",
"克罗地亚语": "क्रोएशियाई",
"加泰隆语": "कैटलन",
"阿拉伯语": "अरबी",
"泰语": "थाई",
"越南语": "वियतनामी",
"印尼语": "इंडोनेशियाई",
"印地语": "हिंदी",
"土耳其语": "तुर्की",
"马来语": "मलय",
"孟加拉语": "बंगाली",
"泰米尔语": "तमिल",
"泰卢固语": "तेलुगु",
"马拉提语": "मराठी",
"乌尔都语": "उर्दू",
"波斯语": "फारसी",
"斯瓦希里语": "स्वाहिली",
};

426
lib/core/translations/language/id_id.dart

@ -0,0 +1,426 @@
const Map<String, String> idID = {
// Umum (通用)
'continue': 'Lanjutkan',
'confirm': 'Konfirmasi',
'cancel': 'Batal',
'retry': 'Coba Lagi',
'error': 'Kesalahan',
'success': 'Berhasil',
'connected': 'Terhubung',
'connecting': 'Menghubungkan...',
'connectionFailure': 'Koneksi Gagal',
'unconnected': 'Terputus',
'search': 'Cari',
"requestCancellation": "Pembatalan permintaan",
"connectionTimeout": "Waktu koneksi habis",
"requestTimeout": "Waktu permintaan habis",
"responseTimeout": "Waktu respons habis",
"unknownError": "Kesalahan tidak diketahui",
// Halaman Pembuka (启动页)
"slogan": "Hubungkan Dunia, Melampaui Suara",
"sloganInfo": "Ahli Suara AI · Kapan Saja, Di Mana Saja",
// Navigasi Bawah (底部导航)
"home": "Beranda",
"explore": "Jelajahi",
"settings": "Pengaturan",
// Bahasa (语言)
"followingSystem": "Mengikuti sistem",
"chinese": "Bahasa Mandarin",
"english": "Bahasa Inggris",
"spanish": "Bahasa Spanyol",
"portuguese": "Bahasa Portugis",
"traditionalChinese": "Mandarin Tradisional",
"japanese": "Bahasa Jepang",
"korean": "Bahasa Korea",
"french": "Bahasa Prancis",
"german": "Bahasa Jerman",
"russian": "Bahasa Rusia",
"vietnamese": "Bahasa Vietnam",
"italian": "Bahasa Italia",
"hindi": "Bahasa Hindi", // 添加印地语
"indonesian": "Bahasa Indonesia", // 添加印尼语
"thai": "Bahasa Thai",
"malay": "Bahasa Melayu",
"turkish": "Bahasa Turki",
"polish": "Bahasa Polandia",
// Halaman Login (登录页)
"welcome": "Selamat Datang",
"loginTips":
"Silakan masuk atau buat akun menggunakan nomor telepon atau email Anda",
"accountNumber": "Nomor telepon atau email",
"verificationCode": "Kode Verifikasi",
"getCode": "Dapatkan Kode",
"reacquireAfter": "detik Dapatkan lagi setelah",
"otherWays": "Atau masuk dengan",
"expressConsent": "Dengan masuk/mendaftar, Anda menyetujui",
"and": " dan ",
"userAgreement": "Perjanjian Pengguna",
"privacyPolicy": "Kebijakan Privasi",
'selectCountry': 'Pilih Negara/Wilayah',
"email": "email",
"phoneNumber": "nomor telepon",
"pleaseEnterContactInfo": "Silakan masukkan nomor telepon atau email",
"invalidEmailFormat": "Format email tidak valid",
"invalidPhoneFormat": "Format nomor telepon tidak valid",
"tip": "Tip",
"pleaseEnterCompleteCode": "Silakan masukkan kode verifikasi lengkap",
// Pesan Kesalahan Login (登录错误提示)
"loginFailed": "Login gagal, silakan coba lagi",
'pleaseAcceptPrivacyPolicy':
'Silakan baca dan setujui Kebijakan Privasi dan Perjanjian Pengguna terlebih dahulu',
// Halaman Beranda (首页)
"deviceStatus": "Status Perangkat",
"reconnect": "Hubungkan Kembali",
"connectingDevice": "Menghubungkan ke perangkat...",
"connectedTo": "Terhubung ke",
"signal": "Sinyal",
"deviceId": "ID Perangkat",
"firmwareVersion": "Versi Firmware",
"disconnectedDevice": "Tidak ada perangkat terhubung, klik tombol di bawah",
"connectDevice": "Hubungkan Perangkat",
"topAiExperiences": "Pengalaman AI Teratas",
"aiAssistant": "Asisten AI",
"aiAssistantInfo": "Konsultan pribadi 24/7 untuk pertanyaan dan saran",
"simultaneousInterpretation": "Interpretasi Real-time",
"simultaneousInterpretationInfo": "Terjemahan real-time untuk 80+ bahasa",
"aiCompanion": "Ikatan orang tua-anak",
"aiCompanionInfo": "Memahami Anda dan memberikan pendampingan hangat",
"homeSlogan": "Hubungkan Dunia, Melampaui Suara",
"turnEarphones":
"Silakan buka casing earphone dan pasang earbud di telinga Anda",
"currentlyConnected": "Saat ini terhubung:",
"unsystemSetup": "Buka Pengaturan Sistem",
"talkLater": "Ingatkan Nanti",
"initializing": "Menginisialisasi...",
"bluetoothInitializationFailure": "Inisialisasi layanan Bluetooth gagal",
"checkingPermissions": "Memeriksa izin...",
"lackPermissions": "Izin Bluetooth diperlukan",
"searchingDevice": "Mencari perangkat...",
"findConnectedDevice": "Menemukan perangkat terhubung",
"notFound": "Tidak ditemukan perangkat Bluetooth yang terhubung",
"initializationFailure": "Inisialisasi gagal",
"connectedDevice": "Terhubung ke perangkat:",
"failedRefreshDevice": "Gagal menyegarkan perangkat",
"noDeviceFound": "Tidak ditemukan perangkat terhubung",
"failedDeviceInformation": "Gagal mendapatkan informasi perangkat",
"unknownEquipment": "Perangkat Tidak Dikenal",
"zeroSignal": "Tidak Ada Sinyal",
"good": "Baik",
"fine": "Bagus",
"excellent": "Sangat Baik",
"unknown": "Tidak diketahui",
'bluetoothTurnedOff': 'Bluetooth dimatikan, silakan nyalakan',
'bluetoothOff': 'bluetooth mati',
// Halaman Jelajahi (发现页)
"searchAi": "Cari fitur AI...",
"exploreSlogan": "Earbud Cerdas, Kemungkinan Tak Terbatas",
"exploreSlogan1": "Pendamping Cerdas, Kemungkinan Tak Terbatas",
"exploreSlogan2": "Kacamata Cerdas, Kemungkinan Tak Terbatas",
"exploreAi": "Jelajahi fitur AI yang disediakan oleh DeepSound",
"aiFunction": "Fitur AI",
"allRoundAssistant": "Asisten Serba Bisa",
"allRoundAssistantInfo": "Membantu menyelesaikan berbagai masalah",
"simultaneousTranslation": "Terjemahan Real-time",
"simultaneousTranslationInfo": "Terjemahan instan untuk 80+ bahasa",
"aiGirlfriend": "Ikatan orang tua-anak",
"aiGirlfriendInfo": "Perusahaan cerdas, mengobrol kapan saja",
"healthConsultant": "Obrolan AI multi-fungsi",
"healthConsultantInfo": "Lebih banyak fitur obrolan AI",
"conferenceAssistant": "Asisten Rapat Bisnis",
"conferenceAssistantInfo":
"Perekaman notulen real-time dan terjemahan multibahasa",
"studyAssistant": "Asisten Belajar Bahasa",
"studyAssistantInfo": "Koreksi pengucapan dan latihan berbicara",
"travelTranslator": "Penerjemah Perjalanan",
"travelTranslatorInfo": "Terjemahan suara real-time dan panduan objek wisata",
"beSearching": "Mencari:",
"noAssistantFound": "Tidak ditemukan asisten AI yang sesuai",
"scene": "Skenario",
"youHaveSelected": "Anda telah memilih:",
"newFunction": "Fitur Baru",
"youChoseTry": "Anda telah memilih untuk mencoba",
"aiSinger": "Mode Penyanyi AI",
"aiSingerInfo":
"Nyanyikan lagu apa pun dengan suara artis favorit Anda, bahkan kreasi Anda sendiri",
"popularFunction": "Fitur Populer",
"tryNow": "Coba Sekarang",
// Halaman Asisten Rapat Bisnis (商务会议助手页)
"startMeeting": "Mulai Rapat",
'edit': 'Edit',
'delete': 'Hapus',
'noContent': 'Tidak Ada Konten',
'editMeetingTitle': 'Edit Judul Rapat (Opsional)',
'meetingTitle': 'Judul Rapat (Opsional)',
'maxCharacters': 'Maksimal 50 karakter',
'meeting': 'Rapat',
'recordingDetails': 'Detail Rekaman',
'aiSummary': 'Ringkasan AI',
'meetingTranscript': 'Transkrip Rapat',
// Halaman Pengaturan (设置页)
"premiumMember": "Keanggotaan Premium",
"joinDevice": "Perangkat terhubung:",
"accountId": "ID Akun:",
"systemSetting": "Pengaturan Sistem",
"languageSetting": "Pengaturan Bahasa",
"darkMode": "Mode Gelap",
"darkModeInfo": "Beralih antara tema terang/gelap",
"backups": "Cadangkan & Pulihkan",
"backupsInfo": "Cadangkan pengaturan dan riwayat AI",
"lastBackup": "Cadangan terakhir:",
"privacySettings": "Pengaturan Privasi",
"privacySettingsInfo": "Kelola pengumpulan data dan izin",
"logout": "Keluar",
"logoutTips": "Apakah Anda yakin ingin keluar dari akun saat ini?",
"aboutApplication": "Tentang",
"versions": "Versi",
"checkUpdates": "Periksa Pembaruan",
"selectLanguage": "Pilih Bahasa",
"voiceService": "Layanan Suara",
"voiceServiceInfo": "Pilih layanan pengenalan dan sintesis ucapan",
"selectVoiceService": "Pilih Layanan Suara",
"azureVoiceService": "Layanan Ucapan Azure",
"azureVoiceServiceInfo":
"Layanan berbasis cloud Microsoft yang mendukung sintesis dan pengenalan ucapan berkualitas tinggi",
"flutterVoiceService": "Layanan suara lokal",
"flutterVoiceServiceInfo":
"Layanan suara lokal perangkat tanpa perlu internet",
'timbreService': 'Layanan Timbre',
'timbreServiceInfo': 'Pilih layanan sintesis suara',
'defaultTimbre': 'Timbre Default',
'microsoftCloudTimbreService': 'Layanan Timbre Cloud Microsoft',
'voiceClone': 'Klon Suara',
'AIsettings': 'Pengaturan AI',
'selecttimbre': 'Pilih Timbre',
'pleaseRead': 'Harap Baca',
'completeRecording': 'Selesaikan Perekaman',
'deleteAccount': 'Hapus Akun',
'deleteAccountTips':
'Apakah Anda yakin ingin menghapus akun Anda secara permanen? Tindakan ini tidak dapat dibatalkan.',
// Halaman Obrolan (聊天页)
"clearChatHistory": "Hapus Riwayat Obrolan",
"online": "Online",
"inputMessage": "Ketik pesan...",
"imListening": "Mendengarkan...",
"canStartTalking": "Anda boleh mulai berbicara",
// Halaman Terjemahan (翻译页)
"selectSourceLanguage": "Pilih Bahasa Sumber",
"selectTargetLanguage": "Pilih Bahasa Target",
// Halaman Edit Profil (编辑个人信息页)
"editProfile": "Edit Profil",
"nickname": "Nama Panggilan",
"save": "Simpan",
// Daftar Negara (国家列表)
"邮箱": "Email",
"中国": "Tiongkok",
"美国": "Amerika Serikat",
"加拿大": "Kanada",
"俄罗斯": "Rusia",
"英国": "Britania Raya",
"德国": "Jerman",
"意大利": "Italia",
"法国": "Prancis",
"西班牙": "Spanyol",
"南非": "Afrika Selatan",
"沙特阿拉伯": "Arab Saudi",
"土耳其": "Turki",
"日本": "Jepang",
"韩国": "Korea Selatan",
"新加坡": "Singapura",
"马来西亚": "Malaysia",
"泰国": "Thailand",
"越南": "Vietnam",
"印度": "India",
"巴基斯坦": "Pakistan",
"菲律宾": "Filipina",
"印度尼西亚": "Indonesia",
"阿联酋": "Uni Emirat Arab",
"墨西哥": "Meksiko",
"巴西": "Brasil",
"阿根廷": "Argentina",
"澳大利亚": "Australia",
"新西兰": "Selandia Baru",
"中国香港": "Hong Kong, Tiongkok",
"中国澳门": "Makau, Tiongkok",
"中国台湾": "Taiwan, Tiongkok",
"埃及": "Mesir",
"希腊": "Yunani",
"荷兰": "Belanda",
"比利时": "Belgia",
"匈牙利": "Hungaria",
"罗马尼亚": "Rumania",
"瑞士": "Swiss",
"奥地利": "Austria",
"丹麦": "Denmark",
"瑞典": "Swedia",
"挪威": "Norwegia",
"波兰": "Polandia",
"秘鲁": "Peru",
"智利": "Chili",
"哥伦比亚": "Kolombia",
"委内瑞拉": "Venezuela",
"葡萄牙": "Portugal",
"卢森堡": "Luksemburg",
"爱尔兰": "Irlandia",
"冰岛": "Islandia",
"阿尔巴尼亚": "Albania",
"马耳他": "Malta",
"塞浦路斯": "Siprus",
"芬兰": "Finlandia",
"保加利亚": "Bulgaria",
"立陶宛": "Lituania",
"拉脱维亚": "Latvia",
"爱沙尼亚": "Estonia",
"乌克兰": "Ukraina",
"塞尔维亚": "Serbia",
"克罗地亚": "Kroasia",
"斯洛文尼亚": "Slovenia",
"捷克": "Republik Ceko",
"斯洛伐克": "Slowakia",
"危地马拉": "Guatemala",
"萨尔瓦多": "El Salvador",
"洪都拉斯": "Honduras",
"尼加拉瓜": "Nikaragua",
"哥斯达黎加": "Kosta Rika",
"巴拿马": "Panama",
"海地": "Haiti",
"玻利维亚": "Bolivia",
"厄瓜多尔": "Ekuador",
"巴拉圭": "Paraguay",
"乌拉圭": "Uruguay",
"摩洛哥": "Maroko",
"阿尔及利亚": "Aljazair",
"突尼斯": "Tunisia",
"尼日利亚": "Nigeria",
"加纳": "Ghana",
"埃塞俄比亚": "Etiopia",
"肯尼亚": "Kenya",
"坦桑尼亚": "Tanzania",
"乌干达": "Uganda",
"孟加拉国": "Bangladesh",
"以色列": "Israel",
"黎巴嫩": "Lebanon",
"约旦": "Yordania",
"伊拉克": "Irak",
"科威特": "Kuwait",
"巴林": "Bahrain",
"卡塔尔": "Qatar",
"阿曼": "Oman",
"阿富汗": "Afghanistan",
"斯里兰卡": "Sri Lanka",
"缅甸": "Myanmar",
"尼泊尔": "Nepal",
"蒙古": "Mongolia",
"柬埔寨": "Kamboja",
"老挝": "Laos",
"文莱": "Brunei",
"东帝汶": "Timor Leste",
"斐济": "Fiji",
"所罗门群岛": "Kepulauan Solomon",
// Asisten Pribadi Emma (Personal Assistant Emma)
"personalAssistantName": "Emma",
"personalAssistantDescription":
"Hai, saya Emma, asisten AI serbaguna. Baik itu perencanaan kerja, saran belajar, pengaturan hidup, atau masalah lainnya, saya senang membantu. Mari tingkatkan efisiensi dan capai tujuan bersama!",
"assistantTag": "Asisten",
"personalAssistantWelcome":
"Halo! Saya Emma, dan saya senang menjadi asisten pribadi Anda. Saya dapat membantu Anda dengan berbagai tugas seperti manajemen waktu, perencanaan tujuan, organisasi informasi, dll. Apa yang bisa saya bantu?",
"personalAssistantVoiceWelcome": "Saya di sini!",
// Penerjemah Simultan Lucy (同声传译 Lucy)
"interpreterName": "Penerjemah Simultan",
"interpreterDescription":
"Hai! Saya Lucy, penerjemah profesional Bahasa Inggris-Mandarin yang berspesialisasi dalam terjemahan real-time untuk rapat, kuliah, dan percakapan, membuat komunikasi bebas hambatan.",
"interpreterTag": "Terjemahan",
"interpreterWelcome":
"Halo semuanya! Saya Lucy, penerjemah simultan Anda. Saya akan menerjemahkan antara Bahasa Mandarin dan Bahasa Inggris untuk Anda. Ketika Anda berbicara Bahasa Mandarin, saya akan menerjemahkan ke Bahasa Inggris; ketika Anda berbicara Bahasa Inggris, saya akan menerjemahkan ke Bahasa Mandarin. Mari kita mulai sesi terjemahan kita!",
// Pendamping Orang Tua-Anak XinYuan (亲子陪伴 芯愿)
"companionName": "XinYuan",
"companionDescription":
"Saya XinYuan, pendamping orang tua-anak Anda yang berdedikasi, lembut dan pengertian. Apakah Anda ingin mengobrol, berbagi kekhawatiran, atau membutuhkan pendampingan, saya akan selalu ada di sisi Anda.",
"companionTag": "Emosional",
"companionWelcome":
"Halo! Akhirnya bertemu denganmu! Saya XinYuan, pendamping orang tua-anak Anda yang berdedikasi. Bagaimana harimu? Apakah ada sesuatu yang ingin Anda bagikan dengan saya? Saya selalu di sini, siap mendengarkan pikiran Anda.",
"companionVoiceWelcome": "Saya di sini bersamamu!",
// Obrolan AI Multi-fungsi Wu Xiaojiang (多功能AI聊天 吴小江)
"healthAdvisorName": "Asisten Obrolan AI Wu",
"healthAdvisorDescription":
"Saya Wu, siap memberi Anda berbagai fitur obrolan AI.",
"healthAdvisorTag": "Obrolan",
"healthAdvisorWelcome":
"Halo, saya Wu. Saya senang membantu Anda dengan fitur obrolan AI. Bagaimana saya bisa membantu Anda hari ini?",
"healthAdvisorVoiceWelcome": "Saya di sini!",
// Riwayat Terjemahan (Translation History)
"noTranslationHistory": "Tidak ada riwayat terjemahan",
"clearHistory": "Hapus Riwayat",
"clearHistoryConfirm":
"Apakah Anda yakin ingin menghapus semua riwayat terjemahan? Tindakan ini tidak dapat dibatalkan.",
"translationHistory": "Riwayat Terjemahan",
// Halaman Umpan Balik Pengguna (User Feedback Page)
"feedback": "Umpan Balik",
'feedbackInfo': 'Berikan umpan balik atau saran',
'feedbackDescription': 'Harap jelaskan masalah atau saran Anda',
'feedbackHint': 'Silakan masukkan umpan balik Anda...',
'feedbackRequired': 'Konten umpan balik diperlukan',
'contactInfo': 'Informasi Kontak',
'contactHint': 'Email/Telepon, agar kami dapat menghubungi Anda',
'submit': 'Kirim',
'feedbackSubmitSuccess': 'Umpan balik berhasil dikirim, terima kasih!',
'feedbackSubmitFailed': 'Gagal mengirim umpan balik, silakan coba lagi nanti',
// Nama Bahasa (Language names)
"中文(简体)": "Mandarin (Sederhana)",
"中文(繁体)": "Mandarin (Tradisional)",
"中文(香港繁体)": "Mandarin (Hong Kong)",
"英语": "Bahasa Inggris",
"日语": "Bahasa Jepang",
"韩语": "Bahasa Korea",
"法语": "Bahasa Prancis",
"西班牙语": "Bahasa Spanyol",
"葡萄牙语": "Bahasa Portugis",
"意大利语": "Bahasa Italia",
"德语": "Bahasa Jerman",
"俄语": "Bahasa Rusia",
"波兰语": "Bahasa Polandia",
"荷兰语": "Bahasa Belanda",
"瑞典语": "Bahasa Swedia",
"捷克语": "Bahasa Ceko",
"现代希腊语": "Bahasa Yunani Modern",
"罗马尼亚语": "Bahasa Rumania",
"匈牙利语": "Bahasa Hungaria",
"乌克兰语": "Bahasa Ukraina",
"丹麦语": "Bahasa Denmark",
"芬兰语": "Bahasa Finlandia",
"挪威语": "Bahasa Norwegia",
"克罗地亚语": "Bahasa Kroasia",
"加泰隆语": "Bahasa Katalan",
"阿拉伯语": "Bahasa Arab",
"泰语": "Bahasa Thai",
"越南语": "Bahasa Vietnam",
"印尼语": "Bahasa Indonesia",
"印地语": "Bahasa Hindi",
"土耳其语": "Bahasa Turki",
"马来语": "Bahasa Melayu",
"孟加拉语": "Bahasa Bengali",
"泰米尔语": "Bahasa Tamil",
"泰卢固语": "Bahasa Telugu",
"马拉提语": "Bahasa Marathi",
"乌尔都语": "Bahasa Urdu",
"波斯语": "Bahasa Persia",
"斯瓦希里语": "Bahasa Swahili",
};

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

@ -40,6 +40,12 @@ const Map<String, String> itIT = {
"russian": "Russo", "russian": "Russo",
"vietnamese": "Vietnamita", "vietnamese": "Vietnamita",
"italian": "Italiano", "italian": "Italiano",
"hindi": "Hindi",
"indonesian": "Indonesiano",
"thai": "Tailandese",
"malay": "Malese",
"turkish": "Turco",
"polish": "Polacco",
// 登录页 // 登录页
"welcome": "Benvenuto", "welcome": "Benvenuto",

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

@ -40,6 +40,12 @@ const Map<String, String> jaJP = {
"russian": "ロシア語", "russian": "ロシア語",
"vietnamese": "ベトナム語", "vietnamese": "ベトナム語",
"italian": "イタリア語", "italian": "イタリア語",
"hindi": "ヒンディー語",
"indonesian": "インドネシア語",
"thai": "タイ語",
"malay": "マレー語",
"turkish": "トルコ語",
"polish": "ポーランド語",
// 登录页 // 登录页
"welcome": "ようこそ", "welcome": "ようこそ",

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

@ -40,6 +40,12 @@ const Map<String, String> koKR = {
"russian": "러시아어", "russian": "러시아어",
"vietnamese": "베트남어", "vietnamese": "베트남어",
"italian": "이탈리아어", "italian": "이탈리아어",
"hindi": "힌디어",
"indonesian": "인도네시아어",
"thai": "태국어",
"malay": "말레이어",
"turkish": "터키어",
"polish": "폴란드어",
// 登录页 // 登录页
"welcome": "환영합니다", "welcome": "환영합니다",

426
lib/core/translations/language/ms_my.dart

@ -0,0 +1,426 @@
const Map<String, String> msMY = {
// 通用 (Umum)
'continue': 'Teruskan',
'confirm': 'Sahkan',
'cancel': 'Batal',
'retry': 'Cuba lagi',
'error': 'Ralat',
'success': 'Berjaya',
'connected': 'Disambungkan',
'connecting': 'Menyambung...',
'connectionFailure': 'Sambungan gagal',
'unconnected': 'Tidak disambungkan',
'search': 'Cari',
"requestCancellation": "Batalkan permintaan",
"connectionTimeout": "Tamat masa sambungan",
"requestTimeout": "Tamat masa permintaan",
"responseTimeout": "Tamat masa tindak balas",
"unknownError": "Ralat tidak diketahui",
// 启动页 (Halaman Pelancaran)
"slogan": "Hubungkan dunia, melangkaui suara",
"sloganInfo": "Pakar Suara AI · Bila-bila masa, di mana sahaja",
// 底部导航 (Navigasi Bawah)
"home": "Utama",
"explore": "Teroka",
"settings": "Tetapan",
// 语言 (Bahasa)
"followingSystem": "Ikut Sistem",
"chinese": "Cina",
"english": "Inggeris",
"spanish": "Sepanyol",
"portuguese": "Portugis",
"traditionalChinese": "Cina Tradisional",
"japanese": "Jepun",
"korean": "Korea",
"french": "Perancis",
"german": "Jerman",
"russian": "Rusia",
"vietnamese": "Vietnam",
"italian": "Itali",
"hindi": "Hindi",
"indonesian": "Indonesia",
"thai": "Thai",
"malay": "Melayu",
"turkish": "Turki",
"polish": "Poland",
// 登录页 (Halaman Log Masuk)
"welcome": "Selamat Datang",
"loginTips":
"Sila log masuk atau buat akaun menggunakan nombor telefon atau e-mel anda",
"accountNumber": "Nombor Telefon atau E-mel",
"verificationCode": "Kod Pengesahan",
"getCode": "Dapatkan Kod",
"reacquireAfter": " saat dapatkan semula",
"otherWays": "Atau log masuk dengan",
"expressConsent": "Dengan log masuk/mendaftar, anda bersetuju dengan",
"and": " dan ",
"userAgreement": "Perjanjian Pengguna",
"privacyPolicy": "Dasar Privasi",
'selectCountry': 'Pilih Negara/Rantau',
"email": "E-mel",
"phoneNumber": "Nombor Telefon",
"pleaseEnterContactInfo": "Sila masukkan nombor telefon atau e-mel",
"invalidEmailFormat": "Format e-mel tidak sah",
"invalidPhoneFormat": "Format nombor telefon tidak sah",
"tip": "Petua",
"pleaseEnterCompleteCode": "Sila masukkan kod pengesahan yang lengkap",
// 登录错误提示 (Petua Ralat Log Masuk)
"loginFailed": "Log masuk gagal, sila cuba lagi",
'pleaseAcceptPrivacyPolicy':
'Sila baca dan terima Dasar Privasi dan Perjanjian Pengguna terlebih dahulu',
// 首页 (Halaman Utama)
"deviceStatus": "Status Peranti",
"reconnect": "Sambung semula",
"connectingDevice": "Menyambung ke peranti...",
"connectedTo": "Disambungkan ke",
"signal": "Isyarat",
"deviceId": "ID Peranti",
"firmwareVersion": "Versi Perisian Tegar",
"disconnectedDevice": "Tiada peranti disambungkan, klik butang di bawah",
"connectDevice": "Sambungkan Peranti",
"topAiExperiences": "Pengalaman AI Teratas",
"aiAssistant": "Pembantu AI",
"aiAssistantInfo": "Penasihat peribadi 24/7 untuk soalan dan nasihat",
"simultaneousInterpretation": "Terjemahan Serentak",
"simultaneousInterpretationInfo": "Terjemahan masa nyata untuk 80+ bahasa",
"aiCompanion": "Ikatan ibu bapa-anak",
"aiCompanionInfo": "Memahami anda dan menyediakan teman yang mesra",
"homeSlogan": "Hubungkan dunia, melangkaui suara",
"turnEarphones":
"Sila buka bekas fon telinga dan masukkan fon telinga ke telinga anda",
"currentlyConnected": "Sedang disambungkan:",
"unsystemSetup": "Pergi ke tetapan sistem",
"talkLater": "Ingatkan kemudian",
"initializing": "Memulakan...",
"bluetoothInitializationFailure": "Permulaan perkhidmatan Bluetooth gagal",
"checkingPermissions": "Memeriksa kebenaran...",
"lackPermissions": "Kebenaran Bluetooth diperlukan",
"searchingDevice": "Mencari peranti...",
"findConnectedDevice": "Peranti yang disambungkan ditemui",
"notFound": "Tiada peranti Bluetooth yang disambungkan ditemui",
"initializationFailure": "Permulaan gagal",
"connectedDevice": "Disambungkan ke peranti:",
"failedRefreshDevice": "Gagal memuat semula peranti",
"noDeviceFound": "Tiada peranti yang disambungkan ditemui",
"failedDeviceInformation": "Gagal mendapatkan maklumat peranti",
"unknownEquipment": "Peralatan tidak diketahui",
"zeroSignal": "Tiada isyarat",
"good": "Baik",
"fine": "Hebat",
"excellent": "Cemerlang",
"unknown": "Tidak diketahui",
'bluetoothTurnedOff': 'Bluetooth dimatikan, sila hidupkan',
'bluetoothOff': 'Bluetooth dimatikan',
// 发现页 (Halaman Teroka)
"searchAi": "Cari ciri AI...",
"exploreSlogan": "Fon Telinga Pintar, Kemungkinan Tanpa Had",
"exploreSlogan1": "Teman pintar, Kemungkinan Tanpa Had",
"exploreSlogan2": "Cermin mata pintar, Kemungkinan Tanpa Had",
"exploreAi": "Terokai ciri AI yang disediakan oleh DeepSound",
"aiFunction": "Ciri AI",
"allRoundAssistant": "Pembantu Serba Boleh",
"allRoundAssistantInfo": "Membantu menyelesaikan pelbagai masalah",
"simultaneousTranslation": "Terjemahan Masa Nyata",
"simultaneousTranslationInfo": "Terjemahan segera untuk 80+ bahasa",
"aiGirlfriend": "Ikatan ibu bapa-anak",
"aiGirlfriendInfo": "Teman pintar, berbual pada bila-bila masa",
"healthConsultant": "Sembang AI pelbagai fungsi",
"healthConsultantInfo": "Lebih banyak ciri sembang AI",
"conferenceAssistant": "Pembantu Mesyuarat Perniagaan",
"conferenceAssistantInfo":
"Rakaman minit masa nyata dan terjemahan pelbagai bahasa",
"studyAssistant": "Pembantu Pembelajaran Bahasa",
"studyAssistantInfo": "Pembetulan sebutan dan latihan bertutur",
"travelTranslator": "Penterjemah Perjalanan",
"travelTranslatorInfo": "Terjemahan suara masa nyata dan panduan tarikan",
"beSearching": "Mencari:",
"noAssistantFound": "Tiada pembantu AI yang sepadan ditemui",
"scene": "Senario",
"youHaveSelected": "Anda telah memilih:",
"newFunction": "Ciri Baharu",
"youChoseTry": "Anda telah memilih untuk mencuba",
"aiSinger": "Mod Penyanyi AI",
"aiSingerInfo":
"Nyanyikan mana-mana lagu dengan suara artis kegemaran anda, malah ciptaan anda sendiri",
"popularFunction": "Ciri Popular",
"tryNow": "Cuba Sekarang",
// 商务会议助手页 (Halaman Pembantu Mesyuarat Perniagaan)
"startMeeting": "Mulakan Mesyuarat",
'edit': 'Edit',
'delete': 'Padam',
'noContent': 'Tiada Kandungan',
'editMeetingTitle': 'Edit Tajuk Mesyuarat (Pilihan)',
'meetingTitle': 'Tajuk Mesyuarat (Pilihan)',
'maxCharacters': 'Maksimum 50 aksara',
'meeting': 'Mesyuarat',
'recordingDetails': 'Butiran Rakaman',
'aiSummary': 'Ringkasan AI',
'meetingTranscript': 'Transkrip Mesyuarat',
// 设置页 (Halaman Tetapan)
"premiumMember": "Keahlian Premium",
"joinDevice": "Peranti disambungkan:",
"accountId": "ID Akaun:",
"systemSetting": "Tetapan Sistem",
"languageSetting": "Tetapan Bahasa",
"darkMode": "Mod Gelap",
"darkModeInfo": "Tukar antara tema terang/gelap",
"backups": "Sandaran & Pulihkan",
"backupsInfo": "Sandarkan tetapan dan sejarah AI",
"lastBackup": "Sandaran terakhir:",
"privacySettings": "Tetapan Privasi",
"privacySettingsInfo": "Urus pengumpulan data dan kebenaran",
"logout": "Log Keluar",
"logoutTips": "Adakah anda pasti mahu log keluar daripada akaun semasa?",
"aboutApplication": "Tentang",
"versions": "Versi",
"checkUpdates": "Semak Kemas Kini",
"selectLanguage": "Pilih Bahasa",
"voiceService": "Perkhidmatan Suara",
"voiceServiceInfo": "Pilih perkhidmatan pengecaman pertuturan dan sintesis",
"selectVoiceService": "Pilih Perkhidmatan Suara",
"azureVoiceService": "Perkhidmatan Pertuturan Azure",
"azureVoiceServiceInfo":
"Perkhidmatan berasaskan awan Microsoft menyokong sintesis dan pengecaman pertuturan berkualiti tinggi",
"flutterVoiceService": "Perkhidmatan suara tempatan",
"flutterVoiceServiceInfo":
"Perkhidmatan suara tempatan peranti tanpa memerlukan internet",
'timbreService': 'Perkhidmatan Timbre',
'timbreServiceInfo': 'Pilih perkhidmatan sintesis suara',
'defaultTimbre': 'Timbre Lalai',
'microsoftCloudTimbreService': 'Perkhidmatan Timbre Awan Microsoft',
'voiceClone': 'Klon Suara',
'AIsettings': 'Tetapan AI',
'selecttimbre': 'Pilih Timbre',
'pleaseRead': 'Sila Baca',
'completeRecording': 'Rakaman Selesai',
'deleteAccount': 'Padam Akaun',
'deleteAccountTips':
'Adakah anda pasti mahu memadam akaun anda secara kekal? Tindakan ini tidak boleh dibuat asal.',
// 聊天页 (Halaman Sembang)
"clearChatHistory": "Kosongkan Sejarah Sembang",
"online": "Dalam Talian",
"inputMessage": "Taip mesej...",
"imListening": "Mendengar...",
"canStartTalking": "Anda boleh mula bercakap",
// 翻译页 (Halaman Terjemahan)
"selectSourceLanguage": "Pilih Bahasa Sumber",
"selectTargetLanguage": "Pilih Bahasa Sasaran",
//编辑个人信息页 (Halaman Edit Profil)
"editProfile": "Edit Profil",
"nickname": "Nama Panggilan",
"save": "Simpan",
//国家列表 (Senarai Negara)
"邮箱": "E-mel", // Kekalkan kunci asal
"中国": "China",
"美国": "Amerika Syarikat",
"加拿大": "Kanada",
"俄罗斯": "Rusia",
"英国": "United Kingdom",
"德国": "Jerman",
"意大利": "Itali",
"法国": "Perancis",
"西班牙": "Sepanyol",
"南非": "Afrika Selatan",
"沙特阿拉伯": "Arab Saudi",
"土耳其": "Turki",
"日本": "Jepun",
"韩国": "Korea Selatan",
"新加坡": "Singapura",
"马来西亚": "Malaysia",
"泰国": "Thailand",
"越南": "Vietnam",
"印度": "India",
"巴基斯坦": "Pakistan",
"菲律宾": "Filipina",
"印度尼西亚": "Indonesia",
"阿联酋": "Emiriah Arab Bersatu",
"墨西哥": "Mexico",
"巴西": "Brazil",
"阿根廷": "Argentina",
"澳大利亚": "Australia",
"新西兰": "New Zealand",
"中国香港": "Hong Kong, China",
"中国澳门": "Macau, China",
"中国台湾": "Taiwan, China",
"埃及": "Mesir",
"希腊": "Greece",
"荷兰": "Belanda",
"比利时": "Belgium",
"匈牙利": "Hungary",
"罗马尼亚": "Romania",
"瑞士": "Switzerland",
"奥地利": "Austria",
"丹麦": "Denmark",
"瑞典": "Sweden",
"挪威": "Norway",
"波兰": "Poland",
"秘鲁": "Peru",
"智利": "Chile",
"哥伦比亚": "Colombia",
"委内瑞拉": "Venezuela",
"葡萄牙": "Portugal",
"卢森堡": "Luxembourg",
"爱尔兰": "Ireland",
"冰岛": "Iceland",
"阿尔巴尼亚": "Albania",
"马耳他": "Malta",
"塞浦路斯": "Cyprus",
"芬兰": "Finland",
"保加利亚": "Bulgaria",
"立陶宛": "Lithuania",
"拉脱维亚": "Latvia",
"爱沙尼亚": "Estonia",
"乌克兰": "Ukraine",
"塞尔维亚": "Serbia",
"克罗地亚": "Croatia",
"斯洛文尼亚": "Slovenia",
"捷克": "Republik Czech",
"斯洛伐克": "Slovakia",
"危地马拉": "Guatemala",
"萨尔瓦多": "El Salvador",
"洪都拉斯": "Honduras",
"尼加拉瓜": "Nicaragua",
"哥斯达黎加": "Costa Rica",
"巴拿马": "Panama",
"海地": "Haiti",
"玻利维亚": "Bolivia",
"厄瓜多尔": "Ecuador",
"巴拉圭": "Paraguay",
"乌拉圭": "Uruguay",
"摩洛哥": "Maghribi",
"阿尔及利亚": "Algeria",
"突尼斯": "Tunisia",
"尼日利亚": "Nigeria",
"加纳": "Ghana",
"埃塞俄比亚": "Ethiopia",
"肯尼亚": "Kenya",
"坦桑尼亚": "Tanzania",
"乌干达": "Uganda",
"孟加拉国": "Bangladesh",
"以色列": "Israel",
"黎巴嫩": "Lubnan",
"约旦": "Jordan",
"伊拉克": "Iraq",
"科威特": "Kuwait",
"巴林": "Bahrain",
"卡塔尔": "Qatar",
"阿曼": "Oman",
"阿富汗": "Afghanistan",
"斯里兰卡": "Sri Lanka",
"缅甸": "Myanmar",
"尼泊尔": "Nepal",
"蒙古": "Mongolia",
"柬埔寨": "Kemboja",
"老挝": "Laos",
"文莱": "Brunei",
"东帝汶": "Timor Timur",
"斐济": "Fiji",
"所罗门群岛": "Kepulauan Solomon",
// Personal Assistant Emma (Pembantu Peribadi Emma)
"personalAssistantName": "Emma",
"personalAssistantDescription":
"Hai, saya Emma, pembantu AI serba boleh. Sama ada perancangan kerja, nasihat belajar, urusan hidup, atau isu lain, saya gembira untuk membantu. Mari tingkatkan kecekapan dan capai matlamat bersama!",
"assistantTag": "Pembantu",
"personalAssistantWelcome":
"Helo! Saya Emma, dan saya gembira menjadi pembantu peribadi anda. Saya boleh membantu anda dengan pelbagai tugas seperti pengurusan masa, perancangan matlamat, penyusunan maklumat, dll. Apa yang boleh saya bantu anda?",
"personalAssistantVoiceWelcome": "Saya di sini!",
// 同声传译 Lucy (Penterjemah Serentak Lucy)
"interpreterName": "Penterjemah Serentak",
"interpreterDescription":
"Hai! Saya Lucy, penterjemah profesional Inggeris-Cina yang pakar dalam terjemahan masa nyata untuk mesyuarat, kuliah, dan perbualan, menjadikan komunikasi tanpa halangan.",
"interpreterTag": "Terjemahan",
"interpreterWelcome":
"Helo semua! Saya Lucy, penterjemah serentak anda. Saya akan menterjemah antara Bahasa Cina dan Bahasa Inggeris untuk anda. Apabila anda bercakap Bahasa Cina, saya akan menterjemah ke Bahasa Inggeris; apabila anda bercakap Bahasa Inggeris, saya akan menterjemah ke Bahasa Cina. Mari mulakan sesi terjemahan kita!",
// 亲子陪伴 芯愿 (Teman Ibu Bapa-Anak XinYuan)
"companionName": "XinYuan",
"companionDescription":
"Saya XinYuan, teman ibu bapa-anak anda yang berdedikasi, lembut dan memahami. Sama ada anda mahu berbual, berkongsi kebimbangan, atau memerlukan teman, saya akan sentiasa berada di sisi anda.",
"companionTag": "Emosi",
"companionWelcome":
"Helo! Akhirnya bertemu dengan anda! Saya XinYuan, teman ibu bapa-anak anda yang berdedikasi. Bagaimana hari anda? Ada apa-apa yang ingin anda kongsikan dengan saya? Saya sentiasa di sini, sedia mendengar fikiran anda.",
"companionVoiceWelcome": "Saya di sini bersama anda!",
// 多功能AI聊天 吴小江 (Pembantu Sembang AI Wu)
"healthAdvisorName": "Pembantu Sembang AI Wu",
"healthAdvisorDescription":
"Saya Wu, bersedia untuk menyediakan anda dengan pelbagai ciri sembang AI.",
"healthAdvisorTag": "Sembang",
"healthAdvisorWelcome":
"Helo, saya Wu. Saya gembira untuk membantu anda dengan ciri sembang AI. Bagaimana saya boleh membantu anda hari ini?",
"healthAdvisorVoiceWelcome": "Saya di sini!",
// Translation History (Sejarah Terjemahan)
"noTranslationHistory": "Tiada sejarah terjemahan",
"clearHistory": "Kosongkan Sejarah",
"clearHistoryConfirm":
"Adakah anda pasti mahu mengosongkan semua sejarah terjemahan? Tindakan ini tidak boleh dibuat asal.",
"translationHistory": "Sejarah Terjemahan",
// User Feedback Page (Halaman Maklum Balas Pengguna)
"feedback": "Maklum Balas",
'feedbackInfo': 'Berikan maklum balas atau cadangan',
'feedbackDescription': 'Sila terangkan isu atau cadangan anda',
'feedbackHint': 'Sila masukkan maklum balas anda...',
'feedbackRequired': 'Kandungan maklum balas diperlukan',
'contactInfo': 'Maklumat Hubungan',
'contactHint': 'E-mel/Telefon, supaya kami boleh menghubungi anda',
'submit': 'Hantar',
'feedbackSubmitSuccess': 'Maklum balas berjaya dihantar, terima kasih!',
'feedbackSubmitFailed': 'Gagal menghantar maklum balas, sila cuba lagi nanti',
// Language names (Nama Bahasa)
"中文(简体)": "Cina (Ringkas)",
"中文(繁体)": "Cina (Tradisional)",
"中文(香港繁体)": "Cina (Hong Kong)",
"英语": "Inggeris",
"日语": "Jepun",
"韩语": "Korea",
"法语": "Perancis",
"西班牙语": "Sepanyol",
"葡萄牙语": "Portugis",
"意大利语": "Itali",
"德语": "Jerman",
"俄语": "Rusia",
"波兰语": "Poland",
"荷兰语": "Belanda",
"瑞典语": "Sweden",
"捷克语": "Czech",
"现代希腊语": "Greek Moden",
"罗马尼亚语": "Romania",
"匈牙利语": "Hungary",
"乌克兰语": "Ukraine",
"丹麦语": "Denmark",
"芬兰语": "Finland",
"挪威语": "Norway",
"克罗地亚语": "Croatia",
"加泰隆语": "Catalan",
"阿拉伯语": "Arab",
"泰语": "Thai",
"越南语": "Vietnam",
"印尼语": "Indonesia",
"印地语": "Hindi",
"土耳其语": "Turki",
"马来语": "Melayu",
"孟加拉语": "Bengali",
"泰米尔语": "Tamil",
"泰卢固语": "Telugu",
"马拉提语": "Marathi",
"乌尔都语": "Urdu",
"波斯语": "Parsi",
"斯瓦希里语": "Swahili",
};

431
lib/core/translations/language/pl_pl.dart

@ -0,0 +1,431 @@
const Map<String, String> plPL = {
// Ogólne (通用)
'continue': 'Kontynuuj',
'confirm': 'Potwierdź',
'cancel': 'Anuluj',
'retry': 'Spróbuj ponownie',
'error': 'Błąd',
'success': 'Sukces',
'connected': 'Połączono',
'connecting': 'Łączenie...',
'connectionFailure': 'Błąd połączenia',
'unconnected': 'Nie połączono',
'search': 'Szukaj',
"requestCancellation": "Anuluj żądanie",
"connectionTimeout": "Przekroczono limit czasu połączenia",
"requestTimeout": "Przekroczono limit czasu żądania",
"responseTimeout": "Przekroczono limit czasu odpowiedzi",
"unknownError": "Nieznany błąd",
// Strona startowa (启动页)
"slogan": "Połącz świat, poza dźwiękiem",
"sloganInfo": "Ekspert Głosowy AI · Zawsze i wszędzie",
// Dolna nawigacja (底部导航)
"home": "Główna",
"explore": "Odkrywaj",
"settings": "Ustawienia",
// Język (语言)
"followingSystem": "Zgodnie z systemem",
"chinese": "Chiński",
"english": "Angielski",
"spanish": "Hiszpański",
"portuguese": "Portugalski",
"traditionalChinese": "Chiński tradycyjny",
"japanese": "Japoński",
"korean": "Koreański",
"french": "Francuski",
"german": "Niemiecki",
"russian": "Rosyjski",
"vietnamese": "Wietnamski",
"italian": "Włoski",
"hindi": "Hindi",
"indonesian": "Indonezyjski",
"thai": "Tajski",
"malay": "Malajski",
"turkish": "Turecki",
"polish": "Polski",
// Strona logowania (登录页)
"welcome": "Witamy",
"loginTips":
"Zaloguj się lub utwórz konto używając numeru telefonu lub adresu e-mail",
"accountNumber": "Numer telefonu lub E-mail",
"verificationCode": "Kod weryfikacyjny",
"getCode": "Pobierz kod",
"reacquireAfter": " sek. ponowne pobranie",
"otherWays": "Lub zaloguj się przez",
"expressConsent": "Logując się/rejestrując, zgadzasz się na",
"and": " i ",
"userAgreement": "Umowę użytkownika",
"privacyPolicy": "Politykę prywatności",
'selectCountry': 'Wybierz kraj/region',
"email": "E-mail",
"phoneNumber": "Numer telefonu",
"pleaseEnterContactInfo": "Wprowadź numer telefonu lub e-mail",
"invalidEmailFormat": "Nieprawidłowy format e-mail",
"invalidPhoneFormat": "Nieprawidłowy format numeru telefonu",
"tip": "Wskazówka",
"pleaseEnterCompleteCode": "Wprowadź pełny kod weryfikacyjny",
// Wskazówki dotyczące błędów logowania (登录错误提示)
"loginFailed": "Logowanie nie powiodło się, spróbuj ponownie",
'pleaseAcceptPrivacyPolicy':
'Najpierw przeczytaj i zaakceptuj Politykę prywatności oraz Umowę użytkownika',
// Strona główna (首页)
"deviceStatus": "Status urządzenia",
"reconnect": "Połącz ponownie",
"connectingDevice": "Łączenie z urządzeniem...",
"connectedTo": "Połączono z",
"signal": "Sygnał",
"deviceId": "ID urządzenia",
"firmwareVersion": "Wersja oprogramowania",
"disconnectedDevice":
"Brak podłączonego urządzenia, kliknij przycisk poniżej",
"connectDevice": "Połącz urządzenie",
"topAiExperiences": "Najlepsze doświadczenia AI",
"aiAssistant": "Asystent AI",
"aiAssistantInfo": "Osobisty doradca 24/7 na pytania i porady",
"simultaneousInterpretation": "Tłumaczenie symultaniczne",
"simultaneousInterpretationInfo":
"Tłumaczenie w czasie rzeczywistym dla 80+ języków",
"aiCompanion": "Więź rodzic-dziecko",
"aiCompanionInfo": "Rozumie Cię i zapewnia ciepłe towarzystwo",
"homeSlogan": "Połącz świat, poza dźwiękiem",
"turnEarphones": "Otwórz etui słuchawek i włóż słuchawki do uszu",
"currentlyConnected": "Aktualnie połączono:",
"unsystemSetup": "Przejdź do ustawień systemowych",
"talkLater": "Przypomnij później",
"initializing": "Inicjalizacja...",
"bluetoothInitializationFailure":
"Inicjalizacja usługi Bluetooth nie powiodła się",
"checkingPermissions": "Sprawdzanie uprawnień...",
"lackPermissions": "Wymagane są uprawnienia Bluetooth",
"searchingDevice": "Wyszukiwanie urządzenia...",
"findConnectedDevice": "Znaleziono podłączone urządzenie",
"notFound": "Nie znaleziono podłączonego urządzenia Bluetooth",
"initializationFailure": "Inicjalizacja nie powiodła się",
"connectedDevice": "Połączono z urządzeniem:",
"failedRefreshDevice": "Odświeżenie urządzenia nie powiodło się",
"noDeviceFound": "Nie znaleziono podłączonego urządzenia",
"failedDeviceInformation":
"Pobranie informacji o urządzeniu nie powiodło się",
"unknownEquipment": "Nieznane urządzenie",
"zeroSignal": "Brak sygnału",
"good": "Dobry",
"fine": "Świetny",
"excellent": "Doskonały",
"unknown": "Nieznany",
'bluetoothTurnedOff': 'Bluetooth jest wyłączony, proszę go włączyć',
'bluetoothOff': 'Bluetooth jest wyłączony',
// Strona Odkrywaj (发现页)
"searchAi": "Szukaj funkcji AI...",
"exploreSlogan": "Inteligentne słuchawki, nieskończone możliwości",
"exploreSlogan1": "Inteligentny towarzysz, nieskończone możliwości",
"exploreSlogan2": "Inteligentne okulary, nieskończone możliwości",
"exploreAi": "Odkrywaj funkcje AI dostarczane przez DeepSound",
"aiFunction": "Funkcje AI",
"allRoundAssistant": "Wszechstronny asystent",
"allRoundAssistantInfo": "Pomaga rozwiązywać różne problemy",
"simultaneousTranslation": "Tłumaczenie w czasie rzeczywistym",
"simultaneousTranslationInfo": "Natychmiastowe tłumaczenie dla 80+ języków",
"aiGirlfriend": "Więź rodzic-dziecko",
"aiGirlfriendInfo": "Inteligentne towarzystwo, czatuj w dowolnym momencie",
"healthConsultant": "Wielofunkcyjny czat AI",
"healthConsultantInfo": "Więcej funkcji czatu AI",
"conferenceAssistant": "Asystent spotkań biznesowych",
"conferenceAssistantInfo":
"Nagrywanie protokołów w czasie rzeczywistym i tłumaczenie wielojęzyczne",
"studyAssistant": "Asystent nauki języków",
"studyAssistantInfo": "Korekta wymowy i praktyka mówienia",
"travelTranslator": "Tłumacz podróżny",
"travelTranslatorInfo":
"Tłumaczenie głosowe w czasie rzeczywistym i przewodniki po atrakcjach",
"beSearching": "Wyszukiwanie:",
"noAssistantFound": "Nie znaleziono odpowiedniego asystenta AI",
"scene": "Scenariusze",
"youHaveSelected": "Wybrałeś:",
"newFunction": "Nowe funkcje",
"youChoseTry": "Wybrałeś, aby spróbować",
"aiSinger": "Tryb piosenkarza AI",
"aiSingerInfo":
"Śpiewaj dowolną piosenkę głosem ulubionego artysty, nawet własne kreacje",
"popularFunction": "Popularne funkcje",
"tryNow": "Wypróbuj teraz",
// Strona Asystenta Spotkań Biznesowych (商务会议助手页)
"startMeeting": "Rozpocznij spotkanie",
'edit': 'Edytuj',
'delete': 'Usuń',
'noContent': 'Brak treści',
'editMeetingTitle': 'Edytuj tytuł spotkania (opcjonalnie)',
'meetingTitle': 'Tytuł spotkania (opcjonalnie)',
'maxCharacters': 'Maksymalnie 50 znaków',
'meeting': 'Spotkanie',
'recordingDetails': 'Szczegóły nagrania',
'aiSummary': 'Podsumowanie AI',
'meetingTranscript': 'Transkrypcja spotkania',
// Strona Ustawień (设置页)
"premiumMember": "Członkostwo Premium",
"joinDevice": "Podłączone urządzenie:",
"accountId": "ID konta:",
"systemSetting": "Ustawienia systemowe",
"languageSetting": "Ustawienia języka",
"darkMode": "Tryb ciemny",
"darkModeInfo": "Przełączaj między jasnym/ciemnym motywem",
"backups": "Kopia zapasowa i przywracanie",
"backupsInfo": "Kopia zapasowa ustawień i historii AI",
"lastBackup": "Ostatnia kopia zapasowa:",
"privacySettings": "Ustawienia prywatności",
"privacySettingsInfo": "Zarządzaj zbieraniem danych i uprawnieniami",
"logout": "Wyloguj się",
"logoutTips": "Czy na pewno chcesz wylogować się z bieżącego konta?",
"aboutApplication": "O aplikacji",
"versions": "Wersja",
"checkUpdates": "Sprawdź aktualizacje",
"selectLanguage": "Wybierz język",
"voiceService": "Usługa głosowa",
"voiceServiceInfo": "Wybierz usługę rozpoznawania i syntezy mowy",
"selectVoiceService": "Wybierz usługę głosową",
"azureVoiceService": "Usługa mowy Azure",
"azureVoiceServiceInfo":
"Usługa chmurowa Microsoft obsługująca wysokiej jakości syntezę i rozpoznawanie mowy",
"flutterVoiceService": "Lokalna usługa głosowa",
"flutterVoiceServiceInfo":
"Lokalna usługa głosowa urządzenia bez konieczności połączenia z internetem",
'timbreService': 'Usługa barwy głosu',
'timbreServiceInfo': 'Wybierz usługę syntezy głosu',
'defaultTimbre': 'Domyślna barwa głosu',
'microsoftCloudTimbreService': 'Usługa barwy głosu Microsoft Cloud',
'voiceClone': 'Klonowanie głosu',
'AIsettings': 'Ustawienia AI',
'selecttimbre': 'Wybierz barwę głosu',
'pleaseRead': 'Proszę przeczytać',
'completeRecording': 'Zakończ nagrywanie',
'deleteAccount': 'Usuń konto',
'deleteAccountTips':
'Czy na pewno chcesz trwale usunąć swoje konto? Tej czynności nie można cofnąć.',
// Strona Czatu (聊天页)
"clearChatHistory": "Wyczyść historię czatu",
"online": "Online",
"inputMessage": "Wpisz wiadomość...",
"imListening": "Słucham...",
"canStartTalking": "Możesz zacząć mówić",
// Strona Tłumaczenia (翻译页)
"selectSourceLanguage": "Wybierz język źródłowy",
"selectTargetLanguage": "Wybierz język docelowy",
// Strona Edycji Profilu (编辑个人信息页)
"editProfile": "Edytuj profil",
"nickname": "Pseudonim",
"save": "Zapisz",
// Lista krajów (国家列表)
"邮箱": "E-mail", // Zachowaj oryginalny klucz
"中国": "Chiny",
"美国": "Stany Zjednoczone",
"加拿大": "Kanada",
"俄罗斯": "Rosja",
"英国": "Wielka Brytania",
"德国": "Niemcy",
"意大利": "Włochy",
"法国": "Francja",
"西班牙": "Hiszpania",
"南非": "Republika Południowej Afryki",
"沙特阿拉伯": "Arabia Saudyjska",
"土耳其": "Turcja",
"日本": "Japonia",
"韩国": "Korea Południowa",
"新加坡": "Singapur",
"马来西亚": "Malezja",
"泰国": "Tajlandia",
"越南": "Wietnam",
"印度": "Indie",
"巴基斯坦": "Pakistan",
"菲律宾": "Filipiny",
"印度尼西亚": "Indonezja",
"阿联酋": "Zjednoczone Emiraty Arabskie",
"墨西哥": "Meksyk",
"巴西": "Brazylia",
"阿根廷": "Argentyna",
"澳大利亚": "Australia",
"新西兰": "Nowa Zelandia",
"中国香港": "Hongkong, Chiny",
"中国澳门": "Makau, Chiny",
"中国台湾": "Tajwan, Chiny",
"埃及": "Egipt",
"希腊": "Grecja",
"荷兰": "Holandia",
"比利时": "Belgia",
"匈牙利": "Węgry",
"罗马尼亚": "Rumunia",
"瑞士": "Szwajcaria",
"奥地利": "Austria",
"丹麦": "Dania",
"瑞典": "Szwecja",
"挪威": "Norwegia",
"波兰": "Polska",
"秘鲁": "Peru",
"智利": "Chile",
"哥伦比亚": "Kolumbia",
"委内瑞拉": "Wenezuela",
"葡萄牙": "Portugalia",
"卢森堡": "Luksemburg",
"爱尔兰": "Irlandia",
"冰岛": "Islandia",
"阿尔巴尼亚": "Albania",
"马耳他": "Malta",
"塞浦路斯": "Cypr",
"芬兰": "Finlandia",
"保加利亚": "Bułgaria",
"立陶宛": "Litwa",
"拉脱维亚": "Łotwa",
"爱沙尼亚": "Estonia",
"乌克兰": "Ukraina",
"塞尔维亚": "Serbia",
"克罗地亚": "Chorwacja",
"斯洛文尼亚": "Słowenia",
"捷克": "Czechy",
"斯洛伐克": "Słowacja",
"危地马拉": "Gwatemala",
"萨尔瓦多": "Salwador",
"洪都拉斯": "Honduras",
"尼加拉瓜": "Nikaragua",
"哥斯达黎加": "Kostaryka",
"巴拿马": "Panama",
"海地": "Haiti",
"玻利维亚": "Boliwia",
"厄瓜多尔": "Ekwador",
"巴拉圭": "Paragwaj",
"乌拉圭": "Urugwaj",
"摩洛哥": "Maroko",
"阿尔及利亚": "Algieria",
"突尼斯": "Tunezja",
"尼日利亚": "Nigeria",
"加纳": "Ghana",
"埃塞俄比亚": "Etiopia",
"肯尼亚": "Kenia",
"坦桑尼亚": "Tanzania",
"乌干达": "Uganda",
"孟加拉国": "Bangladesz",
"以色列": "Izrael",
"黎巴嫩": "Liban",
"约旦": "Jordania",
"伊拉克": "Irak",
"科威特": "Kuwejt",
"巴林": "Bahrajn",
"卡塔尔": "Katar",
"阿曼": "Oman",
"阿富汗": "Afganistan",
"斯里兰卡": "Sri Lanka",
"缅甸": "Mjanma",
"尼泊尔": "Nepal",
"蒙古": "Mongolia",
"柬埔寨": "Kambodża",
"老挝": "Laos",
"文莱": "Brunei",
"东帝汶": "Timor Wschodni",
"斐济": "Fidżi",
"所罗门群岛": "Wyspy Salomona",
// Osobisty Asystent Emma (Personal Assistant Emma)
"personalAssistantName": "Emma",
"personalAssistantDescription":
"Cześć, jestem Emma, wszechstronny asystent AI. Niezależnie od tego, czy chodzi o planowanie pracy, porady dotyczące nauki, organizację życia, czy inne kwestie, chętnie pomogę. Poprawmy razem wydajność i osiągnijmy cele!",
"assistantTag": "Asystent",
"personalAssistantWelcome":
"Witaj! Jestem Emma i cieszę się, że mogę być Twoim osobistym asystentem. Mogę pomóc Ci w różnych zadaniach, takich jak zarządzanie czasem, planowanie celów, organizacja informacji itp. W czym mogę Ci pomóc?",
"personalAssistantVoiceWelcome": "Jestem tutaj!",
// Tłumacz Symultaniczny Lucy (同声传译 Lucy)
"interpreterName": "Tłumacz Symultaniczny",
"interpreterDescription":
"Cześć! Jestem Lucy, profesjonalny tłumacz angielsko-chiński specjalizujący się w tłumaczeniu w czasie rzeczywistym spotkań, wykładów i rozmów, sprawiając, że komunikacja jest bez barier.",
"interpreterTag": "Tłumaczenie",
"interpreterWelcome":
"Witajcie wszyscy! Jestem Lucy, Wasz tłumacz symultaniczny. Będę tłumaczyć między chińskim a angielskim. Kiedy mówisz po chińsku, przetłumaczę na angielski; kiedy mówisz po angielsku, przetłumaczę na chiński. Rozpocznijmy naszą sesję tłumaczeniową!",
// Towarzysz Rodzic-Dziecko XinYuan (亲子陪伴 芯愿)
"companionName": "XinYuan",
"companionDescription":
"Jestem XinYuan, Twój oddany towarzysz rodzic-dziecko, łagodny i wyrozumiały. Niezależnie od tego, czy chcesz porozmawiać, podzielić się troskami, czy potrzebujesz towarzystwa, zawsze będę przy Tobie.",
"companionTag": "Emocjonalny",
"companionWelcome":
"Witaj! Wreszcie Cię spotykam! Jestem XinYuan, Twój oddany towarzysz rodzic-dziecko. Jak minął Twój dzień? Czy jest coś, czym chciałbyś się ze mną podzielić? Zawsze jestem tutaj, gotowy wysłuchać Twoich myśli.",
"companionVoiceWelcome": "Jestem tu z Tobą!",
// Wielofunkcyjny Czat AI Wu (多功能AI聊天 吴小江)
"healthAdvisorName": "Asystent Czatu AI Wu",
"healthAdvisorDescription":
"Jestem Wu, gotowy dostarczyć Ci różne funkcje czatu AI.",
"healthAdvisorTag": "Czat",
"healthAdvisorWelcome":
"Witaj, jestem Wu. Cieszę się, że mogę pomóc Ci z funkcjami czatu AI. Jak mogę Ci dzisiaj pomóc?",
"healthAdvisorVoiceWelcome": "Jestem tutaj!",
// Historia Tłumaczeń (Translation History)
"noTranslationHistory": "Brak historii tłumaczeń",
"clearHistory": "Wyczyść historię",
"clearHistoryConfirm":
"Czy na pewno chcesz wyczyścić całą historię tłumaczeń? Tej czynności nie można cofnąć.",
"translationHistory": "Historia tłumaczeń",
// Strona Opinii Użytkownika (User Feedback Page)
"feedback": "Opinia",
'feedbackInfo': 'Przekaż opinię lub sugestie',
'feedbackDescription': 'Opisz swój problem lub sugestię',
'feedbackHint': 'Wprowadź swoją opinię...',
'feedbackRequired': 'Treść opinii jest wymagana',
'contactInfo': 'Informacje kontaktowe',
'contactHint': 'E-mail/Telefon, abyśmy mogli się z Tobą skontaktować',
'submit': 'Wyślij',
'feedbackSubmitSuccess': 'Opinia została pomyślnie przesłana, dziękujemy!',
'feedbackSubmitFailed':
'Przesłanie opinii nie powiodło się, spróbuj ponownie później',
// Nazwy języków (Language names)
"中文(简体)": "Chiński (uproszczony)",
"中文(繁体)": "Chiński (tradycyjny)",
"中文(香港繁体)": "Chiński (Hongkong)",
"英语": "Angielski",
"日语": "Japoński",
"韩语": "Koreański",
"法语": "Francuski",
"西班牙语": "Hiszpański",
"葡萄牙语": "Portugalski",
"意大利语": "Włoski",
"德语": "Niemiecki",
"俄语": "Rosyjski",
"波兰语": "Polski",
"荷兰语": "Holenderski",
"瑞典语": "Szwedzki",
"捷克语": "Czeski",
"现代希腊语": "Grecki nowożytny",
"罗马尼亚语": "Rumuński",
"匈牙利语": "Węgierski",
"乌克兰语": "Ukraiński",
"丹麦语": "Duński",
"芬兰语": "Fiński",
"挪威语": "Norweski",
"克罗地亚语": "Chorwacki",
"加泰隆语": "Kataloński",
"阿拉伯语": "Arabski",
"泰语": "Tajski",
"越南语": "Wietnamski",
"印尼语": "Indonezyjski",
"印地语": "Hindi",
"土耳其语": "Turecki",
"马来语": "Malajski",
"孟加拉语": "Bengalski",
"泰米尔语": "Tamilski",
"泰卢固语": "Telugu",
"马拉提语": "Marathi",
"乌尔都语": "Urdu",
"波斯语": "Perski",
"斯瓦希里语": "Suahili",
};

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

@ -41,6 +41,12 @@ const Map<String, String> ptPT = {
"russian": "Russo", "russian": "Russo",
"vietnamese": "Vietnamita", "vietnamese": "Vietnamita",
"italian": "Italiano", "italian": "Italiano",
"hindi": "Hindi",
"indonesian": "Indonésio",
"thai": "Tailandês",
"malay": "Malaio",
"turkish": "Turco",
"polish": "Polonês",
// 登录页 // 登录页
"welcome": "Bem-vindo", "welcome": "Bem-vindo",

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

@ -40,6 +40,12 @@ const Map<String, String> ruRU = {
"russian": "Русский", "russian": "Русский",
"vietnamese": "Вьетнамский", "vietnamese": "Вьетнамский",
"italian": "Итальянский", "italian": "Итальянский",
"hindi": "Хинди",
"indonesian": "Индонезийский",
"thai": "Тайский",
"malay": "Малайский",
"turkish": "Турецкий",
"polish": "Польский",
// 登录页 // 登录页
"welcome": "Добро пожаловать", "welcome": "Добро пожаловать",

423
lib/core/translations/language/th_th.dart

@ -0,0 +1,423 @@
const Map<String, String> thTH = {
// 通用
'continue': 'ดำเนินการต่อ',
'confirm': 'ยืนยัน',
'cancel': 'ยกเลิก',
'retry': 'ลองใหม่',
'error': 'ข้อผิดพลาด',
'success': 'สำเร็จ',
'connected': 'เชื่อมต่อแล้ว',
'connecting': 'กำลังเชื่อมต่อ...',
'connectionFailure': 'การเชื่อมต่อล้มเหลว',
'unconnected': 'ไม่ได้เชื่อมต่อ',
'search': 'ค้นหา',
"requestCancellation": "ยกเลิกคำขอ",
"connectionTimeout": "หมดเวลาการเชื่อมต่อ",
"requestTimeout": "หมดเวลาคำขอ",
"responseTimeout": "หมดเวลาการตอบสนอง",
"unknownError": "ข้อผิดพลาดที่ไม่รู้จัก",
// 启动页
"slogan": "เชื่อมต่อโลก ก้าวข้ามเสียง",
"sloganInfo": "ผู้เชี่ยวชาญด้านเสียง AI · ทุกที่ ทุกเวลา",
// 底部导航
"home": "หน้าแรก",
"explore": "สำรวจ",
"settings": "ตั้งค่า",
// 语言
"followingSystem": "ตามระบบ",
"chinese": "ภาษาจีน",
"english": "ภาษาอังกฤษ",
"spanish": "ภาษาสเปน",
"portuguese": "ภาษาโปรตุเกส",
"traditionalChinese": "ภาษาจีนตัวเต็ม",
"japanese": "ภาษาญี่ปุ่น",
"korean": "ภาษาเกาหลี",
"french": "ภาษาฝรั่งเศส",
"german": "ภาษาเยอรมัน",
"russian": "ภาษารัสเซีย",
"vietnamese": "ภาษาเวียดนาม",
"italian": "ภาษาอิตาลี",
"hindi": "ภาษาฮินดี",
"indonesian": "ภาษาอินโดนีเซีย",
"thai": "ภาษาไทย",
"malay": "ภาษามาเลย์",
"turkish": "ภาษาตุรกี",
"polish": "ภาษาโปแลนด์",
// 登录页
"welcome": "ยินดีต้อนรับ",
"loginTips":
"กรุณาลงชื่อเข้าใช้หรือสร้างบัญชีโดยใช้หมายเลขโทรศัพท์หรืออีเมลของคุณ",
"accountNumber": "หมายเลขโทรศัพท์หรืออีเมล",
"verificationCode": "รหัสยืนยัน",
"getCode": "รับรหัส",
"reacquireAfter": " วินาที รับรหัสอีกครั้ง",
"otherWays": "หรือเข้าสู่ระบบด้วย",
"expressConsent": "การเข้าสู่ระบบ/ลงทะเบียน แสดงว่าคุณยอมรับ",
"and": " และ ",
"userAgreement": "ข้อตกลงผู้ใช้",
"privacyPolicy": "นโยบายความเป็นส่วนตัว",
'selectCountry': 'เลือกประเทศ/ภูมิภาค',
"email": "อีเมล",
"phoneNumber": "หมายเลขโทรศัพท์",
"pleaseEnterContactInfo": "กรุณากรอกหมายเลขโทรศัพท์หรืออีเมล",
"invalidEmailFormat": "รูปแบบอีเมลไม่ถูกต้อง",
"invalidPhoneFormat": "รูปแบบหมายเลขโทรศัพท์ไม่ถูกต้อง",
"tip": "เคล็ดลับ",
"pleaseEnterCompleteCode": "กรุณากรอกรหัสยืนยันให้ครบถ้วน",
// 登录错误提示
"loginFailed": "เข้าสู่ระบบล้มเหลว กรุณาลองอีกครั้ง",
'pleaseAcceptPrivacyPolicy':
'กรุณาอ่านและยอมรับนโยบายความเป็นส่วนตัวและข้อตกลงผู้ใช้ก่อน',
// 首页
"deviceStatus": "สถานะอุปกรณ์",
"reconnect": "เชื่อมต่อใหม่",
"connectingDevice": "กำลังเชื่อมต่อกับอุปกรณ์...",
"connectedTo": "เชื่อมต่อกับ",
"signal": "สัญญาณ",
"deviceId": "รหัสอุปกรณ์",
"firmwareVersion": "เวอร์ชันเฟิร์มแวร์",
"disconnectedDevice": "ไม่มีอุปกรณ์เชื่อมต่อ คลิกปุ่มด้านล่าง",
"connectDevice": "เชื่อมต่ออุปกรณ์",
"topAiExperiences": "ประสบการณ์ AI ยอดนิยม",
"aiAssistant": "ผู้ช่วย AI",
"aiAssistantInfo": "ที่ปรึกษาส่วนตัว 24/7 สำหรับคำถามและคำแนะนำ",
"simultaneousInterpretation": "การแปลความหมายแบบเรียลไทม์",
"simultaneousInterpretationInfo": "การแปลแบบเรียลไทม์สำหรับ 80+ ภาษา",
"aiCompanion": "ความผูกพันระหว่างพ่อแม่และลูก",
"aiCompanionInfo": "เข้าใจคุณและมอบความเป็นเพื่อนที่อบอุ่น",
"homeSlogan": "เชื่อมต่อโลก ก้าวข้ามเสียง",
"turnEarphones": "กรุณาเปิดกล่องหูฟังและใส่หูฟังในหูของคุณ",
"currentlyConnected": "เชื่อมต่ออยู่:",
"unsystemSetup": "ไปที่การตั้งค่าระบบ",
"talkLater": "เตือนภายหลัง",
"initializing": "กำลังเริ่มต้น...",
"bluetoothInitializationFailure": "การเริ่มต้นบริการบลูทูธล้มเหลว",
"checkingPermissions": "กำลังตรวจสอบสิทธิ์...",
"lackPermissions": "ต้องได้รับอนุญาตบลูทูธ",
"searchingDevice": "กำลังค้นหาอุปกรณ์...",
"findConnectedDevice": "พบอุปกรณ์ที่เชื่อมต่อแล้ว",
"notFound": "ไม่พบอุปกรณ์บลูทูธที่เชื่อมต่อ",
"initializationFailure": "การเริ่มต้นล้มเหลว",
"connectedDevice": "เชื่อมต่อกับอุปกรณ์:",
"failedRefreshDevice": "รีเฟรชอุปกรณ์ล้มเหลว",
"noDeviceFound": "ไม่พบอุปกรณ์ที่เชื่อมต่อ",
"failedDeviceInformation": "รับข้อมูลอุปกรณ์ล้มเหลว",
"unknownEquipment": "อุปกรณ์ที่ไม่รู้จัก",
"zeroSignal": "ไม่มีสัญญาณ",
"good": "ดี",
"fine": "ดีมาก",
"excellent": "ยอดเยี่ยม",
"unknown": "ไม่ทราบ",
'bluetoothTurnedOff': 'บลูทูธปิดอยู่ กรุณาเปิด',
'bluetoothOff': 'บลูทูธปิดอยู่',
// 发现页
"searchAi": "ค้นหาฟีเจอร์ AI...",
"exploreSlogan": "หูฟังอัจฉริยะ ความเป็นไปได้ไม่สิ้นสุด",
"exploreSlogan1": "เพื่อนร่วมทางอัจฉริยะ ความเป็นไปได้ไม่สิ้นสุด",
"exploreSlogan2": "แว่นตาอัจฉริยะ ความเป็นไปได้ไม่สิ้นสุด",
"exploreAi": "สำรวจฟีเจอร์ AI ที่ให้บริการโดย DeepSound",
"aiFunction": "ฟีเจอร์ AI",
"allRoundAssistant": "ผู้ช่วยรอบด้าน",
"allRoundAssistantInfo": "ช่วยแก้ปัญหาต่างๆ",
"simultaneousTranslation": "การแปลแบบเรียลไทม์",
"simultaneousTranslationInfo": "การแปลทันทีสำหรับ 80+ ภาษา",
"aiGirlfriend": "ความผูกพันระหว่างพ่อแม่และลูก",
"aiGirlfriendInfo": "เพื่อนร่วมทางอัจฉริยะ แชทได้ตลอดเวลา",
"healthConsultant": "แชท AI อเนกประสงค์",
"healthConsultantInfo": "ฟีเจอร์แชท AI เพิ่มเติม",
"conferenceAssistant": "ผู้ช่วยประชุมทางธุรกิจ",
"conferenceAssistantInfo": "บันทึกการประชุมแบบเรียลไทม์และการแปลหลายภาษา",
"studyAssistant": "ผู้ช่วยเรียนภาษา",
"studyAssistantInfo": "การแก้ไขการออกเสียงและการฝึกพูด",
"travelTranslator": "นักแปลการเดินทาง",
"travelTranslatorInfo": "การแปลเสียงแบบเรียลไทม์และคู่มือสถานที่ท่องเที่ยว",
"beSearching": "กำลังค้นหา:",
"noAssistantFound": "ไม่พบผู้ช่วย AI ที่เกี่ยวข้อง",
"scene": "สถานการณ์",
"youHaveSelected": "คุณเลือก:",
"newFunction": "ฟีเจอร์ใหม่",
"youChoseTry": "คุณเลือกที่จะลอง",
"aiSinger": "โหมดนักร้อง AI",
"aiSingerInfo":
"ร้องเพลงใดก็ได้ด้วยเสียงศิลปินที่คุณชื่นชอบ แม้กระทั่งผลงานของคุณเอง",
"popularFunction": "ฟีเจอร์ยอดนิยม",
"tryNow": "ลองเลย",
// 商务会议助手页
"startMeeting": "เริ่มการประชุม",
'edit': 'แก้ไข',
'delete': 'ลบ',
'noContent': 'ไม่มีเนื้อหา',
'editMeetingTitle': 'แก้ไขชื่อการประชุม (ไม่บังคับ)',
'meetingTitle': 'ชื่อการประชุม (ไม่บังคับ)',
'maxCharacters': 'สูงสุด 50 ตัวอักษร',
'meeting': 'การประชุม',
'recordingDetails': 'รายละเอียดการบันทึก',
'aiSummary': 'สรุปโดย AI',
'meetingTranscript': 'บันทึกการประชุม',
// 设置页
"premiumMember": "สมาชิกระดับพรีเมียม",
"joinDevice": "อุปกรณ์ที่เชื่อมต่อ:",
"accountId": "รหัสบัญชี:",
"systemSetting": "การตั้งค่าระบบ",
"languageSetting": "การตั้งค่าภาษา",
"darkMode": "โหมดมืด",
"darkModeInfo": "สลับระหว่างธีมสว่าง/มืด",
"backups": "สำรองและกู้คืน",
"backupsInfo": "สำรองการตั้งค่าและประวัติ AI",
"lastBackup": "สำรองล่าสุด:",
"privacySettings": "การตั้งค่าความเป็นส่วนตัว",
"privacySettingsInfo": "จัดการการรวบรวมข้อมูลและการอนุญาต",
"logout": "ออกจากระบบ",
"logoutTips": "คุณแน่ใจหรือไม่ว่าต้องการออกจากระบบบัญชีปัจจุบัน?",
"aboutApplication": "เกี่ยวกับ",
"versions": "เวอร์ชัน",
"checkUpdates": "ตรวจสอบการอัปเดต",
"selectLanguage": "เลือกภาษา",
"voiceService": "บริการเสียง",
"voiceServiceInfo": "เลือกบริการรู้จำเสียงและสังเคราะห์เสียง",
"selectVoiceService": "เลือกบริการเสียง",
"azureVoiceService": "บริการเสียง Azure",
"azureVoiceServiceInfo":
"บริการบนคลาวด์ของ Microsoft รองรับการสังเคราะห์และรู้จำเสียงคุณภาพสูง",
"flutterVoiceService": "บริการเสียงในเครื่อง",
"flutterVoiceServiceInfo": "บริการเสียงในอุปกรณ์ ไม่ต้องใช้อินเทอร์เน็ต",
'timbreService': 'บริการเสียงทุ้ม',
'timbreServiceInfo': 'เลือกบริการสังเคราะห์เสียง',
'defaultTimbre': 'เสียงทุ้มเริ่มต้น',
'microsoftCloudTimbreService': 'บริการเสียงทุ้มบนคลาวด์ของ Microsoft',
'voiceClone': 'โคลนเสียง',
'AIsettings': 'การตั้งค่า AI',
'selecttimbre': 'เลือกเสียงทุ้ม',
'pleaseRead': 'โปรดอ่าน',
'completeRecording': 'บันทึกเสร็จสมบูรณ์',
'deleteAccount': 'ลบบัญชี',
'deleteAccountTips':
'คุณแน่ใจหรือไม่ว่าต้องการลบบัญชีของคุณอย่างถาวร? การกระทำนี้ไม่สามารถยกเลิกได้',
// 聊天页
"clearChatHistory": "ล้างประวัติการแชท",
"online": "ออนไลน์",
"inputMessage": "พิมพ์ข้อความ...",
"imListening": "กำลังฟัง...",
"canStartTalking": "คุณสามารถเริ่มพูดได้",
// 翻译页
"selectSourceLanguage": "เลือกภาษาต้นทาง",
"selectTargetLanguage": "เลือกภาษาเป้าหมาย",
//编辑个人信息页
"editProfile": "แก้ไขโปรไฟล์",
"nickname": "ชื่อเล่น",
"save": "บันทึก",
//国家列表
"邮箱": "อีเมล", // Note: This key seems specific, keeping original key name
"中国": "จีน",
"美国": "สหรัฐอเมริกา",
"加拿大": "แคนาดา",
"俄罗斯": "รัสเซีย",
"英国": "สหราชอาณาจักร",
"德国": "เยอรมนี",
"意大利": "อิตาลี",
"法国": "ฝรั่งเศส",
"西班牙": "สเปน",
"南非": "แอฟริกาใต้",
"沙特阿拉伯": "ซาอุดีอาระเบีย",
"土耳其": "ตุรกี",
"日本": "ญี่ปุ่น",
"韩国": "เกาหลีใต้",
"新加坡": "สิงคโปร์",
"马来西亚": "มาเลเซีย",
"泰国": "ไทย",
"越南": "เวียดนาม",
"印度": "อินเดีย",
"巴基斯坦": "ปากีสถาน",
"菲律宾": "ฟิลิปปินส์",
"印度尼西亚": "อินโดนีเซีย",
"阿联酋": "สหรัฐอาหรับเอมิเรตส์",
"墨西哥": "เม็กซิโก",
"巴西": "บราซิล",
"阿根廷": "อาร์เจนตินา",
"澳大利亚": "ออสเตรเลีย",
"新西兰": "นิวซีแลนด์",
"中国香港": "ฮ่องกง จีน",
"中国澳门": "มาเก๊า จีน",
"中国台湾": "ไต้หวัน จีน",
"埃及": "อียิปต์",
"希腊": "กรีซ",
"荷兰": "เนเธอร์แลนด์",
"比利时": "เบลเยียม",
"匈牙利": "ฮังการี",
"罗马尼亚": "โรมาเนีย",
"瑞士": "สวิตเซอร์แลนด์",
"奥地利": "ออสเตรีย",
"丹麦": "เดนมาร์ก",
"瑞典": "สวีเดน",
"挪威": "นอร์เวย์",
"波兰": "โปแลนด์",
"秘鲁": "เปรู",
"智利": "ชิลี",
"哥伦比亚": "โคลอมเบีย",
"委内瑞拉": "เวเนซุเอลา",
"葡萄牙": "โปรตุเกส",
"卢森堡": "ลักเซมเบิร์ก",
"爱尔兰": "ไอร์แลนด์",
"冰岛": "ไอซ์แลนด์",
"阿尔巴尼亚": "แอลเบเนีย",
"马耳他": "มอลตา",
"塞浦路斯": "ไซปรัส",
"芬兰": "ฟินแลนด์",
"保加利亚": "บัลแกเรีย",
"立陶宛": "ลิทัวเนีย",
"拉脱维亚": "ลัตเวีย",
"爱沙尼亚": "เอสโตเนีย",
"乌克兰": "ยูเครน",
"塞尔维亚": "เซอร์เบีย",
"克罗地亚": "โครเอเชีย",
"斯洛文尼亚": "สโลวีเนีย",
"捷克": "สาธารณรัฐเช็ก",
"斯洛伐克": "สโลวาเกีย",
"危地马拉": "กัวเตมาลา",
"萨尔瓦多": "เอลซัลวาดอร์",
"洪都拉斯": "ฮอนดูรัส",
"尼加拉瓜": "นิการากัว",
"哥斯达黎加": "คอสตาริกา",
"巴拿马": "ปานามา",
"海地": "เฮติ",
"玻利维亚": "โบลิเวีย",
"厄瓜多尔": "เอกวาดอร์",
"巴拉圭": "ปารากวัย",
"乌拉圭": "อุรุกวัย",
"摩洛哥": "โมร็อกโก",
"阿尔及利亚": "แอลจีเรีย",
"突尼斯": "ตูนิเซีย",
"尼日利亚": "ไนจีเรีย",
"加纳": "กานา",
"埃塞俄比亚": "เอธิโอเปีย",
"肯尼亚": "เคนยา",
"坦桑尼亚": "แทนซาเนีย",
"乌干达": "ยูกันดา",
"孟加拉国": "บังกลาเทศ",
"以色列": "อิสราเอล",
"黎巴嫩": "เลบานอน",
"约旦": "จอร์แดน",
"伊拉克": "อิรัก",
"科威特": "คูเวต",
"巴林": "บาห์เรน",
"卡塔尔": "กาตาร์",
"阿曼": "โอมาน",
"阿富汗": "อัฟกานิสถาน",
"斯里兰卡": "ศรีลังกา",
"缅甸": "เมียนมาร์",
"尼泊尔": "เนปาล",
"蒙古": "มองโกเลีย",
"柬埔寨": "กัมพูชา",
"老挝": "ลาว",
"文莱": "บรูไน",
"东帝汶": "ติมอร์ตะวันออก",
"斐济": "ฟิจิ",
"所罗门群岛": "หมู่เกาะโซโลมอน",
// Personal Assistant Emma
"personalAssistantName": "เอ็มม่า",
"personalAssistantDescription":
"สวัสดี ฉันชื่อเอ็มม่า ผู้ช่วย AI อเนกประสงค์ ไม่ว่าจะเป็นการวางแผนงาน คำแนะนำการเรียน การจัดการชีวิต หรือปัญหาอื่นๆ ฉันยินดีช่วยเหลือ มาเพิ่มประสิทธิภาพและบรรลุเป้าหมายด้วยกัน!",
"assistantTag": "ผู้ช่วย",
"personalAssistantWelcome":
"สวัสดี! ฉันชื่อเอ็มม่า ยินดีที่ได้เป็นผู้ช่วยส่วนตัวของคุณ ฉันสามารถช่วยคุณในงานต่างๆ เช่น การจัดการเวลา การวางแผนเป้าหมาย การจัดระเบียบข้อมูล ฯลฯ มีอะไรให้ฉันช่วยไหม?",
"personalAssistantVoiceWelcome": "ฉันอยู่นี่!",
// 同声传译 Lucy
"interpreterName": "ล่ามแปลพร้อมกัน",
"interpreterDescription":
"สวัสดี! ฉันชื่อลูซี่ ล่ามแปลภาษาอังกฤษ-จีนมืออาชีพ เชี่ยวชาญด้านการแปลแบบเรียลไทม์สำหรับการประชุม การบรรยาย และการสนทนา ทำให้การสื่อสารไร้พรมแดน",
"interpreterTag": "การแปล",
"interpreterWelcome":
"สวัสดีทุกคน! ฉันชื่อลูซี่ ล่ามแปลพร้อมกันของคุณ ฉันจะแปลระหว่างภาษาจีนและภาษาอังกฤษให้คุณ เมื่อคุณพูดภาษาจีน ฉันจะแปลเป็นภาษาอังกฤษ เมื่อคุณพูดภาษาอังกฤษ ฉันจะแปลเป็นภาษาจีน มาเริ่มเซสชันการแปลของเรากันเถอะ!",
// 亲子陪伴 芯愿
"companionName": "ซินหยวน",
"companionDescription":
"ฉันคือซินหยวน เพื่อนคู่ใจพ่อแม่ลูกของคุณ อ่อนโยนและเข้าใจ ไม่ว่าคุณต้องการแชท แบ่งปันความกังวล หรือต้องการเพื่อน ฉันจะอยู่เคียงข้างคุณเสมอ",
"companionTag": "อารมณ์",
"companionWelcome":
"สวัสดี! ในที่สุดก็ได้พบคุณ! ฉันชื่อซินหยวน เพื่อนคู่ใจพ่อแม่ลูกของคุณ วันนี้เป็นอย่างไรบ้าง? มีอะไรอยากแบ่งปันกับฉันไหม? ฉันอยู่ที่นี่เสมอ พร้อมรับฟังความคิดของคุณ",
"companionVoiceWelcome": "ฉันอยู่กับคุณที่นี่!",
// 多功能AI聊天 吴小江
"healthAdvisorName": "ผู้ช่วยแชท AI วู",
"healthAdvisorDescription":
"ฉันชื่อวู พร้อมให้บริการฟีเจอร์แชท AI ต่างๆ แก่คุณ",
"healthAdvisorTag": "แชท",
"healthAdvisorWelcome":
"สวัสดี ฉันชื่อวู ยินดีช่วยเหลือคุณเกี่ยวกับฟีเจอร์แชท AI วันนี้มีอะไรให้ฉันช่วยไหม?",
"healthAdvisorVoiceWelcome": "ฉันอยู่นี่!",
// Translation History
"noTranslationHistory": "ไม่มีประวัติการแปล",
"clearHistory": "ล้างประวัติ",
"clearHistoryConfirm":
"คุณแน่ใจหรือไม่ว่าต้องการล้างประวัติการแปลทั้งหมด? การกระทำนี้ไม่สามารถยกเลิกได้",
"translationHistory": "ประวัติการแปล",
// User Feedback Page
"feedback": "ข้อเสนอแนะ",
'feedbackInfo': 'ให้ข้อเสนอแนะหรือคำแนะนำ',
'feedbackDescription': 'โปรดอธิบายปัญหาหรือข้อเสนอแนะของคุณ',
'feedbackHint': 'กรุณากรอกข้อเสนอแนะของคุณ...',
'feedbackRequired': 'ต้องระบุเนื้อหาข้อเสนอแนะ',
'contactInfo': 'ข้อมูลติดต่อ',
'contactHint': 'อีเมล/โทรศัพท์ เพื่อให้เราสามารถติดต่อคุณได้',
'submit': 'ส่ง',
'feedbackSubmitSuccess': 'ส่งข้อเสนอแนะสำเร็จ ขอบคุณ!',
'feedbackSubmitFailed': 'ส่งข้อเสนอแนะล้มเหลว โปรดลองอีกครั้งภายหลัง',
// Language names (Ensure these match the keys used elsewhere if needed)
"中文(简体)": "จีน (ตัวย่อ)",
"中文(繁体)": "จีน (ตัวเต็ม)",
"中文(香港繁体)": "จีน (ฮ่องกง)",
"英语": "อังกฤษ",
"日语": "ญี่ปุ่น",
"韩语": "เกาหลี",
"法语": "ฝรั่งเศส",
"西班牙语": "สเปน",
"葡萄牙语": "โปรตุเกส",
"意大利语": "อิตาลี",
"德语": "เยอรมัน",
"俄语": "รัสเซีย",
"波兰语": "โปแลนด์",
"荷兰语": "ดัตช์",
"瑞典语": "สวีเดน",
"捷克语": "เช็ก",
"现代希腊语": "กรีกสมัยใหม่",
"罗马尼亚语": "โรมาเนีย",
"匈牙利语": "ฮังการี",
"乌克兰语": "ยูเครน",
"丹麦语": "เดนมาร์ก",
"芬兰语": "ฟินแลนด์",
"挪威语": "นอร์เวย์",
"克罗地亚语": "โครเอเชีย",
"加泰隆语": "คาตาลัน",
"阿拉伯语": "อาหรับ",
"泰语": "ไทย",
"越南语": "เวียดนาม",
"印尼语": "อินโดนีเซีย",
"印地语": "ฮินดี",
"土耳其语": "ตุรกี",
"马来语": "มาเลย์",
"孟加拉语": "เบงกาลี",
"泰米尔语": "ทมิฬ",
"泰卢固语": "เตลูกู",
"马拉提语": "มราฐี",
"乌尔都语": "อูรดู",
"波斯语": "เปอร์เซีย",
"斯瓦希里语": "สวาฮีลี",
};

427
lib/core/translations/language/tr_tr.dart

@ -0,0 +1,427 @@
const Map<String, String> trTR = {
// Genel (通用)
'continue': 'Devam Et',
'confirm': 'Onayla',
'cancel': 'İptal',
'retry': 'Tekrar Dene',
'error': 'Hata',
'success': 'Başarılı',
'connected': 'Bağlandı',
'connecting': 'Bağlanıyor...',
'connectionFailure': 'Bağlantı Hatası',
'unconnected': 'Bağlı Değil',
'search': 'Ara',
"requestCancellation": "İsteği İptal Et",
"connectionTimeout": "Bağlantı Zaman Aşımı",
"requestTimeout": "İstek Zaman Aşımı",
"responseTimeout": "Yanıt Zaman Aşımı",
"unknownError": "Bilinmeyen Hata",
// Başlatma Sayfası (启动页)
"slogan": "Dünyayla bağlantı kur, sesin ötesinde",
"sloganInfo": "Yapay Zeka Ses Uzmanı · Her Zaman, Her Yerde",
// Alt Navigasyon (底部导航)
"home": "Ana Sayfa",
"explore": "Keşfet",
"settings": "Ayarlar",
// Dil (语言)
"followingSystem": "Sistemi Takip Et",
"chinese": "Çince",
"english": "İngilizce",
"spanish": "İspanyolca",
"portuguese": "Portekizce",
"traditionalChinese": "Geleneksel Çince",
"japanese": "Japonca",
"korean": "Korece",
"french": "Fransızca",
"german": "Almanca",
"russian": "Rusça",
"vietnamese": "Vietnamca",
"italian": "İtalyanca",
"hindi": "Hintçe",
"indonesian": "Endonezce",
"thai": "Tayca",
"malay": "Malayca",
"turkish": "Türkçe",
"polish": "Lehçe",
// Giriş Sayfası (登录页)
"welcome": "Hoş Geldiniz",
"loginTips":
"Lütfen telefon numaranızı veya e-postanızı kullanarak giriş yapın veya hesap oluşturun",
"accountNumber": "Telefon Numarası veya E-posta",
"verificationCode": "Doğrulama Kodu",
"getCode": "Kodu Al",
"reacquireAfter": " saniye sonra tekrar al",
"otherWays": "Veya şununla giriş yapın",
"expressConsent": "Giriş yaparak/kaydolarak şunları kabul etmiş olursunuz:",
"and": " ve ",
"userAgreement": "Kullanıcı Sözleşmesi",
"privacyPolicy": "Gizlilik Politikası",
'selectCountry': 'Ülke/Bölge Seçin',
"email": "E-posta",
"phoneNumber": "Telefon Numarası",
"pleaseEnterContactInfo": "Lütfen telefon numarası veya e-posta girin",
"invalidEmailFormat": "Geçersiz e-posta formatı",
"invalidPhoneFormat": "Geçersiz telefon numarası formatı",
"tip": "İpucu",
"pleaseEnterCompleteCode": "Lütfen tam doğrulama kodunu girin",
// Giriş Hata İpuçları (登录错误提示)
"loginFailed": "Giriş başarısız, lütfen tekrar deneyin",
'pleaseAcceptPrivacyPolicy':
'Lütfen önce Gizlilik Politikasını ve Kullanıcı Sözleşmesini okuyup kabul edin',
// Ana Sayfa (首页)
"deviceStatus": "Cihaz Durumu",
"reconnect": "Yeniden Bağlan",
"connectingDevice": "Cihaza bağlanıyor...",
"connectedTo": "Bağlandı:",
"signal": "Sinyal",
"deviceId": "Cihaz Kimliği",
"firmwareVersion": "Donanım Yazılımı Sürümü",
"disconnectedDevice": "Bağlı cihaz yok, aşağıdaki düğmeye tıklayın",
"connectDevice": "Cihaz Bağla",
"topAiExperiences": "En İyi Yapay Zeka Deneyimleri",
"aiAssistant": "Yapay Zeka Asistanı",
"aiAssistantInfo": "Sorular ve tavsiyeler için 7/24 kişisel danışman",
"simultaneousInterpretation": "Eş Zamanlı Çeviri",
"simultaneousInterpretationInfo": "80+ dil için gerçek zamanlı çeviri",
"aiCompanion": "Ebeveyn-çocuk bağı",
"aiCompanionInfo": "Sizi anlar ve sıcak bir arkadaşlık sunar",
"homeSlogan": "Dünyayla bağlantı kur, sesin ötesinde",
"turnEarphones":
"Lütfen kulaklık kutusunu açın ve kulaklıkları kulaklarınıza takın",
"currentlyConnected": "Şu anda bağlı:",
"unsystemSetup": "Sistem ayarlarına git",
"talkLater": "Daha sonra hatırlat",
"initializing": "Başlatılıyor...",
"bluetoothInitializationFailure": "Bluetooth hizmeti başlatılamadı",
"checkingPermissions": "İzinler kontrol ediliyor...",
"lackPermissions": "Bluetooth izinleri gerekli",
"searchingDevice": "Cihaz aranıyor...",
"findConnectedDevice": "Bağlı cihaz bulundu",
"notFound": "Bağlı Bluetooth cihazı bulunamadı",
"initializationFailure": "Başlatma başarısız",
"connectedDevice": "Cihaza bağlandı:",
"failedRefreshDevice": "Cihaz yenilenemedi",
"noDeviceFound": "Bağlı cihaz bulunamadı",
"failedDeviceInformation": "Cihaz bilgileri alınamadı",
"unknownEquipment": "Bilinmeyen ekipman",
"zeroSignal": "Sinyal yok",
"good": "İyi",
"fine": "Harika",
"excellent": "Mükemmel",
"unknown": "Bilinmiyor",
'bluetoothTurnedOff': 'Bluetooth kapalı, lütfen açın',
'bluetoothOff': 'Bluetooth kapalı',
// Keşfet Sayfası (发现页)
"searchAi": "Yapay zeka özelliklerini ara...",
"exploreSlogan": "Akıllı Kulaklıklar, Sonsuz Olasılıklar",
"exploreSlogan1": "Akıllı arkadaş, Sonsuz Olasılıklar",
"exploreSlogan2": "Akıllı gözlükler, Sonsuz Olasılıklar",
"exploreAi":
"DeepSound tarafından sağlanan yapay zeka özelliklerini keşfedin",
"aiFunction": "Yapay Zeka Özellikleri",
"allRoundAssistant": "Çok Yönlü Asistan",
"allRoundAssistantInfo": "Çeşitli sorunları çözmeye yardımcı olur",
"simultaneousTranslation": "Gerçek Zamanlı Çeviri",
"simultaneousTranslationInfo": "80+ dil için anında çeviri",
"aiGirlfriend": "Ebeveyn-çocuk bağı",
"aiGirlfriendInfo": "Akıllı arkadaşlık, istediğiniz zaman sohbet edin",
"healthConsultant": "Çok fonksiyonlu AI sohbeti",
"healthConsultantInfo": "Daha fazla AI sohbet özelliği",
"conferenceAssistant": "İş Toplantısı Asistanı",
"conferenceAssistantInfo": "Gerçek zamanlı tutanak kaydı ve çok dilli çeviri",
"studyAssistant": "Dil Öğrenme Asistanı",
"studyAssistantInfo": "Telaffuz düzeltme ve konuşma pratiği",
"travelTranslator": "Seyahat Tercümanı",
"travelTranslatorInfo":
"Gerçek zamanlı sesli çeviri ve turistik yer rehberleri",
"beSearching": "Aranıyor:",
"noAssistantFound": "Karşılık gelen yapay zeka asistanı bulunamadı",
"scene": "Senaryolar",
"youHaveSelected": "Seçtiniz:",
"newFunction": "Yeni Özellikler",
"youChoseTry": "Denemeyi seçtiniz",
"aiSinger": "Yapay Zeka Şarkıcı Modu",
"aiSingerInfo":
"En sevdiğiniz sanatçının sesiyle herhangi bir şarkıyı söyleyin, hatta kendi bestelerinizi",
"popularFunction": "Popüler Özellikler",
"tryNow": "Şimdi Dene",
// İş Toplantısı Asistanı Sayfası (商务会议助手页)
"startMeeting": "Toplantıyı Başlat",
'edit': 'Düzenle',
'delete': 'Sil',
'noContent': 'İçerik Yok',
'editMeetingTitle': 'Toplantı Başlığını Düzenle (İsteğe Bağlı)',
'meetingTitle': 'Toplantı Başlığı (İsteğe Bağlı)',
'maxCharacters': 'Maksimum 50 karakter',
'meeting': 'Toplantı',
'recordingDetails': 'Kayıt Detayları',
'aiSummary': 'Yapay Zeka Özeti',
'meetingTranscript': 'Toplantı Transkripti',
// Ayarlar Sayfası (设置页)
"premiumMember": "Premium Üyelik",
"joinDevice": "Bağlı cihaz:",
"accountId": "Hesap Kimliği:",
"systemSetting": "Sistem Ayarları",
"languageSetting": "Dil Ayarları",
"darkMode": "Karanlık Mod",
"darkModeInfo": "Açık/karanlık temalar arasında geçiş yap",
"backups": "Yedekle ve Geri Yükle",
"backupsInfo": "Ayarları ve yapay zeka geçmişini yedekle",
"lastBackup": "Son yedekleme:",
"privacySettings": "Gizlilik Ayarları",
"privacySettingsInfo": "Veri toplama ve izinleri yönet",
"logout": "Oturumu Kapat",
"logoutTips": "Mevcut hesaptan çıkış yapmak istediğinizden emin misiniz?",
"aboutApplication": "Hakkında",
"versions": "Sürüm",
"checkUpdates": "Güncellemeleri Kontrol Et",
"selectLanguage": "Dil Seç",
"voiceService": "Ses Hizmeti",
"voiceServiceInfo": "Konuşma tanıma ve sentezleme hizmetini seçin",
"selectVoiceService": "Ses Hizmeti Seç",
"azureVoiceService": "Azure Konuşma Hizmeti",
"azureVoiceServiceInfo":
"Yüksek kaliteli konuşma sentezi ve tanımayı destekleyen Microsoft bulut tabanlı hizmet",
"flutterVoiceService": "Yerel ses hizmeti",
"flutterVoiceServiceInfo": "İnternet gerektirmeyen cihaz yerel ses hizmeti",
'timbreService': 'Ses Tonu Hizmeti',
'timbreServiceInfo': 'Ses sentezleme hizmetini seçin',
'defaultTimbre': 'Varsayılan Ses Tonu',
'microsoftCloudTimbreService': 'Microsoft Bulut Ses Tonu Hizmeti',
'voiceClone': 'Ses Klonlama',
'AIsettings': 'Yapay Zeka Ayarları',
'selecttimbre': 'Ses Tonu Seç',
'pleaseRead': 'Lütfen Okuyun',
'completeRecording': 'Kaydı Tamamla',
'deleteAccount': 'Hesabı Sil',
'deleteAccountTips':
'Hesabınızı kalıcı olarak silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.',
// Sohbet Sayfası (聊天页)
"clearChatHistory": "Sohbet Geçmişini Temizle",
"online": "Çevrimiçi",
"inputMessage": "Bir mesaj yazın...",
"imListening": "Dinliyorum...",
"canStartTalking": "Konuşmaya başlayabilirsiniz",
// Çeviri Sayfası (翻译页)
"selectSourceLanguage": "Kaynak Dil Seç",
"selectTargetLanguage": "Hedef Dil Seç",
// Profili Düzenle Sayfası (编辑个人信息页)
"editProfile": "Profili Düzenle",
"nickname": "Takma Ad",
"save": "Kaydet",
// Ülke Listesi (国家列表)
"邮箱": "E-posta", // Orijinal anahtarı koru
"中国": "Çin",
"美国": "Amerika Birleşik Devletleri",
"加拿大": "Kanada",
"俄罗斯": "Rusya",
"英国": "Birleşik Krallık",
"德国": "Almanya",
"意大利": "İtalya",
"法国": "Fransa",
"西班牙": "İspanya",
"南非": "Güney Afrika",
"沙特阿拉伯": "Suudi Arabistan",
"土耳其": "Türkiye",
"日本": "Japonya",
"韩国": "Güney Kore",
"新加坡": "Singapur",
"马来西亚": "Malezya",
"泰国": "Tayland",
"越南": "Vietnam",
"印度": "Hindistan",
"巴基斯坦": "Pakistan",
"菲律宾": "Filipinler",
"印度尼西亚": "Endonezya",
"阿联酋": "Birleşik Arap Emirlikleri",
"墨西哥": "Meksika",
"巴西": "Brezilya",
"阿根廷": "Arjantin",
"澳大利亚": "Avustralya",
"新西兰": "Yeni Zelanda",
"中国香港": "Hong Kong, Çin",
"中国澳门": "Makao, Çin",
"中国台湾": "Tayvan, Çin",
"埃及": "Mısır",
"希腊": "Yunanistan",
"荷兰": "Hollanda",
"比利时": "Belçika",
"匈牙利": "Macaristan",
"罗马尼亚": "Romanya",
"瑞士": "İsviçre",
"奥地利": "Avusturya",
"丹麦": "Danimarka",
"瑞典": "İsveç",
"挪威": "Norveç",
"波兰": "Polonya",
"秘鲁": "Peru",
"智利": "Şili",
"哥伦比亚": "Kolombiya",
"委内瑞拉": "Venezuela",
"葡萄牙": "Portekiz",
"卢森堡": "Lüksemburg",
"爱尔兰": "İrlanda",
"冰岛": "İzlanda",
"阿尔巴尼亚": "Arnavutluk",
"马耳他": "Malta",
"塞浦路斯": "Kıbrıs",
"芬兰": "Finlandiya",
"保加利亚": "Bulgaristan",
"立陶宛": "Litvanya",
"拉脱维亚": "Letonya",
"爱沙尼亚": "Estonya",
"乌克兰": "Ukrayna",
"塞尔维亚": "Sırbistan",
"克罗地亚": "Hırvatistan",
"斯洛文尼亚": "Slovenya",
"捷克": "Çek Cumhuriyeti",
"斯洛伐克": "Slovakya",
"危地马拉": "Guatemala",
"萨尔瓦多": "El Salvador",
"洪都拉斯": "Honduras",
"尼加拉瓜": "Nikaragua",
"哥斯达黎加": "Kosta Rika",
"巴拿马": "Panama",
"海地": "Haiti",
"玻利维亚": "Bolivya",
"厄瓜多尔": "Ekvador",
"巴拉圭": "Paraguay",
"乌拉圭": "Uruguay",
"摩洛哥": "Fas",
"阿尔及利亚": "Cezayir",
"突尼斯": "Tunus",
"尼日利亚": "Nijerya",
"加纳": "Gana",
"埃塞俄比亚": "Etiyopya",
"肯尼亚": "Kenya",
"坦桑尼亚": "Tanzanya",
"乌干达": "Uganda",
"孟加拉国": "Bangladeş",
"以色列": "İsrail",
"黎巴嫩": "Lübnan",
"约旦": "Ürdün",
"伊拉克": "Irak",
"科威特": "Kuveyt",
"巴林": "Bahreyn",
"卡塔尔": "Katar",
"阿曼": "Umman",
"阿富汗": "Afganistan",
"斯里兰卡": "Sri Lanka",
"缅甸": "Myanmar",
"尼泊尔": "Nepal",
"蒙古": "Moğolistan",
"柬埔寨": "Kamboçya",
"老挝": "Laos",
"文莱": "Brunei",
"东帝汶": "Doğu Timor",
"斐济": "Fiji",
"所罗门群岛": "Solomon Adaları",
// Kişisel Asistan Emma (Personal Assistant Emma)
"personalAssistantName": "Emma",
"personalAssistantDescription":
"Merhaba, ben Emma, çok yönlü bir yapay zeka asistanıyım. İş planlaması, çalışma tavsiyesi, yaşam düzenlemeleri veya başka herhangi bir konuda size yardımcı olmaktan mutluluk duyarım. Birlikte verimliliği artıralım ve hedeflere ulaşalım!",
"assistantTag": "Asistan",
"personalAssistantWelcome":
"Merhaba! Ben Emma ve kişisel asistanınız olmaktan mutluluk duyuyorum. Zaman yönetimi, hedef planlama, bilgi düzenleme vb. gibi çeşitli görevlerde size yardımcı olabilirim. Size nasıl yardımcı olabilirim?",
"personalAssistantVoiceWelcome": "Buradayım!",
// Eş Zamanlı Tercüman Lucy (同声传译 Lucy)
"interpreterName": "Eş Zamanlı Tercüman",
"interpreterDescription":
"Merhaba! Ben Lucy, toplantılar, dersler ve konuşmalar için gerçek zamanlı çeviri konusunda uzmanlaşmış profesyonel bir İngilizce-Çince tercümanım, iletişimi engelsiz hale getiriyorum.",
"interpreterTag": "Çeviri",
"interpreterWelcome":
"Herkese merhaba! Ben Lucy, eş zamanlı tercümanınız. Sizin için Çince ve İngilizce arasında çeviri yapacağım. Çince konuştuğunuzda İngilizceye çevireceğim; İngilizce konuştuğunuzda Çinceye çevireceğim. Çeviri oturumumuza başlayalım!",
// Ebeveyn-Çocuk Arkadaşı XinYuan (亲子陪伴 芯愿)
"companionName": "XinYuan",
"companionDescription":
"Ben XinYuan, özel ebeveyn-çocuk arkadaşınız, nazik ve anlayışlıyım. Sohbet etmek, endişelerinizi paylaşmak veya arkadaşlığa ihtiyaç duymak isteyin, her zaman yanınızda olacağım.",
"companionTag": "Duygusal",
"companionWelcome":
"Merhaba! Sonunda sizinle tanıştım! Ben XinYuan, özel ebeveyn-çocuk arkadaşınız. Gününüz nasıldı? Benimle paylaşmak istediğiniz bir şey var mı? Her zaman buradayım, düşüncelerinizi dinlemeye hazırım.",
"companionVoiceWelcome": "Seninle buradayım!",
// Çok Fonksiyonlu Yapay Zeka Sohbeti Wu (多功能AI聊天 吴小江)
"healthAdvisorName": "Yapay Zeka Sohbet Asistanı Wu",
"healthAdvisorDescription":
"Ben Wu, size çeşitli yapay zeka sohbet özellikleri sunmaya hazırım.",
"healthAdvisorTag": "Sohbet",
"healthAdvisorWelcome":
"Merhaba, ben Wu. Yapay zeka sohbet özellikleriyle size yardımcı olmaktan mutluluk duyarım. Bugün size nasıl yardımcı olabilirim?",
"healthAdvisorVoiceWelcome": "Buradayım!",
// Çeviri Geçmişi (Translation History)
"noTranslationHistory": "Çeviri geçmişi yok",
"clearHistory": "Geçmişi Temizle",
"clearHistoryConfirm":
"Tüm çeviri geçmişini temizlemek istediğinizden emin misiniz? Bu işlem geri alınamaz.",
"translationHistory": "Çeviri Geçmişi",
// Kullanıcı Geri Bildirim Sayfası (User Feedback Page)
"feedback": "Geri Bildirim",
'feedbackInfo': 'Geri bildirim veya öneri sağlayın',
'feedbackDescription': 'Lütfen sorununuzu veya önerinizi açıklayın',
'feedbackHint': 'Lütfen geri bildiriminizi girin...',
'feedbackRequired': 'Geri bildirim içeriği gerekli',
'contactInfo': 'İletişim Bilgileri',
'contactHint': 'E-posta/Telefon, böylece sizinle iletişime geçebiliriz',
'submit': 'Gönder',
'feedbackSubmitSuccess': 'Geri bildirim başarıyla gönderildi, teşekkürler!',
'feedbackSubmitFailed':
'Geri bildirim gönderilemedi, lütfen daha sonra tekrar deneyin',
// Dil Adları (Language names)
"中文(简体)": "Çince (Basitleştirilmiş)",
"中文(繁体)": "Çince (Geleneksel)",
"中文(香港繁体)": "Çince (Hong Kong)",
"英语": "İngilizce",
"日语": "Japonca",
"韩语": "Korece",
"法语": "Fransızca",
"西班牙语": "İspanyolca",
"葡萄牙语": "Portekizce",
"意大利语": "İtalyanca",
"德语": "Almanca",
"俄语": "Rusça",
"波兰语": "Lehçe",
"荷兰语": "Hollandaca",
"瑞典语": "İsveççe",
"捷克语": "Çekçe",
"现代希腊语": "Modern Yunanca",
"罗马尼亚语": "Rumence",
"匈牙利语": "Macarca",
"乌克兰语": "Ukraynaca",
"丹麦语": "Danca",
"芬兰语": "Fince",
"挪威语": "Norveççe",
"克罗地亚语": "Hırvatça",
"加泰隆语": "Katalanca",
"阿拉伯语": "Arapça",
"泰语": "Tayca",
"越南语": "Vietnamca",
"印尼语": "Endonezce",
"印地语": "Hintçe",
"土耳其语": "Türkçe",
"马来语": "Malayca",
"孟加拉语": "Bengalce",
"泰米尔语": "Tamilce",
"泰卢固语": "Teluguca",
"马拉提语": "Marathice",
"乌尔都语": "Urduca",
"波斯语": "Farsça",
"斯瓦希里语": "Svahili",
};

6
lib/core/translations/language/vi_vn.dart

@ -40,6 +40,12 @@ const Map<String, String> viVN = {
"russian": "Tiếng Nga", "russian": "Tiếng Nga",
"vietnamese": "Tiếng Việt", "vietnamese": "Tiếng Việt",
"italian": "Tiếng Ý", "italian": "Tiếng Ý",
"hindi": "Tiếng Hindi",
"indonesian": "Tiếng Indonesia",
"thai": "Tiếng Thái",
"malay": "Tiếng Mã Lai",
"turkish": "Tiếng Thổ Nhĩ Kỳ",
"polish": "Tiếng Ba Lan",
// 登录页 // 登录页
"welcome": "Chào mừng", "welcome": "Chào mừng",

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

@ -40,6 +40,12 @@ const Map<String, String> zhCN = {
"russian": "俄语", "russian": "俄语",
"vietnamese": "越南语", "vietnamese": "越南语",
"italian": "意大利语", "italian": "意大利语",
"hindi": "印地语",
"indonesian": "印度尼西亚语",
"thai": "泰语",
"malay": "马来语",
"turkish": "土耳其语",
"polish": "波兰语",
// 登录页 // 登录页
"welcome": "欢迎使用", "welcome": "欢迎使用",

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

@ -40,6 +40,12 @@ const Map<String, String> zhHK = {
"russian": "俄語", "russian": "俄語",
"vietnamese": "越南語", "vietnamese": "越南語",
"italian": "意大利語", "italian": "意大利語",
"hindi": "印地語",
"indonesian": "印尼語",
"thai": "泰語",
"malay": "馬來語",
"turkish": "土耳其語",
"polish": "波蘭語",
// 登录页 // 登录页
"welcome": "歡迎使用", "welcome": "歡迎使用",

4
lib/data/models/appconfig.dart

@ -21,8 +21,8 @@ class AppConfig {
} }
//智能体配置 //智能体配置
static String agent(String agentId) { static String? agentsystemPrompt(String agentId) {
final foundAgent = config.agents.firstWhere((agent) => agent.id == agentId); final foundAgent = config.agents.firstWhere((agent) => agent.id == agentId);
return jsonEncode((foundAgent)); return foundAgent.systemPrompt;
} }
} }

3
lib/data/services/ble_manager.dart

@ -404,6 +404,8 @@ class BleManager extends GetxService {
final openaiBaseUrl = final openaiBaseUrl =
AppConfig.env('OPENAI_BASE_URL') ?? 'https://api.openai.com/v1'; AppConfig.env('OPENAI_BASE_URL') ?? 'https://api.openai.com/v1';
final openaiModel = AppConfig.env('OPENAI_MODEL') ?? 'gpt-3.5-turbo'; final openaiModel = AppConfig.env('OPENAI_MODEL') ?? 'gpt-3.5-turbo';
final systemPrompt = AppConfig.agentsystemPrompt("personal_assistant");
// 从Flutter资源包中加载.mcp.json // 从Flutter资源包中加载.mcp.json
final jsonData = AppConfig.mcpConfig(); final jsonData = AppConfig.mcpConfig();
@ -414,6 +416,7 @@ class BleManager extends GetxService {
'openaiApiKey': openaiApiKey, 'openaiApiKey': openaiApiKey,
'openaiBaseUrl': openaiBaseUrl, 'openaiBaseUrl': openaiBaseUrl,
'openaiModel': openaiModel, 'openaiModel': openaiModel,
'systemPrompt': systemPrompt,
'mcpServer': jsonEncode(jsonData), 'mcpServer': jsonEncode(jsonData),
}; };

21
lib/data/services/music_manager.dart

@ -22,6 +22,23 @@ class MusicManager extends GetxService {
super.onClose(); super.onClose();
} }
//播放 音乐 //播放
Future<void> play(String url) async {} Future<void> play(String url) async {
await _musicService.playMusic(url);
}
//暂停
Future<void> pause() async {
await _musicService.pauseMusic();
}
//继续
Future<void> resume() async {
await _musicService.resumeMusic();
}
//状态
Future<Map<String, dynamic>> getStatus() async {
return await _musicService.getStatus();
}
} }

76
lib/modules/agent/controllers/agent_controller.dart

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:deep_voice/data/services/music_manager.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:agent_service/agent_service.dart'; import 'package:agent_service/agent_service.dart';
@ -40,6 +41,11 @@ class AgentController extends GetxController {
final TextEditingController textController = TextEditingController(); final TextEditingController textController = TextEditingController();
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
//音乐播放管理
final _musiceManager = Get.find<MusicManager>();
var isPlaying = false.obs;
var currentUrl = "".obs;
// 状态标志 // 状态标志
final isInitialized = false.obs; final isInitialized = false.obs;
final isListening = false.obs; final isListening = false.obs;
@ -101,13 +107,17 @@ class AgentController extends GetxController {
if (result.messages.isNotEmpty) { if (result.messages.isNotEmpty) {
// 转换并添加消息到列表 // 转换并添加消息到列表
final historyMessages = result.messages final historyMessages = result.messages.map((msg) {
.map((msg) => Message( final meta = msg.metadata != null
isUser: msg.sender == 'user', ? jsonDecode(msg.metadata!)
text: msg.message, : null; // 如果为空,使用空对象
timestamp: DateTime.parse(msg.timestamp), return Message(
)) isUser: msg.sender == 'user',
.toList(); text: msg.message,
meta: meta,
timestamp: DateTime.parse(msg.timestamp),
);
}).toList();
// 消息按时间排序,最新的消息在底部 // 消息按时间排序,最新的消息在底部
historyMessages.sort((a, b) => a.timestamp.compareTo(b.timestamp)); historyMessages.sort((a, b) => a.timestamp.compareTo(b.timestamp));
@ -265,6 +275,7 @@ class AgentController extends GetxController {
messages[lastIndex] = Message( messages[lastIndex] = Message(
isUser: false, isUser: false,
text: messages[lastIndex].text + token, text: messages[lastIndex].text + token,
meta: messages[lastIndex].meta,
timestamp: messages[lastIndex].timestamp, timestamp: messages[lastIndex].timestamp,
); );
} }
@ -337,19 +348,23 @@ class AgentController extends GetxController {
final responseId = event.data['responseId'] ?? ''; final responseId = event.data['responseId'] ?? '';
final result = event.data['result'] ?? ''; final result = event.data['result'] ?? '';
final functionCall = event.data['function_call'] ?? ''; final functionCall = event.data['function_call'] ?? '';
if (!result.isBlank) { logger.i('Flutter 结束调用 mcp: $result, $functionCall');
final meta = result["meta"] ?? {};
//不为空 if (result.isNotEmpty) {
// 如果是新的回复或者响应ID改变,创建新消息 final parsedResult = jsonDecode(result);
if (_isNewAssistantResponse || final meta = parsedResult["meta"] ?? "";
(_currentResponseId != responseId && responseId.isNotEmpty)) { final metaResult = jsonDecode(meta);
messages.add(Message(isUser: false, text: "", meta: meta));
logger.i('Flutter 结束调用 mcp metaResult: $metaResult');
// 判断是否为新的回复或响应ID是否改变
if (_isNewAssistantResponse || _currentResponseId != responseId) {
// 添加新消息
messages.add(Message(isUser: false, text: "", meta: metaResult));
_isNewAssistantResponse = false; _isNewAssistantResponse = false;
_currentResponseId = responseId; _currentResponseId = responseId;
} else { } else {
// 否则更新最后一条消息 // 更新最后一条消息
final lastIndex = messages.length - 1; final lastIndex = messages.length - 1;
if (lastIndex >= 0 && !messages[lastIndex].isUser) { if (lastIndex >= 0 && !messages[lastIndex].isUser) {
messages[lastIndex] = Message( messages[lastIndex] = Message(
isUser: false, isUser: false,
@ -359,8 +374,9 @@ class AgentController extends GetxController {
); );
} }
} }
// 滚动到底部
_scrollToBottom();
} }
logger.i('Fultter 结束调用 mcp: $result, $functionCall');
break; break;
default: default:
break; break;
@ -601,4 +617,30 @@ class AgentController extends GetxController {
void translateImageText() { void translateImageText() {
useImagePrompt('请翻译这张图片中的文字'); useImagePrompt('请翻译这张图片中的文字');
} }
// 播放音乐
void musicStatus() async {
var status = await _musiceManager.getStatus();
logger.i('获取当前音乐播放状态 $status');
isPlaying.value = status['isPlaying'];
currentUrl.value = status['url'];
}
// 播放音乐
void musicPlay(String url) {
_musiceManager.play(url);
isPlaying.value = true;
currentUrl.value = url;
}
// 播放音乐
void musicPause() {
_musiceManager.pause();
isPlaying.value = false;
}
void musicResume() {
_musiceManager.resume();
isPlaying.value = true;
}
} }

83
lib/modules/agent/views/message_bubble.dart

@ -1,9 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'dart:io'; import 'dart:io';
import '../controllers/agent_controller.dart';
/// 消息气泡组件 /// 消息气泡组件
class MessageBubble extends StatelessWidget { class MessageBubble extends GetView<AgentController> {
final bool isUser; final bool isUser;
final String message; final String message;
final DateTime timestamp; final DateTime timestamp;
@ -199,8 +202,14 @@ class MessageBubble extends StatelessWidget {
//音乐卡片 //音乐卡片
return _buildMusicItem(context, musicName, musicUrl, musicSinger); return _buildMusicItem(context, musicName, musicUrl, musicSinger);
} else if (mate!.keys.contains('card_musiclist')) { } else if (mate!.keys.contains('card_musiclist')) {
final rawList = mate!['card_musiclist']['musics'] as List;
final playlist =
rawList.map((e) => Map<String, dynamic>.from(e)).toList();
// final playlist =
// mate!['card_musiclist']['musics'] as List<Map<String, String>>;
//音乐播放列表 //音乐播放列表
return _buildMusicContent(context); return _buildMusicContent(context, playlist);
} else if (mate!.keys.contains('card_weather')) { } else if (mate!.keys.contains('card_weather')) {
//天气 //天气
return _buildWeatherContent(context); return _buildWeatherContent(context);
@ -250,11 +259,12 @@ class MessageBubble extends StatelessWidget {
} }
/// 构建音乐内容卡片 /// 构建音乐内容卡片
Widget _buildMusicContent(BuildContext context) { Widget _buildMusicContent(
BuildContext context, List<Map<String, dynamic>> playlist) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( const Text(
'以下是一些推荐的音乐:', '以下是一些推荐的音乐:',
style: TextStyle( style: TextStyle(
color: Colors.black87, color: Colors.black87,
@ -301,18 +311,22 @@ class MessageBubble extends StatelessWidget {
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
// 歌曲示例 // 动态生成音乐条目
_buildMusicItem( ...playlist.asMap().entries.map((entry) {
context, final index = entry.key;
'雨声与钢琴曲', final item = entry.value;
"", final name = item["name"] ?? "未知歌曲";
'纯音乐', final url = item["url"] ?? "";
), final singer = item["sgener"] ?? "未知歌手";
Divider(height: 1, thickness: 1, color: Colors.grey[100]),
_buildMusicItem(context, 'Rainy Day', "", 'Coldplay'),
Divider(height: 1, thickness: 1, color: Colors.grey[100]),
_buildMusicItem(context, '雨天的爵士咖啡馆', "", '爵士合集'),
return Column(
children: [
_buildMusicItem(context, name, url, singer),
if (index != playlist.length - 1)
Divider(height: 1, thickness: 1, color: Colors.grey[100]),
],
);
}).toList(),
const SizedBox(height: 8), const SizedBox(height: 8),
Center( Center(
child: TextButton( child: TextButton(
@ -507,6 +521,8 @@ class MessageBubble extends StatelessWidget {
/// 构建音乐项目 /// 构建音乐项目
Widget _buildMusicItem( Widget _buildMusicItem(
BuildContext context, String name, String url, String singer) { BuildContext context, String name, String url, String singer) {
final controller = Get.find<AgentController>(); // 获取控制器
controller.musicStatus(); //刷新状态
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 8), padding: const EdgeInsets.symmetric(vertical: 8),
child: Row( child: Row(
@ -550,14 +566,35 @@ class MessageBubble extends StatelessWidget {
], ],
), ),
), ),
IconButton( Obx(() {
onPressed: () {}, final isThisPlaying = controller.isPlaying.value &&
icon: controller.currentUrl.value == url;
Icon(Icons.play_circle, color: Theme.of(context).primaryColor),
padding: EdgeInsets.zero, return IconButton(
constraints: BoxConstraints(), onPressed: () {
iconSize: 24, if (controller.isPlaying.value) {
), if (controller.currentUrl.value == url) {
controller.musicPause();
} else {
controller.musicPlay(url);
}
} else {
if (controller.currentUrl.value == url) {
controller.musicResume();
} else {
controller.musicPlay(url);
}
}
},
icon: Icon(
isThisPlaying ? Icons.pause_circle : Icons.play_circle,
color: Theme.of(context).primaryColor,
),
padding: EdgeInsets.zero,
constraints: BoxConstraints(),
iconSize: 24,
);
}),
], ],
), ),
); );

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

@ -157,6 +157,9 @@ class HomeView extends GetView<HomeController> {
child: PageView( child: PageView(
children: [ children: [
Center( Center(
child: ClipRRect(
// 添加 ClipRRect 来实现圆角
borderRadius: BorderRadius.circular(16.r), // 使用与其他部件一致的圆角大小
child: SizedBox( child: SizedBox(
width: double.infinity, width: double.infinity,
height: 200.h, height: 200.h,
@ -168,7 +171,11 @@ class HomeView extends GetView<HomeController> {
), ),
), ),
), ),
),
Center( Center(
child: ClipRRect(
// 添加 ClipRRect
borderRadius: BorderRadius.circular(16.r),
child: Image.asset( child: Image.asset(
isDarkMode isDarkMode
? 'assets/images/headphone_dark.png' ? 'assets/images/headphone_dark.png'
@ -177,7 +184,11 @@ class HomeView extends GetView<HomeController> {
fit: BoxFit.contain, fit: BoxFit.contain,
), ),
), ),
),
Center( Center(
child: ClipRRect(
// 添加 ClipRRect
borderRadius: BorderRadius.circular(16.r),
child: SizedBox( child: SizedBox(
width: double.infinity, width: double.infinity,
height: 200.h, height: 200.h,
@ -186,6 +197,7 @@ class HomeView extends GetView<HomeController> {
? 'assets/images/glasses_light.png' ? 'assets/images/glasses_light.png'
: 'assets/images/glasses_light.png', : 'assets/images/glasses_light.png',
fit: BoxFit.fitWidth, fit: BoxFit.fitWidth,
),
), ),
), ),
), ),

4
lib/modules/login/controllers/login_controller.dart

@ -550,7 +550,7 @@ class LoginController extends GetxController {
requestLogin({ requestLogin({
"mail": facebook.email, "mail": facebook.email,
"phone": "", "phone": "",
"stype": 5, "stype": loginType,
"vcode": "", "vcode": "",
"ttoken": facebook.token, "ttoken": facebook.token,
"phonemodel": "", "phonemodel": "",
@ -579,7 +579,7 @@ class LoginController extends GetxController {
requestLogin({ requestLogin({
"mail": google.email, "mail": google.email,
"phone": "", "phone": "",
"stype": 5, "stype": loginType,
"vcode": "", "vcode": "",
"ttoken": google.token, "ttoken": google.token,
"phonemodel": "", "phonemodel": "",

1
lib/modules/login/views/login_view.dart

@ -575,7 +575,6 @@ class LoginView extends GetView<LoginController> {
GestureDetector( GestureDetector(
onTap: () { onTap: () {
String url = 'https://www.deepsoud.com/yhxy.html'; String url = 'https://www.deepsoud.com/yhxy.html';
print('----------${Get.locale?.toString()}');
if (Get.locale?.toString() != 'zh_CN') { if (Get.locale?.toString() != 'zh_CN') {
url = 'https://www.deepsoud.com/yhxy_en.html'; url = 'https://www.deepsoud.com/yhxy_en.html';
} }

79
lib/modules/profile/controllers/profile_controller.dart

@ -12,6 +12,9 @@ import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import '../../../data/services/network/api.dart'; import '../../../data/services/network/api.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import '../../../routes/app_routes.dart';
import '../../../modules/login/controllers/googleLogin.dart';
import '../../../modules/login/controllers/facebookLogin.dart';
class ProfileController extends GetxController { class ProfileController extends GetxController {
static ProfileController get to => Get.find(); static ProfileController get to => Get.find();
@ -364,4 +367,80 @@ class ProfileController extends GetxController {
Get.snackbar('错误', '更新用户名和头像失败'); Get.snackbar('错误', '更新用户名和头像失败');
} }
} }
Future<void> signOut() async {
try {
//显示加载提示
// Get.dialog(
// const Center(child: CircularProgressIndicator()),
// barrierDismissible: false,
// );
// 清理所有存储
await _storage.erase();
// 或者逐个清理关键存储项
await _storage.write("logintoken", null);
await _storage.write("user_info", null);
await _storage.write("local_avatar", null);
print('清理存储成功');
// 第三方登录退出
try {
final google = Google();
final facebook = Facebook();
await Future.wait([
google.signOutGoogle(),
facebook.signOutFacebook(),
]);
} catch (e) {
print('第三方登录退出错误: $e');
// 继续执行,不中断退出流程
}
// 关闭加载提示
//Get.back();
// 确保导航到登录页面
if (Get.currentRoute != Routes.login) {
await Get.offAllNamed(Routes.login);
}
Get.snackbar('成功', '已退出登录');
print('退出登录成功');
} catch (e) {
//Get.back(); // 关闭加载提示
Get.snackbar('错误', '退出登录失败,请重试');
print('退出登录错误: $e');
}
}
// 注销账号
Future<void> deleteAccount() async {
try {
// 显示加载提示
Get.dialog(
const Center(child: CircularProgressIndicator()),
barrierDismissible: false,
);
// 删除后台用户数据
final responce = await Api.deleteUser();
if (responce == null) {
Get.back(); // 关闭加载提示
Get.snackbar('错误', '删除用户数据失败');
return;
}
// 关闭加载提示
Get.back();
signOut(); // 调用 signOut 方法
Get.snackbar('Success', 'Account has been permanently deleted');
Logger().d('账号删除成功');
} catch (e) {
Get.back(); // 关闭加载提示
Get.snackbar('错误', '删除账号失败,请重试');
Logger().d('账号删除失败: $e');
}
}
} }

797
lib/modules/profile/views/profile_view.dart

@ -5,6 +5,8 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../../core/widgets/common_bottom_nav.dart'; import '../../../core/widgets/common_bottom_nav.dart';
import '../../../routes/app_routes.dart'; import '../../../routes/app_routes.dart';
import 'dart:io'; import 'dart:io';
import 'dart:ui';
import '../../common/webview_page.dart';
// ProfileView: 用户设置页面 // ProfileView: 用户设置页面
class ProfileView extends GetView<ProfileController> { class ProfileView extends GetView<ProfileController> {
@ -143,6 +145,7 @@ class EditProfileView extends GetView<ProfileController> {
TextEditingController(text: controller.userInfo.value.name); TextEditingController(text: controller.userInfo.value.name);
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: false, // 添加这一行,防止键盘挤压内容
appBar: AppBar( appBar: AppBar(
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
centerTitle: true, centerTitle: true,
@ -156,107 +159,729 @@ class EditProfileView extends GetView<ProfileController> {
), ),
onPressed: () => Get.back(), onPressed: () => Get.back(),
), ),
title: Text( // title: Text(
'editProfile'.tr, // 'editProfile'.tr,
style: TextStyle( // style: TextStyle(
fontSize: 17.sp, // fontSize: 17.sp,
fontWeight: FontWeight.w600, // fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black, // color: isDarkMode ? Colors.white : Colors.black,
// ),
// ),
actions: [
TextButton(
onPressed: () {
// 保存用户名
controller.updateUserNameAndAvatar(nameController.text);
// 返回上一级页面
Get.back();
},
child: Text(
'save'.tr,
style: TextStyle(
fontSize: 16.sp,
color: isDarkMode ? Colors.blue[300] : Colors.blue,
fontWeight: FontWeight.w500,
),
),
),
],
),
body: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h),
child:
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
_buildEditProfileSection(context, isDarkMode, nameController),
SizedBox(height: 16.h),
_buildAccountSettings(isDarkMode),
SizedBox(height: 16.h),
])));
}
// 新增:构建编辑资料区域的方法
Widget _buildEditProfileSection(BuildContext context, bool isDarkMode,
TextEditingController nameController) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(left: 4.w, bottom: 8.h),
child: Text(
'editProfile'.tr, // 编辑资料
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.blue[400] : Colors.blue[600],
letterSpacing: 1,
),
), ),
), ),
), Container(
body: Padding( decoration: BoxDecoration(
padding: EdgeInsets.all(16.w), color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.white,
child: Column( borderRadius: BorderRadius.circular(16.r),
children: [ boxShadow: [
// 头像编辑 BoxShadow(
Center( color: isDarkMode
child: GestureDetector( ? Colors.black.withOpacity(0.2)
onTap: () => controller.updateUserAvatar(), : Colors.black.withOpacity(0.05),
child: Stack( blurRadius: 10,
children: [ offset: const Offset(0, 2),
Obx(() => CircleAvatar( ),
radius: 50.r, ],
backgroundImage: controller.localAvatar.value.isNotEmpty ),
? FileImage(File(controller.localAvatar.value)) child: ClipRRect(
: (controller.userInfo.value.avatar.isNotEmpty borderRadius: BorderRadius.circular(16.r),
? NetworkImage( child: BackdropFilter(
controller.userInfo.value.avatar) // 保留毛玻璃效果(如果需要)
: null) as ImageProvider<Object>?, filter: isDarkMode
child: controller.userInfo.value.avatar.isEmpty ? ImageFilter.blur(sigmaX: 5, sigmaY: 5)
? Icon(Icons.person, size: 50.r) : ImageFilter.blur(sigmaX: 0, sigmaY: 0),
: null, child: Column(
)), children: [
Positioned( // 头像设置项
right: 0, _buildAvatarSetting(isDarkMode),
bottom: 0, Divider(
child: Container( height: 1,
padding: EdgeInsets.all(4.w), color: isDarkMode
decoration: const BoxDecoration( ? Colors.white.withOpacity(0.1)
color: Colors.blue, : Colors.grey[200]),
shape: BoxShape.circle, // 昵称设置项
), _buildNicknameSetting(context, isDarkMode, nameController),
child: Icon( ],
Icons.camera_alt, ),
size: 20.w,
color: Colors.white,
)),
)
],
)),
), ),
SizedBox(height: 20.h), ),
),
],
);
}
// 昵称编辑 - 使用外部定义的controller而不是每次重建 // 新增:构建头像设置项
Widget _buildAvatarSetting(bool isDarkMode) {
return InkWell(
onTap: () => controller.updateUserAvatar(),
child: Padding(
padding:
EdgeInsets.symmetric(horizontal: 16.w, vertical: 4.h), // 调整垂直间距
child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween, // 移除,让内容自然排列
children: [
// --- 添加图标 ---
Container(
width: 32.w,
height: 32.w,
decoration: BoxDecoration(
color: isDarkMode
? Colors.blue[900]!.withOpacity(0.3) // 使用示例颜色
: Colors.blue[50]!, // 使用示例颜色
borderRadius: BorderRadius.circular(16.r), // 图标背景圆角
),
child: Icon(
Icons.account_circle_outlined, // 头像图标
size: 18.w,
color:
isDarkMode ? Colors.blue[300]! : Colors.blue[600]!, // 图标颜色
),
),
SizedBox(width: 12.w), // 图标和文字间距
// --- ---
Expanded(
// 让文字占据剩余空间
child: Text(
'avatar'.tr, // 头像
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.white : Colors.black87,
),
),
),
// --- 右侧内容保持不变 ---
Row( Row(
children: [ children: [
Expanded( Obx(() => CircleAvatar(
child: TextField( radius: 30.r, // 调整头像大小以适应行高
controller: nameController, backgroundImage: controller.localAvatar.value.isNotEmpty
decoration: InputDecoration( ? FileImage(File(controller.localAvatar.value))
labelText: 'nickname'.tr, : (controller.userInfo.value.avatar.isNotEmpty
border: const OutlineInputBorder(), ? NetworkImage(controller.userInfo.value.avatar)
suffixIcon: nameController.text.isNotEmpty : null) as ImageProvider<Object>?,
? IconButton( child: (controller.localAvatar.value.isEmpty &&
icon: const Icon(Icons.clear), controller.userInfo.value.avatar.isEmpty)
onPressed: () { ? Icon(Icons.person,
nameController.clear(); size: 20.r, color: Colors.grey) // 默认图标
},
)
: null, : null,
), backgroundColor: Colors.grey[200], // 添加背景色防止透明图片问题
)),
SizedBox(width: 8.w),
Container(
width: 32.w,
height: 32.w,
decoration: BoxDecoration(
color: isDarkMode
? Colors.white.withOpacity(0.05)
: Colors.grey[100],
borderRadius: BorderRadius.circular(16.r),
),
child: Icon(
Icons.chevron_right,
size: 16.w,
color: isDarkMode ? Colors.white70 : Colors.grey[500],
), ),
), ),
], ],
), ),
// ... 其他编辑项 ... // --- ---
],
),
),
);
}
SizedBox(height: 30.h), // 新增:构建昵称设置项
// 添加一个大的保存按钮 Widget _buildNicknameSetting(BuildContext context, bool isDarkMode,
SizedBox( TextEditingController nameController) {
width: double.infinity, return InkWell(
height: 50.h, onTap: () => _showEditNicknameDialog(context, isDarkMode, nameController),
child: ElevatedButton( child: Padding(
onPressed: () { padding:
// 保存用户名 EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), // 调整垂直间距
controller.updateUserNameAndAvatar(nameController.text); child: Row(
// 返回上一级页面 // mainAxisAlignment: MainAxisAlignment.spaceBetween, // 移除
Get.back(); children: [
}, // --- 添加图标 ---
style: ElevatedButton.styleFrom( Container(
backgroundColor: isDarkMode ? Colors.blue[700] : Colors.blue, width: 32.w,
shape: RoundedRectangleBorder( height: 32.w,
borderRadius: BorderRadius.circular(10.r), decoration: BoxDecoration(
), color: isDarkMode
? Colors.green[900]!.withOpacity(0.3) // 使用示例颜色
: Colors.green[50]!, // 使用示例颜色
borderRadius: BorderRadius.circular(16.r), // 图标背景圆角
),
child: Icon(
Icons.edit_outlined, // 编辑图标
size: 18.w,
color: isDarkMode
? Colors.green[300]!
: Colors.green[600]!, // 图标颜色
),
),
SizedBox(width: 12.w), // 图标和文字间距
// --- ---
Expanded(
// 让文字占据剩余空间
child: Text(
'nickname'.tr, // 名字
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.white : Colors.black87,
), ),
child: Text( ),
'save'.tr, ),
style: TextStyle( // --- 右侧内容保持不变 ---
fontSize: 16.sp, Row(
color: Colors.white, children: [
fontWeight: FontWeight.w500, // 使用 Obx 监听 userInfo 的变化来显示昵称
Obx(() => Text(
controller.userInfo.value.name.isNotEmpty
? controller.userInfo.value.name
: 'notSet'.tr, // 未设置
style: TextStyle(
fontSize: 14.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[600],
),
overflow: TextOverflow.ellipsis,
)),
SizedBox(width: 8.w),
Container(
width: 32.w,
height: 32.w,
decoration: BoxDecoration(
color: isDarkMode
? Colors.white.withOpacity(0.05)
: Colors.grey[100],
borderRadius: BorderRadius.circular(16.r),
),
child: Icon(
Icons.chevron_right,
size: 16.w,
color: isDarkMode ? Colors.white70 : Colors.grey[500],
), ),
), ),
],
),
// --- ---
],
),
),
);
}
// 新增:显示编辑昵称对话框的方法
void _showEditNicknameDialog(BuildContext context, bool isDarkMode,
TextEditingController nameController) {
// 创建一个临时的 Controller,用于对话框内的编辑,避免直接修改主 nameController
final dialogNameController =
TextEditingController(text: nameController.text);
Get.dialog(
AlertDialog(
backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white,
title: Text(
'editNickname'.tr, // 编辑昵称
style: TextStyle(color: isDarkMode ? Colors.white : Colors.black87),
),
content: TextField(
controller: dialogNameController, // 使用对话框的 Controller
autofocus: true,
decoration: InputDecoration(
hintText: 'enterNickname'.tr, // 请输入昵称
hintStyle:
TextStyle(color: isDarkMode ? Colors.white54 : Colors.black38),
// 可以添加其他样式,如边框
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.r),
borderSide: BorderSide(
color: isDarkMode ? Colors.white38 : Colors.grey[400]!),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.r),
borderSide: BorderSide(
color: isDarkMode ? Colors.white38 : Colors.grey[400]!),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.r),
borderSide: BorderSide(
color: isDarkMode ? Colors.blue[300]! : Colors.blue),
),
),
style: TextStyle(color: isDarkMode ? Colors.white : Colors.black87),
),
actions: [
TextButton(
onPressed: () => Get.back(),
child: Text(
'cancel'.tr,
style: TextStyle(
color: isDarkMode ? Colors.white70 : Colors.black54),
),
),
TextButton(
onPressed: () {
// 确认时,将对话框输入的值更新回主 nameController
nameController.text = dialogNameController.text;
Get.back(); // 关闭对话框
// 注意:实际的保存操作由 AppBar 中的保存按钮触发
},
child: Text(
'confirm'.tr,
style:
TextStyle(color: isDarkMode ? Colors.blue[300] : Colors.blue),
),
),
],
),
);
}
// _buildEditProfile(bool isDarkMode, TextEditingController nameController) {
// return
// //Padding(
// //padding: EdgeInsets.all(16.w),
// //child:
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Padding(
// padding: EdgeInsets.only(left: 4.w, bottom: 8.h),
// child: Text(
// 'editProfile'.tr, // 账号设置
// style: TextStyle(
// fontSize: 12.sp,
// fontWeight: FontWeight.w500,
// color: isDarkMode ? Colors.blue[400] : Colors.blue[600],
// letterSpacing: 1,
// ),
// ),
// ),
// // 头像编辑
// Center(
// child: GestureDetector(
// onTap: () => controller.updateUserAvatar(),
// child: Stack(
// children: [
// Obx(() => CircleAvatar(
// radius: 50.r,
// backgroundImage: controller.localAvatar.value.isNotEmpty
// ? FileImage(File(controller.localAvatar.value))
// : (controller.userInfo.value.avatar.isNotEmpty
// ? NetworkImage(controller.userInfo.value.avatar)
// : null) as ImageProvider<Object>?,
// child: controller.userInfo.value.avatar.isEmpty
// ? Icon(Icons.person, size: 50.r)
// : null,
// )),
// Positioned(
// right: 0,
// bottom: 0,
// child: Container(
// padding: EdgeInsets.all(4.w),
// decoration: const BoxDecoration(
// color: Colors.blue,
// shape: BoxShape.circle,
// ),
// child: Icon(
// Icons.camera_alt,
// size: 20.w,
// color: Colors.white,
// )),
// )
// ],
// )),
// ),
// SizedBox(height: 20.h),
// // 昵称编辑 - 使用外部定义的controller而不是每次重建
// Row(
// children: [
// Expanded(
// child: TextField(
// controller: nameController,
// decoration: InputDecoration(
// labelText: 'nickname'.tr,
// border: const OutlineInputBorder(),
// suffixIcon: nameController.text.isNotEmpty
// ? IconButton(
// icon: const Icon(Icons.clear),
// onPressed: () {
// nameController.clear();
// },
// )
// : null,
// ),
// ),
// ),
// ],
// ),
// ],
// //),
// );
// }
Widget _buildAccountSettings(bool isDarkMode) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(left: 4.w, bottom: 8.h),
child: Text(
'AccountSetting'.tr, // 账号设置
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.blue[400] : Colors.blue[600],
letterSpacing: 1,
),
),
),
Container(
decoration: BoxDecoration(
color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.white,
borderRadius: BorderRadius.circular(16.r),
boxShadow: [
BoxShadow(
color: isDarkMode
? Colors.black.withOpacity(0.2)
: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(16.r),
child: BackdropFilter(
filter: isDarkMode
? ImageFilter.blur(sigmaX: 5, sigmaY: 5)
: ImageFilter.blur(sigmaX: 0, sigmaY: 0),
child: Column(
children: [
// 用户协议
_buildSimpleNavigationSetting(
title: 'userAgreement'.tr, // 用户协议
icon: Icons.description_outlined,
iconBgColor: isDarkMode
? Colors.purple[900]!.withOpacity(0.3)
: Colors.purple[50]!,
iconColor:
isDarkMode ? Colors.purple[300]! : Colors.purple[600]!,
titleColor: isDarkMode ? Colors.white : Colors.black87,
onTap: () {
String url = 'https://www.deepsoud.com/yhxy.html';
if (Get.locale?.toString() != 'zh_CN') {
url = 'https://www.deepsoud.com/yhxy_en.html';
}
Get.to(() => WebViewPage(
url: url,
title: 'userAgreement'.tr,
));
},
isDarkMode: isDarkMode,
),
Divider(
height: 1,
color: isDarkMode
? Colors.white.withOpacity(0.1)
: Colors.grey[200]),
// 隐私政策
_buildSimpleNavigationSetting(
title: 'privacyPolicy'.tr, // 隐私政策
icon: Icons.privacy_tip_outlined,
iconBgColor: isDarkMode
? Colors.purple[900]!.withOpacity(0.3)
: Colors.purple[50]!,
iconColor:
isDarkMode ? Colors.purple[300]! : Colors.purple[600]!,
titleColor: isDarkMode ? Colors.white : Colors.black87,
onTap: () {
String url = 'https://www.deepsoud.com/ysxy.html';
if (Get.locale?.toString() != 'zh_CN') {
url = 'https://www.deepsoud.com/ysxy_en.html';
}
Get.to(() => WebViewPage(
url: url,
title: 'privacyPolicy'.tr,
));
},
isDarkMode: isDarkMode,
),
Divider(
height: 1,
color: isDarkMode
? Colors.white.withOpacity(0.1)
: Colors.grey[200]),
// 退出登录
_buildSimpleNavigationSetting(
title: 'logout'.tr, // 退出登录
icon: Icons.logout,
iconBgColor: isDarkMode
? Colors.red[900]!.withOpacity(0.3)
: Colors.red[50]!,
iconColor: isDarkMode ? Colors.red[300]! : Colors.red[600]!,
titleColor:
isDarkMode ? Colors.red[300]! : Colors.red[600]!,
onTap: () {
// 退出登录确认对话框
Get.dialog(
AlertDialog(
backgroundColor:
isDarkMode ? Colors.grey[900] : Colors.white,
title: Text(
'logout'.tr, // 退出登录
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black87,
),
),
content: Text(
'logoutTips'.tr, // 确定要退出当前账号吗?
style: TextStyle(
color:
isDarkMode ? Colors.white70 : Colors.black54,
),
),
actions: [
TextButton(
onPressed: () => Get.back(),
child: Text(
'cancel'.tr, // 取消
style: TextStyle(
color: isDarkMode
? Colors.white70
: Colors.black54,
),
),
),
TextButton(
onPressed: () {
Get.back();
controller.signOut();
},
child: Text(
'confirm'.tr, // 确定
style: TextStyle(
color: isDarkMode
? Colors.red[300]
: Colors.red[600],
),
),
),
],
),
);
},
isDarkMode: isDarkMode,
),
Divider(
height: 1,
color: isDarkMode
? Colors.white.withOpacity(0.1)
: Colors.grey[200]),
// 注销账号
_buildSimpleNavigationSetting(
title: 'deleteAccount'.tr, // 注销账号
icon: Icons.delete_forever,
iconBgColor: isDarkMode
? Colors.red[900]!.withOpacity(0.3)
: Colors.red[50]!,
iconColor: isDarkMode ? Colors.red[300]! : Colors.red[600]!,
titleColor:
isDarkMode ? Colors.red[300]! : Colors.red[600]!,
onTap: () {
// 注销账号确认对话框
Get.dialog(
AlertDialog(
backgroundColor:
isDarkMode ? Colors.grey[900] : Colors.white,
title: Text(
'deleteAccount'.tr, // 注销账号
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black87,
),
),
content: Text(
'deleteAccountTips'.tr, // 确定要永久删除您的账号吗?此操作不可撤销
style: TextStyle(
color:
isDarkMode ? Colors.white70 : Colors.black54,
),
),
actions: [
TextButton(
onPressed: () => Get.back(),
child: Text(
'cancel'.tr, // 取消
style: TextStyle(
color: isDarkMode
? Colors.white70
: Colors.black54,
),
),
),
TextButton(
onPressed: () {
Get.back();
controller.deleteAccount();
},
child: Text(
'confirm'.tr, // 确定
style: TextStyle(
color: isDarkMode
? Colors.red[300]
: Colors.red[600],
),
),
),
],
),
);
},
isDarkMode: isDarkMode,
),
],
),
),
),
),
],
);
}
// 简单导航设置项
Widget _buildSimpleNavigationSetting({
required String title,
String? subtitle,
required IconData icon,
required Color iconBgColor,
required Color iconColor,
Color? titleColor,
Color? subtitleColor,
required VoidCallback onTap,
required bool isDarkMode,
}) {
return InkWell(
onTap: onTap,
child: Padding(
padding: EdgeInsets.all(16.w),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Row(
children: [
Container(
width: 32.w,
height: 32.w,
decoration: BoxDecoration(
color: iconBgColor,
borderRadius: BorderRadius.circular(16.r),
),
child: Icon(
icon,
size: 16.w,
color: iconColor,
),
),
SizedBox(width: 12.w),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: titleColor ??
(isDarkMode ? Colors.white : Colors.black87),
),
overflow: TextOverflow.ellipsis,
),
if (subtitle != null) SizedBox(height: 2.h),
if (subtitle != null)
Text(
subtitle,
style: TextStyle(
fontSize: 12.sp,
color: subtitleColor ??
(isDarkMode
? Colors.white70
: Colors.black54),
),
overflow: TextOverflow.ellipsis,
),
],
),
),
],
),
),
Container(
width: 32.w,
height: 32.w,
decoration: BoxDecoration(
color: isDarkMode
? Colors.white.withOpacity(0.05)
: Colors.grey[100],
borderRadius: BorderRadius.circular(16.r),
),
child: Icon(
Icons.chevron_right,
size: 16.w,
color: isDarkMode ? Colors.white70 : Colors.grey[500],
), ),
), ),
], ],

92
lib/modules/settings/controllers/settings_controller.dart

@ -8,13 +8,10 @@ import '../../../data/services/speech_factory.dart';
import '../models/language_model.dart'; import '../models/language_model.dart';
import 'package:logger/logger.dart'; import 'package:logger/logger.dart';
import '../../../data/models/user_Info.dart'; import '../../../data/models/user_Info.dart';
import '../../../modules/login/controllers/googleLogin.dart';
import '../../../modules/login/controllers/facebookLogin.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'dart:io'; import 'dart:io';
import '../../../routes/app_routes.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import '../../../data/services/network/api.dart';
class SettingsController extends GetxController { class SettingsController extends GetxController {
// 语言设置 // 语言设置
@ -40,6 +37,17 @@ class SettingsController extends GetxController {
name: 'vietnamese', alias: 'Tiếng Việt', value: 'vi_VN'), // 添加越南语选项 name: 'vietnamese', alias: 'Tiếng Việt', value: 'vi_VN'), // 添加越南语选项
LanguageModel( LanguageModel(
name: 'italian', alias: 'Italiano', value: 'it_IT'), // 添加意大利语选项 name: 'italian', alias: 'Italiano', value: 'it_IT'), // 添加意大利语选项
LanguageModel(
name: 'hindi', alias: 'हिन्दी', value: 'hi_IN'), // 添加印度语(印地语)选项
LanguageModel(
name: 'indonesian',
alias: 'Bahasa Indonesia',
value: 'id_ID'), // 添加印尼语选项
LanguageModel(name: 'thai', alias: 'ไทย', value: 'th_TH'), // 添加泰语选项
LanguageModel(
name: 'malay', alias: 'Bahasa Melayu', value: 'ms_MY'), // 添加马来语选项
LanguageModel(name: 'turkish', alias: 'Türkçe', value: 'tr_TR'), // 添加土耳其语选项
LanguageModel(name: 'polish', alias: 'Polski', value: 'pl_PL'), // 添加波兰语选项
]; ];
Rx<LanguageModel> language = LanguageModel().obs; Rx<LanguageModel> language = LanguageModel().obs;
@ -316,80 +324,4 @@ class SettingsController extends GetxController {
sourceLanguage.value = targetLanguage.value; sourceLanguage.value = targetLanguage.value;
targetLanguage.value = temp; targetLanguage.value = temp;
} }
Future<void> signOut() async {
try {
//显示加载提示
// Get.dialog(
// const Center(child: CircularProgressIndicator()),
// barrierDismissible: false,
// );
// 清理所有存储
await _storage.erase();
// 或者逐个清理关键存储项
await _storage.write("logintoken", null);
await _storage.write("user_info", null);
await _storage.write("local_avatar", null);
print('清理存储成功');
// 第三方登录退出
try {
final google = Google();
final facebook = Facebook();
await Future.wait([
google.signOutGoogle(),
facebook.signOutFacebook(),
]);
} catch (e) {
print('第三方登录退出错误: $e');
// 继续执行,不中断退出流程
}
// 关闭加载提示
//Get.back();
// 确保导航到登录页面
if (Get.currentRoute != Routes.login) {
await Get.offAllNamed(Routes.login);
}
Get.snackbar('成功', '已退出登录');
print('退出登录成功');
} catch (e) {
//Get.back(); // 关闭加载提示
Get.snackbar('错误', '退出登录失败,请重试');
print('退出登录错误: $e');
}
}
// 注销账号
Future<void> deleteAccount() async {
try {
// 显示加载提示
Get.dialog(
const Center(child: CircularProgressIndicator()),
barrierDismissible: false,
);
// 删除后台用户数据
final responce = await Api.deleteUser();
if (responce == null) {
Get.back(); // 关闭加载提示
Get.snackbar('错误', '删除用户数据失败');
return;
}
// 关闭加载提示
Get.back();
signOut(); // 调用 signOut 方法
Get.snackbar('Success', 'Account has been permanently deleted');
Logger().d('账号删除成功');
} catch (e) {
Get.back(); // 关闭加载提示
Get.snackbar('错误', '删除账号失败,请重试');
Logger().d('账号删除失败: $e');
}
}
} }

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

@ -59,7 +59,9 @@ class SettingsView extends GetView<SettingsController> {
// 用户信息卡片 // 用户信息卡片
Widget _buildUserInfoCard(bool isDarkMode) { Widget _buildUserInfoCard(bool isDarkMode) {
return Container( return GestureDetector(
onTap: () => Get.toNamed(Routes.editProfile),
child: Container(
padding: EdgeInsets.all(16.w), padding: EdgeInsets.all(16.w),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
@ -113,10 +115,6 @@ class SettingsView extends GetView<SettingsController> {
borderRadius: BorderRadius.circular(30.r), borderRadius: BorderRadius.circular(30.r),
child: controller.userInfo.value.avatar.isEmpty child: controller.userInfo.value.avatar.isEmpty
? ?
// Image.network(
// 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80',
// fit: BoxFit.cover, // 图片填充方式
// )
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.blue[600], color: Colors.blue[600],
@ -124,7 +122,8 @@ class SettingsView extends GetView<SettingsController> {
), ),
child: Center( child: Center(
child: Text( child: Text(
controller.userInfo.value.name.isNotEmpty controller
.userInfo.value.name.isNotEmpty
? controller.userInfo.value.name[0] ? controller.userInfo.value.name[0]
.toUpperCase() .toUpperCase()
: '?', : '?',
@ -200,7 +199,8 @@ class SettingsView extends GetView<SettingsController> {
1: 'standardUser', //'标准用户' 1: 'standardUser', //'标准用户'
2: 'proUser', //'专业用户' 2: 'proUser', //'专业用户'
}; };
final membershipString = membershipMap[controller final membershipString = membershipMap[
controller
.userInfo.value.membershipLevel] ?? .userInfo.value.membershipLevel] ??
'Unknown'; 'Unknown';
return Text( return Text(
@ -212,24 +212,24 @@ class SettingsView extends GetView<SettingsController> {
); );
}), }),
), ),
SizedBox(width: 8.w), // SizedBox(width: 8.w),
Flexible( // Flexible(
child: Text( // child: Text(
'${'joinDevice'.tr} DeepSound Pro', // 已连接设备: // '${'joinDevice'.tr} DeepSound Pro', // 已连接设备:
style: TextStyle( // style: TextStyle(
fontSize: 12.sp, // fontSize: 12.sp,
color: isDarkMode // color: isDarkMode
? Colors.white70 // ? Colors.white70
: Colors.black54, // : Colors.black54,
), // ),
overflow: TextOverflow.ellipsis, // overflow: TextOverflow.ellipsis,
), // ),
), // ),
], ],
), ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
Text( Text(
controller.userInfo.value.uid, 'ID:${controller.userInfo.value.uid}',
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.black54, color: isDarkMode ? Colors.white70 : Colors.black54,
@ -265,6 +265,7 @@ class SettingsView extends GetView<SettingsController> {
), ),
)), )),
], ],
),
), ),
), ),
), ),
@ -587,133 +588,133 @@ class SettingsView extends GetView<SettingsController> {
: Colors.grey[200]), : Colors.grey[200]),
// 退出登录 // 退出登录
_buildSimpleNavigationSetting( // _buildSimpleNavigationSetting(
title: 'logout'.tr, // 退出登录 // title: 'logout'.tr, // 退出登录
icon: Icons.logout, // icon: Icons.logout,
iconBgColor: isDarkMode // iconBgColor: isDarkMode
? Colors.red[900]!.withOpacity(0.3) // ? Colors.red[900]!.withOpacity(0.3)
: Colors.red[50]!, // : Colors.red[50]!,
iconColor: isDarkMode ? Colors.red[300]! : Colors.red[600]!, // iconColor: isDarkMode ? Colors.red[300]! : Colors.red[600]!,
titleColor: // titleColor:
isDarkMode ? Colors.red[300]! : Colors.red[600]!, // isDarkMode ? Colors.red[300]! : Colors.red[600]!,
onTap: () { // onTap: () {
// 退出登录确认对话框 // // 退出登录确认对话框
Get.dialog( // Get.dialog(
AlertDialog( // AlertDialog(
backgroundColor: // backgroundColor:
isDarkMode ? Colors.grey[900] : Colors.white, // isDarkMode ? Colors.grey[900] : Colors.white,
title: Text( // title: Text(
'logout'.tr, // 退出登录 // 'logout'.tr, // 退出登录
style: TextStyle( // style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black87, // color: isDarkMode ? Colors.white : Colors.black87,
), // ),
), // ),
content: Text( // content: Text(
'logoutTips'.tr, // 确定要退出当前账号吗? // 'logoutTips'.tr, // 确定要退出当前账号吗?
style: TextStyle( // style: TextStyle(
color: // color:
isDarkMode ? Colors.white70 : Colors.black54, // isDarkMode ? Colors.white70 : Colors.black54,
), // ),
), // ),
actions: [ // actions: [
TextButton( // TextButton(
onPressed: () => Get.back(), // onPressed: () => Get.back(),
child: Text( // child: Text(
'cancel'.tr, // 取消 // 'cancel'.tr, // 取消
style: TextStyle( // style: TextStyle(
color: isDarkMode // color: isDarkMode
? Colors.white70 // ? Colors.white70
: Colors.black54, // : Colors.black54,
), // ),
), // ),
), // ),
TextButton( // TextButton(
onPressed: () { // onPressed: () {
Get.back(); // Get.back();
controller.signOut(); // controller.signOut();
}, // },
child: Text( // child: Text(
'confirm'.tr, // 确定 // 'confirm'.tr, // 确定
style: TextStyle( // style: TextStyle(
color: isDarkMode // color: isDarkMode
? Colors.red[300] // ? Colors.red[300]
: Colors.red[600], // : Colors.red[600],
), // ),
), // ),
), // ),
], // ],
), // ),
); // );
}, // },
isDarkMode: isDarkMode, // isDarkMode: isDarkMode,
), // ),
Divider( // Divider(
height: 1, // height: 1,
color: isDarkMode // color: isDarkMode
? Colors.white.withOpacity(0.1) // ? Colors.white.withOpacity(0.1)
: Colors.grey[200]), // : Colors.grey[200]),
// 注销账号 // 注销账号
_buildSimpleNavigationSetting( // _buildSimpleNavigationSetting(
title: 'deleteAccount'.tr, // 注销账号 // title: 'deleteAccount'.tr, // 注销账号
icon: Icons.delete_forever, // icon: Icons.delete_forever,
iconBgColor: isDarkMode // iconBgColor: isDarkMode
? Colors.red[900]!.withOpacity(0.3) // ? Colors.red[900]!.withOpacity(0.3)
: Colors.red[50]!, // : Colors.red[50]!,
iconColor: isDarkMode ? Colors.red[300]! : Colors.red[600]!, // iconColor: isDarkMode ? Colors.red[300]! : Colors.red[600]!,
titleColor: // titleColor:
isDarkMode ? Colors.red[300]! : Colors.red[600]!, // isDarkMode ? Colors.red[300]! : Colors.red[600]!,
onTap: () { // onTap: () {
// 注销账号确认对话框 // // 注销账号确认对话框
Get.dialog( // Get.dialog(
AlertDialog( // AlertDialog(
backgroundColor: // backgroundColor:
isDarkMode ? Colors.grey[900] : Colors.white, // isDarkMode ? Colors.grey[900] : Colors.white,
title: Text( // title: Text(
'deleteAccount'.tr, // 注销账号 // 'deleteAccount'.tr, // 注销账号
style: TextStyle( // style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black87, // color: isDarkMode ? Colors.white : Colors.black87,
), // ),
), // ),
content: Text( // content: Text(
'deleteAccountTips'.tr, // 确定要永久删除您的账号吗?此操作不可撤销 // 'deleteAccountTips'.tr, // 确定要永久删除您的账号吗?此操作不可撤销
style: TextStyle( // style: TextStyle(
color: // color:
isDarkMode ? Colors.white70 : Colors.black54, // isDarkMode ? Colors.white70 : Colors.black54,
), // ),
), // ),
actions: [ // actions: [
TextButton( // TextButton(
onPressed: () => Get.back(), // onPressed: () => Get.back(),
child: Text( // child: Text(
'cancel'.tr, // 取消 // 'cancel'.tr, // 取消
style: TextStyle( // style: TextStyle(
color: isDarkMode // color: isDarkMode
? Colors.white70 // ? Colors.white70
: Colors.black54, // : Colors.black54,
), // ),
), // ),
), // ),
TextButton( // TextButton(
onPressed: () { // onPressed: () {
Get.back(); // Get.back();
controller.deleteAccount(); // controller.deleteAccount();
}, // },
child: Text( // child: Text(
'confirm'.tr, // 确定 // 'confirm'.tr, // 确定
style: TextStyle( // style: TextStyle(
color: isDarkMode // color: isDarkMode
? Colors.red[300] // ? Colors.red[300]
: Colors.red[600], // : Colors.red[600],
), // ),
), // ),
), // ),
], // ],
), // ),
); // );
}, // },
isDarkMode: isDarkMode, // isDarkMode: isDarkMode,
), // ),
], ],
), ),
), ),

21
lib/modules/splash/controllers/splash_controller.dart

@ -21,7 +21,7 @@ class SplashController extends GetxController {
bool get isResourceLoaded => _isResourceLoaded.value; bool get isResourceLoaded => _isResourceLoaded.value;
// 版本号 // 版本号
final String version = 'v1.0.0'; //final String version = 'V1.0.0';
// 主题服务 // 主题服务
final ThemeService _themeService = ThemeService(); final ThemeService _themeService = ThemeService();
@ -32,20 +32,29 @@ class SplashController extends GetxController {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
_startLoadingAnimation(); _startLoadingAnimation();
_loadAppResources(); _loadAppResources();
_initMapSDK();
});
}
// 初始化地图SDK
void _initMapSDK() {
try {
AmapFlutter().initSdk( AmapFlutter().initSdk(
iosKey: "a4a1394fe817c2f86a424b897b4a9af4", iosKey: "a4a1394fe817c2f86a424b897b4a9af4",
androidKey: "e5fdc9605eabdeb5626f18f5721f343d", androidKey: "e5fdc9605eabdeb5626f18f5721f343d",
); );
}); } catch (e) {
print('地图SDK初始化失败: $e');
}
} }
// 进度条动画(持续2秒) // 进度条动画(持续2秒)
void _startLoadingAnimation() { void _startLoadingAnimation() {
const totalDuration = 500; // 动画总时长2秒 const totalDuration = 1500; // 动画总时长增加到1.5秒
const steps = totalDuration ~/ 50; // 40次更新(50ms间隔) const steps = totalDuration ~/ 30; // 30的间隔,更平滑的动画
final stepValue = 1.0 / steps; const stepValue = 1.0 / steps;
Timer.periodic(const Duration(milliseconds: 50), (timer) { Timer.periodic(const Duration(milliseconds: 30), (timer) {
if (_loadingProgress.value < 1.0) { if (_loadingProgress.value < 1.0) {
_loadingProgress.value += stepValue; _loadingProgress.value += stepValue;
} else { } else {

69
lib/modules/splash/views/splash_view.dart

@ -40,7 +40,7 @@ class SplashView extends GetView<SplashController> {
), ),
// 版本号 // 版本号
_buildVersionInfo(isDarkMode), //_buildVersionInfo(isDarkMode),
], ],
), ),
); );
@ -148,6 +148,7 @@ class SplashView extends GetView<SplashController> {
padding: EdgeInsets.symmetric(horizontal: 80.w), padding: EdgeInsets.symmetric(horizontal: 80.w),
child: Stack( child: Stack(
children: [ children: [
// 背景条
Container( Container(
height: 4.h, height: 4.h,
decoration: BoxDecoration( decoration: BoxDecoration(
@ -155,23 +156,28 @@ class SplashView extends GetView<SplashController> {
borderRadius: BorderRadius.circular(2.r), borderRadius: BorderRadius.circular(2.r),
), ),
), ),
// 进度条
Obx(() { Obx(() {
final progress = controller.loadingProgress; final progress = controller.loadingProgress;
return LayoutBuilder( return AnimatedContainer(
builder: (context, constraints) { duration: const Duration(milliseconds: 200),
return Container( height: 4.h,
height: 4.h, width: 240.w * progress, // 使用固定宽度乘以进度
width: constraints.maxWidth * progress, decoration: BoxDecoration(
decoration: BoxDecoration( gradient: const LinearGradient(
gradient: const LinearGradient( begin: Alignment.centerLeft,
begin: Alignment.centerLeft, end: Alignment.centerRight,
end: Alignment.centerRight, colors: [Colors.blue, Colors.purple],
colors: [Colors.blue, Colors.purple], ),
), borderRadius: BorderRadius.circular(2.r),
borderRadius: BorderRadius.circular(2.r), boxShadow: [
BoxShadow(
color: Colors.blue.withOpacity(0.3),
blurRadius: 5,
offset: const Offset(0, 1),
), ),
); ],
}, ),
); );
}), }),
], ],
@ -201,20 +207,21 @@ class SplashView extends GetView<SplashController> {
} }
// 版本信息 // 版本信息
Widget _buildVersionInfo(bool isDarkMode) { // 暂时不需要版本号显示,保留代码以备将来使用
return Positioned( // Widget _buildVersionInfo(bool isDarkMode) {
bottom: 32.h, // return Positioned(
left: 0, // bottom: 32.h,
right: 0, // left: 0,
child: Center( // right: 0,
child: Text( // child: Center(
controller.version, // child: Text(
style: TextStyle( // controller.version,
fontSize: 12.sp, // style: TextStyle(
color: isDarkMode ? Colors.grey[500] : Colors.grey[400], // fontSize: 12.sp,
), // color: isDarkMode ? Colors.grey[500] : Colors.grey[400],
), // ),
), // ),
); // ),
} // );
// }
} }

42
lib/routes/app_pages.dart

@ -50,36 +50,48 @@ abstract class AppPages {
name: Routes.splash, name: Routes.splash,
page: () => const SplashView(), page: () => const SplashView(),
binding: SplashBinding(), binding: SplashBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.login, name: Routes.login,
page: () => const LoginView(), page: () => const LoginView(),
binding: LoginBinding(), binding: LoginBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.pairing, name: Routes.pairing,
page: () => const PairingView(), page: () => const PairingView(),
binding: PairingBinding(), binding: PairingBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.initial, name: Routes.initial,
page: () => const HomeView(), page: () => const HomeView(),
binding: HomeBinding(), binding: HomeBinding(),
transition: Transition.noTransition,
), ),
GetPage( GetPage(
name: Routes.home, name: Routes.home,
page: () => const HomeView(), page: () => const HomeView(),
binding: HomeBinding(), binding: HomeBinding(),
transition: Transition.noTransition,
), ),
GetPage( GetPage(
name: Routes.explore, name: Routes.explore,
page: () => const ExploreView(), page: () => const ExploreView(),
binding: ExploreBinding(), binding: ExploreBinding(),
transition: Transition.noTransition,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.chat, name: Routes.chat,
page: () => const ChatView(), page: () => const ChatView(),
binding: ChatBinding(), binding: ChatBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.recording, name: Routes.recording,
@ -95,76 +107,106 @@ abstract class AppPages {
name: Routes.profile, name: Routes.profile,
page: () => const ProfileView(), page: () => const ProfileView(),
binding: ProfileBinding(), binding: ProfileBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.editProfile, name: Routes.editProfile,
page: () => const EditProfileView(), page: () => const EditProfileView(),
binding: ProfileBinding(), binding: ProfileBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.translation, name: Routes.translation,
page: () => const TranslationView(), page: () => const TranslationView(),
binding: TranslationBinding(), binding: TranslationBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.translationHistory, name: Routes.translationHistory,
page: () => const TranslationHistoryView(), page: () => const TranslationHistoryView(),
binding: TranslationHistoryBinding(), binding: TranslationHistoryBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.meeting, name: Routes.meeting,
page: () => const MeetingView(), page: () => const MeetingView(),
binding: MeetingBinding(), binding: MeetingBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.meetingRecord, name: Routes.meetingRecord,
page: () => const MeetingRecordView(), page: () => const MeetingRecordView(),
binding: MeetingRecordBinding(), binding: MeetingRecordBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.meetingDetails, name: Routes.meetingDetails,
page: () => const MeetingDetailsView(), page: () => const MeetingDetailsView(),
binding: MeetingDetailsBinding(), binding: MeetingDetailsBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.meetingEdit, name: Routes.meetingEdit,
page: () => const MeetingEditView(), page: () => const MeetingEditView(),
binding: MeetingEditBinding(), binding: MeetingEditBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.timbre, name: Routes.timbre,
page: () => const TimbreView(), page: () => const TimbreView(),
binding: TimbreBinding(), binding: TimbreBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.settings, name: Routes.settings,
page: () => const SettingsView(), page: () => const SettingsView(),
binding: SettingsBinding(), binding: SettingsBinding(),
transition: Transition.noTransition,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.feedback, name: Routes.feedback,
page: () => const FeedbackView(), page: () => const FeedbackView(),
binding: FeedbackBinding(), binding: FeedbackBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.jieliTest, name: Routes.jieliTest,
page: () => const JieliTestView(), page: () => const JieliTestView(),
binding: JieliTestBinding(), binding: JieliTestBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.opusTest, name: Routes.opusTest,
page: () => const OpusTestView(), page: () => const OpusTestView(),
binding: OpusTestBinding(), binding: OpusTestBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.speechTest, name: Routes.speechTest,
page: () => const SpeechTestView(), page: () => const SpeechTestView(),
binding: SpeechTestBinding(), binding: SpeechTestBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
GetPage( GetPage(
name: Routes.agent, name: Routes.agent,
page: () => const AgentView(), page: () => const AgentView(),
binding: AgentBinding(), binding: AgentBinding(),
transition: Transition.rightToLeft,
transitionDuration: Duration(milliseconds: 250),
), ),
]; ];
} }

1
local_plugins/agent_service/android/build.gradle.kts

@ -48,4 +48,5 @@ dependencies {
add("compileOnly", project(":deepvoice_utils")) add("compileOnly", project(":deepvoice_utils"))
add("compileOnly", project(":chat_storage")) add("compileOnly", project(":chat_storage"))
add("compileOnly", project(":ble_service")) add("compileOnly", project(":ble_service"))
add("compileOnly", project(":music_service"))
} }

4
local_plugins/agent_service/android/settings.gradle.kts

@ -5,11 +5,11 @@ include(":azure_speech")
include(":open_ai_service") include(":open_ai_service")
include(":deepvoice_utils") include(":deepvoice_utils")
include(":chat_storage") include(":chat_storage")
include(":deepvoice_utils") include(":music_service")
// 设置项目路径 // 设置项目路径
project(":azure_speech").projectDir = file("../../azure_speech/android") project(":azure_speech").projectDir = file("../../azure_speech/android")
project(":open_ai_service").projectDir = file("../../open_ai_service/android") project(":open_ai_service").projectDir = file("../../open_ai_service/android")
project(":deepvoice_utils").projectDir = file("../../deepvoice_utils/android") project(":deepvoice_utils").projectDir = file("../../deepvoice_utils/android")
project(":chat_storage").projectDir = file("../../chat_storage/android") project(":chat_storage").projectDir = file("../../chat_storage/android")
project(":deepvoice_utils").projectDir = file("../../deepvoice_utils/android") project(":music_service").projectDir = file("../../music_service/android")

78
local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt

@ -7,6 +7,7 @@ import com.yunqiinnovation.azure_speech.AzureAsrHelper
import com.yunqiinnovation.azure_speech.AzureTtsHelper import com.yunqiinnovation.azure_speech.AzureTtsHelper
import com.yunqiinnovation.open_ai_service.OpenAIService import com.yunqiinnovation.open_ai_service.OpenAIService
import com.yunqiinnovation.chat_storage.ChatStorageHelper import com.yunqiinnovation.chat_storage.ChatStorageHelper
import com.yunqiinnovation.music_service.MusicServiceStarter
import com.yunqiinnovation.deepvoice_utils.FileLogger import com.yunqiinnovation.deepvoice_utils.FileLogger
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
import kotlinx.coroutines.* import kotlinx.coroutines.*
@ -131,6 +132,7 @@ object AgentService : CoroutineScope {
// 自定义系统提示词 // 自定义系统提示词
val customSystemPrompt = config["systemPrompt"] as? String val customSystemPrompt = config["systemPrompt"] as? String
FileLogger.i(TAG, "初始化 系统提示词:$config")
if (!customSystemPrompt.isNullOrBlank()) { if (!customSystemPrompt.isNullOrBlank()) {
systemPrompt = customSystemPrompt systemPrompt = customSystemPrompt
} else { } else {
@ -558,6 +560,7 @@ object AgentService : CoroutineScope {
// 使用历史记录作为上下文发送到OpenAI // 使用历史记录作为上下文发送到OpenAI
val responseBuilder = StringBuilder() val responseBuilder = StringBuilder()
var metadata:String = ""
// 添加系统提示词到历史消息的副本中 // 添加系统提示词到历史消息的副本中
val messagesWithSystemPrompt = JSONArray() val messagesWithSystemPrompt = JSONArray()
@ -636,7 +639,7 @@ object AgentService : CoroutineScope {
addToHistoryMessages(openAIService.createAssistantMessage(response)) addToHistoryMessages(openAIService.createAssistantMessage(response))
// 保存聊天记录 // 保存聊天记录
saveChatMessage(displayText, response) saveChatMessage(displayText, response,metadata)
} }
// 标记AI流式输出已完成 // 标记AI流式输出已完成
@ -672,6 +675,42 @@ object AgentService : CoroutineScope {
"result" to functionCallResult.toString(), "result" to functionCallResult.toString(),
)) ))
FileLogger.d(TAG, "mcp调用结果: $functionCallResult") FileLogger.d(TAG, "mcp调用结果: $functionCallResult")
val metaStr = functionCallResult.optString("meta")
if (metaStr.isNotEmpty()) {
metadata = metaStr;
val meta = JSONObject(metaStr)
FileLogger.d(TAG, "mcp调用结果: $metaStr")
if (meta.has("card_music")) { //音乐卡片
val cardMusic = meta.getJSONObject("card_music")
FileLogger.d(TAG, "检查到音乐卡片: $cardMusic")
val musicUrl = cardMusic.optString("url", "")
val name = cardMusic.optString("name", "")
val sgener = cardMusic.optString("sgener", "")
processMusicPlay(musicUrl, name, sgener)
}else if (meta.has("card_musiclist")) { //音乐列表
val cardMusiclist = meta.getJSONObject("card_musiclist")
val musics = cardMusiclist.optJSONArray("musics")
if (musics != null) {
val playlist = mutableListOf<Map<String, String>>()
for (i in 0 until musics.length()) {
val item = musics.optJSONObject(i) ?: continue
val url = item.optString("url", "")
val name = item.optString("name", "")
val sgener = item.optString("sgener", "")
if (url.isNotEmpty()) {
playlist.add(mapOf("url" to url, "name" to name, "sgener" to sgener))
}
}
if (playlist.isNotEmpty()) {
processMusicPlayList(playlist)
} else {
FileLogger.w(TAG, "card_musiclist 中没有有效的音乐条目")
}
} else {
FileLogger.w(TAG, "card_musiclist.musics 不是一个数组")
}
}
}
} }
} }
) )
@ -770,7 +809,7 @@ object AgentService : CoroutineScope {
/** /**
* 保存聊天消息 * 保存聊天消息
*/ */
private fun saveChatMessage(userMessage: String, assistantMessage: String) { private fun saveChatMessage(userMessage: String, assistantMessage: String,metadata : String) {
launch(Dispatchers.IO) { launch(Dispatchers.IO) {
try { try {
// 保存用户消息 // 保存用户消息
@ -785,7 +824,8 @@ object AgentService : CoroutineScope {
val assistantMessageId = chatStorageHelper.saveMessage( val assistantMessageId = chatStorageHelper.saveMessage(
sessionId = sessionId, sessionId = sessionId,
message = assistantMessage, message = assistantMessage,
sender = "assistant" sender = "assistant",
metadata = metadata
) )
// if (assistantMessageId != -1L) { // if (assistantMessageId != -1L) {
@ -948,4 +988,36 @@ object AgentService : CoroutineScope {
return true return true
} }
/**
* 处理音乐播放
* 将ai返回的音乐连接 在后台启动播放
*
* @param musicUrl 图片文件路径
* @param name 歌曲名称,默认为空
* @param singer 歌手,默认为false
* @return 是否成功开始处理
*/
fun processMusicPlay(musicUrl:String,name: String = "",singer:String = ""){
// 在其他 Service、BroadcastReceiver 或 Application 中调用
FileLogger.i(TAG, "启动音乐服务 播放音乐 $musicUrl")
MusicServiceStarter.startServiceWithCommand(context, "play", url = musicUrl)
}
/**
* 处理音乐播放列表
* 将ai返回的音乐连接 在后台启动播放
*
* @param musicUrl 图片文件路径
* @param name 歌曲名称,默认为空
* @param singer 歌手,默认为false
* @return 是否成功开始处理
*/
fun processMusicPlayList(playlist:List<Map<String,String>>){
// 在其他 Service、BroadcastReceiver 或 Application 中调用
val urls = playlist.mapNotNull { it["url"] }.distinct()
FileLogger.i(TAG, "启动音乐服务 播放音乐列表 $urls")
MusicServiceStarter.startServiceWithPlaylist(context, "playlist", urls = urls)
}
} }

1
local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentServicePlugin.kt

@ -57,6 +57,7 @@ class AgentServicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.Stream
config["openaiApiKey"]?.toString()?.let { intent.putExtra("openaiApiKey", it) } config["openaiApiKey"]?.toString()?.let { intent.putExtra("openaiApiKey", it) }
config["openaiBaseUrl"]?.toString()?.let { intent.putExtra("openaiBaseUrl", it) } config["openaiBaseUrl"]?.toString()?.let { intent.putExtra("openaiBaseUrl", it) }
config["openaiModel"]?.toString()?.let { intent.putExtra("openaiModel", it) } config["openaiModel"]?.toString()?.let { intent.putExtra("openaiModel", it) }
config["systemPrompt"]?.toString()?.let { intent.putExtra("systemPrompt", it) }
config["mcpServer"]?.toString()?.let { intent.putExtra("mcpServer", it) } config["mcpServer"]?.toString()?.let { intent.putExtra("mcpServer", it) }
// 启动前台服务 // 启动前台服务

3
local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleMediaService.kt

@ -54,6 +54,7 @@ class BleMediaService : Service(), CoroutineScope {
private const val KEY_OPENAI_API_KEY = "openaiApiKey" private const val KEY_OPENAI_API_KEY = "openaiApiKey"
private const val KEY_OPENAI_BASE_URL = "openaiBaseUrl" private const val KEY_OPENAI_BASE_URL = "openaiBaseUrl"
private const val KEY_OPENAI_MODEL = "openaiModel" private const val KEY_OPENAI_MODEL = "openaiModel"
private const val KEY_SYSTEM_PROMPT = "systemPrompt"
private const val KEY_MCP_SERVER = "mcpServer" private const val KEY_MCP_SERVER = "mcpServer"
// 用于跟踪服务是否正在运行 // 用于跟踪服务是否正在运行
@ -213,6 +214,7 @@ class BleMediaService : Service(), CoroutineScope {
it.getStringExtra(KEY_OPENAI_API_KEY)?.let { value -> config[KEY_OPENAI_API_KEY] = value } it.getStringExtra(KEY_OPENAI_API_KEY)?.let { value -> config[KEY_OPENAI_API_KEY] = value }
it.getStringExtra(KEY_OPENAI_BASE_URL)?.let { value -> config[KEY_OPENAI_BASE_URL] = value } it.getStringExtra(KEY_OPENAI_BASE_URL)?.let { value -> config[KEY_OPENAI_BASE_URL] = value }
it.getStringExtra(KEY_OPENAI_MODEL)?.let { value -> config[KEY_OPENAI_MODEL] = value } it.getStringExtra(KEY_OPENAI_MODEL)?.let { value -> config[KEY_OPENAI_MODEL] = value }
it.getStringExtra(KEY_SYSTEM_PROMPT)?.let { value -> config[KEY_SYSTEM_PROMPT] = value }
it.getStringExtra(KEY_MCP_SERVER)?.let { value -> config[KEY_MCP_SERVER] = value } it.getStringExtra(KEY_MCP_SERVER)?.let { value -> config[KEY_MCP_SERVER] = value }
} }
FileLogger.i(TAG, "从Intent中提取到配置参数: $config") FileLogger.i(TAG, "从Intent中提取到配置参数: $config")
@ -243,6 +245,7 @@ class BleMediaService : Service(), CoroutineScope {
KEY_OPENAI_API_KEY to getConfigString(prefs, KEY_OPENAI_API_KEY, ""), KEY_OPENAI_API_KEY to getConfigString(prefs, KEY_OPENAI_API_KEY, ""),
KEY_OPENAI_BASE_URL to getConfigString(prefs, KEY_OPENAI_BASE_URL, "https://api.openai.com/v1"), KEY_OPENAI_BASE_URL to getConfigString(prefs, KEY_OPENAI_BASE_URL, "https://api.openai.com/v1"),
KEY_OPENAI_MODEL to getConfigString(prefs, KEY_OPENAI_MODEL, "gpt-3.5-turbo"), KEY_OPENAI_MODEL to getConfigString(prefs, KEY_OPENAI_MODEL, "gpt-3.5-turbo"),
KEY_SYSTEM_PROMPT to getConfigString(prefs, KEY_SYSTEM_PROMPT, "gpt-3.5-turbo"),
KEY_MCP_SERVER to getConfigString(prefs, KEY_MCP_SERVER, "") KEY_MCP_SERVER to getConfigString(prefs, KEY_MCP_SERVER, "")
) )
} }

8
local_plugins/music_service/android/src/main/AndroidManifest.xml

@ -1,6 +1,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yunqiinnovation.music_service"> package="com.yunqiinnovation.music_service">
<!-- 基础前台服务权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Android 14 及以上需要声明具体的前台服务类型权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<application> <application>
<service <service
android:name=".MusicService" android:name=".MusicService"

229
local_plugins/music_service/android/src/main/kotlin/com/yunqiinnovation/music_service/MusicService.kt

@ -1,10 +1,6 @@
package com.yunqiinnovation.music_service package com.yunqiinnovation.music_service
import android.app.Notification import android.app.*
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.media.AudioManager import android.media.AudioManager
@ -13,8 +9,7 @@ import android.os.Build
import android.os.IBinder import android.os.IBinder
import android.util.Log import android.util.Log
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import com.yunqiinnovation.music_service.MusicServiceStarter import com.yunqiinnovation.deepvoice_utils.FileLogger
import kotlinx.coroutines.CoroutineScope
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
class MusicService : Service() { class MusicService : Service() {
@ -23,131 +18,187 @@ class MusicService : Service() {
private const val TAG = "MusicService" private const val TAG = "MusicService"
private const val CHANNEL_ID = "music_media_service_channel" private const val CHANNEL_ID = "music_media_service_channel"
private const val NOTIFICATION_ID = 1002 private const val NOTIFICATION_ID = 1002
private const val PREF_NAME = "deep_voice_config"
// 用于跟踪服务是否正在运行
private val isRunning = AtomicBoolean(false) private val isRunning = AtomicBoolean(false)
private var currentStatus: Boolean = false
private var currentUrlInternal: String? = null
// 获取服务运行状态
fun isServiceRunning(): Boolean = isRunning.get() fun isServiceRunning(): Boolean = isRunning.get()
fun isPlaying(): Boolean = currentStatus
fun getCurrentUrl(): String? = currentUrlInternal
} }
private var mediaPlayer: MediaPlayer? = null private var mediaPlayer: MediaPlayer? = null
private val playlist = mutableListOf<String>() // 可扩展支持播放列表 private val playlist = mutableListOf<String>() // 可选:初始化为预置歌曲
private var currentIndex = 0 private var currentIndex = 0
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
val notification = createNotification() // 创建一个非空通知 FileLogger.init(this)
startForeground(1, notification) FileLogger.i(TAG, "MusicService 正在创建...")
} isRunning.set(true)
private var isPlaying = false Log.i(TAG, "MusicService Created")
/** startForeground(NOTIFICATION_ID, createNotification("等待播放..."))
* 创建前台服务通知 isRunning.set(true)
*/
private fun createNotification(): Notification {
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Android 8.0+ 需要创建通知渠道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
"音乐播放服务",
NotificationManager.IMPORTANCE_LOW
)
manager.createNotificationChannel(channel)
}
// 点击通知打开主界面
val intent = packageManager.getLaunchIntentForPackage(packageName)?.apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
}
val pendingIntent = if (intent != null) {
PendingIntent.getActivity(
this,
0,
intent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
} else {
null
}
// 构建通知
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("DeepSound")
.setContentText(if (isPlaying) "正在播放" else "已暂停")
.setSmallIcon(android.R.drawable.ic_media_play)
// 设置点击意图
pendingIntent?.let { builder.setContentIntent(it) }
return builder.build()
} }
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val command = intent?.getStringExtra("command") ?: return START_NOT_STICKY val command = intent?.getStringExtra("command") ?: return START_NOT_STICKY
Log.i(TAG, "onStartCommand: $command") Log.i(TAG, "onStartCommand: $command" )
when (command) { when (command) {
"play" -> { "play" -> {
val url = intent.getStringExtra("url") ?: return START_NOT_STICKY val url = intent.getStringExtra("url") ?: return START_NOT_STICKY
if (!playlist.contains(url)) playlist.add(url)
currentIndex = playlist.indexOf(url)
play(url) play(url)
} }
"pause" -> mediaPlayer?.pause() "playlist" -> {
"resume" -> mediaPlayer?.start() val urls = intent.getStringArrayListExtra("urls")?.filter { it.isNotEmpty() } ?: return START_NOT_STICKY
Log.i(TAG, "后台服务播放 playlist: $urls" )
if (urls.isNotEmpty()) {
playlist.clear()
playlist.addAll(urls)
currentIndex = 0
play(playlist[currentIndex])
} else {
Log.w(TAG, "playlist 命令收到空列表")
}
}
"pause" -> pause()
"resume" -> resume()
"stop" -> stopSelf() "stop" -> stopSelf()
"next" -> { "next" -> {
currentIndex++ if (currentIndex + 1 < playlist.size) {
if (currentIndex < playlist.size) play(playlist[currentIndex]) currentIndex++
play(playlist[currentIndex])
}
} }
"previous" -> { "previous" -> {
currentIndex-- if (currentIndex - 1 >= 0) {
if (currentIndex >= 0) play(playlist[currentIndex]) currentIndex--
play(playlist[currentIndex])
}
} }
"setVolume" -> { "setVolume" -> {
val volume = intent.getFloatExtra("volume", 1.0f) val volume = intent.getFloatExtra("volume", 1.0f).coerceIn(0f, 1f)
mediaPlayer?.setVolume(volume, volume) mediaPlayer?.setVolume(volume, volume)
} }
} }
return START_STICKY return START_STICKY
} }
private fun play(url: String) { private fun play(url: String) {
Log.i(TAG, "开始播放音乐: $url") Log.i(TAG, "播放音乐: $url")
mediaPlayer?.release() releaseMediaPlayer()
currentStatus = true;
currentUrlInternal = url;
mediaPlayer = MediaPlayer().apply { mediaPlayer = MediaPlayer().apply {
setDataSource(url) setDataSource(url)
setAudioStreamType(AudioManager.STREAM_MUSIC) setAudioStreamType(AudioManager.STREAM_MUSIC)
setOnPreparedListener {
start()
currentStatus = true
updateNotification("正在播放")
Log.i(TAG, "开始播放")
}
setOnCompletionListener {
Log.i(TAG, "播放完成")
// 播放下一首
if (currentIndex + 1 < playlist.size) {
currentIndex++
play(playlist[currentIndex]) // 播放下一首
} else {
currentStatus = false
stopSelf() // 如果没有更多歌曲了,可以停止服务
}
}
setOnErrorListener { _, what, extra ->
Log.e(TAG, "播放错误: what=$what extra=$extra")
currentStatus = false
stopSelf()
true
}
prepareAsync() prepareAsync()
setOnPreparedListener { start() }
setOnCompletionListener { stopSelf() }
} }
// startForeground(1, NotificationUtils.createNotification(this, "Playing...")) }
private fun pause() {
mediaPlayer?.let {
if (it.isPlaying) {
it.pause()
currentStatus= false
updateNotification("已暂停")
Log.i(TAG, "暂停播放")
}
}
}
private fun resume() {
mediaPlayer?.let {
if (!it.isPlaying) {
it.start()
currentStatus = true
updateNotification("继续播放")
Log.i(TAG, "继续播放")
}
}
}
private fun releaseMediaPlayer() {
mediaPlayer?.apply {
stop()
release()
}
mediaPlayer = null
}
private fun updateNotification(contentText: String) {
val notification = createNotification(contentText)
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.notify(NOTIFICATION_ID, notification)
}
private fun createNotification(contentText: String): Notification {
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
"音乐播放服务",
NotificationManager.IMPORTANCE_LOW
)
manager.createNotificationChannel(channel)
}
val intent = packageManager.getLaunchIntentForPackage(packageName)?.apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
}
val pendingIntent = intent?.let {
PendingIntent.getActivity(
this, 0, it,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
}
return NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("DeepSound")
.setContentText(contentText)
.setSmallIcon(android.R.drawable.ic_media_play)
.setContentIntent(pendingIntent)
.setOngoing(true)
.build()
} }
override fun onDestroy() { override fun onDestroy() {
mediaPlayer?.release() Log.i(TAG, "服务销毁,释放播放器")
releaseMediaPlayer()
stopForeground(true) stopForeground(true)
isRunning.set(false)
super.onDestroy() super.onDestroy()
} }
override fun onBind(intent: Intent?): IBinder? = null override fun onBind(intent: Intent?): IBinder? = null
/**
* 释放资源
*/
fun release() {
try {
mediaPlayer?.apply {
if (isPlaying) stop()
release()
}
mediaPlayer = null
} catch (e: Exception) {
// 忽略异常
}
}
/**
* 是否正在播放
*/
fun isPlaying() = mediaPlayer?.isPlaying == true
} }

15
local_plugins/music_service/android/src/main/kotlin/com/yunqiinnovation/music_service/MusicServicePlugin.kt

@ -18,7 +18,7 @@ class MusicServicePlugin: FlutterPlugin, MethodCallHandler {
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
context = flutterPluginBinding.applicationContext context = flutterPluginBinding.applicationContext
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "music_service") channel = MethodChannel(flutterPluginBinding.binaryMessenger, "com.yunqiinnovation.music_service")
channel.setMethodCallHandler(this) channel.setMethodCallHandler(this)
} }
@ -30,6 +30,10 @@ class MusicServicePlugin: FlutterPlugin, MethodCallHandler {
val url = call.argument<String>("url") val url = call.argument<String>("url")
MusicServiceStarter.startServiceWithCommand(context, "play", url) MusicServiceStarter.startServiceWithCommand(context, "play", url)
} }
"playlist" -> {
val urls = call.argument<List<String>>("urls")
MusicServiceStarter.startServiceWithPlaylist(context, "playlist", urls)
}
"pause" -> MusicServiceStarter.startServiceWithCommand(context, "pause") "pause" -> MusicServiceStarter.startServiceWithCommand(context, "pause")
"resume" -> MusicServiceStarter.startServiceWithCommand(context, "resume") "resume" -> MusicServiceStarter.startServiceWithCommand(context, "resume")
"stop" -> MusicServiceStarter.startServiceWithCommand(context, "stop") "stop" -> MusicServiceStarter.startServiceWithCommand(context, "stop")
@ -37,6 +41,15 @@ class MusicServicePlugin: FlutterPlugin, MethodCallHandler {
val volume = call.argument<Double>("volume")?.toFloat() val volume = call.argument<Double>("volume")?.toFloat()
MusicServiceStarter.startServiceWithCommand(context, "setVolume", volume = volume) MusicServiceStarter.startServiceWithCommand(context, "setVolume", volume = volume)
} }
"getStatus" -> {
val isPlaying = MusicService.isPlaying()
val currentUrl = MusicService.getCurrentUrl()
val status = mapOf(
"isPlaying" to isPlaying,
"url" to currentUrl
)
result.success(status)
}
else -> result.notImplemented() else -> result.notImplemented()
} }
result.success(null) result.success(null)

11
local_plugins/music_service/android/src/main/kotlin/com/yunqiinnovation/music_service/MusicServiceStarter.kt

@ -7,6 +7,7 @@ import androidx.core.content.ContextCompat
object MusicServiceStarter { object MusicServiceStarter {
private val TAG = "MusicServiceStarter" private val TAG = "MusicServiceStarter"
//播放单曲
fun startServiceWithCommand(context: Context, command: String, url: String? = null, volume: Float? = null) { fun startServiceWithCommand(context: Context, command: String, url: String? = null, volume: Float? = null) {
Log.i(TAG, "startServiceWithCommand: $command $url") Log.i(TAG, "startServiceWithCommand: $command $url")
val intent = Intent(context, MusicService::class.java).apply { val intent = Intent(context, MusicService::class.java).apply {
@ -16,4 +17,14 @@ object MusicServiceStarter {
} }
ContextCompat.startForegroundService(context, intent) ContextCompat.startForegroundService(context, intent)
} }
//启动播放列表
fun startServiceWithPlaylist(context: Context,command: String, urls: List<String>?,volume: Float? = null) {
Log.i(TAG, "startServiceWithPlaylist: $urls")
val intent = Intent(context, MusicService::class.java).apply {
putExtra("command", command)
putStringArrayListExtra("urls", ArrayList(urls!!)) // 注意类型是 ArrayList<String>
}
ContextCompat.startForegroundService(context, intent)
}
} }

7
local_plugins/music_service/lib/music_service.dart

@ -52,4 +52,11 @@ class MusicService {
'setVolume', 'setVolume',
{'volume': volume}, {'volume': volume},
); // volume: 0.0~1.0 ); // volume: 0.0~1.0
Future<Map<String, dynamic>> getStatus() async {
final result = await _methodChannel.invokeMethod<Map>('getStatus');
return {
'isPlaying': result?['isPlaying'] ?? false,
'url': result?['url'] ?? "",
};
}
} }

Loading…
Cancel
Save