- Rename catalog: ingredient/* → product/* (canonical_name, barcode, nutrition per 100g)
- Rename pantry: product/* → userproduct/* (user-owned items with expiry)
- Squash migrations into single 001_initial_schema.sql (clean-db baseline)
- product_categories: add English canonical name column; fix COALESCE in queries
- Remove product_translations: product names are stored in their original language
- Add default_unit_name to product API responses via unit_translations JOIN
- Add cmd/importoff: bulk import from OpenFoodFacts JSONL dump (COPY + ON CONFLICT)
- Diary: support product_id entries alongside dish_id (CHECK num_nonnulls = 1)
- Home: getLoggedCalories joins both recipes and catalog products
- Flutter: rename models/providers/services to match backend rename
- Flutter: add barcode scan flow for diary (mobile_scanner, product_portion_sheet)
- Flutter: localise 6 new keys across 12 languages (barcode scan, portion weight)
- Routes: GET /products/search, GET /products/barcode/{barcode}, /user-products
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
115 lines
3.8 KiB
Plaintext
115 lines
3.8 KiB
Plaintext
{
|
|
"@@locale": "ko",
|
|
"appTitle": "FoodAI",
|
|
"greetingMorning": "좋은 아침이에요",
|
|
"greetingAfternoon": "안녕하세요",
|
|
"greetingEvening": "좋은 저녁이에요",
|
|
"caloriesUnit": "kcal",
|
|
"gramsUnit": "g",
|
|
"goalLabel": "목표:",
|
|
"consumed": "섭취",
|
|
"remaining": "남은",
|
|
"exceeded": "초과",
|
|
"proteinLabel": "단백질",
|
|
"fatLabel": "지방",
|
|
"carbsLabel": "탄수화물",
|
|
"today": "오늘",
|
|
"yesterday": "어제",
|
|
"mealsSection": "식사",
|
|
"addDish": "요리 추가",
|
|
"scanDish": "스캔",
|
|
"menu": "메뉴",
|
|
"dishHistory": "요리 기록",
|
|
"recommendCook": "요리 추천",
|
|
"camera": "카메라",
|
|
"gallery": "갤러리",
|
|
"analyzingPhoto": "사진 분석 중...",
|
|
"inQueue": "대기열에 있습니다",
|
|
"queuePosition": "{position}번째",
|
|
"@queuePosition": {
|
|
"placeholders": {
|
|
"position": {
|
|
"type": "int"
|
|
}
|
|
}
|
|
},
|
|
"processing": "처리 중...",
|
|
"upgradePrompt": "대기열 건너뛰기? 업그레이드 →",
|
|
"recognitionFailed": "인식 실패. 다시 시도하세요.",
|
|
"dishRecognition": "요리 인식",
|
|
"all": "전체",
|
|
"dishRecognized": "요리가 인식되었습니다",
|
|
"recognizing": "인식 중…",
|
|
"recognitionError": "인식 오류",
|
|
"dishResultTitle": "요리가 인식되었습니다",
|
|
"selectDish": "요리 선택",
|
|
"dishNotRecognized": "요리를 인식할 수 없습니다",
|
|
"tryAgain": "다시 시도",
|
|
"nutritionApproximate": "영양 정보는 근사치입니다 — 사진을 기반으로 추정되었습니다.",
|
|
"portion": "양",
|
|
"mealType": "식사 유형",
|
|
"dateLabel": "날짜",
|
|
"addToJournal": "일지에 추가",
|
|
"addFailed": "추가 실패. 다시 시도하세요.",
|
|
"historyTitle": "인식 기록",
|
|
"historyLoadError": "기록 로드 실패",
|
|
"retry": "재시도",
|
|
"noHistory": "인식 기록이 없습니다",
|
|
"profileTitle": "프로필",
|
|
"edit": "편집",
|
|
"bodyParams": "신체 매개변수",
|
|
"goalActivity": "목표 & 활동",
|
|
"nutrition": "영양",
|
|
"settings": "설정",
|
|
"height": "키",
|
|
"weight": "체중",
|
|
"age": "나이",
|
|
"gender": "성별",
|
|
"genderMale": "남성",
|
|
"genderFemale": "여성",
|
|
"goalLoss": "체중 감량",
|
|
"goalMaintain": "유지",
|
|
"goalGain": "근육 증가",
|
|
"activityLow": "낮음",
|
|
"activityMedium": "보통",
|
|
"activityHigh": "높음",
|
|
"calorieGoal": "칼로리 목표",
|
|
"mealTypes": "식사 유형",
|
|
"formulaNote": "Mifflin-St Jeor 공식으로 계산",
|
|
"language": "언어",
|
|
"notSet": "설정 안 됨",
|
|
"calorieHint": "칼로리 목표를 계산하려면 신체 매개변수를 입력하세요",
|
|
"logout": "로그아웃",
|
|
"editProfile": "프로필 편집",
|
|
"cancel": "취소",
|
|
"save": "저장",
|
|
"nameLabel": "이름",
|
|
"heightCm": "키 (cm)",
|
|
"weightKg": "체중 (kg)",
|
|
"birthDate": "생년월일",
|
|
"nameRequired": "이름을 입력하세요",
|
|
"profileUpdated": "프로필이 업데이트되었습니다",
|
|
"profileSaveFailed": "저장 실패",
|
|
"mealTypeBreakfast": "아침",
|
|
"mealTypeSecondBreakfast": "두 번째 아침",
|
|
"mealTypeLunch": "점심",
|
|
"mealTypeAfternoonSnack": "간식",
|
|
"mealTypeDinner": "저녁",
|
|
"mealTypeSnack": "스낵",
|
|
"navHome": "홈",
|
|
"navProducts": "식품",
|
|
"navRecipes": "레시피",
|
|
"addFromReceiptOrPhoto": "영수증 또는 사진으로 추가",
|
|
"chooseMethod": "방법 선택",
|
|
"photoReceipt": "영수증 촬영",
|
|
"photoReceiptSubtitle": "영수증의 모든 상품 인식",
|
|
"photoProducts": "식품 촬영",
|
|
"photoProductsSubtitle": "냉장고, 테이블, 선반 — 최대 3장",
|
|
"addPackagedFood": "포장 식품 추가",
|
|
"scanBarcode": "바코드 스캔",
|
|
"portionWeightG": "1회 제공량 (g)",
|
|
"productNotFound": "제품을 찾을 수 없습니다",
|
|
"enterManually": "직접 입력",
|
|
"perHundredG": "100g당"
|
|
}
|