diff --git a/console/src/app/modules/top-view/top-view.component.html b/console/src/app/modules/top-view/top-view.component.html
index 65e68dec7a..7ef4c27e1d 100644
--- a/console/src/app/modules/top-view/top-view.component.html
+++ b/console/src/app/modules/top-view/top-view.component.html
@@ -16,7 +16,7 @@
>
-
+
{{ sub }}
info_outline
diff --git a/console/src/app/modules/top-view/top-view.component.scss b/console/src/app/modules/top-view/top-view.component.scss
index a86282326f..4815cefef4 100644
--- a/console/src/app/modules/top-view/top-view.component.scss
+++ b/console/src/app/modules/top-view/top-view.component.scss
@@ -82,7 +82,7 @@
.cnsl-type {
font-size: 14px;
- margin-top: 2rem;
+ margin-top: 1.5rem;
margin-bottom: 1rem;
}
diff --git a/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.html b/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.html
index c04e428d05..17a41cce91 100644
--- a/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.html
+++ b/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.html
@@ -2,9 +2,7 @@
title="{{ project?.projectName }}"
[hasActions]="false"
docLink="https://zitadel.com/docs/guides/manage/console/projects#what-is-a-granted-project"
- sub="{{ 'PROJECT.PAGES.TYPE.GRANTED_SINGULAR' | translate }} {{ 'ACTIONS.OF' | translate }}
{{
- project?.projectOwnerName
- }}"
+ sub="{{ 'PROJECT.PAGES.TYPE.GRANTED_SINGULAR' | translate: { name: project?.projectOwnerName } }}"
[isActive]="project?.state === ProjectGrantState.PROJECT_GRANT_STATE_ACTIVE"
[isInactive]="project?.state === ProjectGrantState.PROJECT_GRANT_STATE_INACTIVE"
stateTooltip="{{ 'ORG.STATE.' + project?.state | translate }}"
diff --git a/console/src/assets/i18n/bg.json b/console/src/assets/i18n/bg.json
index 4a1131920a..8676366ce9 100644
--- a/console/src/assets/i18n/bg.json
+++ b/console/src/assets/i18n/bg.json
@@ -1770,7 +1770,7 @@
"TYPE": {
"OWNED": "Притежавани проекти",
"OWNED_SINGULAR": "Собствен проект",
- "GRANTED_SINGULAR": "Приет проект"
+ "GRANTED_SINGULAR": "Отпуснат проект на {{name}}"
},
"PRIVATELABEL": {
"0": {
diff --git a/console/src/assets/i18n/cs.json b/console/src/assets/i18n/cs.json
index f7b098c098..ecc2e6cb41 100644
--- a/console/src/assets/i18n/cs.json
+++ b/console/src/assets/i18n/cs.json
@@ -1778,7 +1778,7 @@
"TYPE": {
"OWNED": "Vlastní projekty",
"OWNED_SINGULAR": "Vlastní projekt",
- "GRANTED_SINGULAR": "Přidělený projekt"
+ "GRANTED_SINGULAR": "Projekt přidělený {{name}}"
},
"PRIVATELABEL": {
"TITLE": "Nastavení brandingu",
diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json
index 4c595773c4..7be455590a 100644
--- a/console/src/assets/i18n/de.json
+++ b/console/src/assets/i18n/de.json
@@ -1776,7 +1776,7 @@
"TYPE": {
"OWNED": "Eigene Projekte",
"OWNED_SINGULAR": "Eigenes Projekt",
- "GRANTED_SINGULAR": "Berechtigtes Projekt"
+ "GRANTED_SINGULAR": "Berechtigtes Projekt von {{name}}"
},
"PRIVATELABEL": {
"TITLE": "Branding Verhalten",
diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json
index 8a50cae2cf..46d24b5cd2 100644
--- a/console/src/assets/i18n/en.json
+++ b/console/src/assets/i18n/en.json
@@ -1777,7 +1777,7 @@
"TYPE": {
"OWNED": "Owned Projects",
"OWNED_SINGULAR": "Owned Project",
- "GRANTED_SINGULAR": "Granted Project"
+ "GRANTED_SINGULAR": "Granted Project of {{name}}"
},
"PRIVATELABEL": {
"TITLE": "Branding Setting",
diff --git a/console/src/assets/i18n/es.json b/console/src/assets/i18n/es.json
index d535f44252..1687c87e0f 100644
--- a/console/src/assets/i18n/es.json
+++ b/console/src/assets/i18n/es.json
@@ -1778,7 +1778,7 @@
"TYPE": {
"OWNED": "Proyectos propios",
"OWNED_SINGULAR": "Proyecto propio",
- "GRANTED_SINGULAR": "Proyecto concedido"
+ "GRANTED_SINGULAR": "Proyecto asignado {{name}}"
},
"PRIVATELABEL": {
"TITLE": "Ajustes de imagen de marca",
diff --git a/console/src/assets/i18n/fr.json b/console/src/assets/i18n/fr.json
index 110f0589d3..6245d6af01 100644
--- a/console/src/assets/i18n/fr.json
+++ b/console/src/assets/i18n/fr.json
@@ -1776,7 +1776,7 @@
"TYPE": {
"OWNED": "Projets possédés",
"OWNED_SINGULAR": "Projet possédé",
- "GRANTED_SINGULAR": "Projet octroyé"
+ "GRANTED_SINGULAR": "Projet attribué à {{name}}"
},
"PRIVATELABEL": {
"TITLE": "Image de marque",
diff --git a/console/src/assets/i18n/it.json b/console/src/assets/i18n/it.json
index 258635148e..768ad2b66c 100644
--- a/console/src/assets/i18n/it.json
+++ b/console/src/assets/i18n/it.json
@@ -1776,7 +1776,7 @@
"TYPE": {
"OWNED": "Progetti proprietari",
"OWNED_SINGULAR": "Progetto proprietario",
- "GRANTED_SINGULAR": "Progetto delegato"
+ "GRANTED_SINGULAR": "Progetto concesso di {{name}}"
},
"PRIVATELABEL": {
"TITLE": "Impostazione branding",
diff --git a/console/src/assets/i18n/ja.json b/console/src/assets/i18n/ja.json
index 30f1f8485c..857b0d71ad 100644
--- a/console/src/assets/i18n/ja.json
+++ b/console/src/assets/i18n/ja.json
@@ -1773,7 +1773,7 @@
"TYPE": {
"OWNED": "所有プロジェクト",
"OWNED_SINGULAR": "所有プロジェクト",
- "GRANTED_SINGULAR": "グラントされたプロジェクト"
+ "GRANTED_SINGULAR": "{{name}}に付与されたプロジェクト"
},
"PRIVATELABEL": {
"TITLE": "ブランディング設定",
diff --git a/console/src/assets/i18n/mk.json b/console/src/assets/i18n/mk.json
index 55f52bc24b..065625da90 100644
--- a/console/src/assets/i18n/mk.json
+++ b/console/src/assets/i18n/mk.json
@@ -1778,7 +1778,7 @@
"TYPE": {
"OWNED": "Сопствени проекти",
"OWNED_SINGULAR": "Сопствен проект",
- "GRANTED_SINGULAR": "Доделен проект"
+ "GRANTED_SINGULAR": "Проект доделен на {{name}}"
},
"PRIVATELABEL": {
"TITLE": "Подесувања за брендирање",
diff --git a/console/src/assets/i18n/nl.json b/console/src/assets/i18n/nl.json
index c2526c848d..9befa4746a 100644
--- a/console/src/assets/i18n/nl.json
+++ b/console/src/assets/i18n/nl.json
@@ -1777,7 +1777,7 @@
"TYPE": {
"OWNED": "Eigen Projecten",
"OWNED_SINGULAR": "Eigen Project",
- "GRANTED_SINGULAR": "Verleend Project"
+ "GRANTED_SINGULAR": "Project toegewezen {{name}}"
},
"PRIVATELABEL": {
"TITLE": "Branding Instelling",
diff --git a/console/src/assets/i18n/pl.json b/console/src/assets/i18n/pl.json
index 65e13ce71f..ba5337ab6a 100644
--- a/console/src/assets/i18n/pl.json
+++ b/console/src/assets/i18n/pl.json
@@ -1776,7 +1776,7 @@
"TYPE": {
"OWNED": "Własne Projekty",
"OWNED_SINGULAR": "Własny Projekt",
- "GRANTED_SINGULAR": "Udzielony Projekt"
+ "GRANTED_SINGULAR": "Projekt przydzielony {{name}}"
},
"PRIVATELABEL": {
"TITLE": "Ustawienia marka",
diff --git a/console/src/assets/i18n/pt.json b/console/src/assets/i18n/pt.json
index aee0da5a02..905c454aca 100644
--- a/console/src/assets/i18n/pt.json
+++ b/console/src/assets/i18n/pt.json
@@ -1776,7 +1776,7 @@
"TYPE": {
"OWNED": "Projetos Próprios",
"OWNED_SINGULAR": "Projeto Próprio",
- "GRANTED_SINGULAR": "Projeto Concedido"
+ "GRANTED_SINGULAR": "Projeto atribuído a {{name}}"
},
"PRIVATELABEL": {
"TITLE": "Configuração de Marca",
diff --git a/console/src/assets/i18n/ru.json b/console/src/assets/i18n/ru.json
index 294039adc9..894a5d4c6a 100644
--- a/console/src/assets/i18n/ru.json
+++ b/console/src/assets/i18n/ru.json
@@ -1858,9 +1858,8 @@
"ZITADELPROJECT": "Это принадлежит проекту ZITADEL. Осторожно: Если вы внесёте изменения, ZITADEL может вести себя не так, как предполагалось.",
"TYPE": {
"OWNED": "Собственные проекты",
- "GRANTED": "Проекты доступа",
"OWNED_SINGULAR": "Собственный проект",
- "GRANTED_SINGULAR": "Допуск проекта"
+ "GRANTED_SINGULAR": "Проект, предоставленный {{name}}"
},
"PRIVATELABEL": {
"TITLE": "Настройка брендинга",
diff --git a/console/src/assets/i18n/zh.json b/console/src/assets/i18n/zh.json
index c8b2baa0a1..3ffe728ae2 100644
--- a/console/src/assets/i18n/zh.json
+++ b/console/src/assets/i18n/zh.json
@@ -1775,7 +1775,7 @@
"TYPE": {
"OWNED": "拥有的项目",
"OWNED_SINGULAR": "拥有项目",
- "GRANTED_SINGULAR": "被授予的项目"
+ "GRANTED_SINGULAR": "授予{{name}}的项目"
},
"PRIVATELABEL": {
"TITLE": "品牌标识设置",
diff --git a/internal/notification/templates/templateData.go b/internal/notification/templates/templateData.go
index f9572a4c5d..8ff750da53 100644
--- a/internal/notification/templates/templateData.go
+++ b/internal/notification/templates/templateData.go
@@ -2,7 +2,6 @@ package templates
import (
"fmt"
- "html"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/i18n"
@@ -40,7 +39,7 @@ func (data *TemplateData) Translate(translator *i18n.Translator, msgType string,
data.PreHeader = translator.Localize(fmt.Sprintf("%s.%s", msgType, domain.MessagePreHeader), args, langs...)
data.Subject = translator.Localize(fmt.Sprintf("%s.%s", msgType, domain.MessageSubject), args, langs...)
data.Greeting = translator.Localize(fmt.Sprintf("%s.%s", msgType, domain.MessageGreeting), args, langs...)
- data.Text = html.UnescapeString(translator.Localize(fmt.Sprintf("%s.%s", msgType, domain.MessageText), args, langs...))
+ data.Text = translator.Localize(fmt.Sprintf("%s.%s", msgType, domain.MessageText), args, langs...)
data.ButtonText = translator.Localize(fmt.Sprintf("%s.%s", msgType, domain.MessageButtonText), args, langs...)
// Footer text is neither included in i18n files nor defaults.yaml
footerText := fmt.Sprintf("%s.%s", msgType, domain.MessageFooterText)
diff --git a/internal/notification/types/notification.go b/internal/notification/types/notification.go
index 1a5ccebb21..9bbfb66c8f 100644
--- a/internal/notification/types/notification.go
+++ b/internal/notification/types/notification.go
@@ -2,7 +2,9 @@ package types
import (
"context"
+ "html"
+ "github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/i18n"
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
@@ -42,6 +44,7 @@ func SendEmail(
allowUnverifiedNotificationChannel bool,
) error {
args = mapNotifyUserToArgs(user, args)
+ sanitizeArgsForHTML(args)
data := GetTemplateData(ctx, translator, args, url, messageType, user.PreferredLanguage.String(), colors)
template, err := templates.GetParsedTemplate(mailhtml, data)
if err != nil {
@@ -59,6 +62,23 @@ func SendEmail(
}
}
+func sanitizeArgsForHTML(args map[string]any) {
+ for key, arg := range args {
+ switch a := arg.(type) {
+ case string:
+ args[key] = html.EscapeString(a)
+ case []string:
+ for i, s := range a {
+ a[i] = html.EscapeString(s)
+ }
+ case database.TextArray[string]:
+ for i, s := range a {
+ a[i] = html.EscapeString(s)
+ }
+ }
+ }
+}
+
func SendSMSTwilio(
ctx context.Context,
channels ChannelChains,