18388bb31c
- API: översatt title/displayName/toName läggs nu bredvid Sv-fälten i favoriter,
receptvarianter, /scaled, skapar-profiler, topplistor, memory-impact,
substitutions — samt de denormaliserade titlarna (min dag, historik, matlådor,
matlåde-förslag, veckoplan) via nullable recipeId med svensk fallback.
10 endpoints, batchade resolvers (ett anrop per endpoint).
- Mobil: konsumerar de nya fälten med ?? Sv-fallback (swap-meal, sparade recept,
varianter, min dag, logg, matlådor, veckoplan, inköpslista). Hårdkodade
strängar -> t() (kitchen, scan-review, register, recept protein/Skapat av);
decimalkomma -> Intl.NumberFormat. Allergen-etiketter -> t() (+5 nya nycklar).
11 nya nycklar i alla 12 språk.
- i18n-vakt härdad: fångar nu hårdkodad svenska i prop={`...`}-mallliteraler
(blind fläck förr). Verifierat att den fäller men inte ger falska positiv.
- whySv var redan lokaliserad (buildWhy med språktagg) - orörd.
- typecheck grönt (alla paket), vakt grön (603 nycklar).
Co-Authored-By: Claude <noreply@anthropic.com>
606 lines
33 KiB
JSON
606 lines
33 KiB
JSON
{
|
||
"auth.backToLogin": "Back to login",
|
||
"auth.displayName": "What should we call you?",
|
||
"auth.email": "Email",
|
||
"auth.forgotBody": "Enter your email and we'll send a reset link if the account exists.",
|
||
"auth.forgotLink": "Forgot your password?",
|
||
"auth.forgotSentBody": "If the address has an account, we've sent a link valid for 30 minutes. Open it on this device.",
|
||
"auth.forgotSentTitle": "Check your inbox",
|
||
"auth.forgotSubmit": "Send link",
|
||
"auth.forgotTitle": "Reset password",
|
||
"auth.hasAccount": "Already have an account? Log in",
|
||
"auth.login": "Log in",
|
||
"auth.newPassword": "New password (at least 10 characters)",
|
||
"auth.noAccount": "New here? Create an account",
|
||
"auth.password": "Password",
|
||
"auth.register": "Create account",
|
||
"auth.resetBody": "The link is valid for 30 minutes and can only be used once. All devices are signed out when the password changes.",
|
||
"auth.resetDoneBody": "Your password has been changed. Log in with your new password.",
|
||
"auth.resetDoneTitle": "Done!",
|
||
"auth.resetSubmit": "Change password",
|
||
"auth.resetTitle": "Choose a new password",
|
||
"auth.resetTokenPlaceholder": "Paste the code from the email",
|
||
"auth.trialNote": "14 days of full access – no card required.",
|
||
"auth.verifyDoneBody": "Thanks! Your account is now verified.",
|
||
"auth.verifyDoneTitle": "Email confirmed",
|
||
"auth.verifyFailedBody": "The link is invalid or has expired. Request a new one from your profile.",
|
||
"auth.verifyFailedTitle": "The link didn't work",
|
||
"barcode.addPrompt": "Add to your inventory?",
|
||
"barcode.aim": "Point the camera at the barcode",
|
||
"barcode.allowCamera": "Allow camera",
|
||
"barcode.cameraBody": "{brand} needs the camera to scan barcodes.",
|
||
"barcode.cameraTitle": "Camera needed",
|
||
"barcode.contributing.title": "Reading the package…",
|
||
"barcode.contributing.body": "We're extracting nutrition, allergens and ingredients – and saving the product to the shared catalogue so the next person doesn't have to photograph it.",
|
||
"barcode.contributing.failed": "Couldn't read the package. Try again with a sharp photo and good lighting.",
|
||
"barcode.contributing.saved": "✓ Saved to the shared catalogue – thanks for contributing!",
|
||
"barcode.contributing.frontDone": "Front photo taken",
|
||
"barcode.contributing.backPrompt": "Now photograph the back with the nutrition label and ingredients – that completes the product.",
|
||
"barcode.contributing.skipBack": "Done, analyse",
|
||
"barcode.contributing.shootBack": "Photograph the back",
|
||
"barcode.complete": "Photograph the back (nutrition & ingredients)",
|
||
"barcode.done": "Done",
|
||
"barcode.looksRight": "Looks right – done",
|
||
"barcode.kcalPer100": "{kcal} kcal/100 g",
|
||
"barcode.needHousehold": "You need a household first.",
|
||
"barcode.noLocation": "No storage location found.",
|
||
"barcode.noNutrition": "No nutrition data",
|
||
"barcode.photoPackage": "Photograph the package",
|
||
"barcode.unknownBody": "This product isn't in the database yet. Photograph the front and the nutrition label – we'll read the contents and save the product to the shared catalogue so the next person doesn't have to. (It won't be added to your items.)",
|
||
"barcode.unknownTitle": "Unknown product",
|
||
"common.add": "Add",
|
||
"common.back": "Back",
|
||
"common.cancel": "Cancel",
|
||
"mealbox.ready": "Ready-made food waiting – the fastest dinner in the house.",
|
||
"common.all": "All",
|
||
"auth.tagline": "Less waste, less stress, more left in your wallet",
|
||
"auth.passwordMin8": "Password must be at least 8 characters.",
|
||
"auth.passwordMismatch": "Passwords don't match.",
|
||
"auth.repeatPassword": "Repeat password",
|
||
"plan.swapDish": "Swap dish",
|
||
"scan.maxTitle": "Done",
|
||
"scan.maxBody": "Max {max} photos this scan – analyzing.",
|
||
"scan.photoTaken": "Photo {count} taken",
|
||
"scan.multiAngleHint": "Feel free to take more angles of the same spot – the app lists each item once. Each photo counts as one scan.",
|
||
"scan.takeAnother": "Take another",
|
||
"scan.analyzeCount": "Analyze ({count})",
|
||
"scan.tips.merge": "Fridge/freezer/pantry: take several photos in the same scan – the app merges duplicates.",
|
||
"kitchen.deleteConfirm": "Remove selected items from {label}?",
|
||
"kitchen.scopeSearch": "the search",
|
||
"kitchen.scopeAll": "the whole inventory",
|
||
"kitchen.scopeSelection": "the selection",
|
||
"kitchen.searchPlaceholder": "Search item…",
|
||
"kitchen.clearList": "Clear list",
|
||
"kitchen.empty": "No items to show. Scan or add items.",
|
||
"kitchen.pastBefore": "best before",
|
||
"memory.trainingNote": "Personal memory is never used as training data without separate consent.",
|
||
"recipe.source": "Source: {name}",
|
||
"recipes.sub.bread": "Bread",
|
||
"recipes.sub.bun": "Buns",
|
||
"recipes.sub.pie": "Pie",
|
||
"recipes.sub.cake": "Cakes & bakes",
|
||
"recipes.sub.cookie": "Cookies",
|
||
"recipes.searchPlaceholder": "Search recipes…",
|
||
"recipes.emptyCategory": "No recipes in this category yet – they'll appear as the catalog grows.",
|
||
"savedRecipes.searchPlaceholder": "Search your saved recipes",
|
||
"savedRecipes.empty": "You don't have any saved recipes yet. Tap ☆ Save on a recipe and it'll show up here.",
|
||
"savedRecipes.emptySearch": "No saved recipes match your search.",
|
||
"shopping.removeConfirm": "Remove the item from the list?",
|
||
"swap.addTitle": "Add meal",
|
||
"swap.swapTitle": "Swap meal",
|
||
"swap.chooseFor": "Choose a dish for {meal} – or search for any dish.",
|
||
"swap.chooseOther": "Choose a different dish for {meal} – or search for any dish.",
|
||
"swap.mealLunch": "lunch",
|
||
"swap.mealBreakfast": "breakfast",
|
||
"swap.mealDinner": "dinner",
|
||
"swap.searchPlaceholder": "Search all recipes …",
|
||
"swap.showingResults": "Showing results for ”{query}”.",
|
||
"swap.clearHint": "Clear the search box and search with it empty to see suggestions again.",
|
||
"errors.uploadTimeout": "The upload took too long – check your network and try again.",
|
||
"common.done": "Done",
|
||
"common.error": "Something went wrong. Please try again.",
|
||
"common.estimate": "Estimate",
|
||
"common.loading": "Loading …",
|
||
"common.next": "Next",
|
||
"common.off": "Off",
|
||
"common.offline": "Offline – showing last fetched data",
|
||
"common.on": "On",
|
||
"common.oops": "Oops",
|
||
"common.remove": "Remove",
|
||
"common.retry": "Try again",
|
||
"common.save": "Save",
|
||
"common.skip": "Skip",
|
||
"common.undo": "Undo",
|
||
"cooked.deductPantry": "Deduct ingredients from inventory",
|
||
"cooked.deductPantryNote": "Ingredients are deducted from your inventory, first-expiring first.",
|
||
"cooked.mealBoxes": "Servings to meal boxes",
|
||
"cooked.portionsCooked": "Servings cooked",
|
||
"cooked.rate": "Rate it",
|
||
"cooked.title": "How did it go?",
|
||
"cooked.actualPortionsEaten": "How many portions did you eat?",
|
||
"cooked.actualPortionsEatenHint": "The rest becomes leftovers or meal boxes.",
|
||
"cooked.leftoverEstimatePortions": "How many leftover portions?",
|
||
"cooked.leftoverEstimateHint": "Saved as a meal box if you want.",
|
||
"cooked.whoAte": "Who ate?",
|
||
"cooking.finish": "Done – log the meal",
|
||
"cooking.keepAwake": "The screen stays awake while you cook",
|
||
"cooking.scale": "Servings",
|
||
"cooking.step": "Step {current} of {total}",
|
||
"cooking.approxTime": "About {time}",
|
||
"home.budget": "Food budget",
|
||
"home.emptyInventory": "Your inventory is empty. Scan the fridge or add items manually.",
|
||
"home.expired": "Expired",
|
||
"home.expiresIn_one": "1 day left",
|
||
"home.expiresIn_other": "{days} days left",
|
||
"home.expiresToday": "Expires today",
|
||
"home.household": "Household",
|
||
"home.inventory": "Food inventory",
|
||
"home.mealBoxes": "Meal boxes",
|
||
"home.moreItems_one": "+ 1 more …",
|
||
"home.moreItems_other": "+ {count} more …",
|
||
"home.pastBestBefore": "Past best before – smell and taste first",
|
||
"home.shopping": "Shopping list",
|
||
"home.savedRecipes": "Your saved recipes",
|
||
"home.submitRecipe": "Submit your own recipe",
|
||
"home.inventorySubtitle": "Everything you have at home – open a place or search the whole stock.",
|
||
"home.openAll": "All",
|
||
"home.open": "Open",
|
||
"home.location.fridge": "Fridge",
|
||
"home.location.freezer": "Freezer",
|
||
"home.location.pantry": "Pantry",
|
||
"home.location.garage_freezer": "Garage freezer",
|
||
"home.location.wine_fridge": "Wine fridge",
|
||
"nav.browseRecipes": "Browse recipes",
|
||
"nav.savedRecipes": "Saved recipes",
|
||
"nav.kitchen": "Food storage",
|
||
"nav.barcode": "Barcode",
|
||
"nav.swap": "Swap",
|
||
"home.thisWeek": "This week",
|
||
"home.title": "At home",
|
||
"home.useSoon": "Use soon",
|
||
"home.useSoonHint": "Best before is about quality – smell, look and taste before you throw anything away. Use-by dates, however, should be respected.",
|
||
"home.waste": "Food waste",
|
||
"home.wasteWeek": "Food waste this week",
|
||
"household.empty": "You don't have a household yet. Create one in onboarding or join with a code.",
|
||
"household.invite": "Invite with code: {code}",
|
||
"household.locations": "Storage locations",
|
||
"household.members": "Members",
|
||
"household.portionFactor": "×{factor} portion",
|
||
"household.private": "Private per person: goals, allergies, health data and meal history.",
|
||
"household.role.adult": "Adult",
|
||
"household.role.child": "Child",
|
||
"household.role.member": "Member",
|
||
"household.role.owner": "Owner",
|
||
"household.shareCode": "Share the code with your family to share inventory, list and plan.",
|
||
"household.shared": "Shared in the household: food inventory, shopping list, week plan, meal boxes and budget.",
|
||
"logmeal.manualTitle": "Manual",
|
||
"logmeal.mealTypeTitle": "Meal type",
|
||
"logmeal.photoTip": "Tip: photograph your plate under Scan and the app estimates for you – you always confirm.",
|
||
"logmeal.proteinPlaceholder": "protein (g)",
|
||
"logmeal.quickSubtitle": "Logs the same nutrition values as last time.",
|
||
"logmeal.quickTitle": "Quick re-log",
|
||
"logmeal.validationBody": "Name and calories are required for manual logging.",
|
||
"logmeal.validationTitle": "Missing info",
|
||
"logmeal.whatPlaceholder": "What did you eat?",
|
||
"mealbox.eat": "Eat now",
|
||
"mealbox.eatBy": "Eat by {date}",
|
||
"mealbox.empty": "No meal boxes right now. When you cook, you can save servings here.",
|
||
"mealbox.enjoyBody": "The portion is logged in My day.",
|
||
"mealbox.enjoyTitle": "Enjoy your meal!",
|
||
"mealbox.guidanceNote": "The recommended use-by is guidance – trust smell and taste.",
|
||
"mealbox.portionsLeft_one": "1 serving left",
|
||
"mealbox.portionsLeft_other": "{count} servings left",
|
||
"mealbox.title": "Meal boxes",
|
||
"memory.delete": "Delete",
|
||
"memory.deleteAll": "Delete all memory",
|
||
"memory.deleteAllTitle": "Delete all memory?",
|
||
"memory.empty": "{brand} hasn't learned anything about you yet.",
|
||
"memory.irreversible": "This cannot be undone.",
|
||
"memory.origin.ai_inferred": "AI assumption",
|
||
"memory.origin.observed": "Observed pattern",
|
||
"memory.origin.user_stated": "You told us",
|
||
"memory.pause": "Pause",
|
||
"memory.paused": "Paused",
|
||
"memory.resume": "Resume",
|
||
"memory.subtitle": "Full transparency. Correct what's wrong, pause or delete – you own your memory.",
|
||
"memory.title": "What {brand} knows about me",
|
||
"memory.verified": "Verified",
|
||
"memory.verify": "Correct",
|
||
"myday.calories": "Calories",
|
||
"myday.carbs": "Carbohydrates",
|
||
"myday.estimateNote": "Values marked with ~ are estimates you can adjust.",
|
||
"myday.estimateRange": "{min}–{max} kcal, likely {kcal}",
|
||
"myday.fat": "Fat",
|
||
"myday.fiber": "Fiber",
|
||
"myday.kcalProtein": "{kcal} kcal · {protein} g protein",
|
||
"myday.logMeal": "Log meal",
|
||
"myday.mealType.breakfast": "Breakfast",
|
||
"myday.mealType.dessert": "Dessert",
|
||
"myday.mealType.dinner": "Dinner",
|
||
"myday.mealType.lunch": "Lunch",
|
||
"myday.mealType.snack": "Snack",
|
||
"myday.noMeals": "No meals logged today.",
|
||
"myday.over": "{kcal} kcal over target",
|
||
"myday.overRecommended": "Above recommended",
|
||
"myday.protein": "Protein",
|
||
"myday.remaining": "{kcal} kcal remaining",
|
||
"myday.salt": "Salt",
|
||
"myday.targetsNote": "Targets are guidance, not medical advice.",
|
||
"myday.title": "My day",
|
||
"myday.todaysMeals": "Today's meals",
|
||
"onboarding.allergen.crustaceans": "Crustaceans",
|
||
"onboarding.allergen.eggs": "Eggs",
|
||
"onboarding.allergen.fish": "Fish",
|
||
"onboarding.allergen.gluten": "Gluten",
|
||
"onboarding.allergen.milk": "Milk/lactose",
|
||
"onboarding.allergen.peanuts": "Peanuts",
|
||
"onboarding.allergen.sesame": "Sesame",
|
||
"onboarding.allergen.soy": "Soy",
|
||
"onboarding.allergen.tree_nuts": "Tree nuts",
|
||
"onboarding.allergies": "Allergies and intolerances",
|
||
"onboarding.allergyNote": "Allergy filtering is always strict – dishes with your allergens are never shown.",
|
||
"onboarding.birthYearPlaceholder": "Birth year",
|
||
"onboarding.bodyTitle": "For personal calorie targets (optional)",
|
||
"onboarding.diet": "How do you eat?",
|
||
"onboarding.diet.flexitarian": "Flexitarian",
|
||
"onboarding.diet.omnivore": "Omnivore",
|
||
"onboarding.diet.pescatarian": "Pescatarian",
|
||
"onboarding.diet.vegan": "Vegan",
|
||
"onboarding.diet.vegetarian": "Vegetarian",
|
||
"onboarding.diet.carnivore": "Carnivore",
|
||
"onboarding.diet.low_carb": "LCHF",
|
||
"onboarding.diet.nordic": "Nordic",
|
||
"onboarding.diet.paleo": "Paleo",
|
||
"onboarding.goal": "What is your main goal?",
|
||
"onboarding.goal.build_muscle": "Build muscle",
|
||
"onboarding.goal.cook_more": "Cook more at home",
|
||
"onboarding.goal.less_waste": "Reduce food waste",
|
||
"onboarding.goal.lose_weight": "Lose weight",
|
||
"onboarding.goal.lower_cost": "Spend less on food",
|
||
"onboarding.goal.maintain_weight": "Maintain weight",
|
||
"onboarding.goal.more_protein": "Eat more protein",
|
||
"onboarding.heightPlaceholder": "Height (cm)",
|
||
"onboarding.household": "Your household",
|
||
"onboarding.householdCreate": "Create household",
|
||
"onboarding.householdDefaultName": "Home",
|
||
"onboarding.householdJoin": "Join with a code",
|
||
"onboarding.householdName": "Household name",
|
||
"onboarding.inviteCode": "Invite code",
|
||
"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.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.memoryTransparency": "This is saved in \"What {brand} knows about me\" and you can change it anytime.",
|
||
"onboarding.notMedical": "{brand} provides guidance – not medical advice.",
|
||
"onboarding.stepBSubtitle": "Customize your profile for better suggestions.",
|
||
"onboarding.stepBTitle": "Continue setup",
|
||
"onboarding.stepCSubtitle": "Optional – used for personal calorie targets.",
|
||
"onboarding.stepCTitle": "Your health profile",
|
||
"onboarding.subtitle": "Everything is optional and can be changed at any time. The more you fill in, the better the suggestions.",
|
||
"onboarding.title": "Tell us a little about yourself",
|
||
"onboarding.weightPlaceholder": "Weight (kg)",
|
||
"paywall.choose": "Choose",
|
||
"paywall.fairUse": "Fair-use quota for AI scans included.",
|
||
"paywall.family": "Family · up to 6 people",
|
||
"paywall.freeNote": "Free: 5 AI scans/month, manual inventory, saved recipes and simple logging.",
|
||
"paywall.household": "Household · up to 3 people",
|
||
"paywall.large": "Large Household · up to 12 people",
|
||
"paywall.perMonth": "{price}/month",
|
||
"paywall.popular": "Most popular",
|
||
"paywall.restore": "Restore purchases",
|
||
"paywall.soonBody": "Purchases activate via App Store/Google Play once store integration is switched on (phase 7). The backend flow is already done.",
|
||
"paywall.soonTitle": "Coming soon!",
|
||
"paywall.subtitle": "The whole household's food OS: unlimited inventory, week planning and sharing.",
|
||
"paywall.title": "{brand} Premium",
|
||
"paywall.trialActive_one": "1 day left of your trial",
|
||
"paywall.trialActive_other": "{days} days left of your trial",
|
||
"profile.aiScansUsed": "AI scans: {used} / {total} this month",
|
||
"profile.consent.anonymized_improvement": "Anonymised AI improvement",
|
||
"profile.consent.health_integration": "Health data (Apple Health / Health Connect)",
|
||
"profile.consent.image_training": "My photos may be used for training",
|
||
"profile.consent.location_weather": "Location for weather-based suggestions",
|
||
"profile.consent.personalization": "Personal features (memory & taste profile)",
|
||
"profile.consent.product_analytics": "Product analytics",
|
||
"profile.consent.push_notifications": "Push notifications",
|
||
"profile.consents": "Consents & data",
|
||
"profile.consentsNote": "Consents are separate – personal features never require training consent.",
|
||
"profile.deleteAccount": "Delete account",
|
||
"profile.deleteBody": "All your data is permanently deleted in line with GDPR.",
|
||
"profile.deleteTitle": "Delete your account?",
|
||
"profile.emailUnverified": "Email address not confirmed",
|
||
"profile.export": "Export my data",
|
||
"profile.goals": "Goals & diet",
|
||
"profile.language": "Language",
|
||
"profile.language.da": "Dansk",
|
||
"profile.language.de": "Deutsch",
|
||
"profile.language.en": "English",
|
||
"profile.language.es": "Español",
|
||
"profile.language.fi": "Suomi",
|
||
"profile.language.fr": "Français",
|
||
"profile.language.it": "Italiano",
|
||
"profile.language.nb": "Norsk",
|
||
"profile.language.nl": "Nederlands",
|
||
"profile.language.pl": "Polski",
|
||
"profile.language.pt": "Português",
|
||
"profile.language.sv": "Svenska",
|
||
"profile.logout": "Log out",
|
||
"profile.memory": "What {brand} knows about me",
|
||
"profile.memorySubtitle": "See, correct, pause or delete what the platform has learned.",
|
||
"profile.modeLabel": "Mode:",
|
||
"profile.resendVerification": "Resend confirmation email",
|
||
"profile.subscription": "Subscription",
|
||
"profile.title": "Profile",
|
||
"profile.verificationSent": "Sent! Check your inbox.",
|
||
"recipe.avgRating": "Average {avg} from {count} ratings",
|
||
"recipe.cook": "Cook now",
|
||
"recipe.cost": "approx. {amount}/serving",
|
||
"recipe.coverage.have": "You have {percent}% at home",
|
||
"recipe.coverage.missingCount": "Missing {count}",
|
||
"recipe.coverage.haveAll": "You have everything you need.",
|
||
"recipe.coverage.youAreMissing": "You're missing: {names}",
|
||
"recipe.coverage.addToList": "Add {count} to shopping list",
|
||
"recipe.coverage.added": "Added to shopping list",
|
||
"recipe.coverage.addedBody": "Added: {count}",
|
||
"recipe.iCookedThis": "I cooked this",
|
||
"recipe.ingredients": "Ingredients",
|
||
"recipe.optional": "(optional)",
|
||
"recipe.notSafe": "Doesn't match your dietary settings",
|
||
"recipe.perPortion": "per serving",
|
||
"recipe.portions_one": "1 serving",
|
||
"recipe.portions_other": "{count} servings",
|
||
"recipe.save": "Save",
|
||
"recipe.saved": "Saved",
|
||
"recipe.steps": "Instructions",
|
||
"recipe.substitutions": "Substitute",
|
||
"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",
|
||
"scan.fridge": "Fridge",
|
||
"scan.ingredients": "Ingredients",
|
||
"scan.nutrition": "Nutrition label",
|
||
"scan.pantry": "Pantry",
|
||
"scan.plate": "Plate",
|
||
"scan.quotaLeft_one": "1 AI scan left this month",
|
||
"scan.quotaLeft_other": "{count} AI scans left this month",
|
||
"scan.receipt": "Receipt",
|
||
"scan.review.addItem": "+ Add item",
|
||
"scan.review.approveAll": "Save to inventory",
|
||
"scan.review.bestBeforeNote": "Quality date – the food can be fine well beyond it. Smell and taste before discarding.",
|
||
"scan.review.dateKindBestBefore": "Best before",
|
||
"scan.review.dateKindUseBy": "Use by",
|
||
"scan.review.datePlaceholder": "YYYY-MM-DD (optional)",
|
||
"scan.review.itemPlaceholder": "Item",
|
||
"scan.review.quantityPlaceholder": "Amount",
|
||
"scan.review.rejected": "Removed",
|
||
"scan.review.subtitle": "AI is sometimes uncertain – you decide. Edit, remove or add before saving.",
|
||
"scan.review.title": "Review the result",
|
||
"scan.review.uncertain": "Uncertain – please check",
|
||
"scan.review.unitPlaceholder": "Unit (g, l, pcs …)",
|
||
"scan.review.unknownItem": "Unknown item",
|
||
"scan.review.useByNote": "Safety date – do not eat after this date.",
|
||
"scan.subtitle": "Stock your food inventory or log a meal with the camera.",
|
||
"scan.costNote": "Each photo counts as one scan from your quota. Barcode is always free.",
|
||
"scan.takePhoto": "Take photo",
|
||
"scan.tips.light": "Avoid darkness and shadows",
|
||
"scan.tips.move": "Move items that block each other",
|
||
"scan.tips.overview": "Start with an overview photo",
|
||
"scan.tips.shelf": "Photograph shelf by shelf",
|
||
"scan.tips.title": "How to get the best analysis",
|
||
"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.empty": "The list is empty.",
|
||
"shopping.estimated": "approx. {amount}",
|
||
"shopping.estimatedTotal": "Estimated total: approx. {amount}",
|
||
"shopping.section.brod": "Bread",
|
||
"shopping.section.chark": "Deli & cold cuts",
|
||
"shopping.section.dryck": "Drinks",
|
||
"shopping.section.fisk": "Fish",
|
||
"shopping.section.frukt_gront": "Fruit & veg",
|
||
"shopping.section.frys": "Frozen",
|
||
"shopping.section.hygien_ovrigt": "Other",
|
||
"shopping.section.konserver": "Canned goods",
|
||
"shopping.section.kott_fagel": "Meat & poultry",
|
||
"shopping.section.kryddor_bak": "Spices & baking",
|
||
"shopping.section.mejeri": "Dairy",
|
||
"shopping.section.skafferi": "Pantry",
|
||
"shopping.section.snacks": "Snacks",
|
||
"shopping.title": "Shopping list",
|
||
"tabs.home": "At home",
|
||
"tabs.myDay": "My day",
|
||
"tabs.scan": "Scan",
|
||
"tabs.whatToEat": "What's for dinner?",
|
||
"tabs.plan": "Plan",
|
||
"plan.today": "Today",
|
||
"plan.emptyDay": "Nothing planned",
|
||
"plan.portions": "{count} servings",
|
||
"plan.generate": "Generate week plan",
|
||
"plan.generating": "Generating week plan…",
|
||
"plan.cooked": "Cooked",
|
||
"plan.skipped": "Skipped",
|
||
"plan.activate": "Activate plan",
|
||
"plan.createShopping": "Create shopping list",
|
||
"wte.coverage": "{pct}% at home",
|
||
"wte.searchPlaceholder": "Search recipes, e.g. pancakes…",
|
||
"wte.recommended": "Recommended",
|
||
"wte.topPick": "Top pick",
|
||
"wte.didYouMean": "Did you mean {suggestion}?",
|
||
"wte.emptySearch": "No recipes match your search.",
|
||
"wte.emptyHoliday": "No recipes for this occasion yet.",
|
||
"cat.baking": "Baking",
|
||
"wte.cravingPlaceholder": "I'm craving … (e.g. creamy, Asian, under 500 kcal)",
|
||
"wte.empty": "No suggestions yet – add some food to your inventory or loosen the filters.",
|
||
"wte.mealBoxFirst": "Ready-made food at home",
|
||
"wte.missing": "Missing: {items}",
|
||
"wte.refresh": "New suggestions",
|
||
"wte.subtitle": "Based on what you have at home, what should be used up, and what you like.",
|
||
"wte.title": "What's for dinner?",
|
||
"wte.whyTitle": "Why this suggestion?",
|
||
"onboarding.primaryGoal": "Primary",
|
||
"home.trustStatus.up_to_date": "Up to date",
|
||
"home.trustStatus.needs_check": "Some items need checking",
|
||
"home.trustStatus.uncertain": "Inventory uncertain – do a quick check",
|
||
"reconciliation.title": "Quick inventory check",
|
||
"reconciliation.subtitle": "Confirm what you have left to get better suggestions.",
|
||
"reconciliation.exists": "Still have it",
|
||
"reconciliation.depleted": "It is used up",
|
||
"reconciliation.uncertain": "Not sure",
|
||
"reconciliation.adjustQuantity": "Adjust amount",
|
||
"reconciliation.reason.planned_recipe": "Needed soon for a recipe",
|
||
"reconciliation.reason.expiring_soon": "Expires soon",
|
||
"reconciliation.reason.high_value": "High value",
|
||
"reconciliation.reason.low_confidence": "Estimated amount",
|
||
"reconciliation.reason.stale_trust": "Has not been checked in a while",
|
||
"reconciliation.reason.likely_depleted": "Likely used up soon",
|
||
"reconciliation.done": "Done",
|
||
"reconciliation.next": "Next",
|
||
"reconciliation.empty": "Nothing needs checking right now. Well done!",
|
||
"reconciliation.tasteHint": "Past best before? Smell and taste first – never waste food unnecessarily.",
|
||
"scan.diff.title": "Review differences",
|
||
"scan.diff.subtitle": "Confirm changes from the latest scan.",
|
||
"scan.diff.newItem": "New item",
|
||
"scan.diff.quantityChanged": "Quantity changed",
|
||
"scan.diff.moved": "Moved",
|
||
"scan.diff.vanished": "Missing in photo",
|
||
"scan.diff.unchanged": "Unchanged",
|
||
"scan.diff.accept": "Confirm",
|
||
"scan.diff.reject": "Ignore",
|
||
"scan.diff.acceptAll": "Confirm all",
|
||
"scan.diff.noChanges": "No differences found.",
|
||
"scan.diff.undo": "Undo",
|
||
"scan.diff.undoHint": "Each change can be undone from the item detail view.",
|
||
"cooked.portionsSumExceedsPlanned": "Eaten portions and leftovers cannot exceed the total number of portions.",
|
||
"cooked.undoWindowExpired": "This cooking session can no longer be undone. The 24-hour window has expired.",
|
||
"cooked.leftoverLessThanBox": "Leftovers must be at least as many as the number of meal-box portions.",
|
||
"mealbox.undoConfirmTitle": "Undo cooking?",
|
||
"mealbox.undoConfirmBody": "This reverses the inventory deduction and meal box for this cooking session.",
|
||
"mealbox.undoSuccess": "Cooking session undone.",
|
||
"consent.title": "Before you start",
|
||
"consent.body": "To use Cibello you need to accept our terms. The photos you take in the app (fridge, packaging, dishes) are used to train and improve Cibello's AI – this is part of the terms.",
|
||
"consent.termsLink": "Read the Terms of Use",
|
||
"consent.privacyLink": "Read the Privacy Policy",
|
||
"consent.checkbox": "I have read and accept the Terms of Use and the Privacy Policy.",
|
||
"consent.submit": "Accept and continue",
|
||
"scan.meal.title": "Log meal from photo",
|
||
"scan.meal.estimateNote": "Estimated from your photo – adjust before saving.",
|
||
"scan.meal.calories": "Estimated calories",
|
||
"scan.meal.namePlaceholder": "What did you eat? (optional)",
|
||
"scan.meal.components": "Recognised on the plate",
|
||
"scan.meal.noEstimate": "Couldn't estimate calories from the photo.",
|
||
"swap.title": "Byt ut måltiden",
|
||
"swap.subtitle": "Välj en annan rätt:",
|
||
"plan.swapMeal": "Byt rätt",
|
||
"plan.chooseMeals": "Planera veckan – välj måltider per dag:",
|
||
"scan.progress.analyzing": "Analyserar bilden…",
|
||
"scan.progress.finding": "Hittar ingredienser…",
|
||
"scan.progress.matching": "Matchar mot ditt kök…",
|
||
"scan.progress.almost": "Snart klar…",
|
||
"home.completeProfile.title": "Gör appen smartare",
|
||
"home.completeProfile.body": "Berätta om kost och allergier så blir förslagen mer personliga (ca 30 sek).",
|
||
"onboarding.religious": "Religiös kosthållning",
|
||
"onboarding.religious.none": "Ingen",
|
||
"onboarding.religious.halal": "Halal (inget fläsk)",
|
||
"onboarding.religious.kosher": "Kosher",
|
||
"onboarding.religious.hindu_no_beef": "Inget nötkött",
|
||
"onboarding.religious.buddhist_vegetarian": "Buddhistisk vegetarisk",
|
||
"onboarding.consent.personalization.title": "Gör Cibello till din",
|
||
"onboarding.consent.personalization.body": "Ju mer Cibello lär känna dig, desto bättre blir det – förslag som passar din smak, dina allergier och din vardag. Allt appen lär sig ser du i \"Vad Cibello vet om dig\" och kan ändra eller radera när du vill. Vi rekommenderar att ha den på.",
|
||
"onboarding.consent.personalization.yes": "Ja, gör appen personlig",
|
||
"onboarding.consent.skip": "Inte nu",
|
||
"onboarding.consent.image_training.title": "Var med och göra Cibello smartare",
|
||
"onboarding.consent.image_training.body": "Låt dina foton hjälpa till att träna vår AI så att den känner igen svenska varor och kvitton allt bättre – för dig och alla andra. Din skanning fungerar lika bra oavsett, men varje ja gör appen vassare.",
|
||
"onboarding.consent.image_training.yes": "Ja, jag hjälper till",
|
||
"onboarding.consent.image_training.no": "Nej tack",
|
||
"onboarding.consent.dataPrivacy.title": "Data & integritet",
|
||
"onboarding.consent.dataPrivacy.body": "Två saker är på för att göra appen bättre för alla. Du kan stänga av dem när du vill.",
|
||
"onboarding.consent.anonymized_improvement.body": "Anonym förbättring: helt avidentifierad, aggregerad statistik – aldrig dina bilder eller något som pekar ut dig – hjälper oss göra förslagen bättre.",
|
||
"onboarding.consent.product_analytics.body": "Produktanalys: genom att se hur appen används kan vi fixa buggar och förbättra det som krånglar. Pseudonymt, och vi säljer aldrig din data.",
|
||
"onboarding.consent.dataPrivacy.continue": "Fortsätt",
|
||
"onboarding.consent.health_integration.body": "Koppla Apple Health / Health Connect så kan Cibello sätta kalori- och näringsmål utifrån just dig. Hälsodata är extra känslig och är av tills du själv slår på den.",
|
||
"onboarding.consent.location_weather.body": "Med din plats föreslår vi mat som passar vädret – värmande när det är kallt, grillat när solen är framme.",
|
||
"onboarding.consent.push_notifications.body": "Få en påminnelse innan maten går ut och tips när det är dags att handla eller laga.",
|
||
"barcode.info.title": "Nutrition per 100 g",
|
||
"barcode.info.kcal": "Energy",
|
||
"barcode.info.protein": "Protein",
|
||
"barcode.info.carbs": "Carbohydrate",
|
||
"barcode.info.sugar": "– of which sugars",
|
||
"barcode.info.fat": "Fat",
|
||
"barcode.info.satfat": "– of which saturates",
|
||
"barcode.info.monofat": "– of which monounsaturated",
|
||
"barcode.info.polyfat": "– of which polyunsaturated",
|
||
"barcode.info.fiber": "Fibre",
|
||
"barcode.info.salt": "Salt",
|
||
"barcode.info.allergens": "Allergens",
|
||
"barcode.info.mayContain": "May contain traces of",
|
||
"barcode.info.ingredients": "Ingredients",
|
||
"barcode.info.noNutrition": "No nutrition info for this product yet.",
|
||
"barcode.info.scanAgain": "Scan again",
|
||
"barcode.info.sourceOwn": "Source: own product database",
|
||
"barcode.info.sourceOff": "Source: Open Food Facts",
|
||
"submit.title": "Submit your own recipe",
|
||
"submit.subtitle": "Fill in the template and our AI will polish and publish it — credited with your name.",
|
||
"submit.titleLabel": "Recipe name",
|
||
"submit.titlePlaceholder": "e.g. Grandma's meatballs",
|
||
"submit.ingredientsLabel": "Ingredients (one per line, with amount)",
|
||
"submit.ingredientsPlaceholder": "2 dl flour\n500 g minced beef\n1 yellow onion\n1 dl milk\n1 tsp salt",
|
||
"submit.stepsLabel": "Instructions",
|
||
"submit.stepsPlaceholder": "1. Chop and fry the onion until soft.\n2. Mix mince, egg, milk and spices.\n3. Roll balls and fry golden.",
|
||
"submit.button": "Submit the recipe",
|
||
"submit.sending": "Sending …",
|
||
"submit.reviewNote": "We compare against existing recipes, polish the wording to the same standard and publish automatically. Duplicates aren't published.",
|
||
"submit.successTitle": "Thanks – your recipe is submitted!",
|
||
"submit.successBody": "Our AI reviews and polishes it. It will be published shortly, credited with your name, and appear among the recipes.",
|
||
"submit.premiumTitle": "Own recipes are part of Premium",
|
||
"submit.premiumBody": "Submitting and publishing your own recipes is part of Premium — a paid plan (not the trial). Upgrade to go ahead.",
|
||
"submit.seePlans": "See plans",
|
||
"submit.backHome": "Back",
|
||
"cookedLog.title": "Did you cook this dish?",
|
||
"cookedLog.subtitle": "Log that you made it and we'll deduct the ingredients from your stock. Anything missing at home is simply skipped.",
|
||
"cookedLog.button": "Yes, I cooked it",
|
||
"cookedLog.confirm": "Deduct ingredients for {count} servings from your stock?",
|
||
"cookedLog.doneTitle": "Logged!",
|
||
"cookedLog.doneBody": "The ingredients have been deducted from your stock and the meal is logged.",
|
||
"plan.addMeal": "Add a meal",
|
||
"plan.regenerate": "Re-plan the week",
|
||
"season.midsommar": "Midsummer",
|
||
"season.jul": "Christmas",
|
||
"season.påsk": "Easter",
|
||
"season.nyår": "New Year's Eve",
|
||
"season.kraftskiva": "Crayfish party",
|
||
"season.surstromming": "Surströmming premiere",
|
||
"season.lucia": "St Lucia's Day",
|
||
"season.valborg": "Walpurgis Night",
|
||
"season.grillsasong": "Grilling season",
|
||
"season.skolstart": "Back to school",
|
||
"season.alla-hjartans-dag": "Valentine's Day",
|
||
"season.halloween": "Halloween",
|
||
"season.oktoberfest": "Oktoberfest",
|
||
"season.eid": "Eid al-Fitr",
|
||
"kitchen.itemCount": "{count} items",
|
||
"kitchen.selectedCount": "{count} selected",
|
||
"kitchen.removeSelected": "Remove selected ({count})",
|
||
"scan.review.possibleDuplicate": "Seems to already exist: {name}",
|
||
"auth.passwordHint": "at least 8 characters",
|
||
"recipe.proteinTag": "{g} g protein",
|
||
"onboarding.allergen.celery": "Celery",
|
||
"onboarding.allergen.mustard": "Mustard",
|
||
"onboarding.allergen.sulphites": "Sulphites",
|
||
"onboarding.allergen.lupin": "Lupin",
|
||
"onboarding.allergen.molluscs": "Molluscs"
|
||
}
|