Fix: localize the PWA install prompt

The PWA install prompt was hardcoded English regardless of the selected UI
language (and the large English block tripped Chrome's translate popup on
Android). Add a pwa_install namespace to all 17 locales, switch the component
to useTranslations, and move <PWAInstallPrompt /> from (main)/layout into
(main)/[locale]/layout so it renders inside the IntlProvider. The title keeps
the dynamic {appName}, so per-domain branding still applies.
This commit is contained in:
dealerweb
2026-05-30 15:35:05 +02:00
committed by Linus Rath
parent f0d87d594a
commit 229992853b
20 changed files with 146 additions and 8 deletions
+2
View File
@@ -9,6 +9,7 @@ import { ProtocolLaunchHandlerProvider } from "@/components/protocol/protocol-la
import { ProInterfaceRedirect } from "@/components/pro/pro-interface-redirect";
import { PluginDialogHost } from "@/components/plugins/plugin-dialog-host";
import { PluginConsentDialog } from "@/components/plugins/plugin-consent-dialog";
import { PWAInstallPrompt } from "@/components/pwa-install-prompt";
import { locales } from "@/i18n/routing";
export default async function LocaleLayout({
@@ -41,6 +42,7 @@ export default async function LocaleLayout({
{children}
<PluginDialogHost />
<PluginConsentDialog />
<PWAInstallPrompt />
</ProtocolLaunchHandlerProvider>
</TourProvider>
</EmbeddedBridgeProvider>
-2
View File
@@ -2,7 +2,6 @@ import type { Metadata, Viewport } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import { headers } from "next/headers";
import { getLocale } from "next-intl/server";
import { PWAInstallPrompt } from "@/components/pwa-install-prompt";
import { ServiceWorkerRegistration } from "@/components/service-worker-registration";
import { configManager } from "@/lib/admin/config-manager";
import { withBasePath } from "@/lib/browser-navigation";
@@ -92,7 +91,6 @@ export default async function RootLayout({
>
<ServiceWorkerRegistration />
{children}
<PWAInstallPrompt />
</body>
</html>
);
+8 -6
View File
@@ -1,6 +1,7 @@
"use client";
import { useEffect, useState } from "react";
import { useTranslations } from "next-intl";
import { X, Download } from "lucide-react";
import { useConfig } from "@/hooks/use-config";
import { withBasePath } from "@/lib/browser-navigation";
@@ -17,6 +18,7 @@ export function PWAInstallPrompt() {
useState<BeforeInstallPromptEvent | null>(null);
const [showPrompt, setShowPrompt] = useState(false);
const { appName, faviconUrl, appLogoLightUrl, appLogoDarkUrl } = useConfig();
const t = useTranslations("pwa_install");
useEffect(() => {
if (localStorage.getItem(DISMISSED_KEY)) return;
@@ -84,17 +86,17 @@ export function PWAInstallPrompt() {
)}
<div>
<h3 className="font-semibold text-sm text-neutral-900 dark:text-white">
Install {appName}
{t("title", { appName })}
</h3>
<p className="text-xs text-neutral-600 dark:text-neutral-400 mt-1">
Install our app for quick access and offline support.
{t("description")}
</p>
</div>
</div>
<button
onClick={handleDismiss}
className="text-neutral-400 hover:text-neutral-600 dark:hover:text-neutral-300 transition-colors"
aria-label="Dismiss install prompt"
aria-label={t("dismiss_aria")}
>
<X className="w-4 h-4" />
</button>
@@ -105,20 +107,20 @@ export function PWAInstallPrompt() {
onClick={handleDismiss}
className="flex-1 px-3 py-2 text-sm font-medium text-neutral-700 dark:text-neutral-300 bg-neutral-100 dark:bg-neutral-800 rounded hover:bg-neutral-200 dark:hover:bg-neutral-700 transition-colors"
>
Not now
{t("not_now")}
</button>
<button
onClick={handleInstall}
className="flex-1 px-3 py-2 text-sm font-medium text-white bg-blue-600 rounded hover:bg-blue-700 transition-colors"
>
Install
{t("install")}
</button>
</div>
<button
onClick={handleDismissForever}
className="w-full text-xs text-neutral-400 hover:text-neutral-600 dark:hover:text-neutral-300 transition-colors text-center"
>
Don&apos;t remind me again
{t("dont_remind")}
</button>
</div>
</div>
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "Nainstalovat {appName}",
"description": "Nainstalujte si naši aplikaci pro rychlý přístup a offline podporu.",
"not_now": "Teď ne",
"install": "Nainstalovat",
"dont_remind": "Už mi to nepřipomínat",
"dismiss_aria": "Zavřít výzvu k instalaci"
},
"login": {
"title": "Webmail",
"username_label": "E-mail",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "Installer {appName}",
"description": "Installer vores app for hurtig adgang og offline-understøttelse.",
"not_now": "Ikke nu",
"install": "Installer",
"dont_remind": "Påmind mig ikke igen",
"dismiss_aria": "Afvis installationsprompt"
},
"login": {
"title": "Webmail",
"username_label": "Email",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "{appName} installieren",
"description": "Installiere unsere App für schnellen Zugriff und Offline-Unterstützung.",
"not_now": "Nicht jetzt",
"install": "Installieren",
"dont_remind": "Nicht mehr erinnern",
"dismiss_aria": "Installationshinweis schließen"
},
"login": {
"title": "Webmail",
"username_label": "E-Mail",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "Install {appName}",
"description": "Install our app for quick access and offline support.",
"not_now": "Not now",
"install": "Install",
"dont_remind": "Don't remind me again",
"dismiss_aria": "Dismiss install prompt"
},
"login": {
"title": "Webmail",
"username_label": "Email",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "Instalar {appName}",
"description": "Instala nuestra app para un acceso rápido y soporte sin conexión.",
"not_now": "Ahora no",
"install": "Instalar",
"dont_remind": "No volver a recordármelo",
"dismiss_aria": "Cerrar aviso de instalación"
},
"login": {
"title": "Correo Web",
"username_label": "Correo electrónico",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "Installer {appName}",
"description": "Installez notre application pour un accès rapide et un support hors ligne.",
"not_now": "Pas maintenant",
"install": "Installer",
"dont_remind": "Ne plus me le rappeler",
"dismiss_aria": "Fermer l'invite d'installation"
},
"login": {
"title": "Webmail",
"username_label": "Email",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "Installa {appName}",
"description": "Installa la nostra app per un accesso rapido e il supporto offline.",
"not_now": "Non ora",
"install": "Installa",
"dont_remind": "Non ricordarmelo più",
"dismiss_aria": "Chiudi avviso di installazione"
},
"login": {
"title": "Webmail",
"username_label": "Email",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "{appName} をインストール",
"description": "素早いアクセスとオフライン対応のため、アプリをインストールしましょう。",
"not_now": "後で",
"install": "インストール",
"dont_remind": "今後表示しない",
"dismiss_aria": "インストールプロンプトを閉じる"
},
"login": {
"title": "ウェブメール",
"username_label": "メールアドレス",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "{appName} 설치",
"description": "빠른 액세스와 오프라인 지원을 위해 앱을 설치하세요.",
"not_now": "나중에",
"install": "설치",
"dont_remind": "다시 알리지 않음",
"dismiss_aria": "설치 프롬프트 닫기"
},
"login": {
"title": "웹메일",
"username_label": "이메일",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "Instalēt {appName}",
"description": "Instalējiet mūsu lietotni ātrai piekļuvei un bezsaistes atbalstam.",
"not_now": "Ne tagad",
"install": "Instalēt",
"dont_remind": "Vairs man neatgādināt",
"dismiss_aria": "Aizvērt instalēšanas paziņojumu"
},
"login": {
"title": "Tīmekļa pasts",
"username_label": "E-pasta adrese",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "{appName} installeren",
"description": "Installeer onze app voor snelle toegang en offline-ondersteuning.",
"not_now": "Niet nu",
"install": "Installeren",
"dont_remind": "Niet meer herinneren",
"dismiss_aria": "Installatiemelding sluiten"
},
"login": {
"title": "Webmail",
"username_label": "E-mail",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "Zainstaluj {appName}",
"description": "Zainstaluj naszą aplikację, aby uzyskać szybki dostęp i obsługę offline.",
"not_now": "Nie teraz",
"install": "Zainstaluj",
"dont_remind": "Nie przypominaj mi więcej",
"dismiss_aria": "Zamknij monit instalacji"
},
"login": {
"title": "Webmail",
"username_label": "E-mail",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "Instalar {appName}",
"description": "Instale o nosso app para acesso rápido e suporte offline.",
"not_now": "Agora não",
"install": "Instalar",
"dont_remind": "Não lembrar novamente",
"dismiss_aria": "Dispensar aviso de instalação"
},
"login": {
"title": "Webmail",
"username_label": "E-mail",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "Установить {appName}",
"description": "Установите наше приложение для быстрого доступа и работы офлайн.",
"not_now": "Не сейчас",
"install": "Установить",
"dont_remind": "Больше не напоминать",
"dismiss_aria": "Закрыть запрос на установку"
},
"login": {
"title": "Веб-почта",
"username_label": "Электронная почта",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "{appName} uygulamasını yükle",
"description": "Hızlı erişim ve çevrimdışı destek için uygulamamızı yükleyin.",
"not_now": "Şimdi değil",
"install": "Yükle",
"dont_remind": "Bir daha hatırlatma",
"dismiss_aria": "Yükleme istemini kapat"
},
"login": {
"title": "Webmail",
"username_label": "E-posta",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "Встановити {appName}",
"description": "Встановіть наш застосунок для швидкого доступу та офлайн-підтримки.",
"not_now": "Не зараз",
"install": "Встановити",
"dont_remind": "Більше не нагадувати",
"dismiss_aria": "Закрити запит на встановлення"
},
"login": {
"title": "Веб-пошта",
"username_label": "Електронна пошта",
+8
View File
@@ -1,4 +1,12 @@
{
"pwa_install": {
"title": "安装 {appName}",
"description": "安装我们的应用,以获得快速访问和离线支持。",
"not_now": "暂不",
"install": "安装",
"dont_remind": "不再提醒",
"dismiss_aria": "关闭安装提示"
},
"login": {
"title": "网页邮箱",
"username_label": "邮箱地址",