Skip to content

Feat/i18n#37

Closed
OffCrazyFreak wants to merge 11 commits into
masterfrom
feat/i18n
Closed

Feat/i18n#37
OffCrazyFreak wants to merge 11 commits into
masterfrom
feat/i18n

Conversation

@OffCrazyFreak

Copy link
Copy Markdown
Owner

No description provided.

Changes:
- Add web app manifest (app/manifest.ts) with standalone display, theme
  color, icons, and shortcuts derived from userNavItems
- Generate PWA icon set (192/512/maskable/apple-touch) from the logo via a
  sharp script (scripts/generate-pwa-icons.mjs)
- Add install UX: persistent sidebar banner + dismissible floating banner +
  platform-aware "how to install" sheet, behind a useInstallPrompt hook
- Show install UI whenever the app isn't installed (not only when the native
  beforeinstallprompt has fired), falling back to manual instructions
- Register a minimal service worker (public/sw.js) so browsers offer install
- Wire PWA metadata/viewport into layout and fix stale metadataBase
- Persist floating-banner dismissal in the existing app localStorage object

First stage of the staged PWA roadmap (offline shell, push, and engagement
extras follow). The minimal service worker is replaced by Serwist in Stage 2.

Notes:
- theme_color (#2ec50d) also tints the mobile browser address bar site-wide
- Adds sharp as a devDependency (icon generation only)
… or iOS

  Safari, hide on unsupported browsers and in-app webviews; hide once installed
Changes:
- Lift useInstallPrompt state into a module-level store read via
  useSyncExternalStore, so the floating and sidebar banners share one
  captured beforeinstallprompt event
- Clear the prompt for all consumers after promptInstall(), preventing a
  stale install action in the other banner
- Attach beforeinstallprompt/appinstalled listeners once on first subscribe
  instead of once per component
- Add a `ready` flag (false in the server snapshot) so install UI is gated
  until client detection runs, avoiding a flash in standalone sessions

Fixes CodeRabbit findings on PR #36: separate per-component prompt state
(major) and install UI flashing before hydration (minor).

Notes:
- Public hook API is unchanged, so InstallBanner/InstallSidebarBanner needed
  no edits
- Dropped now-redundant `typeof window` guards in detectIOS/detectStandalone
  since they only run inside the client-only init()
Changes:
- Add Serwist service worker (src/app/sw.ts): precache app shell, /offline
  fallback, StaleWhileRevalidate for public /api/cijene GETs, NetworkOnly for
  other /api (keeps authed responses out of Cache Storage); wire withSerwistInit
  in next.config (disabled in dev), webworker lib in tsconfig, build --webpack
- Persist React Query cache to IndexedDB (src/lib/offline/*): whitelist of
  cijene/lists/watchlist/etc., 7-day maxAge + buster, success-only dehydration;
  swap to PersistQueryClientProvider with gcTime >= maxAge
- Purge persisted cache on logout (user-context handleLogout)
- Add offline UX: online-status hook, offline indicator banner, relative-time
  util, and "last synced" labels on product detail, watchlist, shopping list
- Remove interim Stage-1 sw.js + manual registration (Serwist auto-registers)

Read-only offline; offline writes (queue + replay) follow in Stage 2b. Pins
@TanStack persist packages to 5.101.1 to match react-query (avoids dup
query-core). Adds @serwist/next, serwist, react-query-persist-client,
query-async-storage-persister, idb-keyval.

Notes:
- Service worker is active in production builds only; data-layer offline works
  in dev. TODO(offline) markers mark coming-soon screens (cards/spending/
  updates/map) to wire when they ship.
Changes:
- Add offline mutation allowlist + keys (lib/offline/offline-mutation-keys.ts)
  and replay defaults (lib/offline/offline-mutations.ts): register default
  mutationFn + invalidation per mutationKey so paused writes resume after reload
- Persist only paused, allowlisted mutations (persister shouldDehydrateMutation)
- Register defaults on client creation and resumePausedMutations on cache
  restore (react-query-provider)
- Tag shopping-list and watchlist mutation hooks with their mutationKey
- Offline indicator shows count of queued writes; create/rename list modal
  closes with a "will sync" toast when offline instead of spinning

Builds on Stage 2a read caching: offline edits to shopping lists/items and
watchlist now queue optimistically and replay on reconnect (same session or
after a reload), cross-browser via React Query (no SW Background Sync needed).

Notes:
- Watchlist add/remove and list creation are queued but not yet optimistic
  offline; follow-up enhancement
- No new dependencies
Changes:
- Add .claude/skills/document-subsystem/SKILL.md that generates a docs/<NAME>.md
  reference for a given part of the app, in the style of docs/DEPLOYMENT.md

Gives a reusable, consistent way to produce detailed, beginner-friendly subsystem
docs: explore the code first, then document the flow, automatic vs manual work,
key files, config/env, libraries, gotchas, and future TODOs.

Notes:
- Project-level skill; move to ~/.claude/skills/ to use it across all projects
…l polish

Changes:
- Set status bar / theme color to neutral white (viewport themeColor +
  manifest theme_color), removing the green top bar
- Request persistent storage (navigator.storage.persist) so the offline
  IndexedDB cache isn't evicted, especially on iOS
- Add iOS splash screens: 18 device sizes generated into public/splash via
  scripts/generate-ios-splash.mjs, emitted as apple-touch-startup-image links
  from a shared constants list (rendered in <head>)
- Add manifest screenshots (branded narrow + wide promo cards) for the richer
  install dialog, and launch_handler focus-existing to avoid duplicate windows

Hardens the Stage 2 offline work and completes Stage 1 install UX on iOS.

Notes:
- Splash/screenshot images are generated; re-run the scripts to refresh them
Changes:
- Add next-intl 4.13 with cookie-based locale (NEXT_LOCALE), no URL routing: src/i18n/{config,request,locale-actions,message-fallback,intl-client-provider}.ts, wired via createNextIntlPlugin in next.config.ts and a client provider in the root layout
- Add 4 message catalogs (hr default, en, de, sl), 652 keys each with full parity, plus compile-time key safety (src/typings/next-intl.d.ts)
- Auto-detect locale from Accept-Language on first visit (the cookie still wins); fall back to hr for any missing key; set a global Europe/Zagreb time zone to avoid date/time hydration mismatches
- Localize the root layout (dynamic <html lang>, generateMetadata) and every page.tsx metadata
- Migrate all user-facing surfaces to t()/t.rich()/ICU plurals: header, sidebar, footer, auth modal and forms, settings modals, dashboard, product detail, price history, add-to-list and watchlist modals, scanner, shopping-list detail and its mutation-hook toasts, watchlist/digital-cards/suggestions/updates/map/statistics, offline indicator, and PWA install banners
- Translate attributes too (placeholders, image alts, aria-labels, tooltips) and render account-type/acquisition-channel labels via i18n; add a useNavTranslation hook
- Add a LanguageSwitcher: an icon variant (header for guests, footer) with a muted-to-primary hover, and a sidebar variant shown on mobile above the PWA banner
- Add a "validation" namespace and build the forgot-password and reset-password Zod schemas inside their components so their messages localize

Establishes a type-safe, cookie-based i18n base so the app serves Croatian, English, German, and Slovenian; adding a language is a one-line config change plus a catalog file.

Notes:
- Reading the cookie / Accept-Language header opts routes into dynamic rendering, which is expected for cookie-based i18n without routing.
- next-intl and eslint-plugin-i18next are added via pnpm (package.json / lock are dependency-managed, not hand-edited).
Changes:
- Add getEmailTranslator + an "emails" catalog namespace so the verification, password-reset, set-password, and change-email templates render in the recipient's locale (subject, heading, body, button, footnote, footer)
- Add getRequestLocale to resolve the recipient locale from the cookie / Accept-Language in non-render contexts, and thread it through EmailService and the Better Auth email callbacks in lib/auth.ts
- Set the email <html lang> and time zone per locale; use t.rich for the change-email address and the footer link

Emails previously always sent in Croatian regardless of the user's language; they now match it.

Notes:
- The locale is resolved inside the request context before the fire-and-forget send, so cookies()/headers() are available.
- Email templates keep their react-email PreviewProps (locale defaults to hr) so "pnpm email" preview still works.
Changes:
- Add the i18next/no-literal-string ESLint rule (eslint-plugin-i18next): fails on hardcoded JSX text and on the placeholder/alt/title/aria-label/label attributes, tuned with callees/words excludes for zero false positives
- Add scripts/check-i18n.mjs (run via "pnpm i18n:check") to verify all four catalogs stay in parity
- Document the i18n workflow (rules, scripts, no em dashes) in AGENTS.md

Makes the translation coverage self-defending: a hardcoded string or a missing key now fails CI instead of shipping.

Notes:
- The eslint-plugin-i18next dependency and the i18n:check script entry live in package.json (added in the foundation commit); this commit adds the config and script file that use them.
Copilot AI review requested due to automatic review settings July 4, 2026 20:03
@netlify

netlify Bot commented Jul 4, 2026

Copy link
Copy Markdown

Deploy Preview for disscount ready!

Name Link
🔨 Latest commit 5db081f
🔍 Latest deploy log https://app.netlify.com/projects/disscount/deploys/6a4966f71a395600083ecc5c
😎 Deploy Preview https://deploy-preview-37--disscount.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 163 files, which is 13 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ee6b28e4-d84d-4660-b44e-2685e00ca728

📥 Commits

Reviewing files that changed from the base of the PR and between fdae339 and 5db081f.

⛔ Files ignored due to path filters (25)
  • frontend/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • frontend/public/icons/apple-touch-icon-180.png is excluded by !**/*.png
  • frontend/public/icons/icon-192.png is excluded by !**/*.png
  • frontend/public/icons/icon-512.png is excluded by !**/*.png
  • frontend/public/icons/icon-maskable-512.png is excluded by !**/*.png
  • frontend/public/screenshots/screenshot-narrow.png is excluded by !**/*.png
  • frontend/public/screenshots/screenshot-wide.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1080-2340.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1125-2436.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1170-2532.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1179-2556.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1206-2622.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1242-2208.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1242-2688.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1284-2778.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1290-2796.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1320-2868.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1536-2048.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1620-2160.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1640-2360.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1668-2224.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-1668-2388.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-2048-2732.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-750-1334.png is excluded by !**/*.png
  • frontend/public/splash/apple-splash-828-1792.png is excluded by !**/*.png
📒 Files selected for processing (163)
  • .claude/skills/document-subsystem/SKILL.md
  • .gitignore
  • AGENTS.md
  • frontend/.gitignore
  • frontend/eslint.config.mjs
  • frontend/next.config.ts
  • frontend/package.json
  • frontend/pnpm-workspace.yaml
  • frontend/scripts/check-i18n.mjs
  • frontend/scripts/generate-ios-splash.mjs
  • frontend/scripts/generate-pwa-icons.mjs
  • frontend/scripts/generate-pwa-screenshots.mjs
  • frontend/src/app/(root)/components/sections/hero-actions.tsx
  • frontend/src/app/(root)/components/sections/hero-section.tsx
  • frontend/src/app/(root)/page.tsx
  • frontend/src/app/(user)/digital-cards/components/digital-card-item.tsx
  • frontend/src/app/(user)/digital-cards/components/digital-cards-client.tsx
  • frontend/src/app/(user)/digital-cards/components/forms/digital-card-modal.tsx
  • frontend/src/app/(user)/digital-cards/page.tsx
  • frontend/src/app/(user)/shopping-lists/[id]/components/items/shopping-list-item.tsx
  • frontend/src/app/(user)/shopping-lists/[id]/components/items/shopping-list-items.tsx
  • frontend/src/app/(user)/shopping-lists/[id]/components/shopping-list-action-buttons.tsx
  • frontend/src/app/(user)/shopping-lists/[id]/components/shopping-list-detail-client.tsx
  • frontend/src/app/(user)/shopping-lists/[id]/components/shopping-list-header.tsx
  • frontend/src/app/(user)/shopping-lists/[id]/components/shopping-list-info-table.tsx
  • frontend/src/app/(user)/shopping-lists/[id]/components/shopping-list-price-history.tsx
  • frontend/src/app/(user)/shopping-lists/[id]/components/stores/shopping-list-items-table.tsx
  • frontend/src/app/(user)/shopping-lists/[id]/components/stores/shopping-list-store-card.tsx
  • frontend/src/app/(user)/shopping-lists/[id]/components/stores/shopping-list-stores-list.tsx
  • frontend/src/app/(user)/shopping-lists/[id]/hooks/use-shopping-list-data.ts
  • frontend/src/app/(user)/shopping-lists/[id]/hooks/use-shopping-list-item-mutations.ts
  • frontend/src/app/(user)/shopping-lists/[id]/hooks/use-shopping-list-mutations.ts
  • frontend/src/app/(user)/shopping-lists/[id]/page.tsx
  • frontend/src/app/(user)/shopping-lists/components/create-shopping-list-button.tsx
  • frontend/src/app/(user)/shopping-lists/components/forms/delete-shopping-list-dialog.tsx
  • frontend/src/app/(user)/shopping-lists/components/forms/shopping-list-modal.tsx
  • frontend/src/app/(user)/shopping-lists/components/shopping-list-item.tsx
  • frontend/src/app/(user)/shopping-lists/components/shopping-lists-client.tsx
  • frontend/src/app/(user)/shopping-lists/hooks/use-shopping-list-modal.ts
  • frontend/src/app/(user)/shopping-lists/page.tsx
  • frontend/src/app/(user)/spending/page.tsx
  • frontend/src/app/(user)/watchlist/components/create-discounted-list-button.tsx
  • frontend/src/app/(user)/watchlist/components/watchlist-client.tsx
  • frontend/src/app/(user)/watchlist/components/watchlist-item-discount-info.tsx
  • frontend/src/app/(user)/watchlist/components/watchlist-item.tsx
  • frontend/src/app/(user)/watchlist/page.tsx
  • frontend/src/app/dashboard/components/admin-users-table.tsx
  • frontend/src/app/dashboard/components/dashboard-content.tsx
  • frontend/src/app/dashboard/page.tsx
  • frontend/src/app/data-deletion/page.tsx
  • frontend/src/app/layout.tsx
  • frontend/src/app/manifest.ts
  • frontend/src/app/map/components/map-client.tsx
  • frontend/src/app/map/page.tsx
  • frontend/src/app/not-found.tsx
  • frontend/src/app/offline/components/offline-retry-button.tsx
  • frontend/src/app/offline/page.tsx
  • frontend/src/app/privacy-policy/page.tsx
  • frontend/src/app/products/[id]/components/price-history/price-history-base.tsx
  • frontend/src/app/products/[id]/components/price-history/price-history-chart.tsx
  • frontend/src/app/products/[id]/components/product-detail-client.tsx
  • frontend/src/app/products/[id]/components/store-item/store-item.tsx
  • frontend/src/app/products/[id]/components/store-item/store-prices-table.tsx
  • frontend/src/app/products/[id]/page.tsx
  • frontend/src/app/products/components/forms/add-to-shopping-list-form.tsx
  • frontend/src/app/products/components/forms/mark-as-checked-checkbox.tsx
  • frontend/src/app/products/components/forms/quantity-input.tsx
  • frontend/src/app/products/components/forms/shopping-list-selector.tsx
  • frontend/src/app/products/components/forms/watchlist-item-modal.tsx
  • frontend/src/app/products/components/product-action-buttons.tsx
  • frontend/src/app/products/components/product-info-display.tsx
  • frontend/src/app/products/components/product-info-table.tsx
  • frontend/src/app/products/components/product-item/product-info.tsx
  • frontend/src/app/products/components/product-item/product-price.tsx
  • frontend/src/app/products/components/products-client.tsx
  • frontend/src/app/products/components/watchlist-action-button.tsx
  • frontend/src/app/products/page.tsx
  • frontend/src/app/providers/providers.tsx
  • frontend/src/app/providers/react-query-provider.tsx
  • frontend/src/app/reset-password/page.tsx
  • frontend/src/app/reset-password/reset-password-modal.tsx
  • frontend/src/app/statistics/components/health-status.tsx
  • frontend/src/app/statistics/components/store-item.tsx
  • frontend/src/app/statistics/components/stores-list.tsx
  • frontend/src/app/statistics/page.tsx
  • frontend/src/app/suggestions/[id]/components/suggestion-details-client.tsx
  • frontend/src/app/suggestions/[id]/page.tsx
  • frontend/src/app/suggestions/components/suggestions-client.tsx
  • frontend/src/app/suggestions/page.tsx
  • frontend/src/app/sw.ts
  • frontend/src/app/terms-of-service/page.tsx
  • frontend/src/app/updates/[id]/page.tsx
  • frontend/src/app/updates/components/updates-client.tsx
  • frontend/src/app/updates/page.tsx
  • frontend/src/components/custom/app-sidebar.tsx
  • frontend/src/components/custom/camera-scanner.tsx
  • frontend/src/components/custom/coming-soon.tsx
  • frontend/src/components/custom/footer.tsx
  • frontend/src/components/custom/header/forms/account-credentials-form.tsx
  • frontend/src/components/custom/header/forms/auth-modal.tsx
  • frontend/src/components/custom/header/forms/forgot-password-form.tsx
  • frontend/src/components/custom/header/forms/inbox-notice.tsx
  • frontend/src/components/custom/header/forms/linked-accounts.tsx
  • frontend/src/components/custom/header/forms/login-form.tsx
  • frontend/src/components/custom/header/forms/profile-modal.tsx
  • frontend/src/components/custom/header/forms/security-modal.tsx
  • frontend/src/components/custom/header/forms/signup-form.tsx
  • frontend/src/components/custom/header/forms/user-preferences-modal.tsx
  • frontend/src/components/custom/header/header.tsx
  • frontend/src/components/custom/header/notifications-dropdown.tsx
  • frontend/src/components/custom/header/user-menu.tsx
  • frontend/src/components/custom/language-switcher.tsx
  • frontend/src/components/custom/legal-page.tsx
  • frontend/src/components/custom/no-results.tsx
  • frontend/src/components/custom/oauth-error-toast.tsx
  • frontend/src/components/custom/offline/last-synced-label.tsx
  • frontend/src/components/custom/offline/offline-indicator.tsx
  • frontend/src/components/custom/price-history-period-select.tsx
  • frontend/src/components/custom/pwa/apple-splash-screens.tsx
  • frontend/src/components/custom/pwa/install-banner.tsx
  • frontend/src/components/custom/pwa/install-instructions-sheet.tsx
  • frontend/src/components/custom/pwa/install-sidebar-banner.tsx
  • frontend/src/components/custom/pwa/request-persistent-storage.tsx
  • frontend/src/components/custom/pwa/use-install-prompt.ts
  • frontend/src/components/custom/search-bar.tsx
  • frontend/src/components/custom/store-chain-multi-select.tsx
  • frontend/src/components/custom/store-chain-select.tsx
  • frontend/src/components/custom/view-switcher.tsx
  • frontend/src/constants/ios-splash-screens.json
  • frontend/src/context/user-context.tsx
  • frontend/src/emails/change-email-confirmation.tsx
  • frontend/src/emails/components/action-email.tsx
  • frontend/src/emails/components/email-layout.tsx
  • frontend/src/emails/email-translator.ts
  • frontend/src/emails/password-reset-email.tsx
  • frontend/src/emails/set-password-email.tsx
  • frontend/src/emails/verification-email.tsx
  • frontend/src/hooks/use-nav-translation.ts
  • frontend/src/hooks/use-online-status.ts
  • frontend/src/i18n/config.ts
  • frontend/src/i18n/get-request-locale.ts
  • frontend/src/i18n/intl-client-provider.tsx
  • frontend/src/i18n/locale-actions.ts
  • frontend/src/i18n/message-fallback.ts
  • frontend/src/i18n/messages/de.json
  • frontend/src/i18n/messages/en.json
  • frontend/src/i18n/messages/hr.json
  • frontend/src/i18n/messages/sl.json
  • frontend/src/i18n/request.ts
  • frontend/src/lib/api/shopping-lists/index.ts
  • frontend/src/lib/api/watchlist/index.ts
  • frontend/src/lib/auth.ts
  • frontend/src/lib/email/email-service.ts
  • frontend/src/lib/offline/cached-query-keys.ts
  • frontend/src/lib/offline/offline-mutation-keys.ts
  • frontend/src/lib/offline/offline-mutations.ts
  • frontend/src/lib/offline/persister.ts
  • frontend/src/lib/offline/purge.ts
  • frontend/src/typings/local-storage.ts
  • frontend/src/typings/next-intl.d.ts
  • frontend/src/utils/browser/local-storage.ts
  • frontend/src/utils/date.ts
  • frontend/tsconfig.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a full i18n layer (via next-intl, cookie-based locale), adds PWA/offline capabilities (service worker, install UI, iOS splash wiring, offline fallback page), and enables offline persistence + replay for selected React Query queries/mutations.

Changes:

  • Add next-intl request config, locale management, typings, and broad UI string migration to translation keys.
  • Add offline-first data layer: React Query persistence to IndexedDB, mutation allowlist/keys, logout purge, and offline UI indicators.
  • Add PWA foundations: Serwist service worker, manifest metadata, install prompts/banners, and iOS splash screen support tooling.

Reviewed changes

Copilot reviewed 161 out of 188 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
frontend/tsconfig.json Adds webworker/Serwist typing support and excludes generated SW output.
frontend/src/utils/date.ts Adds human-friendly relative time formatter utility.
frontend/src/utils/browser/local-storage.ts Persists install-banner dismissal state.
frontend/src/typings/next-intl.d.ts Adds strong typing for next-intl locale/message shape.
frontend/src/typings/local-storage.ts Extends AppData for install-banner dismissal.
frontend/src/lib/offline/purge.ts Adds logout-time offline cache purge helper.
frontend/src/lib/offline/persister.ts Adds IndexedDB React Query persister + dehydration rules.
frontend/src/lib/offline/offline-mutation-keys.ts Defines allowlisted mutation keys for offline replay/persistence.
frontend/src/lib/offline/cached-query-keys.ts Defines allowlisted query-key prefixes for persistence.
frontend/src/lib/email/email-service.ts Localizes transactional email subject/body selection by locale.
frontend/src/lib/auth.ts Resolves request locale for auth emails (reset/verify/change-email).
frontend/src/lib/api/watchlist/index.ts Tags watchlist mutations with offline mutation keys.
frontend/src/lib/api/shopping-lists/index.ts Tags shopping-list mutations with offline mutation keys.
frontend/src/i18n/request.ts Implements per-request locale/messages config for next-intl.
frontend/src/i18n/message-fallback.ts Adds hr-based fallback + error handling for missing messages.
frontend/src/i18n/locale-actions.ts Adds server action to persist locale cookie.
frontend/src/i18n/intl-client-provider.tsx Client wrapper for consistent fallback/error handling.
frontend/src/i18n/get-request-locale.ts Extracts locale in non-render server contexts (e.g. email sending).
frontend/src/i18n/config.ts Defines locale list, cookie name, timezone, and Accept-Language matching.
frontend/src/hooks/use-online-status.ts Adds online/offline hook (React Query onlineManager).
frontend/src/hooks/use-nav-translation.ts Centralizes nav label translation/casting logic.
frontend/src/emails/verification-email.tsx Localizes verification email content via translator.
frontend/src/emails/set-password-email.tsx Localizes set-password email content via translator.
frontend/src/emails/password-reset-email.tsx Localizes reset email content via translator.
frontend/src/emails/email-translator.ts Implements synchronous email translator per locale/namespace.
frontend/src/emails/components/email-layout.tsx Localizes shared email layout/footer and sets <Html lang>.
frontend/src/emails/components/action-email.tsx Localizes shared CTA email structure.
frontend/src/emails/change-email-confirmation.tsx Localizes change-email confirmation email content via translator.
frontend/src/context/user-context.tsx Purges persisted offline cache on logout.
frontend/src/constants/ios-splash-screens.json Adds iOS splash device dimension list used by scripts/head tags.
frontend/src/components/custom/view-switcher.tsx Localizes accessibility labels/tooltips.
frontend/src/components/custom/store-chain-select.tsx Localizes placeholder; refactors price-diff color selection.
frontend/src/components/custom/store-chain-multi-select.tsx Localizes placeholder text.
frontend/src/components/custom/search-bar.tsx Localizes labels/titles and adds translated fallbacks.
frontend/src/components/custom/pwa/request-persistent-storage.tsx Requests persistent storage for offline cache (best-effort).
frontend/src/components/custom/pwa/install-sidebar-banner.tsx Adds persistent sidebar install CTA.
frontend/src/components/custom/pwa/install-instructions-sheet.tsx Adds localized manual install instructions (iOS/Android).
frontend/src/components/custom/pwa/install-banner.tsx Adds dismissible install banner with persisted dismissal state.
frontend/src/components/custom/pwa/apple-splash-screens.tsx Renders iOS splash <link> tags from device list.
frontend/src/components/custom/price-history-period-select.tsx Localizes period labels.
frontend/src/components/custom/offline/offline-indicator.tsx Adds top banner when offline + pending write count.
frontend/src/components/custom/offline/last-synced-label.tsx Adds “last refreshed” label using relative time.
frontend/src/components/custom/oauth-error-toast.tsx Localizes OAuth error toasts via message keys.
frontend/src/components/custom/no-results.tsx Localizes default “no results” title/description.
frontend/src/components/custom/legal-page.tsx Localizes static legal-page wrapper labels/warnings.
frontend/src/components/custom/language-switcher.tsx Adds locale switcher that persists cookie + refreshes router.
frontend/src/components/custom/header/user-menu.tsx Localizes menu labels and account type display.
frontend/src/components/custom/header/notifications-dropdown.tsx Localizes notification UI strings and formatting.
frontend/src/components/custom/header/forms/signup-form.tsx Localizes signup form labels/errors/toasts.
frontend/src/components/custom/header/forms/login-form.tsx Localizes login form labels/errors/toasts.
frontend/src/components/custom/header/forms/linked-accounts.tsx Localizes linked-account UI and errors.
frontend/src/components/custom/header/forms/inbox-notice.tsx Localizes inbox notice hint.
frontend/src/components/custom/header/forms/forgot-password-form.tsx Localizes forgot-password schema/messages and UI copy.
frontend/src/components/custom/footer.tsx Localizes footer aria/alt text and adds language switcher placement.
frontend/src/components/custom/coming-soon.tsx Localizes “coming soon” badge/description.
frontend/src/components/custom/camera-scanner.tsx Localizes scanner UI and error strings.
frontend/src/app/updates/page.tsx Localizes metadata generation for Updates page.
frontend/src/app/updates/components/updates-client.tsx Localizes updates list UI.
frontend/src/app/updates/[id]/page.tsx Localizes post detail metadata + UI labels.
frontend/src/app/terms-of-service/page.tsx Localizes TOS metadata/content via translation keys.
frontend/src/app/sw.ts Adds Serwist service worker with runtime caching + offline fallback.
frontend/src/app/suggestions/page.tsx Localizes metadata generation for Suggestions page.
frontend/src/app/suggestions/components/suggestions-client.tsx Localizes suggestions list UI.
frontend/src/app/suggestions/[id]/page.tsx Localizes suggestion detail metadata.
frontend/src/app/suggestions/[id]/components/suggestion-details-client.tsx Localizes suggestion detail UI strings.
frontend/src/app/statistics/page.tsx Localizes metadata and page headings/descriptions.
frontend/src/app/statistics/components/stores-list.tsx Localizes store stats list UI.
frontend/src/app/statistics/components/store-item.tsx Localizes store-item UI and replaces Croatian pluralization helper.
frontend/src/app/statistics/components/health-status.tsx Localizes API health UI messaging.
frontend/src/app/reset-password/page.tsx Localizes metadata generation for reset-password page.
frontend/src/app/providers/react-query-provider.tsx Switches to persisted React Query provider and registers offline replay.
frontend/src/app/providers/providers.tsx Adds persistent-storage request + iOS splash component into provider tree.
frontend/src/app/products/page.tsx Localizes metadata generation for Products page.
frontend/src/app/products/components/watchlist-action-button.tsx Localizes watchlist action labels.
frontend/src/app/products/components/products-client.tsx Localizes product search UI and empty/error states.
frontend/src/app/products/components/product-item/product-price.tsx Localizes unknown-price label.
frontend/src/app/products/components/product-item/product-info.tsx Localizes unknown product name fallback.
frontend/src/app/products/components/product-info-table.tsx Localizes product detail table labels and unknown fallbacks.
frontend/src/app/products/components/product-info-display.tsx Localizes unknown product fallback.
frontend/src/app/products/components/product-action-buttons.tsx Localizes tooltips/aria labels for product actions.
frontend/src/app/products/components/forms/shopping-list-selector.tsx Localizes shopping-list selector copy/labels.
frontend/src/app/products/components/forms/quantity-input.tsx Localizes quantity field labels/aria labels.
frontend/src/app/products/components/forms/mark-as-checked-checkbox.tsx Localizes checkbox label/description.
frontend/src/app/products/[id]/page.tsx Localizes metadata generation for product detail page.
frontend/src/app/products/[id]/components/store-item/store-prices-table.tsx Localizes store price table headers and empty states.
frontend/src/app/products/[id]/components/store-item/store-item.tsx Localizes store chain section labels and badges.
frontend/src/app/products/[id]/components/product-detail-client.tsx Adds last-synced label and localizes product detail strings.
frontend/src/app/products/[id]/components/price-history/price-history-chart.tsx Localizes average label in chart config.
frontend/src/app/products/[id]/components/price-history/price-history-base.tsx Localizes price-history section UI and empty state.
frontend/src/app/privacy-policy/page.tsx Localizes privacy policy metadata/content.
frontend/src/app/offline/page.tsx Adds localized offline fallback page.
frontend/src/app/offline/components/offline-retry-button.tsx Adds localized “retry” button.
frontend/src/app/not-found.tsx Localizes 404 metadata and UI copy.
frontend/src/app/map/page.tsx Localizes metadata generation for Map page.
frontend/src/app/map/components/map-client.tsx Localizes map page UI and coming-soon text.
frontend/src/app/manifest.ts Adds web manifest (shortcuts, screenshots, icons, launch handler).
frontend/src/app/layout.tsx Switches to localized metadata + wraps app in next-intl provider; adds PWA/offline UI.
frontend/src/app/data-deletion/page.tsx Localizes data deletion page metadata/content.
frontend/src/app/dashboard/page.tsx Localizes dashboard metadata.
frontend/src/app/dashboard/components/dashboard-content.tsx Localizes dashboard headings and empty state.
frontend/src/app/(user)/watchlist/page.tsx Localizes watchlist metadata.
frontend/src/app/(user)/watchlist/components/watchlist-item.tsx Localizes watchlist item UI and toasts.
frontend/src/app/(user)/watchlist/components/watchlist-item-discount-info.tsx Localizes discount info UI/errors.
frontend/src/app/(user)/watchlist/components/create-discounted-list-button.tsx Localizes discounted list creation UI/toasts and list title.
frontend/src/app/(user)/spending/page.tsx Localizes spending metadata and coming-soon copy.
frontend/src/app/(user)/shopping-lists/page.tsx Localizes shopping lists metadata.
frontend/src/app/(user)/shopping-lists/hooks/use-shopping-list-modal.ts Adds offline-aware modal behavior and localizes toasts/errors.
frontend/src/app/(user)/shopping-lists/components/shopping-lists-client.tsx Localizes shopping lists UI and empty state.
frontend/src/app/(user)/shopping-lists/components/shopping-list-item.tsx Localizes public/private tooltip.
frontend/src/app/(user)/shopping-lists/components/forms/shopping-list-modal.tsx Localizes modal title/labels/buttons.
frontend/src/app/(user)/shopping-lists/components/forms/delete-shopping-list-dialog.tsx Localizes delete dialog title/description/buttons.
frontend/src/app/(user)/shopping-lists/components/create-shopping-list-button.tsx Localizes create button text.
frontend/src/app/(user)/shopping-lists/[id]/page.tsx Localizes shopping list detail metadata.
frontend/src/app/(user)/shopping-lists/[id]/hooks/use-shopping-list-mutations.ts Localizes mutations toasts and copy suffix.
frontend/src/app/(user)/shopping-lists/[id]/hooks/use-shopping-list-item-mutations.ts Localizes item mutation toasts/errors.
frontend/src/app/(user)/shopping-lists/[id]/hooks/use-shopping-list-data.ts Exposes dataUpdatedAt for last-synced UI.
frontend/src/app/(user)/shopping-lists/[id]/components/stores/shopping-list-stores-list.tsx Localizes store-chain section UI and error/empty states.
frontend/src/app/(user)/shopping-lists/[id]/components/stores/shopping-list-store-card.tsx Localizes availability and pricing labels/badges.
frontend/src/app/(user)/shopping-lists/[id]/components/stores/shopping-list-items-table.tsx Localizes table headers and accessibility labels.
frontend/src/app/(user)/shopping-lists/[id]/components/shopping-list-price-history.tsx Localizes price-history section UI and empty state.
frontend/src/app/(user)/shopping-lists/[id]/components/shopping-list-info-table.tsx Localizes shopping list stats labels.
frontend/src/app/(user)/shopping-lists/[id]/components/shopping-list-header.tsx Localizes public/private tooltip title.
frontend/src/app/(user)/shopping-lists/[id]/components/shopping-list-detail-client.tsx Adds last-synced label and localizes error/back text.
frontend/src/app/(user)/shopping-lists/[id]/components/items/shopping-list-items.tsx Localizes products section heading and empty states.
frontend/src/app/(user)/shopping-lists/[id]/components/items/shopping-list-item.tsx Localizes item action aria labels.
frontend/src/app/(user)/digital-cards/page.tsx Localizes digital cards metadata.
frontend/src/app/(user)/digital-cards/components/digital-cards-client.tsx Localizes digital cards UI and empty state.
frontend/src/app/(user)/digital-cards/components/digital-card-item.tsx Localizes delete confirm/toasts/labels.
frontend/src/app/(root)/page.tsx Localizes homepage metadata.
frontend/src/app/(root)/components/sections/hero-section.tsx Localizes hero tagline selection and logo alt text.
frontend/src/app/(root)/components/sections/hero-actions.tsx Localizes hero search and scan CTA.
frontend/scripts/generate-pwa-screenshots.mjs Adds generator for manifest screenshot images.
frontend/scripts/generate-pwa-icons.mjs Adds generator for PWA icon set.
frontend/scripts/generate-ios-splash.mjs Adds generator for iOS splash images.
frontend/scripts/check-i18n.mjs Adds catalog parity checker (pnpm i18n:check).
frontend/pnpm-workspace.yaml Expands allowBuilds list for native deps used by tooling.
frontend/package.json Adds i18n script and dependencies for next-intl, Serwist, persistence.
frontend/next.config.ts Wires next-intl plugin and Serwist SW build config.
frontend/eslint.config.mjs Enforces no hardcoded JSX strings via i18next/no-literal-string.
frontend/.gitignore Ignores generated service worker artifacts.
AGENTS.md Documents i18n conventions and required checks.
.gitignore Adds docs ignore pattern; normalizes newline/spacing.
.claude/skills/document-subsystem/SKILL.md Adds documentation-writing skill scaffold.
Files not reviewed (1)
  • frontend/pnpm-lock.yaml: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread frontend/package.json
Comment on lines 6 to 12
"scripts": {
"dev": "next dev",
"build": "next build",
"build": "next build --webpack",
"start": "next start",
"lint": "eslint .",
"i18n:check": "node scripts/check-i18n.mjs",
"email": "email dev --dir src/emails --port 3366"
Comment on lines +7 to +10
export async function purgeOfflineCache(queryClient: QueryClient) {
queryClient.clear();
await offlinePersister.removeClient();
}
Comment on lines 20 to 26
<CameraScannerProvider>
<ToasterProvider>
<ReactScan />
<RequestPersistentStorage />
<AppleSplashScreens />

{children}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants