From 6cff7413709b393440bb77f711307ac5dee6bc19 Mon Sep 17 00:00:00 2001 From: jjangddu Date: Mon, 29 Jun 2026 11:31:50 +0900 Subject: [PATCH] =?UTF-8?q?feat(locale):=20DeviceScanView=20=ED=95=9C?= =?UTF-8?q?=EA=B8=80=ED=99=94=20=E2=80=94=20=EA=B8=B0=EA=B8=B0=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0=20=ED=8E=98=EC=9D=B4=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 이전 sweep 에서 누락됐던 두번째 '기기 연결' 화면 풀 한글화. 추가 strings: 25 신규 (각 언어) - '기기 연결' 제목, 검색/탭 안내 - 페어링 필요 알림 (다이얼로그 + 에러 메시지) - Bluetooth off / 권한 필요 경고 - 검색 중 / 기기 없음 / 트러블슈팅 4단계 - 저장된 기기 / 새 기기 섹션 - 권한 허용 / 검색 시작·중지 버튼 - 최근, 페어링 삭제, 신호 좋음/보통/약함 설계: - signalLabel(rssi) → 영어 — dev/log 용 유지 - signalLabelRes(rssi) 신규 — UI 용 Locale-aware 라벨 Co-Authored-By: Claude Opus 4.7 --- .../ui/views/connection/DeviceScanView.kt | 63 ++++++++++--------- app/src/main/res/values-ko/strings.xml | 31 +++++++++ app/src/main/res/values/strings.xml | 31 +++++++++ 3 files changed, 97 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/example/medilightv2android/ui/views/connection/DeviceScanView.kt b/app/src/main/java/com/example/medilightv2android/ui/views/connection/DeviceScanView.kt index 5a7ec5e..99e0def 100644 --- a/app/src/main/java/com/example/medilightv2android/ui/views/connection/DeviceScanView.kt +++ b/app/src/main/java/com/example/medilightv2android/ui/views/connection/DeviceScanView.kt @@ -133,7 +133,7 @@ fun DeviceScanView(appState: AppState) { appState.deviceConnected() } else { bleManager.disconnect() - bleManager.connectionError.value = "Pairing required. Please pair the device." + bleManager.connectionError.value = context.getString(R.string.device_scan_pairing_required_err) } } } @@ -149,8 +149,8 @@ fun DeviceScanView(appState: AppState) { if (showPairingHint) { AlertDialog( onDismissRequest = {}, - title = { Text("Pairing Required", fontWeight = FontWeight.Bold) }, - text = { Text("A Bluetooth pairing request will appear.\nTap 'Pair', then enter PIN if prompted.") }, + title = { Text(stringResource(R.string.device_scan_pairing_required_title), fontWeight = FontWeight.Bold) }, + text = { Text(stringResource(R.string.device_scan_pairing_required_msg)) }, confirmButton = {} ) } @@ -166,7 +166,7 @@ fun DeviceScanView(appState: AppState) { verticalAlignment = Alignment.CenterVertically ) { IconButton(onClick = { appState.backToSensorSelect() }) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, "Back", tint = MlPrimary) + Icon(Icons.AutoMirrored.Filled.ArrowBack, stringResource(R.string.device_scan_back_desc), tint = MlPrimary) } Spacer(modifier = Modifier.weight(1f)) } @@ -175,11 +175,11 @@ fun DeviceScanView(appState: AppState) { modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { - Text("Connect Device", fontSize = 24.sp, fontWeight = FontWeight.Bold) + Text(stringResource(R.string.device_scan_title), fontSize = 24.sp, fontWeight = FontWeight.Bold) Spacer(modifier = Modifier.height(8.dp)) Text( - if (knownDevices.isEmpty()) "Searching for nearby devices..." - else "Tap a saved device or scan for new", + if (knownDevices.isEmpty()) stringResource(R.string.device_scan_searching) + else stringResource(R.string.device_scan_tap_or_scan), fontSize = 14.sp, color = MlSecondaryText ) } @@ -197,10 +197,10 @@ fun DeviceScanView(appState: AppState) { .padding(16.dp), verticalAlignment = Alignment.CenterVertically ) { - Icon(Icons.Default.Warning, "Warning", tint = Color.White) + Icon(Icons.Default.Warning, stringResource(R.string.device_scan_warning_desc), tint = Color.White) Spacer(modifier = Modifier.width(12.dp)) Column { - Text("Bluetooth is off", fontWeight = FontWeight.Bold, color = Color.White, fontSize = 14.sp) + Text(stringResource(R.string.device_scan_bluetooth_off), fontWeight = FontWeight.Bold, color = Color.White, fontSize = 14.sp) Text("Enable Bluetooth in Settings", color = Color.White.copy(alpha = 0.8f), fontSize = 12.sp) } } @@ -218,10 +218,10 @@ fun DeviceScanView(appState: AppState) { .padding(16.dp), verticalAlignment = Alignment.CenterVertically ) { - Icon(Icons.Default.Warning, "Warning", tint = Color.White) + Icon(Icons.Default.Warning, stringResource(R.string.device_scan_warning_desc), tint = Color.White) Spacer(modifier = Modifier.width(12.dp)) Column { - Text("Permissions required", fontWeight = FontWeight.Bold, color = Color.White, fontSize = 14.sp) + Text(stringResource(R.string.device_scan_permissions_required), fontWeight = FontWeight.Bold, color = Color.White, fontSize = 14.sp) Text("Bluetooth and Location permissions are needed to scan for devices", color = Color.White.copy(alpha = 0.8f), fontSize = 12.sp) } } @@ -239,11 +239,11 @@ fun DeviceScanView(appState: AppState) { .padding(12.dp), verticalAlignment = Alignment.CenterVertically ) { - Icon(Icons.Default.Close, "Error", tint = Color.White) + Icon(Icons.Default.Close, stringResource(R.string.device_scan_error_desc), tint = Color.White) Spacer(modifier = Modifier.width(12.dp)) Text(error, color = Color.White, fontSize = 13.sp, modifier = Modifier.weight(1f)) IconButton(onClick = { bleManager.connectionError.value = null }) { - Icon(Icons.Default.Close, "Dismiss", tint = Color.White.copy(alpha = 0.8f)) + Icon(Icons.Default.Close, stringResource(R.string.device_scan_dismiss_desc), tint = Color.White.copy(alpha = 0.8f)) } } Spacer(modifier = Modifier.height(8.dp)) @@ -259,7 +259,7 @@ fun DeviceScanView(appState: AppState) { ) { BladdyIdleRiveView(size = 180.dp) Spacer(modifier = Modifier.height(16.dp)) - Text("Scanning...", color = MlSecondaryText) + Text(stringResource(R.string.device_scan_scanning), color = MlSecondaryText) } } else if (emptyAll) { Column( @@ -269,17 +269,17 @@ fun DeviceScanView(appState: AppState) { horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { - Text("No devices found", fontSize = 16.sp, fontWeight = FontWeight.SemiBold, color = MlSecondaryText) + Text(stringResource(R.string.device_scan_no_devices), fontSize = 16.sp, fontWeight = FontWeight.SemiBold, color = MlSecondaryText) Spacer(modifier = Modifier.height(16.dp)) Card( shape = RoundedCornerShape(14.dp), colors = CardDefaults.cardColors(containerColor = MlCardBackground) ) { Column(modifier = Modifier.padding(16.dp)) { - TroubleshootItem("1.", "Make sure the device is powered on") - TroubleshootItem("2.", "Keep the device within 1 meter") - TroubleshootItem("3.", "Check Bluetooth is enabled in Settings") - TroubleshootItem("4.", "Try restarting the device") + TroubleshootItem("1.", stringResource(R.string.device_scan_troubleshoot_1)) + TroubleshootItem("2.", stringResource(R.string.device_scan_troubleshoot_2)) + TroubleshootItem("3.", stringResource(R.string.device_scan_troubleshoot_3)) + TroubleshootItem("4.", stringResource(R.string.device_scan_troubleshoot_4)) } } if (appState.isDevMode) { @@ -293,7 +293,7 @@ fun DeviceScanView(appState: AppState) { shape = RoundedCornerShape(12.dp), colors = ButtonDefaults.buttonColors(containerColor = MlPrimary.copy(alpha = 0.15f)) ) { - Text("Enter Measurement Mode (Dev)", color = MlPrimary, fontWeight = FontWeight.SemiBold) + Text(stringResource(R.string.device_scan_enter_measurement_dev), color = MlPrimary, fontWeight = FontWeight.SemiBold) } } } @@ -305,7 +305,7 @@ fun DeviceScanView(appState: AppState) { ) { if (knownDevices.isNotEmpty()) { item("known_header") { - SectionHeader("Saved Devices", knownDevices.size) + SectionHeader(stringResource(R.string.device_scan_saved_devices), knownDevices.size) } items(knownDevices, key = { "k_${it.address}" }) { known -> KnownDeviceRow( @@ -323,7 +323,7 @@ fun DeviceScanView(appState: AppState) { if (newDevices.isNotEmpty()) { item("new_header") { Spacer(modifier = Modifier.height(8.dp)) - SectionHeader("New Devices", newDevices.size) + SectionHeader(stringResource(R.string.device_scan_new_devices), newDevices.size) } items(newDevices, key = { "n_${it.address}" }) { device -> DeviceRow( @@ -390,9 +390,9 @@ fun DeviceScanView(appState: AppState) { ) { Text( when { - !permissionsGranted -> "Grant Permissions" - isScanning -> "Stop Scan" - else -> "Start Scan" + !permissionsGranted -> stringResource(R.string.device_scan_grant_permissions) + isScanning -> stringResource(R.string.device_scan_stop_scan) + else -> stringResource(R.string.device_scan_start_scan) }, fontSize = 16.sp, fontWeight = FontWeight.SemiBold, @@ -451,7 +451,7 @@ private fun KnownDeviceRow( Spacer(modifier = Modifier.width(12.dp)) Column(modifier = Modifier.weight(1f)) { Text(device.name, fontSize = 15.sp, fontWeight = FontWeight.SemiBold) - Text("Last: $lastConnectedLabel", fontSize = 11.sp, color = MlSecondaryText) + Text(stringResource(R.string.device_scan_last_label, lastConnectedLabel), fontSize = 11.sp, color = MlSecondaryText) } if (isConnecting) { CircularProgressIndicator(modifier = Modifier.size(22.dp), strokeWidth = 2.dp) @@ -461,7 +461,7 @@ private fun KnownDeviceRow( enabled = enabled, modifier = Modifier.size(36.dp) ) { - Icon(Icons.Default.Delete, "Delete pairing", + Icon(Icons.Default.Delete, stringResource(R.string.device_scan_delete_pairing_desc), tint = Color.Red.copy(alpha = 0.7f), modifier = Modifier.size(18.dp)) } @@ -501,7 +501,7 @@ private fun DeviceRow(device: BleDevice, isConnecting: Boolean, enabled: Boolean Row(verticalAlignment = Alignment.CenterVertically) { SignalBars(rssi = device.rssi) Spacer(modifier = Modifier.width(4.dp)) - Text(signalLabel(device.rssi), fontSize = 12.sp, color = MlSecondaryText) + Text(stringResource(signalLabelRes(device.rssi)), fontSize = 12.sp, color = MlSecondaryText) } } @@ -545,6 +545,13 @@ private fun signalLabel(rssi: Int): String = when { else -> "Weak" } +/** UI 용 — Locale 적용된 라벨. signalLabel(rssi) 는 dev/log 용으로 유지. */ +private fun signalLabelRes(rssi: Int): Int = when { + rssi >= -80 -> R.string.device_scan_signal_good + rssi >= -90 -> R.string.device_scan_signal_fair + else -> R.string.device_scan_signal_weak +} + @Composable private fun TroubleshootItem(number: String, text: String) { Row(modifier = Modifier.padding(vertical = 4.dp)) { diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index df0fe91..ce2cbf9 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -367,4 +367,35 @@ 뒤로 최대 방광 용량 배뇨 알림 기준 + + + 기기 연결 + 주변 기기를 찾는 중… + 저장된 기기를 탭하거나 새 기기를 검색하세요 + 페어링 필요 + 블루투스 페어링 요청이 표시됩니다.\n\'페어링\' 을 누르고, PIN 이 나타나면 입력하세요. + 페어링이 필요합니다. 기기를 페어링해주세요. + 뒤로 + 경고 + 오류 + 닫기 + 블루투스가 꺼져 있습니다 + 권한이 필요합니다 + 검색 중… + 기기를 찾을 수 없습니다 + 기기 전원이 켜져 있는지 확인하세요 + 기기를 1 미터 이내에 두세요 + 설정에서 블루투스를 켜주세요 + 기기를 다시 켜보세요 + 측정 모드 진입 (Dev) + 저장된 기기 + 새 기기 + 권한 허용 + 검색 중지 + 검색 시작 + 최근: %1$s + 페어링 삭제 + 좋음 + 보통 + 약함 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6ef8353..bfa3977 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -367,4 +367,35 @@ Back Maximum Bladder Capacity Voiding Reminder + + + Connect Device + Searching for nearby devices... + Tap a saved device or scan for new + Pairing Required + A Bluetooth pairing request will appear.\nTap \'Pair\', then enter PIN if prompted. + Pairing required. Please pair the device. + Back + Warning + Error + Dismiss + Bluetooth is off + Permissions required + Scanning... + No devices found + Make sure the device is powered on + Keep the device within 1 meter + Check Bluetooth is enabled in Settings + Try restarting the device + Enter Measurement Mode (Dev) + Saved Devices + New Devices + Grant Permissions + Stop Scan + Start Scan + Last: %1$s + Delete pairing + Good + Fair + Weak