feat(locale): DeviceScanView 한글화 — 기기 연결 페이지
이전 sweep 에서 누락됐던 두번째 '기기 연결' 화면 풀 한글화. 추가 strings: 25 신규 (각 언어) - '기기 연결' 제목, 검색/탭 안내 - 페어링 필요 알림 (다이얼로그 + 에러 메시지) - Bluetooth off / 권한 필요 경고 - 검색 중 / 기기 없음 / 트러블슈팅 4단계 - 저장된 기기 / 새 기기 섹션 - 권한 허용 / 검색 시작·중지 버튼 - 최근, 페어링 삭제, 신호 좋음/보통/약함 설계: - signalLabel(rssi) → 영어 — dev/log 용 유지 - signalLabelRes(rssi) 신규 — UI 용 Locale-aware 라벨 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+35
-28
@@ -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)) {
|
||||
|
||||
Reference in New Issue
Block a user