Backend:
- migration 005: expand menu_items.meal_type CHECK to all 6 types (second_breakfast, afternoon_snack, snack)
- ai/types.go: add Days and MealTypes to MenuRequest for partial generation
- openai/menu.go: parametrize GenerateMenu — use requested meal types and day count; add caloric fractions for all 6 meal types
- menu/repository.go: add UpsertItemsInTx for partial upsert (preserves existing slots); fix meal_type sort order in GetByWeek
- menu/handler.go: add dates+meal_types path to POST /ai/generate-menu; extract fetchImages/saveRecipes helpers; returns {"plans":[...]} for dates mode; backward-compatible with week mode
Client:
- PlanMenuSheet: bottom sheet with 4 planning horizon options
- PlanDatePickerSheet: adaptive sheet with date strip (single day/meal) or custom CalendarRangePicker (multi-day/week); sliding 7-day window for week mode
- menu_service.dart: add generateForDates
- menu_provider.dart: add PlanMenuService (generates + invalidates week providers), lastPlannedDateProvider
- home_screen.dart: add _PlanMenuButton card below quick actions; opens planning wizard
- l10n: 16 new keys for planning UI across all 12 languages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
422 lines
8.7 KiB
Dart
422 lines
8.7 KiB
Dart
// ignore: unused_import
|
||
import 'package:intl/intl.dart' as intl;
|
||
import 'app_localizations.dart';
|
||
|
||
// ignore_for_file: type=lint
|
||
|
||
/// The translations for Japanese (`ja`).
|
||
class AppLocalizationsJa extends AppLocalizations {
|
||
AppLocalizationsJa([String locale = 'ja']) : super(locale);
|
||
|
||
@override
|
||
String get appTitle => 'FoodAI';
|
||
|
||
@override
|
||
String get greetingMorning => 'おはようございます';
|
||
|
||
@override
|
||
String get greetingAfternoon => 'こんにちは';
|
||
|
||
@override
|
||
String get greetingEvening => 'こんばんは';
|
||
|
||
@override
|
||
String get caloriesUnit => 'kcal';
|
||
|
||
@override
|
||
String get gramsUnit => 'g';
|
||
|
||
@override
|
||
String get goalLabel => '目標:';
|
||
|
||
@override
|
||
String get consumed => '摂取済み';
|
||
|
||
@override
|
||
String get remaining => '残り';
|
||
|
||
@override
|
||
String get exceeded => '超過';
|
||
|
||
@override
|
||
String get proteinLabel => 'タンパク質';
|
||
|
||
@override
|
||
String get fatLabel => '脂質';
|
||
|
||
@override
|
||
String get carbsLabel => '炭水化物';
|
||
|
||
@override
|
||
String get today => '今日';
|
||
|
||
@override
|
||
String get yesterday => '昨日';
|
||
|
||
@override
|
||
String get mealsSection => '食事';
|
||
|
||
@override
|
||
String get addDish => '料理を追加';
|
||
|
||
@override
|
||
String get scanDish => 'スキャン';
|
||
|
||
@override
|
||
String get menu => 'メニュー';
|
||
|
||
@override
|
||
String get dishHistory => '料理履歴';
|
||
|
||
@override
|
||
String get recommendCook => 'おすすめレシピ';
|
||
|
||
@override
|
||
String get camera => 'カメラ';
|
||
|
||
@override
|
||
String get gallery => 'ギャラリー';
|
||
|
||
@override
|
||
String get analyzingPhoto => '写真を分析中...';
|
||
|
||
@override
|
||
String get inQueue => '順番待ち中';
|
||
|
||
@override
|
||
String queuePosition(int position) {
|
||
return '$position番目';
|
||
}
|
||
|
||
@override
|
||
String get processing => '処理中...';
|
||
|
||
@override
|
||
String get upgradePrompt => '順番をスキップ?アップグレード →';
|
||
|
||
@override
|
||
String get recognitionFailed => '認識に失敗しました。もう一度お試しください。';
|
||
|
||
@override
|
||
String get dishRecognition => '料理認識';
|
||
|
||
@override
|
||
String get all => 'すべて';
|
||
|
||
@override
|
||
String get dishRecognized => '料理を認識しました';
|
||
|
||
@override
|
||
String get recognizing => '認識中…';
|
||
|
||
@override
|
||
String get recognitionError => '認識エラー';
|
||
|
||
@override
|
||
String get dishResultTitle => '料理を認識しました';
|
||
|
||
@override
|
||
String get selectDish => '料理を選択';
|
||
|
||
@override
|
||
String get dishNotRecognized => '料理を認識できませんでした';
|
||
|
||
@override
|
||
String get tryAgain => 'もう一度試す';
|
||
|
||
@override
|
||
String get nutritionApproximate => '栄養値は概算です — 写真から推定されました。';
|
||
|
||
@override
|
||
String get portion => '量';
|
||
|
||
@override
|
||
String get mealType => '食事タイプ';
|
||
|
||
@override
|
||
String get dateLabel => '日付';
|
||
|
||
@override
|
||
String get addToJournal => '日記に追加';
|
||
|
||
@override
|
||
String get addFailed => '追加に失敗しました。もう一度お試しください。';
|
||
|
||
@override
|
||
String get historyTitle => '認識履歴';
|
||
|
||
@override
|
||
String get historyLoadError => '履歴の読み込みに失敗しました';
|
||
|
||
@override
|
||
String get retry => '再試行';
|
||
|
||
@override
|
||
String get noHistory => '認識履歴がありません';
|
||
|
||
@override
|
||
String get profileTitle => 'プロフィール';
|
||
|
||
@override
|
||
String get edit => '編集';
|
||
|
||
@override
|
||
String get bodyParams => '身体パラメータ';
|
||
|
||
@override
|
||
String get goalActivity => '目標 & 活動';
|
||
|
||
@override
|
||
String get nutrition => '栄養';
|
||
|
||
@override
|
||
String get settings => '設定';
|
||
|
||
@override
|
||
String get height => '身長';
|
||
|
||
@override
|
||
String get weight => '体重';
|
||
|
||
@override
|
||
String get age => '年齢';
|
||
|
||
@override
|
||
String get gender => '性別';
|
||
|
||
@override
|
||
String get genderMale => '男性';
|
||
|
||
@override
|
||
String get genderFemale => '女性';
|
||
|
||
@override
|
||
String get goalLoss => '体重減少';
|
||
|
||
@override
|
||
String get goalMaintain => '維持';
|
||
|
||
@override
|
||
String get goalGain => '筋肉増量';
|
||
|
||
@override
|
||
String get activityLow => '低い';
|
||
|
||
@override
|
||
String get activityMedium => '普通';
|
||
|
||
@override
|
||
String get activityHigh => '高い';
|
||
|
||
@override
|
||
String get calorieGoal => 'カロリー目標';
|
||
|
||
@override
|
||
String get mealTypes => '食事タイプ';
|
||
|
||
@override
|
||
String get formulaNote => 'ミフリン・セントジョー式で計算';
|
||
|
||
@override
|
||
String get language => '言語';
|
||
|
||
@override
|
||
String get notSet => '未設定';
|
||
|
||
@override
|
||
String get calorieHint => 'カロリー目標を計算するために身体パラメータを入力してください';
|
||
|
||
@override
|
||
String get logout => 'ログアウト';
|
||
|
||
@override
|
||
String get editProfile => 'プロフィールを編集';
|
||
|
||
@override
|
||
String get cancel => 'キャンセル';
|
||
|
||
@override
|
||
String get save => '保存';
|
||
|
||
@override
|
||
String get nameLabel => '名前';
|
||
|
||
@override
|
||
String get heightCm => '身長(cm)';
|
||
|
||
@override
|
||
String get weightKg => '体重(kg)';
|
||
|
||
@override
|
||
String get birthDate => '生年月日';
|
||
|
||
@override
|
||
String get nameRequired => '名前を入力してください';
|
||
|
||
@override
|
||
String get profileUpdated => 'プロフィールを更新しました';
|
||
|
||
@override
|
||
String get profileSaveFailed => '保存に失敗しました';
|
||
|
||
@override
|
||
String get mealTypeBreakfast => '朝食';
|
||
|
||
@override
|
||
String get mealTypeSecondBreakfast => '第二朝食';
|
||
|
||
@override
|
||
String get mealTypeLunch => '昼食';
|
||
|
||
@override
|
||
String get mealTypeAfternoonSnack => 'おやつ';
|
||
|
||
@override
|
||
String get mealTypeDinner => '夕食';
|
||
|
||
@override
|
||
String get mealTypeSnack => '間食';
|
||
|
||
@override
|
||
String get navHome => 'ホーム';
|
||
|
||
@override
|
||
String get navProducts => '食品';
|
||
|
||
@override
|
||
String get navRecipes => 'レシピ';
|
||
|
||
@override
|
||
String get addFromReceiptOrPhoto => 'レシートや写真から追加';
|
||
|
||
@override
|
||
String get chooseMethod => '方法を選択';
|
||
|
||
@override
|
||
String get photoReceipt => 'レシートを撮影';
|
||
|
||
@override
|
||
String get photoReceiptSubtitle => 'レシートから全商品を認識';
|
||
|
||
@override
|
||
String get photoProducts => '食品を撮影';
|
||
|
||
@override
|
||
String get photoProductsSubtitle => '冷蔵庫・テーブル・棚 — 最大3枚';
|
||
|
||
@override
|
||
String get addPackagedFood => 'パッケージ食品を追加';
|
||
|
||
@override
|
||
String get scanBarcode => 'バーコードをスキャン';
|
||
|
||
@override
|
||
String get portionWeightG => '1食分の重さ(g)';
|
||
|
||
@override
|
||
String get productNotFound => '商品が見つかりません';
|
||
|
||
@override
|
||
String get enterManually => '手動で入力';
|
||
|
||
@override
|
||
String get perHundredG => '100gあたり';
|
||
|
||
@override
|
||
String get searchFoodHint => '食品と料理を検索...';
|
||
|
||
@override
|
||
String get recentlyUsedLabel => '最近使用';
|
||
|
||
@override
|
||
String get productsSection => '食品';
|
||
|
||
@override
|
||
String get dishesSection => '料理';
|
||
|
||
@override
|
||
String noResultsForQuery(String query) {
|
||
return '「$query」の検索結果はありません';
|
||
}
|
||
|
||
@override
|
||
String get servingsLabel => '人前';
|
||
|
||
@override
|
||
String get addToDiary => '日記に追加';
|
||
|
||
@override
|
||
String get scanDishPhoto => '写真をスキャン';
|
||
|
||
@override
|
||
String planningForDate(String date) {
|
||
return '';
|
||
}
|
||
|
||
@override
|
||
String get markAsEaten => '食べた印をつける';
|
||
|
||
@override
|
||
String get plannedMealLabel => '予定済み';
|
||
|
||
@override
|
||
String get generateWeekLabel => '週を計画する';
|
||
|
||
@override
|
||
String get generateWeekSubtitle => 'AIが一週間の朝食・昼食・夕食のメニューを作成します';
|
||
|
||
@override
|
||
String get generatingMenu => 'メニューを生成中...';
|
||
|
||
@override
|
||
String get weekPlannedLabel => '週の計画済み';
|
||
|
||
@override
|
||
String get planMenuButton => '食事を計画する';
|
||
|
||
@override
|
||
String get planMenuTitle => '何を計画する?';
|
||
|
||
@override
|
||
String get planOptionSingleMeal => '1食';
|
||
|
||
@override
|
||
String get planOptionSingleMealDesc => '日と食事タイプを選択';
|
||
|
||
@override
|
||
String get planOptionDay => '1日';
|
||
|
||
@override
|
||
String get planOptionDayDesc => '1日分の全食事';
|
||
|
||
@override
|
||
String get planOptionDays => '数日';
|
||
|
||
@override
|
||
String get planOptionDaysDesc => '期間をカスタマイズ';
|
||
|
||
@override
|
||
String get planOptionWeek => '1週間';
|
||
|
||
@override
|
||
String get planOptionWeekDesc => '7日分まとめて';
|
||
|
||
@override
|
||
String get planSelectDate => '日付を選択';
|
||
|
||
@override
|
||
String get planSelectMealType => '食事タイプ';
|
||
|
||
@override
|
||
String get planSelectRange => '期間を選択';
|
||
|
||
@override
|
||
String get planGenerateButton => '計画する';
|
||
|
||
@override
|
||
String get planGenerating => 'プランを生成中…';
|
||
|
||
@override
|
||
String get planSuccess => 'メニューが計画されました!';
|
||
}
|