From 8ccff04259d89e1e3ab2b5da49ba964e857afc1b Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:18:02 +0300 Subject: [PATCH] Install PWA prompt on the front page Closes #2988 --- .../components/PWAInstallBanner.module.css | 62 ++++++ .../components/PWAInstallBanner.tsx | 188 ++++++++++++++++++ app/features/front-page/routes/index.tsx | 2 + locales/da/common.json | 1 + locales/da/front.json | 12 +- locales/de/common.json | 1 + locales/de/front.json | 12 +- locales/en/common.json | 1 + locales/en/front.json | 12 +- locales/es-ES/common.json | 1 + locales/es-ES/front.json | 12 +- locales/es-US/common.json | 1 + locales/es-US/front.json | 12 +- locales/fr-CA/common.json | 1 + locales/fr-CA/front.json | 12 +- locales/fr-EU/common.json | 1 + locales/fr-EU/front.json | 12 +- locales/he/common.json | 1 + locales/he/front.json | 12 +- locales/it/common.json | 1 + locales/it/front.json | 12 +- locales/ja/common.json | 1 + locales/ja/front.json | 12 +- locales/ko/common.json | 1 + locales/ko/front.json | 12 +- locales/nl/common.json | 1 + locales/nl/front.json | 12 +- locales/pl/common.json | 1 + locales/pl/front.json | 12 +- locales/pt-BR/common.json | 1 + locales/pt-BR/front.json | 12 +- locales/ru/common.json | 1 + locales/ru/front.json | 12 +- locales/zh/common.json | 1 + locales/zh/front.json | 12 +- 35 files changed, 444 insertions(+), 16 deletions(-) create mode 100644 app/features/front-page/components/PWAInstallBanner.module.css create mode 100644 app/features/front-page/components/PWAInstallBanner.tsx diff --git a/app/features/front-page/components/PWAInstallBanner.module.css b/app/features/front-page/components/PWAInstallBanner.module.css new file mode 100644 index 000000000..aeac4abe1 --- /dev/null +++ b/app/features/front-page/components/PWAInstallBanner.module.css @@ -0,0 +1,62 @@ +.banner { + /* needed for firefox to have a valid output */ + --l: 50%; + + position: relative; + background: linear-gradient( + to right, + var(--color-bg), + var(--l), + var(--color-bg-higher) + ); + border: var(--border-style-high); + border-radius: var(--radius-box); + padding: var(--s-4); + overflow: hidden; +} + +.bannerContent { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: var(--s-2); + padding-inline-end: min(130px, 30%); + line-height: 1.15; +} + +.bannerTitle { + font-size: var(--font-lg); + font-weight: var(--weight-bold); + margin: 0; +} + +.homeScreenIcon { + position: absolute; + right: var(--s-6); + top: 50%; + translate: 0 -50%; + display: flex; + flex-direction: column; + align-items: center; + gap: var(--s-1); +} + +.homeScreenIconImg { + width: 56px; + border-radius: 22.5%; + box-shadow: 0 2px 6px rgb(0 0 0 / 25%); +} + +.homeScreenIconLabel { + font-size: var(--font-2xs); + font-weight: var(--weight-semi); + color: var(--color-text); +} + +.instructionsList { + display: flex; + flex-direction: column; + gap: var(--s-2); + margin: 0; + padding-inline-start: var(--s-6); +} diff --git a/app/features/front-page/components/PWAInstallBanner.tsx b/app/features/front-page/components/PWAInstallBanner.tsx new file mode 100644 index 000000000..88b09d04d --- /dev/null +++ b/app/features/front-page/components/PWAInstallBanner.tsx @@ -0,0 +1,188 @@ +import { Download } from "lucide-react"; +import * as React from "react"; +import { useTranslation } from "react-i18next"; +import { SendouButton } from "~/components/elements/Button"; +import { SendouDialog } from "~/components/elements/Dialog"; +import styles from "./PWAInstallBanner.module.css"; + +interface BeforeInstallPromptEvent extends Event { + prompt: () => Promise<{ outcome: "accepted" | "dismissed" }>; +} + +type InstallState = "hidden" | "native" | "ios" | "safari"; + +const SAFARI_MIN_INSTALL_VERSION = 17; +const BANNER_DISMISSED_KEY = "pwa-install-banner-dismissed"; + +let deferredInstallPrompt: BeforeInstallPromptEvent | null = null; +let bannerDismissed = false; +const installStateListeners = new Set<() => void>(); + +if (typeof window !== "undefined") { + try { + bannerDismissed = localStorage.getItem(BANNER_DISMISSED_KEY) === "true"; + } catch { + // localStorage may be unavailable + } + + window.addEventListener("beforeinstallprompt", (event) => { + event.preventDefault(); + deferredInstallPrompt = event as BeforeInstallPromptEvent; + notifyInstallStateChanged(); + }); + window.addEventListener("appinstalled", () => { + deferredInstallPrompt = null; + notifyInstallStateChanged(); + }); +} + +export function PWAInstallBanner() { + const { t } = useTranslation(["front", "common"]); + const installState = useInstallState(); + + if (installState === "hidden") return null; + + return ( +
+
+

+ {t("front:install.banner.title")} +

+

+ {t("front:install.banner.description")} +

+
+ + + {t("common:actions.dismiss")} + +
+
+
+ + sendou.ink +
+
+ ); +} + +function InstallAction({ + installState, +}: { + installState: Exclude; +}) { + const { t } = useTranslation(["front"]); + + const installButton = ( + } + onPress={ + installState === "native" + ? () => deferredInstallPrompt?.prompt() + : undefined + } + > + {t("front:install.button")} + + ); + + if (installState === "native") { + return installButton; + } + + return ( + +
    +
  1. {t(`front:install.${installState}.step1`)}
  2. +
  3. {t(`front:install.${installState}.step2`)}
  4. +
  5. {t(`front:install.${installState}.step3`)}
  6. +
+
+ ); +} + +function useInstallState() { + return React.useSyncExternalStore( + subscribeToInstallState, + getInstallStateSnapshot, + getServerInstallStateSnapshot, + ); +} + +function subscribeToInstallState(callback: () => void) { + installStateListeners.add(callback); + return () => installStateListeners.delete(callback); +} + +function dismissBanner() { + bannerDismissed = true; + try { + localStorage.setItem(BANNER_DISMISSED_KEY, "true"); + } catch { + // localStorage may be unavailable + } + notifyInstallStateChanged(); +} + +function getInstallStateSnapshot(): InstallState { + if (bannerDismissed) return "hidden"; + if (isStandalone()) return "hidden"; + if (deferredInstallPrompt) return "native"; + if (isIos()) return "ios"; + if (isInstallCapableSafariDesktop()) return "safari"; + return "hidden"; +} + +function getServerInstallStateSnapshot(): InstallState { + return "hidden"; +} + +function notifyInstallStateChanged() { + for (const listener of installStateListeners) { + listener(); + } +} + +function isStandalone() { + return ( + window.matchMedia("(display-mode: standalone)").matches || + window.matchMedia("(display-mode: tabbed)").matches || + (navigator as { standalone?: boolean }).standalone === true + ); +} + +function isIos() { + return ( + /iPad|iPhone|iPod/.test(navigator.userAgent) || + (navigator.userAgent.includes("Mac") && navigator.maxTouchPoints > 1) + ); +} + +function isInstallCapableSafariDesktop() { + const userAgent = navigator.userAgent; + const isSafari = + userAgent.includes("Safari") && + !userAgent.includes("Chrome") && + !userAgent.includes("Chromium"); + if (!isSafari || !userAgent.includes("Mac")) return false; + + const versionMatch = userAgent.match(/Version\/(\d+)/); + if (!versionMatch) return false; + + return Number(versionMatch[1]) >= SAFARI_MIN_INSTALL_VERSION; +} diff --git a/app/features/front-page/routes/index.tsx b/app/features/front-page/routes/index.tsx index c5b8b3ea6..330aee54d 100644 --- a/app/features/front-page/routes/index.tsx +++ b/app/features/front-page/routes/index.tsx @@ -14,6 +14,7 @@ import { LocaleTimeRange } from "~/components/LocaleTimeRange"; import { navItems } from "~/components/layout/nav-items"; import { Main } from "~/components/Main"; import { TournamentCard } from "~/features/calendar/components/TournamentCard"; +import { PWAInstallBanner } from "~/features/front-page/components/PWAInstallBanner"; import { SplatoonRotations } from "~/features/front-page/components/SplatoonRotations"; import type * as Changelog from "~/features/front-page/core/Changelog.server"; import * as Seasons from "~/features/mmr/core/Seasons"; @@ -309,6 +310,7 @@ function DiscoverFeatures() { ))} + ); } diff --git a/locales/da/common.json b/locales/da/common.json index ee4958a23..66d8575e1 100644 --- a/locales/da/common.json +++ b/locales/da/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "", "actions.create": "Skab", "actions.close": "Luk", + "actions.dismiss": "", "actions.cancel": "Annuller", "actions.loading": "Indlæser...", "actions.clear": "Ryd", diff --git a/locales/da/front.json b/locales/da/front.json index 0d3964023..c9c33047c 100644 --- a/locales/da/front.json +++ b/locales/da/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" } diff --git a/locales/de/common.json b/locales/de/common.json index 08a744b64..c6d200f64 100644 --- a/locales/de/common.json +++ b/locales/de/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "Discord-Zeitstempel kopieren", "actions.create": "Erstellen", "actions.close": "Schließen", + "actions.dismiss": "", "actions.cancel": "Abbrechen", "actions.loading": "Lädt...", "actions.clear": "Leeren", diff --git a/locales/de/front.json b/locales/de/front.json index 0d3964023..c9c33047c 100644 --- a/locales/de/front.json +++ b/locales/de/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" } diff --git a/locales/en/common.json b/locales/en/common.json index aa8742261..a78581ef4 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "Copy Discord timestamp", "actions.create": "Create", "actions.close": "Close", + "actions.dismiss": "Dismiss", "actions.cancel": "Cancel", "actions.loading": "Loading...", "actions.clear": "Clear", diff --git a/locales/en/front.json b/locales/en/front.json index 424cd6274..23c31e255 100644 --- a/locales/en/front.json +++ b/locales/en/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "Next", "rotations.credit": "Data from splatoon3.ink", "rotations.filter.all": "All", - "discover.header": "Discover all the features" + "discover.header": "Discover all the features", + "install.button": "Install app", + "install.header": "Install sendou.ink", + "install.banner.title": "Get the sendou.ink app", + "install.banner.description": "Add sendou.ink to your home screen for quick access", + "install.ios.step1": "Tap the share button in your browser", + "install.ios.step2": "Select \"Add to Home Screen\"", + "install.ios.step3": "Tap \"Add\"", + "install.safari.step1": "Click the share button in Safari's toolbar", + "install.safari.step2": "Select \"Add to Dock\"", + "install.safari.step3": "Click \"Add\"" } diff --git a/locales/es-ES/common.json b/locales/es-ES/common.json index 66115f914..6c2fe3263 100644 --- a/locales/es-ES/common.json +++ b/locales/es-ES/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "Copiar timestamp para Discord", "actions.create": "Crear", "actions.close": "Cerrar", + "actions.dismiss": "", "actions.cancel": "Cancelar", "actions.loading": "Cargando...", "actions.clear": "Limpiar", diff --git a/locales/es-ES/front.json b/locales/es-ES/front.json index eee79a690..546b20009 100644 --- a/locales/es-ES/front.json +++ b/locales/es-ES/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" } diff --git a/locales/es-US/common.json b/locales/es-US/common.json index 492b77686..a60d00b23 100644 --- a/locales/es-US/common.json +++ b/locales/es-US/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "", "actions.create": "Crear", "actions.close": "Cerrar", + "actions.dismiss": "", "actions.cancel": "Cancelar", "actions.loading": "Cargando...", "actions.clear": "Aclarar", diff --git a/locales/es-US/front.json b/locales/es-US/front.json index 0d3964023..c9c33047c 100644 --- a/locales/es-US/front.json +++ b/locales/es-US/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" } diff --git a/locales/fr-CA/common.json b/locales/fr-CA/common.json index 60613675e..09ca5f2de 100644 --- a/locales/fr-CA/common.json +++ b/locales/fr-CA/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "", "actions.create": "Créer", "actions.close": "Fermer", + "actions.dismiss": "", "actions.cancel": "Annuler", "actions.loading": "Chargement...", "actions.clear": "Effacer", diff --git a/locales/fr-CA/front.json b/locales/fr-CA/front.json index 0d3964023..c9c33047c 100644 --- a/locales/fr-CA/front.json +++ b/locales/fr-CA/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" } diff --git a/locales/fr-EU/common.json b/locales/fr-EU/common.json index 19d40ac1f..7490ad3ed 100644 --- a/locales/fr-EU/common.json +++ b/locales/fr-EU/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "", "actions.create": "Créer", "actions.close": "Fermer", + "actions.dismiss": "", "actions.cancel": "Annuler le match", "actions.loading": "Chargement...", "actions.clear": "Effacer", diff --git a/locales/fr-EU/front.json b/locales/fr-EU/front.json index b30b52a3e..901ccea24 100644 --- a/locales/fr-EU/front.json +++ b/locales/fr-EU/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" } diff --git a/locales/he/common.json b/locales/he/common.json index 8b2170c9a..7ecb65f0f 100644 --- a/locales/he/common.json +++ b/locales/he/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "", "actions.create": "יצירה", "actions.close": "סגירה", + "actions.dismiss": "", "actions.cancel": "ביטול", "actions.loading": "טוען...", "actions.clear": "ניקוי", diff --git a/locales/he/front.json b/locales/he/front.json index 0d3964023..c9c33047c 100644 --- a/locales/he/front.json +++ b/locales/he/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" } diff --git a/locales/it/common.json b/locales/it/common.json index 971d99064..b77569349 100644 --- a/locales/it/common.json +++ b/locales/it/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "", "actions.create": "Crea", "actions.close": "Chiudi", + "actions.dismiss": "", "actions.cancel": "Cancella", "actions.loading": "Caricamento in corso...", "actions.clear": "Svuota", diff --git a/locales/it/front.json b/locales/it/front.json index 335f984d0..7f0e3a871 100644 --- a/locales/it/front.json +++ b/locales/it/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" } diff --git a/locales/ja/common.json b/locales/ja/common.json index 877d54a76..4082df256 100644 --- a/locales/ja/common.json +++ b/locales/ja/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "", "actions.create": "作成", "actions.close": "閉じる", + "actions.dismiss": "", "actions.cancel": "キャンセル", "actions.loading": "Loading...", "actions.clear": "クリア", diff --git a/locales/ja/front.json b/locales/ja/front.json index 0d3964023..c9c33047c 100644 --- a/locales/ja/front.json +++ b/locales/ja/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" } diff --git a/locales/ko/common.json b/locales/ko/common.json index fc2ec26b1..23294439f 100644 --- a/locales/ko/common.json +++ b/locales/ko/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "", "actions.create": "생성", "actions.close": "닫기", + "actions.dismiss": "", "actions.cancel": "취소", "actions.loading": "로딩 중...", "actions.clear": "비우기", diff --git a/locales/ko/front.json b/locales/ko/front.json index 0d3964023..c9c33047c 100644 --- a/locales/ko/front.json +++ b/locales/ko/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" } diff --git a/locales/nl/common.json b/locales/nl/common.json index 2dfd88b5d..8282032fe 100644 --- a/locales/nl/common.json +++ b/locales/nl/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "", "actions.create": "", "actions.close": "", + "actions.dismiss": "", "actions.cancel": "", "actions.loading": "", "actions.clear": "", diff --git a/locales/nl/front.json b/locales/nl/front.json index 0d3964023..c9c33047c 100644 --- a/locales/nl/front.json +++ b/locales/nl/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" } diff --git a/locales/pl/common.json b/locales/pl/common.json index c3408e935..347b56286 100644 --- a/locales/pl/common.json +++ b/locales/pl/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "", "actions.create": "Stwórz", "actions.close": "Zamknij", + "actions.dismiss": "", "actions.cancel": "Anuluj", "actions.loading": "Ładowanie...", "actions.clear": "Wyczyść", diff --git a/locales/pl/front.json b/locales/pl/front.json index 0d3964023..c9c33047c 100644 --- a/locales/pl/front.json +++ b/locales/pl/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" } diff --git a/locales/pt-BR/common.json b/locales/pt-BR/common.json index bdd3bdbfd..0b9a927bc 100644 --- a/locales/pt-BR/common.json +++ b/locales/pt-BR/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "", "actions.create": "Criar", "actions.close": "Fechar", + "actions.dismiss": "", "actions.cancel": "Cancelar", "actions.loading": "Carregando...", "actions.clear": "Limpar", diff --git a/locales/pt-BR/front.json b/locales/pt-BR/front.json index 0d3964023..c9c33047c 100644 --- a/locales/pt-BR/front.json +++ b/locales/pt-BR/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" } diff --git a/locales/ru/common.json b/locales/ru/common.json index 6c5d3deb4..0a0623af4 100644 --- a/locales/ru/common.json +++ b/locales/ru/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "", "actions.create": "Создать", "actions.close": "Закрыть", + "actions.dismiss": "", "actions.cancel": "Отменить", "actions.loading": "Загрузка...", "actions.clear": "Очистить", diff --git a/locales/ru/front.json b/locales/ru/front.json index 97c7cd0c2..5a870e114 100644 --- a/locales/ru/front.json +++ b/locales/ru/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" } diff --git a/locales/zh/common.json b/locales/zh/common.json index 89f7952ca..70d9e7dc1 100644 --- a/locales/zh/common.json +++ b/locales/zh/common.json @@ -126,6 +126,7 @@ "actions.copyTimestampForDiscord": "", "actions.create": "创建", "actions.close": "关闭", + "actions.dismiss": "", "actions.cancel": "取消", "actions.loading": "加载中...", "actions.clear": "清除", diff --git a/locales/zh/front.json b/locales/zh/front.json index 0d3964023..c9c33047c 100644 --- a/locales/zh/front.json +++ b/locales/zh/front.json @@ -40,5 +40,15 @@ "rotations.nextLabel": "", "rotations.credit": "", "rotations.filter.all": "", - "discover.header": "" + "discover.header": "", + "install.button": "", + "install.header": "", + "install.banner.title": "", + "install.banner.description": "", + "install.ios.step1": "", + "install.ios.step2": "", + "install.ios.step3": "", + "install.safari.step1": "", + "install.safari.step2": "", + "install.safari.step3": "" }