| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- """
- Label translator for hazard detection system.
- Translates pinyin/English labels to Chinese for display and database queries.
- """
- from typing import List, Dict, Optional
- # Complete mapping: pinyin/English -> Chinese
- LABEL_MAPPING: Dict[str, str] = {
- # Gas Station (加油站) labels
- "fangzhuanglan": "防撞栏",
- "jiayouqiang": "加油枪",
- "jiayouji": "加油机",
- "miehuoqi": "灭火器",
- "zhuixingtong": "锥形桶",
- "push_extinguisher": "手推灭火器",
- "support_pillar": "支撑柱",
- "fuel_hose": "加油机输油软管",
- "vent_pipe": "通气管",
- "oil_discharge_port": "卸油口",
- "static_release_post": "静电释放桩",
- "static_wire": "静电线",
- "static_clip": "静电夹",
- "power_distribution_box": "配电箱",
-
- # Alternative English names (aliases)
- "crash_barrier": "防撞栏",
- "fuel_nozzle": "加油枪",
- "fuel_dispenser": "加油机",
- "fire_extinguisher": "灭火器",
- "traffic_cone": "锥形桶",
- "pillar": "支撑柱",
- "oil_hose": "加油机输油软管",
- "ventilation_pipe": "通气管",
- "discharge_port": "卸油口",
- "grounding_post": "静电释放桩",
- "grounding_wire": "静电线",
- "grounding_clip": "静电夹",
- "distribution_box": "配电箱",
- }
- # Reverse mapping: Chinese -> pinyin/English (for reference)
- REVERSE_MAPPING: Dict[str, str] = {v: k for k, v in LABEL_MAPPING.items()}
- def translate_label(label: str, fallback_to_original: bool = True) -> str:
- """
- Translate a single label from pinyin/English to Chinese.
-
- Args:
- label: The label to translate (pinyin or English)
- fallback_to_original: If True, return original label when no translation found
-
- Returns:
- Translated Chinese label, or original label if not found and fallback is True
-
- Examples:
- >>> translate_label("fangzhuanglan")
- "防撞栏"
- >>> translate_label("fuel_hose")
- "加油机输油软管"
- >>> translate_label("防撞栏") # Already Chinese
- "防撞栏"
- >>> translate_label("unknown_label")
- "unknown_label"
- """
- if not label:
- return label
-
- label_stripped = label.strip()
- if not label_stripped:
- return label
-
- # Check if already Chinese (contains Chinese characters)
- if _contains_chinese(label_stripped):
- return label_stripped
-
- # Try exact match (case-insensitive)
- label_lower = label_stripped.lower()
- if label_lower in LABEL_MAPPING:
- return LABEL_MAPPING[label_lower]
-
- # Try with underscores replaced by spaces
- label_spaced = label_lower.replace("_", " ")
- if label_spaced in LABEL_MAPPING:
- return LABEL_MAPPING[label_spaced]
-
- # Fallback to original if no translation found
- if fallback_to_original:
- return label_stripped
-
- return ""
- def translate_labels(labels: List[str], fallback_to_original: bool = True) -> List[str]:
- """
- Translate a list of labels from pinyin/English to Chinese.
-
- Args:
- labels: List of labels to translate
- fallback_to_original: If True, keep original labels when no translation found
-
- Returns:
- List of translated Chinese labels
-
- Examples:
- >>> translate_labels(["fangzhuanglan", "jiayouqiang", "防撞栏"])
- ["防撞栏", "加油枪", "防撞栏"]
- """
- if not labels:
- return []
-
- return [translate_label(label, fallback_to_original) for label in labels]
- def is_translated(label: str) -> bool:
- """
- Check if a label is already in Chinese (translated).
-
- Args:
- label: The label to check
-
- Returns:
- True if label contains Chinese characters, False otherwise
- """
- return _contains_chinese(label)
- def get_english_name(chinese_label: str) -> Optional[str]:
- """
- Get the English/pinyin name for a Chinese label (reverse lookup).
-
- Args:
- chinese_label: Chinese label to look up
-
- Returns:
- English/pinyin name if found, None otherwise
-
- Examples:
- >>> get_english_name("防撞栏")
- "fangzhuanglan"
- """
- return REVERSE_MAPPING.get(chinese_label.strip())
- def add_custom_mapping(pinyin_or_english: str, chinese: str) -> None:
- """
- Add a custom label mapping at runtime.
-
- Args:
- pinyin_or_english: The pinyin or English label
- chinese: The Chinese translation
-
- Note:
- This is useful for dynamic label additions without modifying the source code.
- """
- key = pinyin_or_english.strip().lower()
- value = chinese.strip()
- LABEL_MAPPING[key] = value
- REVERSE_MAPPING[value] = key
- def get_all_mappings() -> Dict[str, str]:
- """
- Get all label mappings.
-
- Returns:
- Dictionary of all pinyin/English -> Chinese mappings
- """
- return LABEL_MAPPING.copy()
- def _contains_chinese(text: str) -> bool:
- """
- Check if text contains Chinese characters.
-
- Args:
- text: Text to check
-
- Returns:
- True if text contains at least one Chinese character
- """
- if not text:
- return False
-
- for char in text:
- if '\u4e00' <= char <= '\u9fff':
- return True
-
- return False
- # Sub-secondary to secondary scene mapping
- # Used only for database queries - these scenes still appear as-is in UI and storage
- SUB_SECONDARY_TO_SECONDARY_MAPPING: Dict[str, str] = {
- # 加油设施_附属场地 -> maps to parent secondary scene (note: uses underscore in DB)
- "加油机": "加油设施_附属场地",
- "加油枪": "加油设施_附属场地",
- "加油机输油软管": "加油设施_附属场地",
- "防撞栏": "加油设施_附属场地",
- "锥形桶": "加油设施_附属场地",
- "灭火器": "加油设施_附属场地",
-
- # 罩棚 and 立柱 are separate scenes in DB, map support pillar to 立柱
- "支撑立柱": "立柱",
- }
- def translate_scene_for_query(scene_name: str) -> str:
- """
- Translate sub-secondary scene to its parent secondary scene for database queries.
- This is ONLY used when querying the database, not for display or storage.
-
- Args:
- scene_name: The scene name to translate (could be sub-secondary or secondary)
-
- Returns:
- Parent secondary scene name if it's a sub-secondary scene, otherwise original name
-
- Examples:
- >>> translate_scene_for_query("加油机")
- "加油设施及附属场地"
- >>> translate_scene_for_query("支撑立柱")
- "罩棚及立柱"
- >>> translate_scene_for_query("加油设施及附属场地")
- "加油设施及附属场地"
- """
- if not scene_name:
- return scene_name
-
- scene_stripped = scene_name.strip()
- return SUB_SECONDARY_TO_SECONDARY_MAPPING.get(scene_stripped, scene_stripped)
- def translate_scenes_for_query(scene_names: List[str]) -> List[str]:
- """
- Translate a list of sub-secondary scenes to their parent secondary scenes for database queries.
-
- Args:
- scene_names: List of scene names to translate
-
- Returns:
- List of translated scene names (parent secondary scenes)
-
- Examples:
- >>> translate_scenes_for_query(["加油机", "加油枪", "支撑立柱"])
- ["加油设施及附属场地", "加油设施及附属场地", "罩棚及立柱"]
- """
- if not scene_names:
- return []
-
- return [translate_scene_for_query(scene) for scene in scene_names]
- # Export main functions
- __all__ = [
- "translate_label",
- "translate_labels",
- "is_translated",
- "get_english_name",
- "add_custom_mapping",
- "get_all_mappings",
- "translate_scene_for_query",
- "translate_scenes_for_query",
- "LABEL_MAPPING",
- "SUB_SECONDARY_TO_SECONDARY_MAPPING",
- ]
|