Fas 1b punkt 6: First Scan Coach + aktiveringsmätning

This commit is contained in:
Sven (AAMOS AI)
2026-08-06 04:14:49 +07:00
parent 2f3cdf8016
commit bd8df59138
29 changed files with 9378 additions and 29 deletions
+8 -1
View File
@@ -1,4 +1,4 @@
import { useState } from "react";
import { useEffect, useState } from "react";
import { Alert, View } from "react-native";
import { router } from "expo-router";
import * as ImagePicker from "expo-image-picker";
@@ -17,6 +17,7 @@ import {
Title,
} from "@/components/ui";
import { spacing } from "@/lib/theme";
import { FirstScanCoach, useFirstScanCoach } from "@/components/FirstScanCoach";
/** Skanna (spec §4.2): kyl, frys, skafferi, ingredienser, tallrik, kvitto, streckkod, datum, näringsdeklaration. */
@@ -43,11 +44,16 @@ interface Entitlements {
export default function ScanScreen() {
const [busyType, setBusyType] = useState<string | null>(null);
const coach = useFirstScanCoach();
const entitlements = useQuery({
queryKey: ["entitlements"],
queryFn: () => api<Entitlements>("/v1/me/entitlements"),
});
useEffect(() => {
void coach.showIfNeeded();
}, []);
const startScan = async (scanType: string) => {
if (scanType === "barcode") {
router.push("/barcode");
@@ -93,6 +99,7 @@ export default function ScanScreen() {
return (
<Screen>
<FirstScanCoach visible={coach.visible} onDismiss={coach.dismiss} />
<Title>{t("scan.title")}</Title>
<Small>{t("scan.subtitle")}</Small>
{quota != null && <Small>{t("scan.quotaLeft", { count: Math.max(0, quota) })}</Small>}
@@ -0,0 +1,50 @@
import { useState } from "react";
import { Modal, View } from "react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { Body, Button, Card, Heading, Screen, Small, Spacer } from "@/components/ui";
import { spacing } from "@/lib/theme";
import { t } from "@/lib/i18n";
const COACH_DISMISSED_KEY = "firstScanCoachDismissed";
export function useFirstScanCoach() {
const [visible, setVisible] = useState(false);
const showIfNeeded = async () => {
const dismissed = await AsyncStorage.getItem(COACH_DISMISSED_KEY);
if (dismissed !== "true") setVisible(true);
};
const dismiss = async () => {
await AsyncStorage.setItem(COACH_DISMISSED_KEY, "true");
setVisible(false);
};
return { visible, showIfNeeded, dismiss };
}
export function FirstScanCoach({ visible, onDismiss }: { visible: boolean; onDismiss: () => void }) {
return (
<Modal visible={visible} transparent animationType="fade">
<View
style={{
flex: 1,
backgroundColor: "rgba(0,0,0,0.6)",
justifyContent: "center",
padding: spacing.lg,
}}
>
<Card>
<Heading>{t("scan.coach.title")}</Heading>
<Small>{t("scan.coach.body")}</Small>
<Spacer size={spacing.md} />
<Small> {t("scan.coach.tip1")}</Small>
<Small> {t("scan.coach.tip2")}</Small>
<Small> {t("scan.coach.tip3")}</Small>
<Spacer size={spacing.lg} />
<Button label={t("scan.coach.button")} onPress={onDismiss} />
</Card>
</View>
</Modal>
);
}
+8 -2
View File
@@ -191,9 +191,9 @@
"onboarding.mode": "Hvor præcis vil du være?",
"onboarding.modeExact": "Præcis tilstand",
"onboarding.modeExactDesc": "Vej maden, indtast gram, fuld kontrol over tallene.",
"onboarding.modesCombine": "Tilstandene kan kombineres enkelt til hverdag, præcist når du vil.",
"onboarding.modeSimple": "Enkel tilstand",
"onboarding.modeSimpleDesc": "Tag billeder af maden, accepter estimater, minimalt besvær.",
"onboarding.modesCombine": "Tilstandene kan kombineres enkelt til hverdag, præcist når du vil.",
"onboarding.notMedical": "{brand} giver vejledning ikke lægelig rådgivning.",
"onboarding.stepBSubtitle": "Tilpas din profil for bedre forslag.",
"onboarding.stepBTitle": "Fortsæt opsætning",
@@ -270,6 +270,12 @@
"recipe.time": "{min} min",
"scan.analyzing": "Analyserer …",
"scan.barcode": "Stregkode",
"scan.coach.body": "Tag et billede af hele hylden eller køleskabet. Hold telefonen rolig og sørg for godt lys.",
"scan.coach.button": "Forstået",
"scan.coach.tip1": "Sørg for at alle varer er synlige",
"scan.coach.tip2": "Undgå blitz og skygger",
"scan.coach.tip3": "Bekræft usikre rækker i næste trin",
"scan.coach.title": "Første scanning",
"scan.expiry": "Bedst før-dato",
"scan.failed": "Analysen mislykkedes. Prøv igen eller registrér manuelt.",
"scan.freezer": "Fryser",
@@ -306,10 +312,10 @@
"scan.title": "Scan",
"shopping.addPlaceholder": "Tilføj vare …",
"shopping.complete": "Afslut indkøbsturen",
"shopping.completeNote": "Afkrydsede varer lægges på madlageret.",
"shopping.completedBody_one": "1 vare blev lagt i madlageret.",
"shopping.completedBody_other": "{count} varer blev lagt i madlageret.",
"shopping.completedTitle": "Færdig!",
"shopping.completeNote": "Afkrydsede varer lægges på madlageret.",
"shopping.empty": "Listen er tom.",
"shopping.estimated": "ca. {amount}",
"shopping.estimatedTotal": "Anslået i alt: ca. {amount}",
+8 -2
View File
@@ -191,9 +191,9 @@
"onboarding.mode": "Wie genau möchtest du es?",
"onboarding.modeExact": "Exakter Modus",
"onboarding.modeExactDesc": "Essen wiegen, Gramm eingeben, volle Kontrolle über die Zahlen.",
"onboarding.modesCombine": "Die Modi lassen sich kombinieren im Alltag einfach, exakt wenn du willst.",
"onboarding.modeSimple": "Einfacher Modus",
"onboarding.modeSimpleDesc": "Essen fotografieren, Schätzungen akzeptieren, kein Aufwand.",
"onboarding.modesCombine": "Die Modi lassen sich kombinieren im Alltag einfach, exakt wenn du willst.",
"onboarding.notMedical": "{brand} bietet Orientierung keine medizinische Beratung.",
"onboarding.stepBSubtitle": "Passe dein Profil für bessere Vorschläge an.",
"onboarding.stepBTitle": "Einrichtung fortsetzen",
@@ -270,6 +270,12 @@
"recipe.time": "{min} Min.",
"scan.analyzing": "Analyse läuft …",
"scan.barcode": "Barcode",
"scan.coach.body": "Take a photo of the whole shelf or fridge. Keep the phone steady and make sure the light is good.",
"scan.coach.button": "Verstanden",
"scan.coach.tip1": "Make sure all items are visible",
"scan.coach.tip2": "Avoid flash and shadows",
"scan.coach.tip3": "Confirm uncertain items in the next step",
"scan.coach.title": "Erster Scan",
"scan.expiry": "Mindesthaltbarkeitsdatum",
"scan.failed": "Analyse fehlgeschlagen. Erneut versuchen oder manuell erfassen.",
"scan.freezer": "Gefrierschrank",
@@ -306,10 +312,10 @@
"scan.title": "Scannen",
"shopping.addPlaceholder": "Artikel hinzufügen …",
"shopping.complete": "Einkauf abschließen",
"shopping.completeNote": "Abgehakte Artikel wandern in den Vorrat.",
"shopping.completedBody_one": "1 Artikel wurde in den Vorrat übernommen.",
"shopping.completedBody_other": "{count} Artikel wurden in den Vorrat übernommen.",
"shopping.completedTitle": "Fertig!",
"shopping.completeNote": "Abgehakte Artikel wandern in den Vorrat.",
"shopping.empty": "Die Liste ist leer.",
"shopping.estimated": "ca. {amount}",
"shopping.estimatedTotal": "Geschätzte Summe: ca. {amount}",
+8 -2
View File
@@ -191,9 +191,9 @@
"onboarding.mode": "How precise do you want to be?",
"onboarding.modeExact": "Exact mode",
"onboarding.modeExactDesc": "Weigh food, enter grams, full control of the numbers.",
"onboarding.modesCombine": "You can mix modes simple day to day, exact when you want.",
"onboarding.modeSimple": "Simple mode",
"onboarding.modeSimpleDesc": "Snap photos of your food, accept estimates, minimal fuss.",
"onboarding.modesCombine": "You can mix modes simple day to day, exact when you want.",
"onboarding.notMedical": "{brand} provides guidance not medical advice.",
"onboarding.stepBSubtitle": "Customize your profile for better suggestions.",
"onboarding.stepBTitle": "Continue setup",
@@ -270,6 +270,12 @@
"recipe.time": "{min} min",
"scan.analyzing": "Analyzing …",
"scan.barcode": "Barcode",
"scan.coach.body": "Take a photo of the whole shelf or fridge. Keep the phone steady and make sure the light is good.",
"scan.coach.button": "Got it",
"scan.coach.tip1": "Make sure all items are visible",
"scan.coach.tip2": "Avoid flash and shadows",
"scan.coach.tip3": "Confirm uncertain items in the next step",
"scan.coach.title": "First scan",
"scan.expiry": "Best-before date",
"scan.failed": "The analysis failed. Try again or add items manually.",
"scan.freezer": "Freezer",
@@ -306,10 +312,10 @@
"scan.title": "Scan",
"shopping.addPlaceholder": "Add item …",
"shopping.complete": "Finish shopping trip",
"shopping.completeNote": "Checked items are added to your food inventory.",
"shopping.completedBody_one": "1 item was added to your inventory.",
"shopping.completedBody_other": "{count} items were added to your inventory.",
"shopping.completedTitle": "Done!",
"shopping.completeNote": "Checked items are added to your food inventory.",
"shopping.empty": "The list is empty.",
"shopping.estimated": "approx. {amount}",
"shopping.estimatedTotal": "Estimated total: approx. {amount}",
+8 -2
View File
@@ -191,9 +191,9 @@
"onboarding.mode": "¿Cuánta precisión quieres?",
"onboarding.modeExact": "Modo exacto",
"onboarding.modeExactDesc": "Pesa la comida, introduce gramos, control total de las cifras.",
"onboarding.modesCombine": "Puedes combinar los modos: sencillo a diario, exacto cuando quieras.",
"onboarding.modeSimple": "Modo sencillo",
"onboarding.modeSimpleDesc": "Fotografía tu comida, acepta estimaciones, sin complicaciones.",
"onboarding.modesCombine": "Puedes combinar los modos: sencillo a diario, exacto cuando quieras.",
"onboarding.notMedical": "{brand} ofrece orientación, no consejo médico.",
"onboarding.stepBSubtitle": "Personaliza tu perfil para mejores sugerencias.",
"onboarding.stepBTitle": "Continuar configuración",
@@ -270,6 +270,12 @@
"recipe.time": "{min} min",
"scan.analyzing": "Analizando …",
"scan.barcode": "Código de barras",
"scan.coach.body": "Take a photo of the whole shelf or fridge. Keep the phone steady and make sure the light is good.",
"scan.coach.button": "Entendido",
"scan.coach.tip1": "Make sure all items are visible",
"scan.coach.tip2": "Avoid flash and shadows",
"scan.coach.tip3": "Confirm uncertain items in the next step",
"scan.coach.title": "Primer escaneo",
"scan.expiry": "Fecha de consumo preferente",
"scan.failed": "El análisis falló. Inténtalo de nuevo o añade manualmente.",
"scan.freezer": "Congelador",
@@ -306,10 +312,10 @@
"scan.title": "Escanear",
"shopping.addPlaceholder": "Añadir producto …",
"shopping.complete": "Terminar la compra",
"shopping.completeNote": "Los productos marcados se añaden al inventario.",
"shopping.completedBody_one": "Se añadió 1 producto al inventario.",
"shopping.completedBody_other": "Se añadieron {count} productos al inventario.",
"shopping.completedTitle": "¡Listo!",
"shopping.completeNote": "Los productos marcados se añaden al inventario.",
"shopping.empty": "La lista está vacía.",
"shopping.estimated": "aprox. {amount}",
"shopping.estimatedTotal": "Total estimado: aprox. {amount}",
+8 -2
View File
@@ -191,9 +191,9 @@
"onboarding.mode": "Kuinka tarkka haluat olla?",
"onboarding.modeExact": "Tarkka tila",
"onboarding.modeExactDesc": "Punnitse ruoka, syötä grammat, täysi hallinta lukuihin.",
"onboarding.modesCombine": "Tiloja voi yhdistellä arjessa helposti, tarkasti kun haluat.",
"onboarding.modeSimple": "Helppo tila",
"onboarding.modeSimpleDesc": "Kuvaa ruokasi, hyväksy arviot, mahdollisimman vaivatonta.",
"onboarding.modesCombine": "Tiloja voi yhdistellä arjessa helposti, tarkasti kun haluat.",
"onboarding.notMedical": "{brand} antaa ohjeita ei lääketieteellisiä neuvoja.",
"onboarding.stepBSubtitle": "Mukauta profiiliasi parempia ehdotuksia varten.",
"onboarding.stepBTitle": "Jatka asetuksia",
@@ -270,6 +270,12 @@
"recipe.time": "{min} min",
"scan.analyzing": "Analysoidaan …",
"scan.barcode": "Viivakoodi",
"scan.coach.body": "Take a photo of the whole shelf or fridge. Keep the phone steady and make sure the light is good.",
"scan.coach.button": "Ymmärrän",
"scan.coach.tip1": "Make sure all items are visible",
"scan.coach.tip2": "Avoid flash and shadows",
"scan.coach.tip3": "Confirm uncertain items in the next step",
"scan.coach.title": "Ensimmäinen skannaus",
"scan.expiry": "Parasta ennen -päiväys",
"scan.failed": "Analyysi epäonnistui. Yritä uudelleen tai lisää käsin.",
"scan.freezer": "Pakastin",
@@ -306,10 +312,10 @@
"scan.title": "Skannaa",
"shopping.addPlaceholder": "Lisää tuote …",
"shopping.complete": "Päätä ostosreissu",
"shopping.completeNote": "Merkityt tuotteet lisätään ruokavarastoon.",
"shopping.completedBody_one": "1 tuote lisättiin ruokavarastoon.",
"shopping.completedBody_other": "{count} tuotetta lisättiin ruokavarastoon.",
"shopping.completedTitle": "Valmis!",
"shopping.completeNote": "Merkityt tuotteet lisätään ruokavarastoon.",
"shopping.empty": "Lista on tyhjä.",
"shopping.estimated": "n. {amount}",
"shopping.estimatedTotal": "Arvioitu yhteensä: n. {amount}",
+8 -2
View File
@@ -191,9 +191,9 @@
"onboarding.mode": "Quel niveau de précision ?",
"onboarding.modeExact": "Mode exact",
"onboarding.modeExactDesc": "Pesez, saisissez les grammes, contrôle total des chiffres.",
"onboarding.modesCombine": "Les modes se combinent : simple au quotidien, précis quand vous voulez.",
"onboarding.modeSimple": "Mode simple",
"onboarding.modeSimpleDesc": "Photographiez vos aliments, acceptez les estimations, zéro prise de tête.",
"onboarding.modesCombine": "Les modes se combinent : simple au quotidien, précis quand vous voulez.",
"onboarding.notMedical": "{brand} fournit des repères, pas un avis médical.",
"onboarding.stepBSubtitle": "Personnalisez votre profil pour de meilleures suggestions.",
"onboarding.stepBTitle": "Continuer la configuration",
@@ -270,6 +270,12 @@
"recipe.time": "{min} min",
"scan.analyzing": "Analyse en cours …",
"scan.barcode": "Code-barres",
"scan.coach.body": "Take a photo of the whole shelf or fridge. Keep the phone steady and make sure the light is good.",
"scan.coach.button": "Compris",
"scan.coach.tip1": "Make sure all items are visible",
"scan.coach.tip2": "Avoid flash and shadows",
"scan.coach.tip3": "Confirm uncertain items in the next step",
"scan.coach.title": "Premier scan",
"scan.expiry": "Date limite",
"scan.failed": "L'analyse a échoué. Réessayez ou saisissez manuellement.",
"scan.freezer": "Congélateur",
@@ -306,10 +312,10 @@
"scan.title": "Scanner",
"shopping.addPlaceholder": "Ajouter un article …",
"shopping.complete": "Terminer les courses",
"shopping.completeNote": "Les articles cochés rejoignent le stock.",
"shopping.completedBody_one": "1 article a été ajouté au stock.",
"shopping.completedBody_other": "{count} articles ont été ajoutés au stock.",
"shopping.completedTitle": "Terminé !",
"shopping.completeNote": "Les articles cochés rejoignent le stock.",
"shopping.empty": "La liste est vide.",
"shopping.estimated": "env. {amount}",
"shopping.estimatedTotal": "Total estimé : env. {amount}",
+8 -2
View File
@@ -191,9 +191,9 @@
"onboarding.mode": "Quanta precisione vuoi?",
"onboarding.modeExact": "Modalità esatta",
"onboarding.modeExactDesc": "Pesa il cibo, inserisci i grammi, pieno controllo dei numeri.",
"onboarding.modesCombine": "Le modalità si possono combinare: semplice ogni giorno, esatta quando vuoi.",
"onboarding.modeSimple": "Modalità semplice",
"onboarding.modeSimpleDesc": "Fotografa il cibo, accetta le stime, zero complicazioni.",
"onboarding.modesCombine": "Le modalità si possono combinare: semplice ogni giorno, esatta quando vuoi.",
"onboarding.notMedical": "{brand} offre indicazioni, non consigli medici.",
"onboarding.stepBSubtitle": "Personalizza il profilo per suggerimenti migliori.",
"onboarding.stepBTitle": "Continua configurazione",
@@ -270,6 +270,12 @@
"recipe.time": "{min} min",
"scan.analyzing": "Analisi in corso …",
"scan.barcode": "Codice a barre",
"scan.coach.body": "Take a photo of the whole shelf or fridge. Keep the phone steady and make sure the light is good.",
"scan.coach.button": "Capito",
"scan.coach.tip1": "Make sure all items are visible",
"scan.coach.tip2": "Avoid flash and shadows",
"scan.coach.tip3": "Confirm uncertain items in the next step",
"scan.coach.title": "Prima scansione",
"scan.expiry": "Data di scadenza",
"scan.failed": "Analisi non riuscita. Riprova o inserisci manualmente.",
"scan.freezer": "Congelatore",
@@ -306,10 +312,10 @@
"scan.title": "Scansiona",
"shopping.addPlaceholder": "Aggiungi prodotto …",
"shopping.complete": "Concludi la spesa",
"shopping.completeNote": "I prodotti spuntati vengono aggiunti alla dispensa.",
"shopping.completedBody_one": "1 prodotto aggiunto alla dispensa.",
"shopping.completedBody_other": "{count} prodotti aggiunti alla dispensa.",
"shopping.completedTitle": "Fatto!",
"shopping.completeNote": "I prodotti spuntati vengono aggiunti alla dispensa.",
"shopping.empty": "La lista è vuota.",
"shopping.estimated": "circa {amount}",
"shopping.estimatedTotal": "Totale stimato: circa {amount}",
+8 -2
View File
@@ -191,9 +191,9 @@
"onboarding.mode": "Hvor nøyaktig vil du være?",
"onboarding.modeExact": "Nøyaktig modus",
"onboarding.modeExactDesc": "Vei maten, angi gram, full kontroll på tallene.",
"onboarding.modesCombine": "Modusene kan kombineres enkelt til hverdags, nøyaktig når du vil.",
"onboarding.modeSimple": "Enkel modus",
"onboarding.modeSimpleDesc": "Ta bilde av maten, godta estimater, minimalt styr.",
"onboarding.modesCombine": "Modusene kan kombineres enkelt til hverdags, nøyaktig når du vil.",
"onboarding.notMedical": "{brand} gir veiledning ikke medisinske råd.",
"onboarding.stepBSubtitle": "Tilpass profilen din for bedre forslag.",
"onboarding.stepBTitle": "Fortsett oppsett",
@@ -270,6 +270,12 @@
"recipe.time": "{min} min",
"scan.analyzing": "Analyserer …",
"scan.barcode": "Strekkode",
"scan.coach.body": "Ta et bilde av hele hyllen eller kjøleskapet. Hold telefonen i ro og sørg for godt lys.",
"scan.coach.button": "Skjønner",
"scan.coach.tip1": "Sørg for at alle varer er synlige",
"scan.coach.tip2": "Unngå blitz og skygger",
"scan.coach.tip3": "Bekreft usikre rader i neste steg",
"scan.coach.title": "Første skanning",
"scan.expiry": "Best før-dato",
"scan.failed": "Analysen mislyktes. Prøv igjen eller registrer manuelt.",
"scan.freezer": "Fryser",
@@ -306,10 +312,10 @@
"scan.title": "Skann",
"shopping.addPlaceholder": "Legg til vare …",
"shopping.complete": "Avslutt handleturen",
"shopping.completeNote": "Avkryssede varer legges i matlageret.",
"shopping.completedBody_one": "1 vare ble lagt inn i matlageret.",
"shopping.completedBody_other": "{count} varer ble lagt inn i matlageret.",
"shopping.completedTitle": "Ferdig!",
"shopping.completeNote": "Avkryssede varer legges i matlageret.",
"shopping.empty": "Listen er tom.",
"shopping.estimated": "ca. {amount}",
"shopping.estimatedTotal": "Anslått totalt: ca. {amount}",
+8 -2
View File
@@ -191,9 +191,9 @@
"onboarding.mode": "Hoe precies wil je het?",
"onboarding.modeExact": "Exacte modus",
"onboarding.modeExactDesc": "Weeg je eten, voer grammen in, volledige controle over de cijfers.",
"onboarding.modesCombine": "De standen zijn te combineren simpel in het dagelijks leven, exact wanneer je wilt.",
"onboarding.modeSimple": "Simpele modus",
"onboarding.modeSimpleDesc": "Fotografeer je eten, accepteer schattingen, minimaal gedoe.",
"onboarding.modesCombine": "De standen zijn te combineren simpel in het dagelijks leven, exact wanneer je wilt.",
"onboarding.notMedical": "{brand} geeft richtlijnen geen medisch advies.",
"onboarding.stepBSubtitle": "Pas je profiel aan voor betere suggesties.",
"onboarding.stepBTitle": "Doorgaan met instellen",
@@ -270,6 +270,12 @@
"recipe.time": "{min} min",
"scan.analyzing": "Analyseren …",
"scan.barcode": "Barcode",
"scan.coach.body": "Take a photo of the whole shelf or fridge. Keep the phone steady and make sure the light is good.",
"scan.coach.button": "Begrepen",
"scan.coach.tip1": "Make sure all items are visible",
"scan.coach.tip2": "Avoid flash and shadows",
"scan.coach.tip3": "Confirm uncertain items in the next step",
"scan.coach.title": "Eerste scan",
"scan.expiry": "THT-datum",
"scan.failed": "De analyse is mislukt. Probeer opnieuw of voer handmatig in.",
"scan.freezer": "Vriezer",
@@ -306,10 +312,10 @@
"scan.title": "Scannen",
"shopping.addPlaceholder": "Product toevoegen …",
"shopping.complete": "Boodschappen afronden",
"shopping.completeNote": "Afgevinkte producten gaan naar de voorraad.",
"shopping.completedBody_one": "1 product is aan de voorraad toegevoegd.",
"shopping.completedBody_other": "{count} producten zijn aan de voorraad toegevoegd.",
"shopping.completedTitle": "Klaar!",
"shopping.completeNote": "Afgevinkte producten gaan naar de voorraad.",
"shopping.empty": "De lijst is leeg.",
"shopping.estimated": "ca. {amount}",
"shopping.estimatedTotal": "Geschat totaal: ca. {amount}",
+8 -2
View File
@@ -197,9 +197,9 @@
"onboarding.mode": "Jak dokładnie chcesz to robić?",
"onboarding.modeExact": "Tryb dokładny",
"onboarding.modeExactDesc": "Waż jedzenie, wpisuj gramy, pełna kontrola nad liczbami.",
"onboarding.modesCombine": "Tryby można łączyć na co dzień prosto, dokładnie, gdy chcesz.",
"onboarding.modeSimple": "Tryb prosty",
"onboarding.modeSimpleDesc": "Fotografuj jedzenie, akceptuj szacunki, minimum zachodu.",
"onboarding.modesCombine": "Tryby można łączyć na co dzień prosto, dokładnie, gdy chcesz.",
"onboarding.notMedical": "{brand} to wskazówki nie porada medyczna.",
"onboarding.stepBSubtitle": "Dostosuj swój profil, aby uzyskać lepsze sugestie.",
"onboarding.stepBTitle": "Kontynuuj konfigurację",
@@ -280,6 +280,12 @@
"recipe.time": "{min} min",
"scan.analyzing": "Analizowanie …",
"scan.barcode": "Kod kreskowy",
"scan.coach.body": "Take a photo of the whole shelf or fridge. Keep the phone steady and make sure the light is good.",
"scan.coach.button": "Rozumiem",
"scan.coach.tip1": "Make sure all items are visible",
"scan.coach.tip2": "Avoid flash and shadows",
"scan.coach.tip3": "Confirm uncertain items in the next step",
"scan.coach.title": "Pierwsze skanowanie",
"scan.expiry": "Data przydatności",
"scan.failed": "Analiza się nie powiodła. Spróbuj ponownie lub dodaj ręcznie.",
"scan.freezer": "Zamrażarka",
@@ -318,12 +324,12 @@
"scan.title": "Skanuj",
"shopping.addPlaceholder": "Dodaj produkt …",
"shopping.complete": "Zakończ zakupy",
"shopping.completeNote": "Odhaczone produkty trafiają do spiżarni.",
"shopping.completedBody_few": "{count} produkty trafiły do spiżarni.",
"shopping.completedBody_many": "{count} produktów trafiło do spiżarni.",
"shopping.completedBody_one": "1 produkt trafił do spiżarni.",
"shopping.completedBody_other": "{count} produktu trafiło do spiżarni.",
"shopping.completedTitle": "Gotowe!",
"shopping.completeNote": "Odhaczone produkty trafiają do spiżarni.",
"shopping.empty": "Lista jest pusta.",
"shopping.estimated": "ok. {amount}",
"shopping.estimatedTotal": "Szacowana suma: ok. {amount}",
+8 -2
View File
@@ -191,9 +191,9 @@
"onboarding.mode": "Que nível de precisão quer?",
"onboarding.modeExact": "Modo exato",
"onboarding.modeExactDesc": "Pese a comida, introduza gramas, controlo total dos números.",
"onboarding.modesCombine": "Os modos podem combinar-se: simples no dia a dia, exato quando quiser.",
"onboarding.modeSimple": "Modo simples",
"onboarding.modeSimpleDesc": "Fotografe a comida, aceite estimativas, zero complicações.",
"onboarding.modesCombine": "Os modos podem combinar-se: simples no dia a dia, exato quando quiser.",
"onboarding.notMedical": "{brand} dá orientações não aconselhamento médico.",
"onboarding.stepBSubtitle": "Personaliza o teu perfil para melhores sugestões.",
"onboarding.stepBTitle": "Continuar configuração",
@@ -270,6 +270,12 @@
"recipe.time": "{min} min",
"scan.analyzing": "A analisar …",
"scan.barcode": "Código de barras",
"scan.coach.body": "Take a photo of the whole shelf or fridge. Keep the phone steady and make sure the light is good.",
"scan.coach.button": "Entendi",
"scan.coach.tip1": "Make sure all items are visible",
"scan.coach.tip2": "Avoid flash and shadows",
"scan.coach.tip3": "Confirm uncertain items in the next step",
"scan.coach.title": "Primeira verificação",
"scan.expiry": "Data de validade",
"scan.failed": "A análise falhou. Tente novamente ou adicione manualmente.",
"scan.freezer": "Congelador",
@@ -306,10 +312,10 @@
"scan.title": "Digitalizar",
"shopping.addPlaceholder": "Adicionar artigo …",
"shopping.complete": "Terminar as compras",
"shopping.completeNote": "Os artigos marcados vão para a despensa.",
"shopping.completedBody_one": "1 produto foi adicionado à despensa.",
"shopping.completedBody_other": "{count} produtos foram adicionados à despensa.",
"shopping.completedTitle": "Feito!",
"shopping.completeNote": "Os artigos marcados vão para a despensa.",
"shopping.empty": "A lista está vazia.",
"shopping.estimated": "aprox. {amount}",
"shopping.estimatedTotal": "Total estimado: aprox. {amount}",
+8 -2
View File
@@ -191,9 +191,9 @@
"onboarding.mode": "Hur noggrann vill du vara?",
"onboarding.modeExact": "Exakt läge",
"onboarding.modeExactDesc": "Väg mat, ange gram, full kontroll på siffrorna.",
"onboarding.modesCombine": "Lägena kan kombineras enkelt till vardags, exakt när du vill.",
"onboarding.modeSimple": "Enkelt läge",
"onboarding.modeSimpleDesc": "Fota maten, acceptera uppskattningar, minimalt pyssel.",
"onboarding.modesCombine": "Lägena kan kombineras enkelt till vardags, exakt när du vill.",
"onboarding.notMedical": "{brand} ger vägledning inte medicinsk rådgivning.",
"onboarding.stepBSubtitle": "Anpassa din profil för bättre förslag.",
"onboarding.stepBTitle": "Fortsätt konfiguration",
@@ -270,6 +270,12 @@
"recipe.time": "{min} min",
"scan.analyzing": "Analyserar …",
"scan.barcode": "Streckkod",
"scan.coach.body": "Fota hela hyllan eller kylen. Håll telefonen stilla och se till att ljuset är bra.",
"scan.coach.button": "Jag förstår",
"scan.coach.tip1": "Se till att alla varor syns",
"scan.coach.tip2": "Undvik blixt och skuggor",
"scan.coach.tip3": "Bekräfta osäkra rader i nästa steg",
"scan.coach.title": "Första skanningen",
"scan.expiry": "Bäst före-datum",
"scan.failed": "Analysen misslyckades. Försök igen eller registrera manuellt.",
"scan.freezer": "Frys",
@@ -306,10 +312,10 @@
"scan.title": "Skanna",
"shopping.addPlaceholder": "Lägg till vara …",
"shopping.complete": "Avsluta köprundan",
"shopping.completeNote": "Bockade varor läggs in i matlagret.",
"shopping.completedBody_one": "1 vara lades in i matlagret.",
"shopping.completedBody_other": "{count} varor lades in i matlagret.",
"shopping.completedTitle": "Klart!",
"shopping.completeNote": "Bockade varor läggs in i matlagret.",
"shopping.empty": "Listan är tom.",
"shopping.estimated": "ca {amount}",
"shopping.estimatedTotal": "Uppskattad totalsumma: ca {amount}",