""" Vietnamese Pronunciation Tips for English Learners Mẹo phát âm tiếng Anh dành cho người Việt Nam This module provides detailed pronunciation guidance in Vietnamese for common English phonemes that are challenging for Vietnamese speakers. """ from typing import Dict, List, Optional, Tuple from dataclasses import dataclass import random @dataclass class PronunciationTip: """Structured pronunciation tip with detailed guidance""" phoneme: str vietnamese_name: str mouth_position: str tongue_position: str breathing: str common_mistakes: List[str] practice_words: List[str] detailed_instruction: str difficulty_level: int # 1-5, where 5 is most difficult class VietnameseTipsProvider: """Provides detailed pronunciation tips in Vietnamese for English learners""" def __init__(self): self.tips_database = self._initialize_tips_database() self.error_patterns = self._initialize_error_patterns() def _initialize_tips_database(self) -> Dict[str, PronunciationTip]: """Initialize comprehensive tips database""" tips = { # Consonants that are difficult for Vietnamese speakers "θ": PronunciationTip( phoneme="θ", vietnamese_name="âm th không thanh (như trong 'think')", mouth_position="Miệng mở vừa phải, môi tự nhiên", tongue_position="Đưa lưỡi ra ngoài, đặt giữa răng trên và răng dưới", breathing="Thổi khí nhẹ qua khe giữa lưỡi và răng", common_mistakes=[ "Phát âm thành /f/ (như 'think' thành 'fink')", "Phát âm thành /s/ (như 'think' thành 'sink')", "Phát âm thành /t/ (như 'think' thành 'tink')", ], practice_words=["think", "three", "thank", "thing", "throw"], detailed_instruction=""" Cách luyện tập chi tiết: 1. Đưa lưỡi ra ngoài sao cho đầu lưỡi chạm nhẹ vào răng trên 2. Thổi khí nhẹ qua khe giữa lưỡi và răng - KHÔNG rung dây thanh 3. Luyện tập từ 'think' - bắt đầu chậm, sau đó tăng tốc 4. Đặt gương trước mặt để kiểm tra vị trí lưỡi 5. Luyện tập 10-15 phút mỗi ngày """, difficulty_level=5, ), "ð": PronunciationTip( phoneme="ð", vietnamese_name="âm th có thanh (như trong 'this')", mouth_position="Miệng mở vừa phải, môi tự nhiên", tongue_position="Đưa lưỡi ra ngoài, đặt giữa răng trên và răng dưới", breathing="Rung dây thanh và thổi khí nhẹ", common_mistakes=[ "Phát âm thành /d/ (như 'this' thành 'dis')", "Phát âm thành /z/ (như 'this' thành 'zis')", "Phát âm thành /v/ (như 'this' thành 'vis')", ], practice_words=["this", "that", "they", "there", "mother"], detailed_instruction=""" Cách luyện tập chi tiết: 1. Giống như âm /θ/ nhưng phải rung dây thanh 2. Đặt tay lên cổ họng để cảm nhận rung động 3. Bắt đầu với âm /z/, sau đó đưa lưỡi ra giữa răng 4. Luyện cặp từ: 'sink/think' và 'zis/this' 5. Tập đọc câu: 'This is the thing they threw' """, difficulty_level=5, ), "v": PronunciationTip( phoneme="v", vietnamese_name="âm v (như trong 'very')", mouth_position="Môi dưới chạm nhẹ vào răng trên", tongue_position="Lưỡi ở vị trí tự nhiên, không chạm răng", breathing="Rung dây thanh, khí thổi qua khe môi-răng", common_mistakes=[ "Phát âm thành /w/ (như 'very' thành 'wery')", "Phát âm thành /f/ (như 'very' thành 'fery')", "Dùng cả hai môi như âm /w/ trong tiếng Việt", ], practice_words=["very", "voice", "video", "love", "have"], detailed_instruction=""" Cách luyện tập chi tiết: 1. CHỈ dùng môi dưới chạm răng trên - đây là điểm khác biệt chính 2. Đừng dùng cả hai môi như âm 'u' trong tiếng Việt 3. Luyện phân biệt: 'west/vest', 'wine/vine' 4. Đặt ngón tay lên môi trên để tránh cử động 5. Tập đọc: 'Very valuable video' """, difficulty_level=4, ), "w": PronunciationTip( phoneme="w", vietnamese_name="âm w (như trong 'water')", mouth_position="Cả hai môi chu tròn như âm 'u'", tongue_position="Lưỡi co lại ở phía sau", breathing="Rung dây thanh, thổi qua môi tròn", common_mistakes=[ "Phát âm thành /v/ (như 'water' thành 'vater')", "Không chu môi đủ tròn", "Lưỡi đặt sai vị trí", ], practice_words=["water", "wind", "wall", "woman", "sweet"], detailed_instruction=""" Cách luyện tập chi tiết: 1. Bắt đầu với âm 'u' trong tiếng Việt, sau đó chuyển sang âm tiếp theo 2. Cả hai môi phải chu tròn - không chỉ môi dưới 3. Luyện phân biệt: 'vest/west', 'vine/wine' 4. Tập nói chậm: 'W-A-T-E-R' rồi tăng tốc 5. Luyện câu: 'We went to the west wall' """, difficulty_level=3, ), "r": PronunciationTip( phoneme="r", vietnamese_name="âm r tiếng Anh (như trong 'red')", mouth_position="Miệng mở vừa, không mỉm cười", tongue_position="Cuộn lưỡi lên không chạm vòm miệng", breathing="Rung dây thanh, khí đi qua lưỡi cuộn", common_mistakes=[ "Cuộn lưỡi quá mạnh như tiếng Việt", "Lưỡi chạm vào vòm miệng", "Phát âm thành /l/", "Rung lưỡi như âm 'r' tiếng Việt", ], practice_words=["red", "run", "right", "car", "very"], detailed_instruction=""" Cách luyện tập chi tiết: 1. Cuộn lưỡi lên NHƯNG KHÔNG chạm vào vòm miệng 2. Âm /r/ tiếng Anh mềm hơn nhiều so với tiếng Việt 3. Luyện phân biệt: 'light/right', 'long/wrong' 4. Bắt đầu với âm 'ơ' rồi cuộn lưỡi nhẹ 5. Tập từ cuối: 'car', 'far', 'star' - đây dễ hơn """, difficulty_level=4, ), "l": PronunciationTip( phoneme="l", vietnamese_name="âm l tiếng Anh (như trong 'love')", mouth_position="Miệng mở tự nhiên", tongue_position="Đầu lưỡi chạm vào nướu răng trên", breathing="Rung dây thanh, khí đi qua hai bên lưỡi", common_mistakes=[ "Phát âm thành /r/", "Đầu lưỡi không chạm đúng vị trí", "Phát âm quá nặng như tiếng Việt", ], practice_words=["love", "light", "blue", "apple", "wall"], detailed_instruction=""" Cách luyện tập chi tiết: 1. Đầu lưỡi phải chạm vào nướu răng trên, không phải răng 2. Âm /l/ tiếng Anh nhẹ hơn tiếng Việt 3. Luyện phân biệt: 'right/light', 'wrong/long' 4. Tập âm /l/ cuối từ: 'wall', 'ball', 'call' 5. Luyện câu: 'Lucy loves blue apples' """, difficulty_level=3, ), "z": PronunciationTip( phoneme="z", vietnamese_name="âm z (như trong 'zero')", mouth_position="Miệng như âm /s/ nhưng rung dây thanh", tongue_position="Đầu lưỡi gần răng trên nhưng không chạm", breathing="Rung dây thanh, khí đi qua khe nhỏ", common_mistakes=[ "Phát âm thành /s/ (không rung dây thanh)", "Phát âm thành /dʒ/ (như 'gi' trong tiếng Việt)", "Quá to, quá rõ", ], practice_words=["zero", "zoo", "easy", "buzz", "maze"], detailed_instruction=""" Cách luyện tập chi tiết: 1. Giống hệt âm /s/ nhưng phải rung dây thanh 2. Đặt tay lên cổ họng để kiểm tra rung động 3. Luyện cặp: 'sip/zip', 'seal/zeal' 4. Bắt đầu với âm 's' rồi thêm rung dây thanh 5. Tập câu: 'Zero zebras in the zoo' """, difficulty_level=3, ), "ʒ": PronunciationTip( phoneme="ʒ", vietnamese_name="âm zh (như trong 'measure')", mouth_position="Môi chu tròn nhẹ", tongue_position="Đầu lưỡi gần vòm miệng nhưng không chạm", breathing="Rung dây thanh, khí đi qua khe rộng hơn /z/", common_mistakes=[ "Phát âm thành /ʃ/ (như 'sh' nhưng không thanh)", "Phát âm thành /z/", "Quá giống âm 'gi' tiếng Việt", ], practice_words=["measure", "pleasure", "vision", "usual", "garage"], detailed_instruction=""" Cách luyện tập chi tiết: 1. Giống âm /ʃ/ (sh) nhưng có rung dây thanh 2. Luyện cặp: 'ship/vision', 'cash/casual' 3. Bắt đầu với 'sh' rồi thêm thanh âm 4. Âm này ít gặp ở đầu từ, nhiều ở giữa và cuối 5. Tập câu: 'It's my pleasure to measure' """, difficulty_level=4, ), "ʃ": PronunciationTip( phoneme="ʃ", vietnamese_name="âm sh (như trong 'ship')", mouth_position="Môi chu tròn nhẹ, hơi thụt vào", tongue_position="Lưỡi cong lên gần vòm miệng", breathing="Không rung dây thanh, thổi khí mạnh", common_mistakes=[ "Phát âm thành /s/", "Không chu môi", "Lưỡi đặt sai vị trí", ], practice_words=["ship", "shoe", "wash", "fish", "shell"], detailed_instruction=""" Cách luyện tập chi tiết: 1. Chu môi như chuẩn bị huýt sáo nhưng nhẹ hơn 2. Lưỡi cong lên, tạo khoảng rộng hơn âm /s/ 3. Luyện phân biệt: 'sip/ship', 'sass/shash' 4. Âm /ʃ/ dài hơn và êm hơn âm /s/ 5. Tập câu: 'She sells seashells' """, difficulty_level=3, ), # Vowels challenging for Vietnamese speakers "æ": PronunciationTip( phoneme="æ", vietnamese_name="âm ae (như trong 'cat')", mouth_position="Miệng mở rộng, góc miệng kéo ra", tongue_position="Lưỡi thấp, phẳng ở đáy miệng", breathing="Rung dây thanh", common_mistakes=[ "Phát âm thành /ɛ/ (như 'bet')", "Phát âm thành /a/ (như 'car')", "Không mở miệng đủ rộng", ], practice_words=["cat", "hat", "bad", "man", "apple"], detailed_instruction=""" Cách luyện tập chi tiết: 1. Mở miệng rộng như đang cười nhưng kéo dài 2. Lưỡi phải thấp xuống đáy miệng 3. Luyện phân biệt: 'bet/bat', 'pen/pan' 4. Âm này không có trong tiếng Việt 5. Tập câu: 'The fat cat sat on the mat' """, difficulty_level=4, ), "ɪ": PronunciationTip( phoneme="ɪ", vietnamese_name="âm i ngắn (như trong 'bit')", mouth_position="Miệng mở hẹp hơn âm /i/", tongue_position="Lưỡi hơi thấp hơn âm /i/ dài", breathing="Rung dây thanh, âm ngắn", common_mistakes=[ "Phát âm thành /i/ dài (như 'bee')", "Kéo dài âm quá mức", "Lưỡi đặt quá cao", ], practice_words=["bit", "sit", "big", "fish", "list"], detailed_instruction=""" Cách luyện tập chi tiết: 1. Ngắn và thư giãn hơn âm /i/ dài 2. Miệng mở hơi rộng hơn âm /i/ 3. Luyện phân biệt: 'bit/beat', 'sit/seat' 4. Đừng kéo dài như âm 'i' tiếng Việt 5. Tập câu: 'The big fish sits in the dish' """, difficulty_level=3, ), "ʊ": PronunciationTip( phoneme="ʊ", vietnamese_name="âm u ngắn (như trong 'book')", mouth_position="Môi chu tròn nhẹ, không căng", tongue_position="Lưỡi co lại ở phía sau, thấp hơn /u/", breathing="Rung dây thanh, âm ngắn", common_mistakes=[ "Phát âm thành /u/ dài (như 'boot')", "Chu môi quá mạnh", "Kéo dài âm", ], practice_words=["book", "look", "good", "put", "could"], detailed_instruction=""" Cách luyện tập chi tiết: 1. Thư giãn hơn âm /u/ dài 2. Môi chu tròn nhẹ, không căng 3. Luyện phân biệt: 'book/boot', 'look/Luke' 4. Âm ngắn và êm dịu 5. Tập câu: 'Look at the good book' """, difficulty_level=3, ), "ŋ": PronunciationTip( phoneme="ŋ", vietnamese_name="âm ng (như trong 'sing')", mouth_position="Miệng mở tự nhiên", tongue_position="Phần sau lưỡi chạm vào vòm miệng mềm", breathing="Rung dây thanh, khí đi qua mũi", common_mistakes=[ "Thêm âm /g/ ở cuối (sing thành 'singg')", "Phát âm thành /n/", "Không dùng mũi", ], practice_words=["sing", "ring", "long", "thing", "walking"], detailed_instruction=""" Cách luyện tập chi tiết: 1. Phần sau lưỡi chạm vòm miệng mềm - như chuẩn bị nuốt 2. KHÔNG phát âm /g/ ở cuối 3. Khí ra qua mũi, không qua miệng 4. Luyện: 'sin' vs 'sing' - cảm nhận khác biệt 5. Tập câu: 'The king is singing a long song' """, difficulty_level=2, ), } return tips def _initialize_error_patterns(self) -> Dict[str, List[str]]: """Initialize common error patterns for Vietnamese speakers""" return { "th_sounds": [ "Âm /θ/ và /ð/ là khó nhất với người Việt - hãy kiên nhẫn luyện tập", "Đặt gương trước mặt để kiểm tra vị trí lưỡi khi phát âm /θ/ và /ð/", "Luyện tập /θ/ và /ð/ ít nhất 10 phút mỗi ngày", ], "v_w_confusion": [ "Nhớ: âm /v/ chỉ dùng môi dưới, âm /w/ dùng cả hai môi", "Luyện cặp từ: 'very/wary', 'vest/west' để phân biệt /v/ và /w/", "Đặt ngón tay lên môi trên khi tập âm /v/ để tránh cử động", ], "r_l_confusion": [ "Âm /r/ tiếng Anh không rung lưỡi như tiếng Việt", "Âm /l/ cần đầu lưỡi chạm nướu răng trên", "Luyện từ có cả /r/ và /l/: 'really', 'library', 'world'", ], "final_consonants": [ "Phát âm âm cuối rõ ràng nhưng không thêm nguyên âm", "Tập nhóm âm cuối: -st, -nd, -th, -ng", "Đừng nuốt âm cuối như trong tiếng Việt", ], "vowel_length": [ "Phân biệt nguyên âm dài/ngắn: /i/ vs /ɪ/, /u/ vs /ʊ/", "Nguyên âm tiếng Anh có nhiều biến thể hơn tiếng Việt", "Luyện các cặp tối thiểu: 'bit/beat', 'book/boot'", ], } def get_detailed_tip(self, phoneme: str) -> Optional[PronunciationTip]: """Get detailed pronunciation tip for a specific phoneme""" return self.tips_database.get(phoneme) def get_error_pattern_tips(self, error_phonemes: List[str]) -> List[str]: """Get tips based on common error patterns""" tips = [] # Analyze error patterns has_th_sounds = any(p in ["θ", "ð"] for p in error_phonemes) has_v_w = any(p in ["v", "w"] for p in error_phonemes) has_r_l = any(p in ["r", "l"] for p in error_phonemes) if has_th_sounds: tips.extend(random.sample(self.error_patterns["th_sounds"], 2)) if has_v_w: tips.extend(random.sample(self.error_patterns["v_w_confusion"], 1)) if has_r_l: tips.extend(random.sample(self.error_patterns["r_l_confusion"], 1)) return tips def get_comprehensive_feedback( self, incorrect_phonemes: List[str], difficulty_threshold: float = 0.7 ) -> Dict[str, any]: """ Generate comprehensive feedback with detailed tips Args: incorrect_phonemes: List of phonemes that were pronounced incorrectly difficulty_threshold: Score threshold below which to provide detailed tips Returns: Dictionary with comprehensive feedback and tips """ if not incorrect_phonemes: return { "status": "excellent", "message": "Phát âm xuất sắc! Bạn đã phát âm chính xác.", "tips": [], "practice_suggestions": [ "Tiếp tục luyện tập để duy trì độ chính xác", "Thử các từ khó hơn để thách thức bản thân", ], } # Get detailed tips for each problematic phoneme detailed_tips = [] practice_words = set() for phoneme in incorrect_phonemes[:3]: # Limit to top 3 problematic phonemes tip = self.get_detailed_tip(phoneme) if tip: detailed_tips.append( { "phoneme": phoneme, "vietnamese_name": tip.vietnamese_name, "instruction": tip.detailed_instruction, "common_mistakes": tip.common_mistakes, "difficulty": tip.difficulty_level, } ) practice_words.update(tip.practice_words[:3]) # Get pattern-based tips pattern_tips = self.get_error_pattern_tips(incorrect_phonemes) # Generate practice suggestions practice_suggestions = [ f"Luyện tập các từ này: {', '.join(list(practice_words)[:5])}", "Tập phát âm trước gương để kiểm tra vị trí môi và lưỡi", "Thu âm và nghe lại để so sánh với bản gốc", "Luyện tập 10-15 phút mỗi ngày cho mỗi âm khó", ] return { "status": "needs_improvement", "message": f"Cần cải thiện {len(incorrect_phonemes)} âm. Đừng nản lòng, cứ luyện tập từ từ!", "detailed_tips": detailed_tips, "pattern_tips": pattern_tips, "practice_suggestions": practice_suggestions, "priority_phonemes": incorrect_phonemes[ :2 ], # Focus on top 2 most problematic } def get_encouragement_message(self, score: float) -> str: """Get encouraging message based on score""" if score >= 0.9: messages = [ "Tuyệt vời! Phát âm của bạn rất chuẩn!", "Xuất sắc! Bạn đã tiến bộ rất nhiều!", "Hoàn hảo! Tiếp tục duy trì nhé!", ] elif score >= 0.8: messages = [ "Rất tốt! Chỉ còn một vài điểm nhỏ cần cải thiện.", "Tuyệt! Bạn đang trên đúng con đường.", "Giỏi lắm! Tiếp tục cố gắng nhé!", ] elif score >= 0.6: messages = [ "Khá tốt! Hãy tập trung vào những âm được gạch chân.", "Bạn đang tiến bộ! Cứ luyện tập đều đặn.", "Tốt đấy! Từ từ sẽ chuẩn thôi.", ] elif score >= 0.4: messages = [ "Đừng nản lòng! Mọi người đều phải trải qua giai đoạn này.", "Tiếp tục cố gắng! Luyện tập là chìa khóa thành công.", "Bạn đang học! Mỗi lần luyện là một bước tiến.", ] else: messages = [ "Bạn đang bắt đầu hành trình! Hãy luyện chậm và rõ ràng.", "Đừng vội! Phát âm cần thời gian để hoàn thiện.", "Cứ bình tĩnh luyện tập, bạn sẽ tiến bộ nhanh thôi!", ] return random.choice(messages) def get_audio_quality_tips(self) -> List[str]: """Get tips for better audio recording quality""" return [ "Nói to và rõ ràng hơn - microphone cần âm thanh đủ mạnh", "Tìm nơi yên tĩnh để thu âm, tránh tiếng ồn xung quanh", "Giữ khoảng cách 15-20cm từ miệng đến microphone", "Nói chậm rãi và phát âm từng âm một cách rõ ràng", "Kiểm tra microphone có hoạt động tốt không", "Thử thu âm lại nếu âm thanh không rõ ràng", ] def get_retry_encouragement(self) -> str: """Get encouraging message for retry attempts""" messages = [ "Không sao! Hãy thử lại và nói to hơn một chút.", "Microphone không nghe rõ. Bạn có thể nói rõ ràng hơn không?", "Thử nói chậm và to hơn để hệ thống có thể nhận diện tốt hơn.", "Đừng lo! Hãy thở sâu và thử lại một lần nữa.", "Có thể do tiếng ồn xung quanh. Hãy tìm nơi yên tĩnh hơn và thử lại.", ] return random.choice(messages) # Global instance for easy access vietnamese_tips = VietnameseTipsProvider() def get_phoneme_tip(phoneme: str) -> Optional[str]: """Quick access function to get tip for a phoneme""" tip = vietnamese_tips.get_detailed_tip(phoneme) return tip.detailed_instruction if tip else None def get_quick_tips(phonemes: List[str]) -> List[str]: """Get quick tips for a list of phonemes""" tips = [] for phoneme in phonemes[:3]: # Limit to 3 most important tip = vietnamese_tips.get_detailed_tip(phoneme) if tip: tips.append(f"Âm /{phoneme}/: {tip.vietnamese_name} - {tip.mouth_position}") return tips