mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	Backport #27856 The only conflict is `ThemeName` in `500.tmpl`, it has been resolved manually by keeping using old `{{.SignedUser.Theme}}{{else}}{{DefaultTheme}}`
This commit is contained in:
		| @@ -157,7 +157,6 @@ func Contexter() func(next http.Handler) http.Handler { | |||||||
| 			ctx.Data["Context"] = ctx // TODO: use "ctx" in template and remove this | 			ctx.Data["Context"] = ctx // TODO: use "ctx" in template and remove this | ||||||
| 			ctx.Data["CurrentURL"] = setting.AppSubURL + req.URL.RequestURI() | 			ctx.Data["CurrentURL"] = setting.AppSubURL + req.URL.RequestURI() | ||||||
| 			ctx.Data["Link"] = ctx.Link | 			ctx.Data["Link"] = ctx.Link | ||||||
| 			ctx.Data["locale"] = ctx.Locale |  | ||||||
|  |  | ||||||
| 			// PageData is passed by reference, and it will be rendered to `window.config.pageData` in `head.tmpl` for JavaScript modules | 			// PageData is passed by reference, and it will be rendered to `window.config.pageData` in `head.tmpl` for JavaScript modules | ||||||
| 			ctx.PageData = map[string]any{} | 			ctx.PageData = map[string]any{} | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ import ( | |||||||
|  |  | ||||||
| 	user_model "code.gitea.io/gitea/models/user" | 	user_model "code.gitea.io/gitea/models/user" | ||||||
| 	"code.gitea.io/gitea/modules/base" | 	"code.gitea.io/gitea/modules/base" | ||||||
|  | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	"code.gitea.io/gitea/modules/httpcache" | 	"code.gitea.io/gitea/modules/httpcache" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| @@ -35,20 +36,18 @@ func RenderPanicErrorPage(w http.ResponseWriter, req *http.Request, err any) { | |||||||
| 	httpcache.SetCacheControlInHeader(w.Header(), 0, "no-transform") | 	httpcache.SetCacheControlInHeader(w.Header(), 0, "no-transform") | ||||||
| 	w.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions) | 	w.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions) | ||||||
|  |  | ||||||
| 	data := middleware.GetContextData(req.Context()) | 	tmplCtx := context.TemplateContext{} | ||||||
| 	if data["locale"] == nil { | 	tmplCtx["Locale"] = middleware.Locale(w, req) | ||||||
| 		data = middleware.CommonTemplateContextData() | 	ctxData := middleware.GetContextData(req.Context()) | ||||||
| 		data["locale"] = middleware.Locale(w, req) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// This recovery handler could be called without Gitea's web context, so we shouldn't touch that context too much. | 	// This recovery handler could be called without Gitea's web context, so we shouldn't touch that context too much. | ||||||
| 	// Otherwise, the 500-page may cause new panics, eg: cache.GetContextWithData, it makes the developer&users couldn't find the original panic. | 	// Otherwise, the 500-page may cause new panics, eg: cache.GetContextWithData, it makes the developer&users couldn't find the original panic. | ||||||
| 	user, _ := data[middleware.ContextDataKeySignedUser].(*user_model.User) | 	user, _ := ctxData[middleware.ContextDataKeySignedUser].(*user_model.User) | ||||||
| 	if !setting.IsProd || (user != nil && user.IsAdmin) { | 	if !setting.IsProd || (user != nil && user.IsAdmin) { | ||||||
| 		data["ErrorMsg"] = "PANIC: " + combinedErr | 		ctxData["ErrorMsg"] = "PANIC: " + combinedErr | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	err = templates.HTMLRenderer().HTML(w, http.StatusInternalServerError, string(tplStatus500), data, nil) | 	err = templates.HTMLRenderer().HTML(w, http.StatusInternalServerError, string(tplStatus500), ctxData, tmplCtx) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Error("Error occurs again when rendering error page: %v", err) | 		log.Error("Error occurs again when rendering error page: %v", err) | ||||||
| 		w.WriteHeader(http.StatusInternalServerError) | 		w.WriteHeader(http.StatusInternalServerError) | ||||||
|   | |||||||
| @@ -27,6 +27,7 @@ func TestRenderPanicErrorPage(t *testing.T) { | |||||||
| 	respContent := w.Body.String() | 	respContent := w.Body.String() | ||||||
| 	assert.Contains(t, respContent, `class="page-content status-page-500"`) | 	assert.Contains(t, respContent, `class="page-content status-page-500"`) | ||||||
| 	assert.Contains(t, respContent, `</html>`) | 	assert.Contains(t, respContent, `</html>`) | ||||||
|  | 	assert.Contains(t, respContent, `lang="en-US"`) // make sure the locale work | ||||||
|  |  | ||||||
| 	// the 500 page doesn't have normal pages footer, it makes it easier to distinguish a normal page and a failed page. | 	// the 500 page doesn't have normal pages footer, it makes it easier to distinguish a normal page and a failed page. | ||||||
| 	// especially when a sub-template causes page error, the HTTP response code is still 200, | 	// especially when a sub-template causes page error, the HTTP response code is still 200, | ||||||
|   | |||||||
| @@ -26,7 +26,6 @@ import ( | |||||||
| 	"code.gitea.io/gitea/modules/markup" | 	"code.gitea.io/gitea/modules/markup" | ||||||
| 	"code.gitea.io/gitea/modules/markup/markdown" | 	"code.gitea.io/gitea/modules/markup/markdown" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	"code.gitea.io/gitea/modules/templates" |  | ||||||
| 	"code.gitea.io/gitea/modules/timeutil" | 	"code.gitea.io/gitea/modules/timeutil" | ||||||
| 	"code.gitea.io/gitea/modules/translation" | 	"code.gitea.io/gitea/modules/translation" | ||||||
| 	incoming_payload "code.gitea.io/gitea/services/mailer/incoming/payload" | 	incoming_payload "code.gitea.io/gitea/services/mailer/incoming/payload" | ||||||
| @@ -68,15 +67,12 @@ func SendTestMail(email string) error { | |||||||
| func sendUserMail(language string, u *user_model.User, tpl base.TplName, code, subject, info string) { | func sendUserMail(language string, u *user_model.User, tpl base.TplName, code, subject, info string) { | ||||||
| 	locale := translation.NewLocale(language) | 	locale := translation.NewLocale(language) | ||||||
| 	data := map[string]any{ | 	data := map[string]any{ | ||||||
|  | 		"locale":            locale, | ||||||
| 		"DisplayName":       u.DisplayName(), | 		"DisplayName":       u.DisplayName(), | ||||||
| 		"ActiveCodeLives":   timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, locale), | 		"ActiveCodeLives":   timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, locale), | ||||||
| 		"ResetPwdCodeLives": timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, locale), | 		"ResetPwdCodeLives": timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, locale), | ||||||
| 		"Code":              code, | 		"Code":              code, | ||||||
| 		"Language":          locale.Language(), | 		"Language":          locale.Language(), | ||||||
| 		// helper |  | ||||||
| 		"locale":    locale, |  | ||||||
| 		"Str2html":  templates.Str2html, |  | ||||||
| 		"DotEscape": templates.DotEscape, |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var content bytes.Buffer | 	var content bytes.Buffer | ||||||
| @@ -119,15 +115,12 @@ func SendActivateEmailMail(u *user_model.User, email *user_model.EmailAddress) { | |||||||
| 	} | 	} | ||||||
| 	locale := translation.NewLocale(u.Language) | 	locale := translation.NewLocale(u.Language) | ||||||
| 	data := map[string]any{ | 	data := map[string]any{ | ||||||
|  | 		"locale":          locale, | ||||||
| 		"DisplayName":     u.DisplayName(), | 		"DisplayName":     u.DisplayName(), | ||||||
| 		"ActiveCodeLives": timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, locale), | 		"ActiveCodeLives": timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, locale), | ||||||
| 		"Code":            u.GenerateEmailActivateCode(email.Email), | 		"Code":            u.GenerateEmailActivateCode(email.Email), | ||||||
| 		"Email":           email.Email, | 		"Email":           email.Email, | ||||||
| 		"Language":        locale.Language(), | 		"Language":        locale.Language(), | ||||||
| 		// helper |  | ||||||
| 		"locale":    locale, |  | ||||||
| 		"Str2html":  templates.Str2html, |  | ||||||
| 		"DotEscape": templates.DotEscape, |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var content bytes.Buffer | 	var content bytes.Buffer | ||||||
| @@ -152,13 +145,10 @@ func SendRegisterNotifyMail(u *user_model.User) { | |||||||
| 	locale := translation.NewLocale(u.Language) | 	locale := translation.NewLocale(u.Language) | ||||||
|  |  | ||||||
| 	data := map[string]any{ | 	data := map[string]any{ | ||||||
|  | 		"locale":      locale, | ||||||
| 		"DisplayName": u.DisplayName(), | 		"DisplayName": u.DisplayName(), | ||||||
| 		"Username":    u.Name, | 		"Username":    u.Name, | ||||||
| 		"Language":    locale.Language(), | 		"Language":    locale.Language(), | ||||||
| 		// helper |  | ||||||
| 		"locale":    locale, |  | ||||||
| 		"Str2html":  templates.Str2html, |  | ||||||
| 		"DotEscape": templates.DotEscape, |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var content bytes.Buffer | 	var content bytes.Buffer | ||||||
| @@ -185,14 +175,11 @@ func SendCollaboratorMail(u, doer *user_model.User, repo *repo_model.Repository) | |||||||
|  |  | ||||||
| 	subject := locale.Tr("mail.repo.collaborator.added.subject", doer.DisplayName(), repoName) | 	subject := locale.Tr("mail.repo.collaborator.added.subject", doer.DisplayName(), repoName) | ||||||
| 	data := map[string]any{ | 	data := map[string]any{ | ||||||
|  | 		"locale":   locale, | ||||||
| 		"Subject":  subject, | 		"Subject":  subject, | ||||||
| 		"RepoName": repoName, | 		"RepoName": repoName, | ||||||
| 		"Link":     repo.HTMLURL(), | 		"Link":     repo.HTMLURL(), | ||||||
| 		"Language": locale.Language(), | 		"Language": locale.Language(), | ||||||
| 		// helper |  | ||||||
| 		"locale":    locale, |  | ||||||
| 		"Str2html":  templates.Str2html, |  | ||||||
| 		"DotEscape": templates.DotEscape, |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var content bytes.Buffer | 	var content bytes.Buffer | ||||||
| @@ -259,6 +246,7 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient | |||||||
| 	locale := translation.NewLocale(lang) | 	locale := translation.NewLocale(lang) | ||||||
|  |  | ||||||
| 	mailMeta := map[string]any{ | 	mailMeta := map[string]any{ | ||||||
|  | 		"locale":          locale, | ||||||
| 		"FallbackSubject": fallback, | 		"FallbackSubject": fallback, | ||||||
| 		"Body":            body, | 		"Body":            body, | ||||||
| 		"Link":            link, | 		"Link":            link, | ||||||
| @@ -275,10 +263,6 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient | |||||||
| 		"ReviewComments":  reviewComments, | 		"ReviewComments":  reviewComments, | ||||||
| 		"Language":        locale.Language(), | 		"Language":        locale.Language(), | ||||||
| 		"CanReply":        setting.IncomingEmail.Enabled && commentType != issues_model.CommentTypePullRequestPush, | 		"CanReply":        setting.IncomingEmail.Enabled && commentType != issues_model.CommentTypePullRequestPush, | ||||||
| 		// helper |  | ||||||
| 		"locale":    locale, |  | ||||||
| 		"Str2html":  templates.Str2html, |  | ||||||
| 		"DotEscape": templates.DotEscape, |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var mailSubject bytes.Buffer | 	var mailSubject bytes.Buffer | ||||||
| @@ -469,7 +453,7 @@ func SendIssueAssignedMail(ctx context.Context, issue *issues_model.Issue, doer | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		SendAsyncs(msgs) | 		SendAsync(msgs...) | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -162,7 +162,7 @@ func mailIssueCommentBatch(ctx *mailCommentContext, users []*user_model.User, vi | |||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| 			SendAsyncs(msgs) | 			SendAsync(msgs...) | ||||||
| 			receivers = receivers[:i] | 			receivers = receivers[:i] | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -14,7 +14,6 @@ import ( | |||||||
| 	"code.gitea.io/gitea/modules/markup" | 	"code.gitea.io/gitea/modules/markup" | ||||||
| 	"code.gitea.io/gitea/modules/markup/markdown" | 	"code.gitea.io/gitea/modules/markup/markdown" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	"code.gitea.io/gitea/modules/templates" |  | ||||||
| 	"code.gitea.io/gitea/modules/translation" | 	"code.gitea.io/gitea/modules/translation" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -69,13 +68,10 @@ func mailNewRelease(ctx context.Context, lang string, tos []string, rel *repo_mo | |||||||
|  |  | ||||||
| 	subject := locale.Tr("mail.release.new.subject", rel.TagName, rel.Repo.FullName()) | 	subject := locale.Tr("mail.release.new.subject", rel.TagName, rel.Repo.FullName()) | ||||||
| 	mailMeta := map[string]any{ | 	mailMeta := map[string]any{ | ||||||
|  | 		"locale":   locale, | ||||||
| 		"Release":  rel, | 		"Release":  rel, | ||||||
| 		"Subject":  subject, | 		"Subject":  subject, | ||||||
| 		"Language": locale.Language(), | 		"Language": locale.Language(), | ||||||
| 		// helper |  | ||||||
| 		"locale":    locale, |  | ||||||
| 		"Str2html":  templates.Str2html, |  | ||||||
| 		"DotEscape": templates.DotEscape, |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var mailBody bytes.Buffer | 	var mailBody bytes.Buffer | ||||||
| @@ -95,5 +91,5 @@ func mailNewRelease(ctx context.Context, lang string, tos []string, rel *repo_mo | |||||||
| 		msgs = append(msgs, msg) | 		msgs = append(msgs, msg) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	SendAsyncs(msgs) | 	SendAsync(msgs...) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -12,7 +12,6 @@ import ( | |||||||
| 	repo_model "code.gitea.io/gitea/models/repo" | 	repo_model "code.gitea.io/gitea/models/repo" | ||||||
| 	user_model "code.gitea.io/gitea/models/user" | 	user_model "code.gitea.io/gitea/models/user" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	"code.gitea.io/gitea/modules/templates" |  | ||||||
| 	"code.gitea.io/gitea/modules/translation" | 	"code.gitea.io/gitea/modules/translation" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -65,6 +64,7 @@ func sendRepoTransferNotifyMailPerLang(lang string, newOwner, doer *user_model.U | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	data := map[string]any{ | 	data := map[string]any{ | ||||||
|  | 		"locale":      locale, | ||||||
| 		"Doer":        doer, | 		"Doer":        doer, | ||||||
| 		"User":        repo.Owner, | 		"User":        repo.Owner, | ||||||
| 		"Repo":        repo.FullName(), | 		"Repo":        repo.FullName(), | ||||||
| @@ -72,10 +72,6 @@ func sendRepoTransferNotifyMailPerLang(lang string, newOwner, doer *user_model.U | |||||||
| 		"Subject":     subject, | 		"Subject":     subject, | ||||||
| 		"Language":    locale.Language(), | 		"Language":    locale.Language(), | ||||||
| 		"Destination": destination, | 		"Destination": destination, | ||||||
| 		// helper |  | ||||||
| 		"locale":    locale, |  | ||||||
| 		"Str2html":  templates.Str2html, |  | ||||||
| 		"DotEscape": templates.DotEscape, |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := bodyTemplates.ExecuteTemplate(&content, string(mailRepoTransferNotify), data); err != nil { | 	if err := bodyTemplates.ExecuteTemplate(&content, string(mailRepoTransferNotify), data); err != nil { | ||||||
|   | |||||||
| @@ -14,7 +14,6 @@ import ( | |||||||
| 	"code.gitea.io/gitea/modules/base" | 	"code.gitea.io/gitea/modules/base" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	"code.gitea.io/gitea/modules/templates" |  | ||||||
| 	"code.gitea.io/gitea/modules/translation" | 	"code.gitea.io/gitea/modules/translation" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -53,16 +52,13 @@ func MailTeamInvite(ctx context.Context, inviter *user_model.User, team *org_mod | |||||||
|  |  | ||||||
| 	subject := locale.Tr("mail.team_invite.subject", inviter.DisplayName(), org.DisplayName()) | 	subject := locale.Tr("mail.team_invite.subject", inviter.DisplayName(), org.DisplayName()) | ||||||
| 	mailMeta := map[string]any{ | 	mailMeta := map[string]any{ | ||||||
|  | 		"locale":       locale, | ||||||
| 		"Inviter":      inviter, | 		"Inviter":      inviter, | ||||||
| 		"Organization": org, | 		"Organization": org, | ||||||
| 		"Team":         team, | 		"Team":         team, | ||||||
| 		"Invite":       invite, | 		"Invite":       invite, | ||||||
| 		"Subject":      subject, | 		"Subject":      subject, | ||||||
| 		"InviteURL":    inviteURL, | 		"InviteURL":    inviteURL, | ||||||
| 		// helper |  | ||||||
| 		"locale":    locale, |  | ||||||
| 		"Str2html":  templates.Str2html, |  | ||||||
| 		"DotEscape": templates.DotEscape, |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var mailBody bytes.Buffer | 	var mailBody bytes.Buffer | ||||||
|   | |||||||
| @@ -426,15 +426,12 @@ func NewContext(ctx context.Context) { | |||||||
| 	go graceful.GetManager().RunWithCancel(mailQueue) | 	go graceful.GetManager().RunWithCancel(mailQueue) | ||||||
| } | } | ||||||
|  |  | ||||||
| // SendAsync send mail asynchronously | // SendAsync send emails asynchronously (make it mockable) | ||||||
| func SendAsync(msg *Message) { | var SendAsync = sendAsync | ||||||
| 	SendAsyncs([]*Message{msg}) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // SendAsyncs send mails asynchronously | func sendAsync(msgs ...*Message) { | ||||||
| func SendAsyncs(msgs []*Message) { |  | ||||||
| 	if setting.MailService == nil { | 	if setting.MailService == nil { | ||||||
| 		log.Error("Mailer: SendAsyncs is being invoked but mail service hasn't been initialized") | 		log.Error("Mailer: SendAsync is being invoked but mail service hasn't been initialized") | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| {{/* This page should only depend the minimal template functions/variables, to avoid triggering new panics. | {{/* This page should only depend the minimal template functions/variables, to avoid triggering new panics. | ||||||
| * base template functions: AppName, AssetUrlPrefix, AssetVersion, AppSubUrl, DefaultTheme, Str2html | * base template functions: AppName, AssetUrlPrefix, AssetVersion, AppSubUrl, DefaultTheme, Str2html | ||||||
| * locale | * ctx.Locale | ||||||
| * Flash | * .Flash | ||||||
| * ErrorMsg | * .ErrorMsg | ||||||
| * SignedUser (optional) | * .SignedUser (optional) | ||||||
| */}} | */}} | ||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html lang="{{.locale.Lang}}" class="theme-{{if .SignedUser.Theme}}{{.SignedUser.Theme}}{{else}}{{DefaultTheme}}{{end}}"> | <html lang="{{ctx.Locale.Lang}}" class="theme-{{if .SignedUser.Theme}}{{.SignedUser.Theme}}{{else}}{{DefaultTheme}}{{end}}"> | ||||||
| <head> | <head> | ||||||
| 	<meta name="viewport" content="width=device-width, initial-scale=1"> | 	<meta name="viewport" content="width=device-width, initial-scale=1"> | ||||||
| 	<title>Internal Server Error - {{AppName}}</title> | 	<title>Internal Server Error - {{AppName}}</title> | ||||||
| @@ -19,8 +19,8 @@ | |||||||
| 		<nav class="ui secondary menu gt-border-secondary-bottom"> | 		<nav class="ui secondary menu gt-border-secondary-bottom"> | ||||||
| 			<div class="ui container gt-df"> | 			<div class="ui container gt-df"> | ||||||
| 				<div class="item gt-f1"> | 				<div class="item gt-f1"> | ||||||
| 					<a href="{{AppSubUrl}}/" aria-label="{{.locale.Tr "home"}}"> | 					<a href="{{AppSubUrl}}/" aria-label="{{ctx.Locale.Tr "home"}}"> | ||||||
| 						<img width="30" height="30" src="{{AssetUrlPrefix}}/img/logo.svg" alt="{{.locale.Tr "logo"}}" aria-hidden="true"> | 						<img width="30" height="30" src="{{AssetUrlPrefix}}/img/logo.svg" alt="{{ctx.Locale.Tr "logo"}}" aria-hidden="true"> | ||||||
| 					</a> | 					</a> | ||||||
| 				</div> | 				</div> | ||||||
| 				<div class="item"> | 				<div class="item"> | ||||||
| @@ -37,12 +37,12 @@ | |||||||
| 			<div class="divider"></div> | 			<div class="divider"></div> | ||||||
| 			<div class="ui container gt-my-5"> | 			<div class="ui container gt-my-5"> | ||||||
| 				{{if .ErrorMsg}} | 				{{if .ErrorMsg}} | ||||||
| 					<p>{{.locale.Tr "error.occurred"}}:</p> | 					<p>{{ctx.Locale.Tr "error.occurred"}}:</p> | ||||||
| 					<pre class="gt-whitespace-pre-wrap gt-break-all">{{.ErrorMsg}}</pre> | 					<pre class="gt-whitespace-pre-wrap gt-break-all">{{.ErrorMsg}}</pre> | ||||||
| 				{{end}} | 				{{end}} | ||||||
| 				<div class="center gt-mt-5"> | 				<div class="center gt-mt-5"> | ||||||
| 					{{if or .SignedUser.IsAdmin .ShowFooterVersion}}<p>{{.locale.Tr "admin.config.app_ver"}}: {{AppVer}}</p>{{end}} | 					{{if or .SignedUser.IsAdmin .ShowFooterVersion}}<p>{{ctx.Locale.Tr "admin.config.app_ver"}}: {{AppVer}}</p>{{end}} | ||||||
| 					{{if .SignedUser.IsAdmin}}<p>{{.locale.Tr "error.report_message" | Str2html}}</p>{{end}} | 					{{if .SignedUser.IsAdmin}}<p>{{ctx.Locale.Tr "error.report_message" | Str2html}}</p>{{end}} | ||||||
| 				</div> | 				</div> | ||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 wxiaoguang
					wxiaoguang