merge: develop → main (shelf life, banner vacuum, preloader, ricetta, porzioni, fix traduzioni)

This commit is contained in:
dadaloop82
2026-05-17 18:21:17 +00:00
15 changed files with 982 additions and 216 deletions
@@ -58,8 +58,10 @@ import javax.net.ssl.X509TrustManager
* 2 — Permissions rationale + grant
* 3 — Server URL + auto-discovery + connection test
* 4 — Smart scale question → gateway info + install
* 5 — Screensaver toggle (NEW)
* 6 — Done
* 5 — Features (screensaver / prices / meal-plan / zero-waste)
* 6 — Gemini AI key (optional, auto-skipped if already set)
* 7 — Bring! credentials (optional, auto-skipped if already set)
* 8 — Done
*/
class SetupActivity : AppCompatActivity() {
@@ -73,6 +75,8 @@ class SetupActivity : AppCompatActivity() {
private lateinit var stepServer: LinearLayout
private lateinit var stepScale: LinearLayout
private lateinit var stepScreensaver: LinearLayout
private lateinit var stepGemini: LinearLayout
private lateinit var stepBring: LinearLayout
private lateinit var stepDone: LinearLayout
// Progress dots
@@ -114,6 +118,11 @@ class SetupActivity : AppCompatActivity() {
private lateinit var setupSwitchMealPlan: SwitchMaterial
private lateinit var setupSwitchZeroWaste: SwitchMaterial
// Gemini + Bring steps
private lateinit var setupGeminiKeyEdit: EditText
private lateinit var setupBringEmailEdit: EditText
private lateinit var setupBringPasswordEdit: EditText
// Done step
private lateinit var summaryText: TextView
@@ -134,6 +143,9 @@ class SetupActivity : AppCompatActivity() {
private const val KEY_PRICE_ENABLED = "price_enabled"
private const val KEY_MEAL_PLAN = "meal_plan_enabled"
private const val KEY_ZEROWASTE_TIPS = "zerowaste_tips_enabled"
private const val KEY_GEMINI_KEY = "gemini_api_key"
private const val KEY_BRING_EMAIL = "bring_email"
private const val KEY_BRING_PASSWORD = "bring_password"
private const val PERMISSION_REQUEST_CODE = 2004
private const val BLE_PERMISSION_REQUEST = 2006
@@ -184,8 +196,11 @@ class SetupActivity : AppCompatActivity() {
override fun onBackPressed() {
when (currentStep) {
0 -> confirmExit()
1 -> showStep(0) // back to language
0 -> confirmExit()
1 -> showStep(0) // back to language
8 -> showStep(7) // done → bring
7 -> showStep(6) // bring → gemini
6 -> showStep(5) // gemini → features
else -> showStep(currentStep - 1)
}
}
@@ -221,8 +236,18 @@ class SetupActivity : AppCompatActivity() {
stepServer = findViewById(R.id.stepServer)
stepScale = findViewById(R.id.stepScale)
stepScreensaver = findViewById(R.id.stepScreensaver)
stepGemini = findViewById(R.id.stepGemini)
stepBring = findViewById(R.id.stepBring)
stepDone = findViewById(R.id.stepDone)
// Gemini + Bring fields
setupGeminiKeyEdit = findViewById(R.id.setupGeminiKeyEdit)
setupBringEmailEdit = findViewById(R.id.setupBringEmailEdit)
setupBringPasswordEdit = findViewById(R.id.setupBringPasswordEdit)
// Pre-fill from saved prefs
(prefs.getString(KEY_GEMINI_KEY, "") ?: "").takeIf { it.isNotEmpty() }?.let { setupGeminiKeyEdit.setText(it) }
(prefs.getString(KEY_BRING_EMAIL, "") ?: "").takeIf { it.isNotEmpty() }?.let { setupBringEmailEdit.setText(it) }
// Server step
urlEdit = findViewById(R.id.setupUrlEdit)
urlStatus = findViewById(R.id.setupUrlStatus)
@@ -273,6 +298,8 @@ class SetupActivity : AppCompatActivity() {
findViewById<MaterialButton>(R.id.btnLangIt).setOnClickListener { selectLanguage("it") }
findViewById<MaterialButton>(R.id.btnLangEn).setOnClickListener { selectLanguage("en") }
findViewById<MaterialButton>(R.id.btnLangDe).setOnClickListener { selectLanguage("de") }
findViewById<MaterialButton>(R.id.btnLangEs).setOnClickListener { selectLanguage("es") }
findViewById<MaterialButton>(R.id.btnLangFr).setOnClickListener { selectLanguage("fr") }
// ── Welcome ──────────────────────────────────────────────────────
findViewById<MaterialButton>(R.id.btnSetupExit).setOnClickListener { confirmExit() }
@@ -375,10 +402,10 @@ class SetupActivity : AppCompatActivity() {
bleSetupCard.visibility = View.VISIBLE
tvSelectedScale.text = ""
tvSelectedScale.visibility = View.GONE
tvScanStatus.text = "Bilancia non confermata. Riprova la scansione."
tvScanStatus.text = getString(R.string.ble_not_confirmed)
tvScanStatus.setTextColor(0xFFfbbf24.toInt())
btnScanBle.isEnabled = true
btnScanBle.text = "🔍 Cerca bilancia"
btnScanBle.text = getString(R.string.ble_scan_again)
findViewById<MaterialButton>(R.id.btnScaleNext).isEnabled = false
}
findViewById<MaterialButton>(R.id.btnTestSkip).setOnClickListener {
@@ -398,14 +425,34 @@ class SetupActivity : AppCompatActivity() {
findViewById<MaterialButton>(R.id.btnScreensaverBack).setOnClickListener { showStep(4) }
findViewById<MaterialButton>(R.id.btnScreensaverNext).setOnClickListener {
prefs.edit()
.putBoolean(KEY_SCREENSAVER, setupSwitchScreensaver.isChecked)
.putBoolean(KEY_PRICE_ENABLED, setupSwitchPrices.isChecked)
.putBoolean(KEY_MEAL_PLAN, setupSwitchMealPlan.isChecked)
.putBoolean(KEY_SCREENSAVER, setupSwitchScreensaver.isChecked)
.putBoolean(KEY_PRICE_ENABLED, setupSwitchPrices.isChecked)
.putBoolean(KEY_MEAL_PLAN, setupSwitchMealPlan.isChecked)
.putBoolean(KEY_ZEROWASTE_TIPS, setupSwitchZeroWaste.isChecked)
.apply()
showStep(6)
}
// ── Gemini step ───────────────────────────────────────────────────
findViewById<MaterialButton>(R.id.btnGeminiBack).setOnClickListener { showStep(5) }
findViewById<MaterialButton>(R.id.btnGeminiSkip).setOnClickListener { showStep(7) }
findViewById<MaterialButton>(R.id.btnGeminiNext).setOnClickListener {
val key = setupGeminiKeyEdit.text.toString().trim()
if (key.isNotEmpty()) prefs.edit().putString(KEY_GEMINI_KEY, key).apply()
showStep(7)
}
// ── Bring step ────────────────────────────────────────────────────
findViewById<MaterialButton>(R.id.btnBringBack).setOnClickListener { showStep(6) }
findViewById<MaterialButton>(R.id.btnBringSkip).setOnClickListener { showStep(8) }
findViewById<MaterialButton>(R.id.btnBringNext).setOnClickListener {
val email = setupBringEmailEdit.text.toString().trim()
val pass = setupBringPasswordEdit.text.toString().trim()
if (email.isNotEmpty()) prefs.edit().putString(KEY_BRING_EMAIL, email).apply()
if (pass.isNotEmpty()) prefs.edit().putString(KEY_BRING_PASSWORD, pass).apply()
showStep(8)
}
// ── Done ──────────────────────────────────────────────────────────
findViewById<MaterialButton>(R.id.btnLaunch).setOnClickListener { finishSetup() }
}
@@ -421,20 +468,27 @@ class SetupActivity : AppCompatActivity() {
private fun highlightSelectedLang() {
val saved = prefs.getString(KEY_LANGUAGE, null) ?: return
val (btnIt, btnEn, btnDe) = Triple(
findViewById<MaterialButton>(R.id.btnLangIt),
findViewById<MaterialButton>(R.id.btnLangEn),
findViewById<MaterialButton>(R.id.btnLangDe)
)
val btnIt = findViewById<MaterialButton>(R.id.btnLangIt)
val btnEn = findViewById<MaterialButton>(R.id.btnLangEn)
val btnDe = findViewById<MaterialButton>(R.id.btnLangDe)
val btnEs = findViewById<MaterialButton>(R.id.btnLangEs)
val btnFr = findViewById<MaterialButton>(R.id.btnLangFr)
// Add checkmark to selected
btnIt.text = if (saved == "it") "✅ 🇮🇹 Italiano" else "🇮🇹 Italiano"
btnEn.text = if (saved == "en") "✅ 🇬🇧 English" else "🇬🇧 English"
btnDe.text = if (saved == "de") "✅ 🇩🇪 Deutsch" else "🇩🇪 Deutsch"
btnEs.text = if (saved == "es") "✅ 🇪🇸 Español" else "🇪🇸 Español"
btnFr.text = if (saved == "fr") "✅ 🇫🇷 Français" else "🇫🇷 Français"
}
// ── Step navigation ───────────────────────────────────────────────────
private fun showStep(step: Int) {
// Auto-skip Gemini step if already configured
if (step == 6 && !(prefs.getString(KEY_GEMINI_KEY, "") ?: "").isNullOrEmpty()) { showStep(7); return }
// Auto-skip Bring step if already configured
if (step == 7 && !(prefs.getString(KEY_BRING_EMAIL, "") ?: "").isNullOrEmpty()) { showStep(8); return }
currentStep = step
stepLanguage.visibility = if (step == 0) View.VISIBLE else View.GONE
stepWelcome.visibility = if (step == 1) View.VISIBLE else View.GONE
@@ -442,7 +496,9 @@ class SetupActivity : AppCompatActivity() {
stepServer.visibility = if (step == 3) View.VISIBLE else View.GONE
stepScale.visibility = if (step == 4) View.VISIBLE else View.GONE
stepScreensaver.visibility = if (step == 5) View.VISIBLE else View.GONE
stepDone.visibility = if (step == 6) View.VISIBLE else View.GONE
stepGemini.visibility = if (step == 6) View.VISIBLE else View.GONE
stepBring.visibility = if (step == 7) View.VISIBLE else View.GONE
stepDone.visibility = if (step == 8) View.VISIBLE else View.GONE
updateProgressDots()
@@ -478,7 +534,7 @@ class SetupActivity : AppCompatActivity() {
}
// Build summary when entering done step
if (step == 6) buildSummary()
if (step == 8) buildSummary()
// Cancel auto-discover when leaving server step
if (step != 3) discoverCancelled.set(true)
@@ -489,11 +545,11 @@ class SetupActivity : AppCompatActivity() {
private fun updateProgressDots() {
progressDots.removeAllViews()
// Show 5 dots for steps 1-5; step 0 (language) and step 6 (done) have no dots
if (currentStep == 0 || currentStep == 6) return
val active = currentStep // 1..5
// Show 7 dots for steps 1-7; step 0 (language) and step 8 (done) have no dots
if (currentStep == 0 || currentStep == 8) return
val active = currentStep // 1..7
val density = resources.displayMetrics.density
for (i in 1..5) {
for (i in 1..7) {
val dot = View(this)
val sizeDp = if (i == active) 10 else 7
val px = (sizeDp * density).toInt()
@@ -837,7 +893,7 @@ class SetupActivity : AppCompatActivity() {
}
discoveredDevices.clear()
deviceAdapter?.notifyDataSetChanged()
tvScanStatus.text = "🔍 Scansione in corso…"
tvScanStatus.text = getString(R.string.ble_scanning)
tvScanStatus.setTextColor(0xFF94a3b8.toInt())
btnScanBle.isEnabled = false
mgr.startScan()
@@ -850,7 +906,7 @@ class SetupActivity : AppCompatActivity() {
tvSelectedScale.text = "${info.name}"
tvSelectedScale.visibility = View.VISIBLE
btnScanBle.isEnabled = true
btnScanBle.text = "🔄 Scansiona di nuovo"
btnScanBle.text = getString(R.string.ble_scan_again)
// Start connection test
startScaleTest(info)
}
@@ -863,7 +919,7 @@ class SetupActivity : AppCompatActivity() {
scaleTestCard.visibility = View.VISIBLE
testWeightBox.visibility = View.GONE
step3NextButtons.visibility = View.GONE
tvTestStatus.text = "🔗 Connessione a ${info.name}"
tvTestStatus.text = getString(R.string.ble_connecting_to).format(info.name)
tvTestStatus.setTextColor(0xFF94a3b8.toInt())
tvTestWeight.text = "— g"
// Disable confirm/retry until we have data
@@ -887,19 +943,19 @@ class SetupActivity : AppCompatActivity() {
}
override fun onConnecting(device: BluetoothDevice) {
if (!isInTestMode) return
tvTestStatus.text = "🔗 Connessione in corso…"
tvTestStatus.text = getString(R.string.ble_connecting)
tvTestStatus.setTextColor(0xFF94a3b8.toInt())
}
override fun onConnected(deviceName: String) {
if (!isInTestMode) return
tvTestStatus.text = "⚖️ Connesso! Posiziona un oggetto sulla bilancia…"
tvTestStatus.text = getString(R.string.ble_connected)
tvTestStatus.setTextColor(0xFF34d399.toInt())
testWeightBox.visibility = View.VISIBLE
findViewById<MaterialButton>(R.id.btnTestRetry).isEnabled = true
}
override fun onDisconnected() {
if (!isInTestMode) return
tvTestStatus.text = "⚠️ Connessione persa. Riprova."
tvTestStatus.text = getString(R.string.ble_disconnected)
tvTestStatus.setTextColor(0xFFfbbf24.toInt())
testWeightBox.visibility = View.GONE
testHasWeight = false
@@ -914,7 +970,7 @@ class SetupActivity : AppCompatActivity() {
"%g ${reading.unit}".format(reading.value)
tvTestWeight.text = display
testWeightBox.visibility = View.VISIBLE
tvTestStatus.text = "Peso ricevuto — coincide con quello sulla bilancia?"
tvTestStatus.text = getString(R.string.ble_weight_received)
tvTestStatus.setTextColor(0xFF94a3b8.toInt())
findViewById<MaterialButton>(R.id.btnTestConfirm).isEnabled = true
findViewById<MaterialButton>(R.id.btnTestRetry).isEnabled = true
@@ -936,10 +992,10 @@ class SetupActivity : AppCompatActivity() {
override fun onScanStopped() {
btnScanBle.isEnabled = true
if (discoveredDevices.isEmpty()) {
tvScanStatus.text = "Nessuna bilancia trovata. Assicurati che sia accesa e vicina, poi riprova."
tvScanStatus.text = getString(R.string.ble_no_scale_found)
tvScanStatus.setTextColor(0xFFfbbf24.toInt())
} else {
tvScanStatus.text = "Seleziona la tua bilancia dall'elenco."
tvScanStatus.text = getString(R.string.ble_select_from_list)
tvScanStatus.setTextColor(0xFF94a3b8.toInt())
}
}
@@ -998,19 +1054,23 @@ class SetupActivity : AppCompatActivity() {
val scaleName = bleManager?.getSavedDeviceName()
val scaleOk = hasScale && scaleName != null
val lang = prefs.getString(KEY_LANGUAGE, "it") ?: "it"
val langLabel = when (lang) { "en" -> "English 🇬🇧"; "de" -> "Deutsch 🇩🇪"; else -> "Italiano 🇮🇹" }
val langLabel = when (lang) { "en" -> "English 🇬🇧"; "de" -> "Deutsch 🇩🇪"; "es" -> "Español 🇪🇸"; "fr" -> "Français 🇫🇷"; else -> "Italiano 🇮🇹" }
val sb = StringBuilder()
sb.appendLine("🌐 ${getString(R.string.summary_lang)}: $langLabel")
if (url.isNotEmpty()) sb.appendLine("🖥️ Server: $url")
sb.appendLine(when {
scaleOk -> "✅ Bilancia: $scaleName"
hasScale -> "⚠️ Bilancia: da configurare"
scaleOk -> getString(R.string.summary_scale_ok).format(scaleName)
hasScale -> "⚠️ ${getString(R.string.summary_scale_warn)}"
else -> "${getString(R.string.summary_scale_skip)}"
})
sb.appendLine(if (screensOn) getString(R.string.summary_screensaver_on) else getString(R.string.summary_screensaver_off))
if (pricesOn) sb.appendLine(getString(R.string.summary_prices_on))
if (mealPlanOn) sb.appendLine(getString(R.string.summary_mealplan_on))
if (zeroWasteOn) sb.appendLine(getString(R.string.summary_zerowaste_on))
val geminiSet = !(prefs.getString(KEY_GEMINI_KEY, "") ?: "").isNullOrEmpty()
val bringSet = !(prefs.getString(KEY_BRING_EMAIL, "") ?: "").isNullOrEmpty()
sb.appendLine(if (geminiSet) getString(R.string.summary_gemini_set) else getString(R.string.summary_gemini_skip))
sb.appendLine(if (bringSet) getString(R.string.summary_bring_set) else getString(R.string.summary_bring_skip))
summaryText.text = sb.toString().trimEnd()
}
@@ -1026,6 +1086,9 @@ class SetupActivity : AppCompatActivity() {
Thread {
try {
val url = "$baseUrl/api/index.php?action=save_settings"
val geminiKey = prefs.getString(KEY_GEMINI_KEY, "") ?: ""
val bringEmail = prefs.getString(KEY_BRING_EMAIL, "") ?: ""
val bringPassword = prefs.getString(KEY_BRING_PASSWORD, "") ?: ""
val body = buildString {
append("{\"screensaver_enabled\":$screensaver")
append(",\"price_enabled\":$priceEnabled")
@@ -1035,6 +1098,9 @@ class SetupActivity : AppCompatActivity() {
val lanIp = getDeviceLanIp() ?: "127.0.0.1"
append(",\"scale_enabled\":true,\"scale_gateway_url\":\"ws://$lanIp:8765\"")
}
if (geminiKey.isNotEmpty()) append(",\"gemini_api_key\":\"${geminiKey.replace("\"", "\\\"\")}\"")
if (bringEmail.isNotEmpty()) append(",\"bring_email\":\"${bringEmail.replace("\"", "\\\"\")}\"")
if (bringPassword.isNotEmpty()) append(",\"bring_password\":\"${bringPassword.replace("\"", "\\\"\")}\"")
append("}")
}
val conn = (java.net.URL(url).openConnection() as java.net.HttpURLConnection).apply {
@@ -78,11 +78,11 @@
android:layout_marginBottom="24dp"
android:contentDescription="EverShelf" />
<!-- Title shown in all 3 languages so it's always readable -->
<!-- Title shown in all 5 languages so it's always readable -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Scegli la lingua\nChoose your language\nSprache wählen"
android:text="Scegli la lingua · Choose your language\nSprache wählen · Elige el idioma\nChoisissez votre langue"
android:textColor="#f1f5f9"
android:textSize="22sp"
android:textStyle="bold"
@@ -117,7 +117,27 @@
android:text="🇩🇪 Deutsch"
android:textSize="18sp"
android:textAllCaps="false"
android:backgroundTint="#b91c1c" />
android:backgroundTint="#b91c1c"
android:layout_marginBottom="16dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnLangEs"
android:layout_width="match_parent"
android:layout_height="64dp"
android:text="🇪🇸 Español"
android:textSize="18sp"
android:textAllCaps="false"
android:backgroundTint="#c2410c"
android:layout_marginBottom="16dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnLangFr"
android:layout_width="match_parent"
android:layout_height="64dp"
android:text="🇫🇷 Français"
android:textSize="18sp"
android:textAllCaps="false"
android:backgroundTint="#1d4ed8" />
</LinearLayout>
@@ -1241,7 +1261,7 @@
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="← Indietro"
android:text="@string/setup_step_back"
android:textSize="14sp"
android:textAllCaps="false"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
@@ -1254,7 +1274,7 @@
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="2"
android:text="Avanti →"
android:text="@string/setup_step_next"
android:textSize="15sp"
android:textAllCaps="false"
android:backgroundTint="#7c3aed" />
@@ -1262,7 +1282,230 @@
</LinearLayout>
<!-- ════════════════════════════════════════════
STEP 6 — Done
STEP 6 — Gemini AI key
════════════════════════════════════════════ -->
<LinearLayout
android:id="@+id/stepGemini"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="🤖"
android:textSize="52sp"
android:layout_marginBottom="12dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/setup_gemini_title"
android:textColor="#f1f5f9"
android:textSize="24sp"
android:textStyle="bold"
android:layout_marginBottom="8dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/setup_gemini_desc"
android:textColor="#94a3b8"
android:textSize="15sp"
android:gravity="center"
android:lineSpacingExtra="4dp"
android:layout_marginBottom="16dp" />
<!-- How-to card -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@drawable/card_background"
android:padding="14dp"
android:gravity="center_vertical"
android:layout_marginBottom="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="💡"
android:textSize="20sp"
android:layout_marginEnd="10dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/setup_gemini_how"
android:textColor="#7dd3fc"
android:textSize="13sp"
android:lineSpacingExtra="3dp" />
</LinearLayout>
<EditText
android:id="@+id/setupGeminiKeyEdit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/setup_gemini_hint"
android:textColor="#f1f5f9"
android:textColorHint="#475569"
android:backgroundTint="#334155"
android:inputType="textVisiblePassword"
android:textSize="14sp"
android:fontFamily="monospace"
android:layout_marginBottom="20dp" />
<!-- Navigation -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/btnGeminiBack"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="@string/setup_step_back"
android:textSize="14sp"
android:textAllCaps="false"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:strokeColor="#334155"
android:textColor="#64748b"
android:layout_marginEnd="8dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnGeminiSkip"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="@string/setup_skip_later"
android:textSize="13sp"
android:textAllCaps="false"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:strokeColor="#475569"
android:textColor="#94a3b8"
android:layout_marginEnd="8dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnGeminiNext"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="@string/setup_confirm"
android:textSize="14sp"
android:textAllCaps="false"
android:backgroundTint="#7c3aed" />
</LinearLayout>
</LinearLayout>
<!-- ════════════════════════════════════════════
STEP 7 — Bring! credentials
════════════════════════════════════════════ -->
<LinearLayout
android:id="@+id/stepBring"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="🛒"
android:textSize="52sp"
android:layout_marginBottom="12dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/setup_bring_title"
android:textColor="#f1f5f9"
android:textSize="24sp"
android:textStyle="bold"
android:layout_marginBottom="8dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/setup_bring_desc"
android:textColor="#94a3b8"
android:textSize="15sp"
android:gravity="center"
android:lineSpacingExtra="4dp"
android:layout_marginBottom="16dp" />
<EditText
android:id="@+id/setupBringEmailEdit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/setup_bring_email_hint"
android:textColor="#f1f5f9"
android:textColorHint="#475569"
android:backgroundTint="#334155"
android:inputType="textEmailAddress"
android:textSize="15sp"
android:layout_marginBottom="10dp" />
<EditText
android:id="@+id/setupBringPasswordEdit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/setup_bring_pass_hint"
android:textColor="#f1f5f9"
android:textColorHint="#475569"
android:backgroundTint="#334155"
android:inputType="textPassword"
android:textSize="15sp"
android:layout_marginBottom="20dp" />
<!-- Navigation -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/btnBringBack"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="@string/setup_step_back"
android:textSize="14sp"
android:textAllCaps="false"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:strokeColor="#334155"
android:textColor="#64748b"
android:layout_marginEnd="8dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnBringSkip"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="@string/setup_skip_later"
android:textSize="13sp"
android:textAllCaps="false"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:strokeColor="#475569"
android:textColor="#94a3b8"
android:layout_marginEnd="8dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnBringNext"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="@string/setup_confirm"
android:textSize="14sp"
android:textAllCaps="false"
android:backgroundTint="#059669" />
</LinearLayout>
</LinearLayout>
<!-- ════════════════════════════════════════════
STEP 8 — Done
════════════════════════════════════════════ -->
<LinearLayout
android:id="@+id/stepDone"
@@ -1282,7 +1525,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tutto pronto!"
android:text="@string/setup_done_title"
android:textColor="#f1f5f9"
android:textSize="28sp"
android:textStyle="bold"
@@ -1291,7 +1534,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="La configurazione è completa. Premi il pulsante per avviare EverShelf in modalità kiosk."
android:text="@string/setup_done_desc"
android:textColor="#94a3b8"
android:textSize="15sp"
android:gravity="center"
@@ -1310,10 +1553,10 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Riepilogo configurazione"
android:text="@string/setup_done_summary_label"
android:textColor="#94a3b8"
android:textSize="13sp"
android:textAllCaps="true"
android:textAllCaps="false"
android:letterSpacing="0.08"
android:layout_marginBottom="12dp" />
@@ -1331,7 +1574,7 @@
android:id="@+id/btnLaunch"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="🚀 Avvia EverShelf"
android:text="@string/btn_launch"
android:textSize="18sp"
android:textAllCaps="false"
android:backgroundTint="#059669" />
@@ -1,29 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">EverShelf Kiosk</string>
<!-- Setup-Assistent Zeichenfolgen -->
<string name="setup_enter_url">Bitte zuerst eine URL eingeben</string>
<string name="setup_testing">Verbindung wird getestet…</string>
<string name="setup_server_found">EverShelf-Server gefunden und API aktiv!</string>
<string name="setup_api_not_found">Server erreichbar, aber EverShelf-API nicht gefunden. Pfad prüfen.</string>
<string name="setup_unreachable">Server nicht erreichbar</string>
<string name="setup_discover_btn">🔍 Lokales Netzwerk durchsuchen</string> <string name="setup_perms_granted_next">✅ Berechtigungen erteilt — Weiter →</string> <string name="setup_discovering">Suche läuft…</string>
<string name="setup_discover_btn">🔍 Lokales Netzwerk durchsuchen</string>
<string name="setup_perms_granted_next">✅ Berechtigungen erteilt — Weiter →</string>
<string name="setup_discovering">Suche läuft…</string>
<string name="setup_discovering_detail">Suche nach EverShelf-Servern im lokalen Netzwerk…</string>
<string name="setup_discover_not_found">Kein EverShelf-Server automatisch gefunden. URL manuell eingeben.</string>
<string name="setup_exit_title">Setup beenden?</string>
<string name="setup_exit_message">Die Einrichtung kann später beim erneuten Öffnen der App abgeschlossen werden.</string>
<string name="setup_exit_confirm">Beenden</string>
<string name="setup_exit_cancel">Weiter</string>
<!-- Wizard Schritt 3: Smart-Waage -->
<string name="setup_step_back">← Zurück</string>
<string name="setup_step_next">Weiter →</string>
<string name="setup_skip_later">Später einrichten</string>
<string name="setup_confirm">Bestätigen →</string>
<string name="wizard_step3_title">Smart-Waage (Optional)</string>
<string name="wizard_step3_description">Um eine Bluetooth-Küchenwaage zu verwenden, musst du die EverShelf Scale Gateway App separat installieren.</string>
<string name="wizard_step3_question">Hast du eine Bluetooth-Küchenwaage?</string>
<string name="wizard_step3_yes">✅ Ja, ich habe eine Waage</string>
<string name="wizard_step3_no">➡️ Nein, überspringen</string>
<!-- Gateway-Statusmeldungen -->
<string name="ble_scanning">🔍 Suche läuft…</string>
<string name="ble_connected">Verbunden! Gegenstand auf die Waage legen…</string>
<string name="ble_disconnected">Verbindung getrennt. Erneut versuchen.</string>
<string name="ble_no_scale_found">Keine Waage gefunden. Sicherstellen, dass sie eingeschaltet und in der Nähe ist, und erneut versuchen.</string>
<string name="ble_select_from_list">Waage aus der Liste auswählen.</string>
<string name="ble_not_confirmed">Waage nicht bestätigt. Erneut scannen.</string>
<string name="ble_scan_again">🔄 Erneut scannen</string>
<string name="ble_weight_received">Gewicht empfangen — Stimmt es mit der Anzeige überein?</string>
<string name="wizard_gateway_installed">Scale Gateway installiert ✅</string>
<string name="wizard_gateway_installed_detail">Wird beim Fortfahren im Hintergrund gestartet.</string>
<string name="wizard_gateway_not_installed">Scale Gateway nicht installiert</string>
@@ -32,8 +40,6 @@
<string name="wizard_gateway_up_to_date">Scale Gateway ist aktuell.</string>
<string name="wizard_gateway_update_available">Update für Scale Gateway verfügbar</string>
<string name="wizard_gateway_update_detail">Tippe auf den Button, um jetzt zu aktualisieren.</string>
<!-- Download- / Installationsfortschritt -->
<string name="install_downloading">Download läuft…</string>
<string name="install_downloading_detail">Bitte warten, die Datei wird heruntergeladen.</string>
<string name="install_installing">Installation läuft…</string>
@@ -43,31 +49,56 @@
<string name="install_error_download">Download fehlgeschlagen</string>
<string name="install_error_download_detail">Verbindung prüfen und erneut versuchen.</string>
<string name="install_error_install">Installation fehlgeschlagen</string>
<string name="install_perm_detail">Aktiviere \'Unbekannte Apps installieren\' in den Einstellungen, dann komm zurück.</string>
<string name="install_perm_detail">Aktiviere 'Unbekannte Apps installieren' in den Einstellungen, dann komm zurück.</string>
<string name="install_btn_retry">↩ Nochmal versuchen</string>
<!-- Schaltflächen -->
<string name="btn_back">Zurück</string>
<string name="btn_launch">🚀 EverShelf starten</string>
<string name="btn_launch_no_scale">🚀 Ohne Waage starten</string>
<string name="btn_download_gateway">📥 Scale Gateway installieren</string>
<string name="btn_update_gateway">📥 Scale Gateway aktualisieren</string>
<!-- Server-Erreichbarkeit prüfen (Wizard Schritt 3) -->
<string name="wizard_server_checking">Server-Verbindung wird geprüft…</string>
<string name="wizard_server_ok">Server erreichbar ✅</string>
<string name="wizard_server_ok_detail">Fehlerberichterstattung aktiv — Installationsfehler werden automatisch an GitHub Issues gesendet.</string>
<string name="wizard_server_error">Server nicht erreichbar ⚠️</string>
<string name="wizard_server_error_detail">Fehler werden GitHub Issues nicht erreichen. URL in Schritt 2 prüfen.</string>
<!-- Bildschirmschoner-Schritt -->
<string name="setup_screensaver_title">Bildschirmschoner</string>
<string name="setup_screensaver_desc">Zeigt nach 5 Minuten Inaktivität eine Uhr mit nützlichen Fakten. Standardmäßig deaktiviert (Bildschirm bleibt immer an).</string>
<string name="setup_screensaver_toggle_label">Bildschirmschoner aktivieren</string>
<string name="setup_screensaver_toggle_hint">Wenn deaktiviert, bleibt der Bildschirm immer an.</string>
<string name="setup_features_title">Funktionen</string>
<string name="setup_features_desc">Aktiviere die gewünschten Funktionen. Du kannst sie später jederzeit in den Servereinstellungen ändern.</string>
<string name="setup_screensaver_toggle_label">Uhr-Bildschirmschoner</string>
<string name="setup_screensaver_toggle_hint">Zeigt eine Uhranzeige nach 5 Min. Inaktivität.</string>
<string name="setup_prices_toggle_label">Einkaufslisten-Preise</string>
<string name="setup_prices_toggle_hint">KI-gestützte automatische Kostensätzung für jeden Artikel.</string>
<string name="setup_mealplan_toggle_label">Mahlzeitenplan</string>
<string name="setup_mealplan_toggle_hint">Plane die Wöchentliche Mahlzeiten mit Rezepten aus deiner Vorratskammer.</string>
<string name="setup_zerowaste_toggle_label">Zero-Waste-Tipps</string>
<string name="setup_zerowaste_toggle_hint">Beim Kochen Tipps zur Wiederverwendung von Resten anzeigen (Schalen, Kochwasser usw.).</string>
<string name="setup_gemini_title">Google Gemini AI</string>
<string name="setup_gemini_desc">EverShelf nutzt Google Gemini AI für Rezeptvorschläge, smarte Einkaufsschätzungen und mehr.
<!-- Zusammenfassung -->
Zum Aktivieren den kostenlosen Gemini API-Schlüssel eingeben.</string>
<string name="setup_gemini_how">Kostenlosen Schlüssel unter: aistudio.google.com → "API-Schlüssel erhalten"</string>
<string name="setup_gemini_hint">API-Schlüssel einfügen (beginnt mit AIza…)</string>
<string name="setup_bring_title">Bring! Einkaufsliste</string>
<string name="setup_bring_desc">EverShelf kann die Einkaufsliste mit der Bring!-App synchronisieren.
Bring!-Zugangsdaten eingeben, um die Integration zu aktivieren.</string>
<string name="setup_bring_email_hint">Bring!-E-Mail-Adresse</string>
<string name="setup_bring_pass_hint">Bring!-Passwort</string>
<string name="setup_done_title">Alles bereit!</string>
<string name="setup_done_desc">Die Einrichtung ist abgeschlossen. Auf den Button tippen, um EverShelf im Kiosk-Modus zu starten.</string>
<string name="setup_done_summary_label">KONFIGURATIONSSÜBERSICHT</string>
<string name="summary_lang">Sprache</string>
<string name="summary_scale_skip">Waage: nicht konfiguriert</string>
<string name="summary_screensaver_on">Bildschirmschoner: aktiv</string>
<string name="summary_screensaver_off">Bildschirm immer an (Bildschirmschoner deaktiviert)</string>
</resources>
<string name="summary_prices_on">Einkaufslisten-Preise: aktiviert</string>
<string name="summary_mealplan_on">Mahlzeitenplan: aktiviert</string>
<string name="summary_zerowaste_on">Zero-Waste-Tipps: aktiviert</string>
<string name="summary_gemini_set">Gemini AI: aktiviert</string>
<string name="summary_gemini_skip">Gemini AI: nicht konfiguriert</string>
<string name="summary_bring_set">Bring!: verbunden</string>
<string name="summary_bring_skip">Bring!: nicht konfiguriert</string>
<string name="ble_connecting_to">🔗 Verbinde mit %s…</string>
<string name="ble_connecting">🔗 Verbindung wird hergestellt…</string>
<string name="summary_scale_ok">Waage: %s</string>
<string name="summary_scale_warn">Waage: nicht bestätigt</string>
</resources>
@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">EverShelf Kiosk</string>
<string name="setup_enter_url">Introduce primero una URL</string>
<string name="setup_testing">Probando conexión…</string>
<string name="setup_server_found">¡Servidor EverShelf encontrado y API activa!</string>
<string name="setup_api_not_found">Servidor accesible pero API EverShelf no encontrada. Comprueba la ruta.</string>
<string name="setup_unreachable">No se puede alcanzar el servidor</string>
<string name="setup_discover_btn">🔍 Buscar en la red local</string>
<string name="setup_perms_granted_next">✅ Permisos concedidos — Continuar →</string>
<string name="setup_discovering">Escaneando…</string>
<string name="setup_discovering_detail">Buscando servidores EverShelf en la red local…</string>
<string name="setup_discover_not_found">Ningún servidor EverShelf encontrado automáticamente. Introduce la URL manualmente.</string>
<string name="setup_exit_title">¿Salir de la configuración?</string>
<string name="setup_exit_message">Puedes completar la configuración más tarde cuando vuelvas a abrir la app.</string>
<string name="setup_exit_confirm">Salir</string>
<string name="setup_exit_cancel">Continuar</string>
<string name="setup_step_back">← Atrás</string>
<string name="setup_step_next">Siguiente →</string>
<string name="setup_skip_later">Configurar después</string>
<string name="setup_confirm">Confirmar →</string>
<string name="wizard_step3_title">Báscula inteligente</string>
<string name="wizard_step3_description">EverShelf Kiosk incluye una pasarela Bluetooth integrada — no necesitas ninguna app externa. Selecciona tu báscula abajo.</string>
<string name="wizard_step3_question">¿Tienes una báscula inteligente Bluetooth?</string>
<string name="wizard_step3_yes">✅ Sí, tengo una báscula</string>
<string name="wizard_step3_no">➡️ No, saltar este paso</string>
<string name="ble_scanning">🔍 Escaneando…</string>
<string name="ble_connected">¡Conectado! Coloca un objeto en la báscula…</string>
<string name="ble_disconnected">Conexión perdida. Reintentar.</string>
<string name="ble_no_scale_found">No se encontró ninguna báscula. Asegúrate de que esté encendida y cerca, e inténtalo de nuevo.</string>
<string name="ble_select_from_list">Selecciona tu báscula de la lista.</string>
<string name="ble_not_confirmed">Báscula no confirmada. Vuelve a escanear.</string>
<string name="ble_scan_again">🔄 Volver a escanear</string>
<string name="ble_weight_received">Peso recibido — ¿coincide con el mostrado en la báscula?</string>
<string name="wizard_gateway_installed">Báscula guardada ✅</string>
<string name="wizard_gateway_installed_detail">La pasarela BLE integrada se conectará automáticamente al inicio.</string>
<string name="wizard_gateway_not_installed">Ninguna báscula seleccionada</string>
<string name="wizard_gateway_not_installed_detail">Escanea las básculas BLE cercanas y toca una para seleccionarla.</string>
<string name="wizard_gateway_checking">Escaneando básculas BLE…</string>
<string name="wizard_gateway_up_to_date">Servicio BLE de báscula listo.</string>
<string name="wizard_gateway_update_available">Báscula BLE encontrada</string>
<string name="wizard_gateway_update_detail">Toca la báscula en la lista para conectarte.</string>
<string name="install_downloading">Descargando…</string>
<string name="install_downloading_detail">Por favor, espera mientras se descarga el archivo.</string>
<string name="install_installing">Instalando…</string>
<string name="install_confirm_detail">Confirma la instalación en el diálogo que se ha abierto.</string>
<string name="install_success">¡Instalado correctamente!</string>
<string name="install_success_detail">La app ha sido actualizada.</string>
<string name="install_error_download">Descarga fallida</string>
<string name="install_error_download_detail">Comprueba la conexión e inténtalo de nuevo.</string>
<string name="install_error_install">Instalación fallida</string>
<string name="install_perm_detail">Habilita 'Instalar apps desconocidas' en los ajustes y vuelve aquí.</string>
<string name="install_btn_retry">↩ Reintentar</string>
<string name="btn_back">Atrás</string>
<string name="btn_launch">🚀 Iniciar EverShelf</string>
<string name="btn_launch_no_scale">🚀 Iniciar sin báscula</string>
<string name="btn_download_gateway">📥 Instalar Scale Gateway</string>
<string name="btn_update_gateway">📥 Actualizar Scale Gateway</string>
<string name="wizard_server_checking">Comprobando conexión al servidor…</string>
<string name="wizard_server_ok">Servidor accesible ✅</string>
<string name="wizard_server_ok_detail">Informe de errores activo — los fallos de instalación se enviarán automáticamente a GitHub Issues.</string>
<string name="wizard_server_error">Servidor no accesible ⚠️</string>
<string name="wizard_server_error_detail">Los errores no llegarán a GitHub Issues. Comprueba la URL introducida en el paso 2.</string>
<string name="setup_features_title">Funcionalidades</string>
<string name="setup_features_desc">Activa las funciones que quieras usar. Puedes cambiarlas en cualquier momento desde los ajustes del servidor.</string>
<string name="setup_screensaver_toggle_label">Salvapantallas reloj</string>
<string name="setup_screensaver_toggle_hint">Muestra un reloj después de 5 min de inactividad.</string>
<string name="setup_prices_toggle_label">Precios lista de la compra</string>
<string name="setup_prices_toggle_hint">Estimación automática del coste de cada artículo mediante IA.</string>
<string name="setup_mealplan_toggle_label">Plan de comidas</string>
<string name="setup_mealplan_toggle_hint">Planifica las comidas de la semana con recetas basadas en tu despensa.</string>
<string name="setup_zerowaste_toggle_label">Consejos zero-waste</string>
<string name="setup_zerowaste_toggle_hint">Muestra consejos para reutilizar restos (cáscaras, agua de cocción, etc.) al cocinar.</string>
<string name="setup_gemini_title">Google Gemini AI</string>
<string name="setup_gemini_desc">EverShelf usa Google Gemini AI para sugerencias de recetas, estimaciones inteligentes de la compra y más.
Para activarla, introduce tu clave API de Gemini gratuita.</string>
<string name="setup_gemini_how">Obtén tu clave gratuita en: aistudio.google.com → "Obtener clave API"</string>
<string name="setup_gemini_hint">Pega la clave API aquí (empieza por AIza…)</string>
<string name="setup_bring_title">Bring! Lista de la compra</string>
<string name="setup_bring_desc">EverShelf puede sincronizar tu lista de la compra con la app Bring!.
Introduce tus credenciales de Bring! para activar la integración.</string>
<string name="setup_bring_email_hint">Correo electrónico de Bring!</string>
<string name="setup_bring_pass_hint">Contraseña de Bring!</string>
<string name="setup_done_title">¡Todo listo!</string>
<string name="setup_done_desc">La configuración está completa. Pulsa el botón para iniciar EverShelf en modo quiosco.</string>
<string name="setup_done_summary_label">RESUMEN DE CONFIGURACIÓN</string>
<string name="summary_lang">Idioma</string>
<string name="summary_scale_skip">Báscula: no configurada</string>
<string name="summary_screensaver_on">Salvapantallas: activo</string>
<string name="summary_screensaver_off">Pantalla siempre encendida (salvapantallas desactivado)</string>
<string name="summary_prices_on">Precios lista de la compra: activados</string>
<string name="summary_mealplan_on">Plan de comidas: activado</string>
<string name="summary_zerowaste_on">Consejos zero-waste: activados</string>
<string name="summary_gemini_set">Gemini AI: activada</string>
<string name="summary_gemini_skip">Gemini AI: no configurada</string>
<string name="summary_bring_set">Bring!: conectada</string>
<string name="summary_bring_skip">Bring!: no configurada</string>
<string name="ble_connecting_to">🔗 Conectando con %s…</string>
<string name="ble_connecting">🔗 Estableciendo conexión…</string>
<string name="summary_scale_ok">Báscula: %s</string>
<string name="summary_scale_warn">Báscula: no confirmada</string>
</resources>
@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">EverShelf Kiosk</string>
<string name="setup_enter_url">Veuillez d'abord saisir une URL</string>
<string name="setup_testing">Test de connexion…</string>
<string name="setup_server_found">Serveur EverShelf trouvé et API active !</string>
<string name="setup_api_not_found">Serveur accessible mais API EverShelf introuvable. Vérifiez le chemin.</string>
<string name="setup_unreachable">Impossible d'atteindre le serveur</string>
<string name="setup_discover_btn">🔍 Rechercher sur le réseau local</string>
<string name="setup_perms_granted_next">✅ Permissions accordées — Continuer →</string>
<string name="setup_discovering">Analyse en cours…</string>
<string name="setup_discovering_detail">Recherche de serveurs EverShelf sur le réseau local…</string>
<string name="setup_discover_not_found">Aucun serveur EverShelf trouvé automatiquement. Entrez l'URL manuellement.</string>
<string name="setup_exit_title">Quitter la configuration ?</string>
<string name="setup_exit_message">Vous pouvez terminer la configuration plus tard en rouvrant l'app.</string>
<string name="setup_exit_confirm">Quitter</string>
<string name="setup_exit_cancel">Continuer</string>
<string name="setup_step_back">← Retour</string>
<string name="setup_step_next">Suivant →</string>
<string name="setup_skip_later">Configurer plus tard</string>
<string name="setup_confirm">Confirmer →</string>
<string name="wizard_step3_title">Balance intelligente</string>
<string name="wizard_step3_description">EverShelf Kiosk inclut une passerelle Bluetooth intégrée — aucune app externe nécessaire. Sélectionnez votre balance ci-dessous.</string>
<string name="wizard_step3_question">Avez-vous une balance intelligente Bluetooth ?</string>
<string name="wizard_step3_yes">✅ Oui, j'ai une balance</string>
<string name="wizard_step3_no">➡️ Non, ignorer cette étape</string>
<string name="ble_scanning">🔍 Scan en cours…</string>
<string name="ble_connected">Connecté ! Posez un objet sur la balance…</string>
<string name="ble_disconnected">Connexion perdue. Réessayer.</string>
<string name="ble_no_scale_found">Aucune balance trouvée. Vérifiez qu'elle est allumée et à proximité, puis réessayez.</string>
<string name="ble_select_from_list">Sélectionnez votre balance dans la liste.</string>
<string name="ble_not_confirmed">Balance non confirmée. Relancer le scan.</string>
<string name="ble_scan_again">🔄 Scanner à nouveau</string>
<string name="ble_weight_received">Poids reçu — correspond-il à l'affichage de la balance ?</string>
<string name="wizard_gateway_installed">Balance enregistrée ✅</string>
<string name="wizard_gateway_installed_detail">La passerelle BLE intégrée se connectera automatiquement au démarrage.</string>
<string name="wizard_gateway_not_installed">Aucune balance sélectionnée</string>
<string name="wizard_gateway_not_installed_detail">Scannez les balances BLE à proximité et appuyez sur l'une d'elles pour la sélectionner.</string>
<string name="wizard_gateway_checking">Scan des balances BLE en cours…</string>
<string name="wizard_gateway_up_to_date">Service BLE de la balance prêt.</string>
<string name="wizard_gateway_update_available">Balance BLE trouvée</string>
<string name="wizard_gateway_update_detail">Appuyez sur la balance dans la liste pour vous connecter.</string>
<string name="install_downloading">Téléchargement en cours…</string>
<string name="install_downloading_detail">Veuillez patienter, le fichier est en cours de téléchargement.</string>
<string name="install_installing">Installation en cours…</string>
<string name="install_confirm_detail">Confirmez l'installation dans la boîte de dialogue ouverte.</string>
<string name="install_success">Installé avec succès !</string>
<string name="install_success_detail">L'app a été mise à jour.</string>
<string name="install_error_download">Téléchargement échoué</string>
<string name="install_error_download_detail">Vérifiez la connexion et réessayez.</string>
<string name="install_error_install">Installation échouée</string>
<string name="install_perm_detail">Activez 'Installer des apps inconnues' dans les paramètres, puis revenez ici.</string>
<string name="install_btn_retry">↩ Réessayer</string>
<string name="btn_back">Retour</string>
<string name="btn_launch">🚀 Lancer EverShelf</string>
<string name="btn_launch_no_scale">🚀 Lancer sans balance</string>
<string name="btn_download_gateway">📥 Installer Scale Gateway</string>
<string name="btn_update_gateway">📥 Mettre à jour Scale Gateway</string>
<string name="wizard_server_checking">Vérification de la connexion au serveur…</string>
<string name="wizard_server_ok">Serveur accessible ✅</string>
<string name="wizard_server_ok_detail">Rapport d'erreurs actif — les échecs d'installation seront envoyés automatiquement aux GitHub Issues.</string>
<string name="wizard_server_error">Serveur inaccessible ⚠️</string>
<string name="wizard_server_error_detail">Les erreurs n'atteindront pas GitHub Issues. Vérifiez l'URL saisie à l'étape 2.</string>
<string name="setup_features_title">Fonctionnalités</string>
<string name="setup_features_desc">Activez les fonctions que vous souhaitez utiliser. Vous pourrez les modifier plus tard dans les paramètres du serveur.</string>
<string name="setup_screensaver_toggle_label">Horloge écran de veille</string>
<string name="setup_screensaver_toggle_hint">Affiche une horloge après 5 min d'inactivité.</string>
<string name="setup_prices_toggle_label">Prix liste de courses</string>
<string name="setup_prices_toggle_hint">Estimation automatique du coût de chaque article via IA.</string>
<string name="setup_mealplan_toggle_label">Plan de repas</string>
<string name="setup_mealplan_toggle_hint">Planifiez les repas de la semaine avec des recettes basées sur votre garde-manger.</string>
<string name="setup_zerowaste_toggle_label">Conseils zéro déchet</string>
<string name="setup_zerowaste_toggle_hint">Affiche des conseils pour réutiliser les restes (peaux, eau de cuisson, etc.) pendant la cuisson.</string>
<string name="setup_gemini_title">Google Gemini AI</string>
<string name="setup_gemini_desc">EverShelf utilise Google Gemini AI pour les suggestions de recettes, les estimations intelligentes des courses et plus encore.
Pour l'activer, entrez votre clé API Gemini gratuite.</string>
<string name="setup_gemini_how">Obtenez votre clé gratuite sur : aistudio.google.com → "Obtenir une clé API"</string>
<string name="setup_gemini_hint">Collez la clé API ici (commence par AIza…)</string>
<string name="setup_bring_title">Bring! Liste de courses</string>
<string name="setup_bring_desc">EverShelf peut synchroniser votre liste de courses avec l'app Bring!.
Entrez vos identifiants Bring! pour activer l'intégration.</string>
<string name="setup_bring_email_hint">Adresse e-mail Bring!</string>
<string name="setup_bring_pass_hint">Mot de passe Bring!</string>
<string name="setup_done_title">Tout est prêt !</string>
<string name="setup_done_desc">La configuration est terminée. Appuyez sur le bouton pour lancer EverShelf en mode kiosque.</string>
<string name="setup_done_summary_label">RÉSUMÉ DE CONFIGURATION</string>
<string name="summary_lang">Langue</string>
<string name="summary_scale_skip">Balance : non configurée</string>
<string name="summary_screensaver_on">Écran de veille : actif</string>
<string name="summary_screensaver_off">Écran toujours allumé (écran de veille désactivé)</string>
<string name="summary_prices_on">Prix liste de courses : activés</string>
<string name="summary_mealplan_on">Plan de repas : activé</string>
<string name="summary_zerowaste_on">Conseils zéro déchet : activés</string>
<string name="summary_gemini_set">Gemini AI : activée</string>
<string name="summary_gemini_skip">Gemini AI : non configurée</string>
<string name="summary_bring_set">Bring! : connectée</string>
<string name="summary_bring_skip">Bring! : non configurée</string>
<string name="ble_connecting_to">🔗 Connexion à %s…</string>
<string name="ble_connecting">🔗 Connexion en cours…</string>
<string name="summary_scale_ok">Balance : %s</string>
<string name="summary_scale_warn">Balance : non confirmée</string>
</resources>
@@ -1,73 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">EverShelf Kiosk</string>
<!-- Stringhe setup wizard -->
<string name="setup_enter_url">Inserisci prima un URL</string>
<string name="setup_testing">Verifica connessione…</string>
<string name="setup_server_found">Server EverShelf trovato e API attiva!</string>
<string name="setup_api_not_found">Server raggiungibile ma API EverShelf non trovata. Verifica il percorso.</string>
<string name="setup_unreachable">Impossibile raggiungere il server</string>
<string name="setup_discover_btn">🔍 Cerca nella rete locale</string> <string name="setup_perms_granted_next">✅ Permessi concessi — Continua →</string> <string name="setup_discovering">Scansione in corso…</string>
<string name="setup_discover_btn">🔍 Cerca nella rete locale</string>
<string name="setup_perms_granted_next">✅ Permessi concessi — Continua →</string>
<string name="setup_discovering">Scansione in corso…</string>
<string name="setup_discovering_detail">Ricerca server EverShelf nella rete locale…</string>
<string name="setup_discover_not_found">Nessun server EverShelf trovato automaticamente. Inserisci l\'URL manualmente.</string>
<string name="setup_discover_not_found">Nessun server EverShelf trovato automaticamente. Inserisci l'URL manualmente.</string>
<string name="setup_exit_title">Uscire dalla configurazione?</string>
<string name="setup_exit_message">Puoi completare la configurazione più tardi riaprendo l\'app.</string>
<string name="setup_exit_message">Puoi completare la configurazione più tardi riaprendo l'app.</string>
<string name="setup_exit_confirm">Esci</string>
<string name="setup_exit_cancel">Continua</string>
<!-- Wizard Step 3: Bilancia smart -->
<string name="setup_step_back">← Indietro</string>
<string name="setup_step_next">Avanti →</string>
<string name="setup_skip_later">Lo faccio dopo</string>
<string name="setup_confirm">Conferma →</string>
<string name="wizard_step3_title">Bilancia Smart</string>
<string name="wizard_step3_description">EverShelf Kiosk include un gateway Bluetooth integrato — nessuna app esterna necessaria. Seleziona la tua bilancia qui sotto.</string>
<string name="wizard_step3_question">Hai una bilancia smart Bluetooth?</string>
<string name="wizard_step3_yes">✅ Sì, ho una bilancia</string>
<string name="wizard_step3_no">➡️ No, salta questo passaggio</string>
<!-- Messaggi stato gateway -->
<string name="ble_scanning">🔍 Scansione in corso…</string>
<string name="ble_connected">Connesso! Posiziona un oggetto sulla bilancia…</string>
<string name="ble_disconnected">Connessione persa. Riprova.</string>
<string name="ble_no_scale_found">Nessuna bilancia trovata. Assicurati che sia accesa e vicina, poi riprova.</string>
<string name="ble_select_from_list">Seleziona la tua bilancia dall'elenco.</string>
<string name="ble_not_confirmed">Bilancia non confermata. Riprova la scansione.</string>
<string name="ble_scan_again">🔄 Scansiona di nuovo</string>
<string name="ble_weight_received">Peso ricevuto — coincide con quello sulla bilancia?</string>
<string name="wizard_gateway_installed">Bilancia salvata ✅</string>
<string name="wizard_gateway_installed_detail">Il gateway BLE integrato si collegherà automaticamente all\'avvio.</string>
<string name="wizard_gateway_installed_detail">Il gateway BLE integrato si collegher automaticamente all'avvio.</string>
<string name="wizard_gateway_not_installed">Nessuna bilancia selezionata</string>
<string name="wizard_gateway_not_installed_detail">Scansiona le bilance BLE nelle vicinanze e tocca una per selezionarla.</string>
<string name="wizard_gateway_checking">Scansione bilance BLE in corso…</string>
<string name="wizard_gateway_up_to_date">Servizio BLE bilancia pronto.</string>
<string name="wizard_gateway_update_available">Bilancia BLE trovata</string>
<string name="wizard_gateway_update_detail">Tocca la bilancia nell\'elenco per connettersi.</string>
<!-- Stati scaricamento / installazione -->
<string name="wizard_gateway_update_detail">Tocca la bilancia nell'elenco per connettersi.</string>
<string name="install_downloading">Scaricamento in corso…</string>
<string name="install_downloading_detail">Attendi, il file viene scaricato.</string>
<string name="install_installing">Installazione in corso…</string>
<string name="install_confirm_detail">Conferma l\'installazione nel dialog che si è aperto.</string>
<string name="install_confirm_detail">Conferma l'installazione nel dialog che si è aperto.</string>
<string name="install_success">Installato con successo!</string>
<string name="install_success_detail">L\'app è stata aggiornata.</string>
<string name="install_success_detail">L'app è stata aggiornata.</string>
<string name="install_error_download">Download fallito</string>
<string name="install_error_download_detail">Controlla la connessione e riprova.</string>
<string name="install_error_install">Installazione fallita</string>
<string name="install_perm_detail">Abilita \'Installa app sconosciute\' nelle impostazioni, poi torna qui.</string>
<string name="install_perm_detail">Abilita 'Installa app sconosciute' nelle impostazioni, poi torna qui.</string>
<string name="install_btn_retry">↩ Riprova</string>
<!-- Pulsanti -->
<string name="btn_back">Indietro</string>
<string name="btn_launch">🚀 Avvia EverShelf</string>
<string name="btn_launch_no_scale">🚀 Avvia senza bilancia</string>
<string name="btn_download_gateway">📥 Installa Scale Gateway</string>
<string name="btn_update_gateway">📥 Aggiorna Scale Gateway</string>
<!-- Verifica raggiungibilità server (step 3 wizard) -->
<string name="wizard_server_checking">Verifica connessione server…</string>
<string name="wizard_server_ok">Server raggiungibile ✅</string>
<string name="wizard_server_ok_detail">Segnalazione errori attiva — i problemi di installazione vengono inviati automaticamente alle GitHub Issues.</string>
<string name="wizard_server_error">Server non raggiungibile ⚠️</string>
<string name="wizard_server_error_detail">Gli errori non raggiungeranno GitHub Issues. Verifica l\'URL inserito al passaggio 2.</string>
<!-- Passo salvaschermo -->
<string name="setup_screensaver_title">Salvaschermo</string>
<string name="setup_screensaver_desc">Mostra un orologio con fatti utili dopo 5 minuti di inattività. Di default è disattivato (lo schermo resta sempre acceso).</string>
<string name="setup_screensaver_toggle_label">Attiva salvaschermo</string>
<string name="setup_screensaver_toggle_hint">Se disattivo, lo schermo resta sempre acceso.</string>
<string name="wizard_server_error_detail">Gli errori non raggiungeranno GitHub Issues. Verifica l'URL inserito al passaggio 2.</string>
<string name="setup_features_title">Funzionalità</string>
<string name="setup_features_desc">Attiva le funzioni che vuoi usare. Puoi sempre cambiarle in seguito dalle impostazioni del server.</string>
<string name="setup_screensaver_toggle_label">Salvaschermo orologio</string>
<string name="setup_screensaver_toggle_hint">Mostra l'overlay orologio dopo 5 min di inattività.</string>
<string name="setup_prices_toggle_label">Prezzi lista spesa</string>
<string name="setup_prices_toggle_hint">Stima automatica del costo di ogni articolo in lista tramite AI.</string>
<string name="setup_mealplan_toggle_label">Piano pasti</string>
<string name="setup_mealplan_toggle_hint">Pianifica i pasti della settimana suggerendo ricette basate sulla dispensa.</string>
<string name="setup_zerowaste_toggle_label">Suggerimenti zero-waste</string>
<string name="setup_zerowaste_toggle_hint">Durante la cottura mostra consigli per riutilizzare scarti (bucce, acqua di cottura, ecc.).</string>
<string name="setup_gemini_title">Google Gemini AI</string>
<string name="setup_gemini_desc">EverShelf usa Google Gemini AI per suggerimenti di ricette, stime intelligenti della spesa e altro ancora.
<!-- Riepilogo -->
Per abilitarla, inserisci la tua chiave API Gemini gratuita.</string>
<string name="setup_gemini_how">Ottieni la chiave gratuita su: aistudio.google.com → "Ottieni chiave API"</string>
<string name="setup_gemini_hint">Incolla la chiave API (inizia con AIza…)</string>
<string name="setup_bring_title">Bring! Lista della spesa</string>
<string name="setup_bring_desc">EverShelf può sincronizzare la lista della spesa con l'app Bring!.
Inserisci le credenziali del tuo account Bring! per abilitare l'integrazione.</string>
<string name="setup_bring_email_hint">Email Bring!</string>
<string name="setup_bring_pass_hint">Password Bring!</string>
<string name="setup_done_title">Tutto pronto!</string>
<string name="setup_done_desc">La configurazione è completa. Premi il pulsante per avviare EverShelf in modalità kiosk.</string>
<string name="setup_done_summary_label">RIEPILOGO CONFIGURAZIONE</string>
<string name="summary_lang">Lingua</string>
<string name="summary_scale_skip">Bilancia: non configurata</string>
<string name="summary_screensaver_on">Salvaschermo: attivo</string>
<string name="summary_screensaver_off">Schermo sempre acceso (salvaschermo disattivato)</string>
</resources>
<string name="summary_prices_on">Prezzi lista spesa: abilitati</string>
<string name="summary_mealplan_on">Piano pasti: abilitato</string>
<string name="summary_zerowaste_on">Suggerimenti zero-waste: abilitati</string>
<string name="summary_gemini_set">Gemini AI: abilitata</string>
<string name="summary_gemini_skip">Gemini AI: non configurata</string>
<string name="summary_bring_set">Bring!: connessa</string>
<string name="summary_bring_skip">Bring!: non configurata</string>
<string name="ble_connecting_to">🔗 Connessione a %s…</string>
<string name="ble_connecting">🔗 Connessione in corso…</string>
<string name="summary_scale_ok">Bilancia: %s</string>
<string name="summary_scale_warn">Bilancia: da configurare</string>
</resources>
@@ -1,28 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">EverShelf Kiosk</string>
<!-- Setup wizard strings -->
<!-- ── Setup wizard ─────────────────────────────────────────────────── -->
<string name="setup_enter_url">Please enter a URL first</string>
<string name="setup_testing">Testing connection…</string>
<string name="setup_server_found">EverShelf server found and API active!</string>
<string name="setup_api_not_found">Server reachable but EverShelf API not found. Check the path.</string>
<string name="setup_unreachable">Cannot reach server</string>
<string name="setup_discover_btn">🔍 Search local network</string> <string name="setup_perms_granted_next">✅ Permissions granted — Continue →</string> <string name="setup_discovering">Scanning…</string>
<string name="setup_discover_btn">🔍 Search local network</string>
<string name="setup_perms_granted_next">✅ Permissions granted — Continue →</string>
<string name="setup_discovering">Scanning…</string>
<string name="setup_discovering_detail">Searching for EverShelf servers on the local network…</string>
<string name="setup_discover_not_found">No EverShelf server found automatically. Enter the URL manually.</string>
<string name="setup_exit_title">Exit setup?</string>
<string name="setup_exit_message">You can complete setup later when you reopen the app.</string>
<string name="setup_exit_confirm">Exit</string>
<string name="setup_exit_cancel">Continue</string>
<string name="setup_step_back">← Back</string>
<string name="setup_step_next">Next →</string>
<string name="setup_skip_later">Set up later</string>
<string name="setup_confirm">Confirm →</string>
<!-- Wizard Step 3: Smart scale -->
<!-- ── Wizard Step 4: Smart scale ───────────────────────────────────── -->
<string name="wizard_step3_title">Smart Scale</string>
<string name="wizard_step3_description">EverShelf Kiosk includes a built-in Bluetooth gateway — no external app needed. Select your scale below.</string>
<string name="wizard_step3_question">Do you have a Bluetooth smart scale?</string>
<string name="wizard_step3_yes">✅ Yes, I have a scale</string>
<string name="wizard_step3_no">➡️ No, skip this step</string>
<!-- Gateway status messages -->
<!-- BLE scan / test feedback (previously hardcoded) -->
<string name="ble_scanning">🔍 Scanning…</string>
<string name="ble_connected">Connected! Place an object on the scale…</string>
<string name="ble_disconnected">Connection lost. Retry.</string>
<string name="ble_no_scale_found">No scale found. Make sure it is on and nearby, then retry.</string>
<string name="ble_select_from_list">Select your scale from the list.</string>
<string name="ble_not_confirmed">Scale not confirmed. Retry scan.</string>
<string name="ble_scan_again">🔄 Scan again</string>
<string name="ble_weight_received">Weight received — does it match the display?</string>
<!-- ── Gateway status messages ──────────────────────────────────────── -->
<string name="wizard_gateway_installed">Scale device saved ✅</string>
<string name="wizard_gateway_installed_detail">The integrated BLE gateway will connect automatically on startup.</string>
<string name="wizard_gateway_not_installed">No scale selected</string>
@@ -32,52 +49,76 @@
<string name="wizard_gateway_update_available">BLE scale found</string>
<string name="wizard_gateway_update_detail">Tap the scale in the list to connect.</string>
<!-- Install / download progress states -->
<string name="install_downloading">Scaricamento in corso</string>
<string name="install_downloading_detail">Attendi, il file viene scaricato.</string>
<string name="install_installing">Installazione in corso</string>
<string name="install_confirm_detail">Conferma l\'installazione nel dialog che si è aperto.</string>
<string name="install_success">Installato con successo!</string>
<string name="install_success_detail">L\'app è stata aggiornata.</string>
<string name="install_error_download">Download fallito</string>
<string name="install_error_download_detail">Controlla la connessione e riprova.</string>
<string name="install_error_install">Installazione fallita</string>
<string name="install_perm_detail">Abilita \'Installa app sconosciute\' nelle impostazioni, poi torna qui.</string>
<string name="install_btn_retry">↩ Riprova</string>
<!-- ── Install / download progress states ───────────────────────────── -->
<string name="install_downloading">Downloading</string>
<string name="install_downloading_detail">Please wait, the file is being downloaded.</string>
<string name="install_installing">Installing</string>
<string name="install_confirm_detail">Confirm the installation in the dialog that has opened.</string>
<string name="install_success">Installed successfully!</string>
<string name="install_success_detail">The app has been updated.</string>
<string name="install_error_download">Download failed</string>
<string name="install_error_download_detail">Check your connection and try again.</string>
<string name="install_error_install">Installation failed</string>
<string name="install_perm_detail">Enable \'Install unknown apps\' in settings, then come back here.</string>
<string name="install_btn_retry">↩ Retry</string>
<!-- Buttons -->
<!-- ── Buttons ───────────────────────────────────────────────────────── -->
<string name="btn_back">Back</string>
<string name="btn_launch">🚀 Launch EverShelf</string>
<string name="btn_launch_no_scale">🚀 Launch without scale</string>
<string name="btn_download_gateway">📥 Install Scale Gateway</string>
<string name="btn_update_gateway">📥 Update Scale Gateway</string>
<!-- Server reachability check (wizard step 3) -->
<!-- ── Server reachability check ────────────────────────────────────── -->
<string name="wizard_server_checking">Checking server connection…</string>
<string name="wizard_server_ok">Server reachable ✅</string>
<string name="wizard_server_ok_detail">Error reporting is active — install failures will be sent to GitHub Issues automatically.</string>
<string name="wizard_server_error">Server not reachable ⚠️</string>
<string name="wizard_server_error_detail">Install errors won\'t reach GitHub Issues. Check the URL entered in step 2.</string>
<!-- Features step (step 5) -->
<string name="setup_features_title">Funzionalità</string>
<string name="setup_features_desc">Attiva le funzioni che vuoi usare. Puoi sempre cambiarle in seguito dalle impostazioni del server.</string>
<string name="setup_screensaver_title">Salvaschermo in-app</string>
<string name="setup_screensaver_desc">Shows a clock with useful facts after 5 minutes of inactivity. Off by default (screen stays always on).</string>
<string name="setup_screensaver_toggle_label">Salvaschermo orologio</string>
<string name="setup_screensaver_toggle_hint">Mostra l\'overlay orologio dopo 5 min di inattività.</string>
<string name="setup_prices_toggle_label">Prezzi lista spesa</string>
<string name="setup_prices_toggle_hint">Stima automatica del costo di ogni articolo in lista tramite AI.</string>
<string name="setup_mealplan_toggle_label">Piano pasti</string>
<string name="setup_mealplan_toggle_hint">Pianifica i pasti della settimana suggerendo ricette basate sulla dispensa.</string>
<string name="setup_zerowaste_toggle_label">Suggerimenti zero-waste</string>
<string name="setup_zerowaste_toggle_hint">Durante la cottura mostra consigli per riutilizzare scarti (bucce, acqua di cottura, ecc.).</string>
<!-- Summary -->
<!-- ── Step 5 — Features ─────────────────────────────────────────────── -->
<string name="setup_features_title">Features</string>
<string name="setup_features_desc">Enable the features you want to use. You can always change them later in the server settings.</string>
<string name="setup_screensaver_toggle_label">Clock screensaver</string>
<string name="setup_screensaver_toggle_hint">Shows a clock overlay after 5 min of inactivity.</string>
<string name="setup_prices_toggle_label">Shopping list prices</string>
<string name="setup_prices_toggle_hint">AI-powered automatic cost estimate for each item in the list.</string>
<string name="setup_mealplan_toggle_label">Meal plan</string>
<string name="setup_mealplan_toggle_hint">Plan the week\'s meals with recipes based on your pantry.</string>
<string name="setup_zerowaste_toggle_label">Zero-waste tips</string>
<string name="setup_zerowaste_toggle_hint">Show tips for reusing scraps (peels, cooking water, etc.) while cooking.</string>
<!-- ── Step 6 — Gemini AI key ─────────────────────────────────────────── -->
<string name="setup_gemini_title">Google Gemini AI</string>
<string name="setup_gemini_desc">EverShelf uses Google Gemini AI for recipe suggestions, smart shopping estimates and more.\n\nTo enable it, enter your free Gemini API key below.</string>
<string name="setup_gemini_how">Get your free key at: aistudio.google.com → \"Get API key\"</string>
<string name="setup_gemini_hint">Paste your API key here (starts with AIza…)</string>
<!-- ── Step 7 — Bring! credentials ──────────────────────────────────── -->
<string name="setup_bring_title">Bring! Shopping List</string>
<string name="setup_bring_desc">EverShelf can sync your shopping list with the Bring! app.\n\nEnter your Bring! account credentials to enable this integration.</string>
<string name="setup_bring_email_hint">Bring! email address</string>
<string name="setup_bring_pass_hint">Bring! password</string>
<!-- ── Step 8 — Done ─────────────────────────────────────────────────── -->
<string name="setup_done_title">All set!</string>
<string name="setup_done_desc">Setup is complete. Press the button below to launch EverShelf in kiosk mode.</string>
<string name="setup_done_summary_label">CONFIGURATION SUMMARY</string>
<!-- ── Summary lines ─────────────────────────────────────────────────── -->
<string name="summary_lang">Language</string>
<string name="summary_scale_skip">Scale: not configured</string>
<string name="summary_screensaver_on">Screensaver: abilitato</string>
<string name="summary_screensaver_off">Screensaver: disabilitato</string>
<string name="summary_prices_on">Prezzi lista spesa: abilitati</string>
<string name="summary_mealplan_on">Piano pasti: abilitato</string>
<string name="summary_zerowaste_on">Suggerimenti zero-waste: abilitati</string>
<string name="summary_screensaver_on">Screensaver: enabled</string>
<string name="summary_screensaver_off">Screen always on (screensaver disabled)</string>
<string name="summary_prices_on">Shopping list prices: enabled</string>
<string name="summary_mealplan_on">Meal plan: enabled</string>
<string name="summary_zerowaste_on">Zero-waste tips: enabled</string>
<string name="summary_gemini_set">Gemini AI: enabled</string>
<string name="summary_gemini_skip">Gemini AI: not configured</string>
<string name="summary_bring_set">Bring!: connected</string>
<string name="summary_bring_skip">Bring!: not configured</string>
<string name="ble_connecting_to">🔗 Connecting to %s…</string>
<string name="ble_connecting">🔗 Connecting…</string>
<string name="summary_scale_ok">Scale: %s</string>
<string name="summary_scale_warn">Scale: not confirmed</string>
</resources>