278:         self._btn_select = QPushButton(tr("✔ Select this image"))
314:             f"✅ {tr('Auto-selected')}: {d}  {cloud_str}")
334:             self._lbl_selected.setText(f"✅ {tr('Selected')}: {d}  {cloud_str}")
358:         self.setWindowTitle(tr("🌿 Forest Change Detective — LVT4U"))
372:         self.setWindowTitle(tr("🌿 Forest Change Detective — LVT4U"))
374:             "🌿  <b>" + tr("🌿 Forest Change Detective").replace("🌿 ", "") + "</b>"
375:             "  —  <span style='color:#74C69D'>" + tr("Forest Change Detection & Deforestation Alert") + "</span>"
378:         self.tabs.setTabText(0, tr("🛰️ Data"))
379:         self.tabs.setTabText(1, tr("📊 Analysis"))
380:         self.tabs.setTabText(2, tr("📋 Results"))
381:         self.tabs.setTabText(3, tr("⚙️ Settings"))
383:         self.btn_analyze.setText(tr("▶  Analyze Changes"))
384:         self.btn_cancel.setText(tr("✖ Cancel"))
391:         self.btn_use_extent.setText(tr("📐 Use current canvas extent"))
406:         self.grp_mode.setTitle(tr("Select T₁ and T₂ Images"))
407:         self.rb_mode_a.setText(tr("A — Manual search from catalog"))
408:         self.rb_mode_b.setText(tr("B — Enter date, system auto-selects best image"))
409:         self.rb_mode_c.setText(tr("C — Combined (T₁ auto, T₂ manual or vice versa)"))
414:             self.btn_search.setText(tr("🔍 Search Images"))
416:         self._img_t1._lbl_title.setText(f"<b>{tr('📅 Image T₁ (Before)')}</b>")
417:         self._img_t2._lbl_title.setText(f"<b>{tr('📅 Image T₂ (After)')}</b>")
418:         self._img_t1._btn_select.setText(tr("✔ Select this image"))
419:         self._img_t2._btn_select.setText(tr("✔ Select this image"))
422:             self.page_b_layout.labelForField(self.de_t1_auto).setText(tr("T₁ date (target):"))
424:             self.page_b_layout.labelForField(self.de_t2_auto).setText(tr("T₂ date (target):"))
426:             self.page_b_layout.labelForField(self.spin_window_days).setText(tr("Search window ±:"))
430:             self.btn_auto_find.setText(tr("🤖 Auto-find best images"))
433:             self.page_b_layout.labelForField(self._lbl_auto_t1).setText(tr("T₁ selected:"))
435:             self.page_b_layout.labelForField(self._lbl_auto_t2).setText(tr("T₂ selected:"))
441:         if "DEFORESTATION" in self._mode_radios: self._mode_radios["DEFORESTATION"].setText(tr("🌲 Deforestation / Forest Loss"))
442:         if "FIRE" in self._mode_radios: self._mode_radios["FIRE"].setText(tr("🔥 Fire / Burn Scar"))
443:         if "DEGRADATION" in self._mode_radios: self._mode_radios["DEGRADATION"].setText(tr("📉 Degradation / Vegetation Recovery"))
444:         if "MOISTURE" in self._mode_radios: self._mode_radios["MOISTURE"].setText(tr("💧 Canopy Moisture Change"))
448:         self.btn_reset_thresh.setText(tr("↺ Reset to defaults"))
454:                     dir_item.setText(tr("Decrease ≥"))
456:                     dir_item.setText(tr("Increase ≥"))
465:         self.grp_firms.setTitle(tr("🔥 FIRMS Fire Hotspot Validation (NASA)"))
479:         self.btn_open_gpkg.setText(tr("📂 Open GeoPackage"))
480:         self.btn_export_kml.setText(tr("🗺 Export KML"))
481:         self.btn_export_json.setText(tr("📄 Export GeoJSON"))
482:         self.btn_load_canvas.setText(tr("🗺 Add to QGIS"))
503:         self.btn_save.setText(tr("💾 Save settings"))
606:             "🌿  <b>" + tr("🌿 Forest Change Detective").replace("🌿 ", "") + "</b>"
607:             "  —  <span style='color:#74C69D'>" + tr("Forest Change Detection & Deforestation Alert") + "</span>"
619:         self.tabs.addTab(self._build_tab_data(),     tr("🛰️ Data"))
620:         self.tabs.addTab(self._build_tab_analysis(), tr("📊 Analysis"))
621:         self.tabs.addTab(self._build_tab_results(),  tr("📋 Results"))
622:         self.tabs.addTab(self._build_tab_settings(), tr("⚙️ Settings"))
639:         self.btn_analyze = QPushButton(tr("▶  Analyze Changes"))
648:         self.btn_cancel = QPushButton(tr("✖ Cancel"))
655:         self.btn_help = QPushButton(tr("📖 Help"))
694:             tr("Select study area (ROI) — Region of Interest\n\n"
702:         self.btn_use_extent = QPushButton(tr("📐 Use current canvas extent"))
722:             tr("Sentinel-2 L2A (Optical, 10m — Recommended)"),
724:             tr("Landsat 8/9 (30m — Under 500 ha)"),
752:         self.sensor_layout.addRow(tr("☁️ Max cloud:"), self.spin_max_cloud)
757:         self.grp_mode = QGroupBox(tr("Select T₁ and T₂ Images"))
761:         self.rb_mode_a = QRadioButton(tr("A — Manual search from catalog"))
762:         self.rb_mode_b = QRadioButton(tr("B — Enter date, system auto-selects best image"))
763:         self.rb_mode_c = QRadioButton(tr("C — Combined (T₁ auto, T₂ manual or vice versa)"))
799:         self.btn_search = QPushButton(tr("🔍 Search Images"))
811:         self._img_t1 = _ImageListWidget(tr("📅 Image T₁ (Before)"))
812:         self._img_t2 = _ImageListWidget(tr("📅 Image T₂ (After)"))
843:         self.page_b_layout.addRow(tr("T₁ date (target):"), self.de_t1_auto)
844:         self.page_b_layout.addRow(tr("T₂ date (target):"), self.de_t2_auto)
845:         self.page_b_layout.addRow(tr("Search window ±:"), self.spin_window_days)
847:         self.btn_auto_find = QPushButton(tr("🤖 Auto-find best images"))
855:         self._lbl_auto_t1 = QLabel(tr("T₁: not searched yet"))
856:         self._lbl_auto_t2 = QLabel(tr("T₂: not searched yet"))
857:         self.page_b_layout.addRow(tr("T₁ selected:"), self._lbl_auto_t1)
858:         self.page_b_layout.addRow(tr("T₂ selected:"), self._lbl_auto_t2)
874:         btn_browse_forest = QPushButton(tr("📂"))
994:             tr("Δ = Index(T2) − Index(T1)\n"
1013:         self.btn_reset_thresh = QPushButton(tr("\u21ba Đặt lại mặc định"))
1038:         self.mmu_layout.addRow(tr("📍 Minimum area (MMU):"), self.spin_mmu)
1057:             tr("DEM slope threshold — filter SAR noise on mountains\n\n"
1064:         self.mmu_layout.addRow(tr("⛰️ DEM slope filter (SAR):"),
1070:         self.grp_firms = QGroupBox(tr("🔥 FIRMS Fire Hotspot Validation (NASA)"))
1133:         self.btn_preview = QPushButton(tr("🔴  View Preview — Blink change areas"))
1150:         self.btn_open_gpkg = QPushButton(tr("📂 Open GeoPackage"))
1151:         self.btn_export_kml = QPushButton(tr("🗺 Export KML"))
1152:         self.btn_export_json = QPushButton(tr("📄 Export GeoJSON"))
1153:         self.btn_load_canvas = QPushButton(tr("🗺 Add to QGIS"))
1200:         btn_dem = QPushButton(tr("📂"))
1214:         btn_out = QPushButton(tr("📂"))
1221:         self.btn_save = QPushButton(tr("💾 Save settings"))
1257:             dir_label = tr("Decrease ≥") if direction == "below" else tr("Increase ≥")
1384:         self.btn_search.setText(tr("🔄 Searching..."))
1400:         self.btn_search.setText(tr("🔍 Search Images"))
1413:         self.btn_search.setText(tr("🔍 Search Images"))
1438:         self.btn_auto_find.setText(tr("🤖 Searching T₁..."))
1467:         self.btn_auto_find.setText(tr("🤖 Searching T₂..."))
1481:         self.btn_auto_find.setText(tr("🤖 Auto-find best images"))
1505:                 self, tr("Missing Image T₁"),
1506:                 tr("Please select or auto-find image T₁ first."))
1511:                 self, tr("Missing Image T₂"),
1512:                 tr("Please select or auto-find image T₂ first."))
1570:                             tr("⚠️ WARNING: IMAGES IN DIFFERENT SEASONS!\n\n")
1571:                             + tr(f"T₁ ({t1_str}): {_s_label[s1]}\n")
1572:                             + tr(f"T₂ ({t2_str}): {_s_label[s2]}\n\n")
1576:                             + tr("→ ΔNDVI = +0.20 (positive) → Forest \'increase\' → Masks logging!\n\n")
1578:                             + tr("  Choose T₁ and T₂ IN SAME SEASON (same month, different year):\n")
1579:                             + tr("  Example: T₁ = Jan 2025, T₂ = Jan 2026\n\n")
1586:                             tr("⚠️ Season Warning"),
1608:                         self, tr("⚠️ Interval too short"),
1660:         self._lbl_status.setText(tr("✅ Analysis complete!"))
1707:             "critical_count": tr("CRITICAL (≥1 ha)"),
1708:             "warning_count":  tr("WARNING (0.05–1 ha)"),
2098:             dlg.setWindowTitle(tr("📖 Forest Change Detective — User Guide"))
2100:             dlg.setWindowTitle(tr("📖 Forest Change Detective — User Guide"))
2123:             tabs.addTab(_browser(tips_html),  tr("⚡ Quick Tips"))
2124:             tabs.addTab(_browser(guide_html), tr("📚 Full Guide"))
2125:             tabs.addTab(_browser(param_html), tr("📋 Parameter Reference"))
2127:             tabs.addTab(_browser(tips_html),  tr("⚡ Quick Tips"))
2128:             tabs.addTab(_browser(guide_html), tr("📚 Full Guide"))
2129:             tabs.addTab(_browser(param_html), tr("📋 Parameter Reference"))
2208:             layer_display_name = tr(f"Forest Change — {mode}")
