i18n(app-svep) + i18n-vakt: hela mobil-UI:t översatt + CI-vakt mot regress

- Svepte 51 hårdkodade strängar -> t() över konto, sök/bläddra, sparade recept,
  kök, planera, skanna, byt måltid, inköp, minne, cooking, api-fel (+ locLabel/
  kategorier via nycklar). 47 nya nycklar, översatta till alla 12 språk.
- NY: apps/mobile/scripts/i18n-check.mjs (i18n:check) – fäller bygget om ett språk
  saknar en nyckel, en använd nyckel saknas, eller det finns hårdkodad UI-text.
  Wire:ad i CI (.github/workflows/ci.yml) efter typecheck. => 'lägg till språk'
  blir: kör vakten, den listar exakt vad som fattas. Aldrig mer leta för hand.
- Prettier-fixade 5 filer från tidigare leveranser så format:check blir grön.
- submit-recipe fri-text-payload + firebase dev-stubs markerade // i18n-ignore.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Claude
2026-08-21 01:50:08 +00:00
parent cadaa1a41f
commit 2d59a3e636
36 changed files with 1123 additions and 288 deletions
+35 -11
View File
@@ -78,19 +78,43 @@ export default function RootLayout() {
name="cooking/[id]"
options={{ title: "", presentation: "fullScreenModal" }}
/>
<Stack.Screen name="scan-review/[jobId]" options={{ title: t("scan.review.title"), fullScreenGestureEnabled: false }} />
<Stack.Screen name="swap-meal/[entryId]" options={{ presentation: "modal", title: t("nav.swap") }} />
<Stack.Screen name="meal-review/[jobId]" options={{ title: t("scan.meal.title"), fullScreenGestureEnabled: false }} />
<Stack.Screen
name="scan-review/[jobId]"
options={{ title: t("scan.review.title"), fullScreenGestureEnabled: false }}
/>
<Stack.Screen
name="swap-meal/[entryId]"
options={{ presentation: "modal", title: t("nav.swap") }}
/>
<Stack.Screen
name="meal-review/[jobId]"
options={{ title: t("scan.meal.title"), fullScreenGestureEnabled: false }}
/>
<Stack.Screen name="reconciliation" options={{ title: t("reconciliation.title") }} />
<Stack.Screen name="scan-diff-review/[jobId]" options={{ title: t("scan.review.title"), fullScreenGestureEnabled: false }} />
<Stack.Screen name="shopping" options={{ title: t("shopping.title"), presentation: "modal" }} />
<Stack.Screen name="meal-boxes" options={{ title: t("mealbox.title"), presentation: "modal" }} />
<Stack.Screen name="household" options={{ title: t("home.household"), presentation: "modal" }} />
<Stack.Screen
name="scan-diff-review/[jobId]"
options={{ title: t("scan.review.title"), fullScreenGestureEnabled: false }}
/>
<Stack.Screen
name="shopping"
options={{ title: t("shopping.title"), presentation: "modal" }}
/>
<Stack.Screen
name="meal-boxes"
options={{ title: t("mealbox.title"), presentation: "modal" }}
/>
<Stack.Screen
name="household"
options={{ title: t("home.household"), presentation: "modal" }}
/>
<Stack.Screen name="memory" options={{ title: t("memory.title") }} />
<Stack.Screen name="saved-recipes" options={{ title: t("nav.savedRecipes") }} />
<Stack.Screen name="recipes" options={{ title: t("nav.browseRecipes") }} />
<Stack.Screen name="kitchen" options={{ title: t("nav.kitchen") }} />
<Stack.Screen name="profile" options={{ title: t("profile.title"), presentation: "modal" }} />
<Stack.Screen name="saved-recipes" options={{ title: t("nav.savedRecipes") }} />
<Stack.Screen name="recipes" options={{ title: t("nav.browseRecipes") }} />
<Stack.Screen name="kitchen" options={{ title: t("nav.kitchen") }} />
<Stack.Screen
name="profile"
options={{ title: t("profile.title"), presentation: "modal" }}
/>
<Stack.Screen
name="paywall"
options={{ title: t("paywall.title"), presentation: "modal" }}