feat(theme): ship exactly 2 themes (SRC default + VNClagoon); rebrand user-facing VNCmail+

Product decision 2026-08-05: exactly SRC (default) and VNClagoon ship as
selectable themes. Everything else (Qui, Nord, Catppuccin, Solarized,
Roundcube Elastic, Aurora Glass) is hidden via ThemePolicy.disabledBuiltinThemes
rather than deleted - cheap to re-enable later, zero code lost. Also removed
the hardcoded "Default/Bulwark" theme card from the Settings > Themes grid
(product wants exactly 2 theme choices, not 3).

Separately, found and fixed real "still says Bulwark" branding gaps:
- All 24 locale files: "Bulwark"/"Bulwark Mail"/"Bulwark Webmail" ->
  "VNCmail+" in every user-facing string (verified via the translations
  test, which only checks structural key parity across locales, not
  content - a straight string swap is safe against it. 48/48 still pass).
- PWA manifest fallback app name, package.json description/author.
- Demo mode fixtures: the "Welcome to Bulwark Mail!" email and identity
  signature a first-time demo user actually sees.
- The demo empty-state's logo was hardcoded to a literal Bulwark SVG file
  regardless of active theme - a real bug, not just stale text, since
  lib/theme-logo.ts's resolveThemeLogo() already exists and is already used
  correctly by the login page and nav rail for exactly this (theme-aware
  SRC mark / VNClagoon wordmark). Wired the same helper in here instead of
  a hardcoded path.

NOT touched: internal code comments referencing "Bulwark" as historical/
attribution context (e.g. design-rationale comments explaining why a value
differs from Bulwark's original) - those are harmless and a full-repo sweep
of every comment wasn't the ask.

Verified: typecheck clean, lint clean, translations test 48/48 passing.
This commit is contained in:
Bernd Rodler
2026-08-05 23:43:19 +02:00
parent 3f99a2fc9e
commit bde9f14832
31 changed files with 416 additions and 404 deletions
+39 -39
View File
@@ -146,18 +146,18 @@
},
"protocol_handlers": {
"title": "Aplicacions predeterminades",
"description": "Trieu si els enllaços de correu i calendari s'obren al Bulwark. Tècnicament, el Bulwark es registra com a gestor de protocol per als enllaços mailto: i webcal:.",
"description": "Trieu si els enllaços de correu i calendari s'obren al VNCmail+. Tècnicament, el VNCmail+ es registra com a gestor de protocol per als enllaços mailto: i webcal:.",
"unsupported": "Aquest navegador o connexió no admet el registre manual de gestors de protocol. És possible que encara pugueu utilitzar la PWA instal·lada des de la configuració del navegador o del sistema operatiu.",
"mailto_label": "Enllaços de correu",
"mailto_description": "Obre els enllaços mailto: al Bulwark amb el redactor emplenat prèviament.",
"mailto_description": "Obre els enllaços mailto: al VNCmail+ amb el redactor emplenat prèviament.",
"protocol_open_mode_label": "En obrir enllaços de protocol",
"protocol_open_mode_description": "Trieu si el Bulwark obre els enllaços mailto: i webcal: en una pestanya nova o reutilitza una sessió oberta. L'opció de sessió activa necessita permís de notificacions perquè pugueu prémer una notificació alternativa per portar el Bulwark al davant si el navegador bloqueja el focus.",
"protocol_open_mode_description": "Trieu si el VNCmail+ obre els enllaços mailto: i webcal: en una pestanya nova o reutilitza una sessió oberta. L'opció de sessió activa necessita permís de notificacions perquè pugueu prémer una notificació alternativa per portar el VNCmail+ al davant si el navegador bloqueja el focus.",
"protocol_open_mode_active_session": "Obre en la sessió activa si és possible",
"protocol_open_mode_new_tab": "Obre sempre una pestanya nova",
"focus_notification_title": "Obre el Bulwark",
"focus_notification_body": "L'enllaç s'ha obert al Bulwark. Feu clic per portar la finestra al davant.",
"focus_notification_title": "Obre el VNCmail+",
"focus_notification_body": "L'enllaç s'ha obert al VNCmail+. Feu clic per portar la finestra al davant.",
"webcal_label": "Enllaços de calendari",
"webcal_description": "Obre els enllaços webcal: al Bulwark amb el diàleg de subscripció al calendari emplenat prèviament.",
"webcal_description": "Obre els enllaços webcal: al VNCmail+ amb el diàleg de subscripció al calendari emplenat prèviament.",
"register_mailto": "Registra com a aplicació de correu",
"register_webcal": "Registra com a aplicació de calendari",
"mailto_registered": "S'ha sol·licitat el registre del gestor de correu",
@@ -165,7 +165,7 @@
"registration_failed": "No s'ha pogut registrar el gestor de protocol",
"opening_mailto": "Obrint el redactor...",
"opening_webcal": "Obrint el calendari...",
"browser_note": "És possible que el navegador o el sistema operatiu us demani confirmar-ho, i que calgui tenir el Bulwark instal·lat per poder seleccionar-lo com a aplicació predeterminada.",
"browser_note": "És possible que el navegador o el sistema operatiu us demani confirmar-ho, i que calgui tenir el VNCmail+ instal·lat per poder seleccionar-lo com a aplicació predeterminada.",
"select_account_title": "Trieu un compte",
"select_mailto_account": "Trieu quin compte ha d'obrir aquest enllaç de correu.",
"select_webcal_account": "Trieu quin compte ha d'obrir aquest enllaç de calendari.",
@@ -738,9 +738,9 @@
"app_title": "Webmail",
"reconnecting": "S'ha perdut la connexió. S'està intentant reconnectar…",
"rate_limited_title": "L'autenticació al servidor està temporalment limitada.",
"rate_limited_detail": "El Bulwark ha aturat les sol·licituds en segon pla per evitar el bloqueig. Es tornarà a provar d'aquí a {seconds} s.",
"rate_limited_detail": "El VNCmail+ ha aturat les sol·licituds en segon pla per evitar el bloqueig. Es tornarà a provar d'aquí a {seconds} s.",
"rate_limited_action_title": "Sol·licitud aturada per evitar el bloqueig.",
"rate_limited_action_detail": "El Bulwark espera que acabi el temps d'espera del servidor abans d'enviar més sol·licituds autenticades. Torneu-ho a provar d'aquí a {seconds} s."
"rate_limited_action_detail": "El VNCmail+ espera que acabi el temps d'espera del servidor abans d'enviar més sol·licituds autenticades. Torneu-ho a provar d'aquí a {seconds} s."
},
"notifications": {
"email_sent": "Correu enviat correctament",
@@ -1052,9 +1052,9 @@
},
"push": {
"title": "Notificacions en segon pla",
"description": "Rebeu notificacions del sistema per al correu nou quan aquest lloc estigui tancat. S'entreguen mitjançant el repetidor push del Bulwark; el repetidor mai no veu el contingut del correu.",
"description": "Rebeu notificacions del sistema per al correu nou quan aquest lloc estigui tancat. S'entreguen mitjançant el repetidor push del VNCmail+; el repetidor mai no veu el contingut del correu.",
"relay_label": "Repetidor push",
"relay_desc": "Per defecte utilitza el repetidor allotjat del Bulwark. Canvieu-ho només si allotgeu el vostre propi servidor.",
"relay_desc": "Per defecte utilitza el repetidor allotjat del VNCmail+. Canvieu-ho només si allotgeu el vostre propi servidor.",
"relay_locked": "Establert per l'administrador",
"relay_locked_desc": "L'URL del repetidor push l'ha establert l'administrador i no es pot canviar.",
"relay_placeholder": "https://notifications.relay.example.com",
@@ -1535,10 +1535,10 @@
},
"link_device": {
"title": "Enllaça l'aplicació mòbil",
"description": "Inicieu la sessió a l'aplicació mòbil Bulwark Mail sense escriure res. Genereu un codi QR aquí i escanegeu-lo des de la pantalla d'inici de sessió de l'aplicació.",
"description": "Inicieu la sessió a l'aplicació mòbil VNCmail+ sense escriure res. Genereu un codi QR aquí i escanegeu-lo des de la pantalla d'inici de sessió de l'aplicació.",
"generate": "Mostra el codi QR",
"regenerate": "Mostra un codi nou",
"instructions": "Obriu l'aplicació Bulwark Mail, toqueu «Escaneja el codi QR» a la pantalla d'inici de sessió i apunteu la càmera aquí.",
"instructions": "Obriu l'aplicació VNCmail+, toqueu «Escaneja el codi QR» a la pantalla d'inici de sessió i apunteu la càmera aquí.",
"expires_in": "Aquest codi caduca d'aquí a {seconds} segons. Només es pot utilitzar una vegada.",
"expired": "Aquest codi ha caducat.",
"generating": "Generant…",
@@ -1650,34 +1650,34 @@
"error_role": "No s'ha pogut actualitzar el rol de la carpeta"
},
"advanced": {
"title": "Avan\u00e7at",
"description": "Opcions avan\u00e7ades i configuraci\u00f3 per a desenvolupadors",
"title": "Avançat",
"description": "Opcions avançades i configuració per a desenvolupadors",
"debug_mode": {
"label": "Mode de depuraci\u00f3",
"description": "Activa el registre detallat per a la resoluci\u00f3 de problemes"
"label": "Mode de depuració",
"description": "Activa el registre detallat per a la resolució de problemes"
},
"debug_categories": {
"description": "Seleccioneu quines categories registrar. Desactiveu les que no necessiteu per reduir el soroll a la consola.",
"jmap": "Client JMAP",
"jmap_description": "Operacions de b\u00fastia, obtenci\u00f3 de correus i sol\u00b7licituds del protocol JMAP",
"jmap_description": "Operacions de bústia, obtenció de correus i sol·licituds del protocol JMAP",
"calendar": "Calendari",
"calendar_description": "Esdeveniments del calendari, importacions i missatges de programaci\u00f3",
"calendar_description": "Esdeveniments del calendari, importacions i missatges de programació",
"tasks": "Tasques",
"tasks_description": "Creaci\u00f3, obtenci\u00f3 i actualitzaci\u00f3 de tasques del calendari",
"auth": "Autenticaci\u00f3",
"auth_description": "Inici de sessi\u00f3, TOTP, intercanvi de testimonis i gesti\u00f3 de sessions",
"tasks_description": "Creació, obtenció i actualització de tasques del calendari",
"auth": "Autenticació",
"auth_description": "Inici de sessió, TOTP, intercanvi de testimonis i gestió de sessions",
"filters": "Filtres",
"filters_description": "Regles de filtre Sieve i scripts de resposta autom\u00e0tica",
"email": "Visualitzaci\u00f3 de correu",
"email_description": "Renderitzaci\u00f3 de correu, processament TNEF i marcatge com a llegit",
"filters_description": "Regles de filtre Sieve i scripts de resposta automàtica",
"email": "Visualització de correu",
"email_description": "Renderització de correu, processament TNEF i marcatge com a llegit",
"push": "Notificacions push",
"push_description": "Configuraci\u00f3 i entrega de notificacions push",
"push_description": "Configuració i entrega de notificacions push",
"contacts": "Contactes i llibretes d'adreces",
"contacts_description": "Sincronitzaci\u00f3 de contactes, operacions de llibreta d'adreces i remitents de confian\u00e7a"
"contacts_description": "Sincronització de contactes, operacions de llibreta d'adreces i remitents de confiança"
},
"settings_sync": {
"label": "Sincronitzaci\u00f3 de la configuraci\u00f3",
"description": "Sincronitzeu la configuraci\u00f3 entre navegadors i dispositius"
"label": "Sincronització de la configuració",
"description": "Sincronitzeu la configuració entre navegadors i dispositius"
},
"sender_favicons": {
"label": "Icones dels remitents",
@@ -1685,7 +1685,7 @@
},
"show_avatars_in_junk": {
"label": "Mostra els avatars a la carpeta de brossa",
"description": "Mostra imatges de perfil i icones dels remitents a la carpeta de brossa. Desactivat per defecte per evitar donar aparen\u00e7a de legitimitat a intents de pesca electr\u00f2nica."
"description": "Mostra imatges de perfil i icones dels remitents a la carpeta de brossa. Desactivat per defecte per evitar donar aparença de legitimitat a intents de pesca electrònica."
},
"keyboard_shortcuts": {
"label": "Dreceres de teclat",
@@ -1694,26 +1694,26 @@
},
"refresh_cache": {
"label": "Actualitza les dades emmagatzemades",
"description": "Torna a carregar els contactes, els calendaris i les carpetes des del servidor. Mant\u00e9 els comptes i les sessions \u2014 soluciona una vista obsoleta o incorrecta sense tancar la sessi\u00f3.",
"description": "Torna a carregar els contactes, els calendaris i les carpetes des del servidor. Manté els comptes i les sessions soluciona una vista obsoleta o incorrecta sense tancar la sessió.",
"button": "Actualitza"
},
"reset_settings": {
"label": "Restableix la configuraci\u00f3",
"description": "Restaura tota la configuraci\u00f3 als valors per defecte",
"label": "Restableix la configuració",
"description": "Restaura tota la configuració als valors per defecte",
"button": "Restableix als valors per defecte"
},
"export_settings": {
"label": "Exporta la configuraci\u00f3",
"description": "Baixeu la configuraci\u00f3 en format JSON",
"label": "Exporta la configuració",
"description": "Baixeu la configuració en format JSON",
"button": "Exporta"
},
"import_settings": {
"label": "Importa la configuraci\u00f3",
"description": "Carregueu la configuraci\u00f3 des d'un fitxer JSON",
"label": "Importa la configuració",
"description": "Carregueu la configuració des d'un fitxer JSON",
"button": "Importa"
},
"about": {
"title": "Bulwark Webmail"
"title": "VNCmail+"
}
},
"sidebar_apps": {
@@ -3055,7 +3055,7 @@
"start_tour": "Comença la visita guiada"
},
"demo_welcome": {
"title": "Us donem la benvinguda al Bulwark Mail",
"title": "Us donem la benvinguda al VNCmail+",
"description": "Exploreu un client de correu web complet, directament al navegador. Totes les dades es queden al vostre dispositiu, així que proveu-ho tot sense cap problema.",
"feature_email": "Llegiu i redacteu correus",
"feature_organize": "Etiquetes, estrelles i carpetes",