@@ -22,6 +22,7 @@ import (
2222 "code.gitea.io/gitea/modules/markup/markdown"
2323 "code.gitea.io/gitea/modules/setting"
2424 "code.gitea.io/gitea/modules/timeutil"
25+ "code.gitea.io/gitea/modules/translation"
2526
2627 "gopkg.in/gomail.v2"
2728)
@@ -57,17 +58,21 @@ func SendTestMail(email string) error {
5758 return gomail .Send (Sender , NewMessage ([]string {email }, "Gitea Test Email!" , "Gitea Test Email!" ).ToMessage ())
5859}
5960
60- // SendUserMail sends a mail to the user
61- func SendUserMail (language string , u * models.User , tpl base.TplName , code , subject , info string ) {
61+ // sendUserMail sends a mail to the user
62+ func sendUserMail (language string , u * models.User , tpl base.TplName , code , subject , info string ) {
63+ locale := translation .NewLocale (language )
6264 data := map [string ]interface {}{
6365 "DisplayName" : u .DisplayName (),
6466 "ActiveCodeLives" : timeutil .MinutesToFriendly (setting .Service .ActiveCodeLives , language ),
6567 "ResetPwdCodeLives" : timeutil .MinutesToFriendly (setting .Service .ResetPwdCodeLives , language ),
6668 "Code" : code ,
69+ "i18n" : locale ,
70+ "Language" : locale .Language (),
6771 }
6872
6973 var content bytes.Buffer
7074
75+ // TODO: i18n templates?
7176 if err := bodyTemplates .ExecuteTemplate (& content , string (tpl ), data ); err != nil {
7277 log .Error ("Template: %v" , err )
7378 return
@@ -79,33 +84,32 @@ func SendUserMail(language string, u *models.User, tpl base.TplName, code, subje
7984 SendAsync (msg )
8085}
8186
82- // Locale represents an interface to translation
83- type Locale interface {
84- Language () string
85- Tr (string , ... interface {}) string
86- }
87-
8887// SendActivateAccountMail sends an activation mail to the user (new user registration)
89- func SendActivateAccountMail (locale Locale , u * models.User ) {
90- SendUserMail (locale .Language (), u , mailAuthActivate , u .GenerateActivateCode ( ), locale .Tr ("mail.activate_account" ), "activate account" )
88+ func SendActivateAccountMail (locale translation. Locale , u * models.User ) {
89+ sendUserMail (locale .Language (), u , mailAuthActivate , u .GenerateEmailActivateCode ( u . Email ), locale .Tr ("mail.activate_account" ), "activate account" )
9190}
9291
9392// SendResetPasswordMail sends a password reset mail to the user
94- func SendResetPasswordMail (locale Locale , u * models.User ) {
95- SendUserMail (locale .Language (), u , mailAuthResetPassword , u .GenerateActivateCode (), locale .Tr ("mail.reset_password" ), "recover account" )
93+ func SendResetPasswordMail (u * models.User ) {
94+ locale := translation .NewLocale (u .Language )
95+ sendUserMail (u .Language , u , mailAuthResetPassword , u .GenerateEmailActivateCode (u .Email ), locale .Tr ("mail.reset_password" ), "recover account" )
9696}
9797
9898// SendActivateEmailMail sends confirmation email to confirm new email address
99- func SendActivateEmailMail (locale Locale , u * models.User , email * models.EmailAddress ) {
99+ func SendActivateEmailMail (u * models.User , email * models.EmailAddress ) {
100+ locale := translation .NewLocale (u .Language )
100101 data := map [string ]interface {}{
101102 "DisplayName" : u .DisplayName (),
102103 "ActiveCodeLives" : timeutil .MinutesToFriendly (setting .Service .ActiveCodeLives , locale .Language ()),
103104 "Code" : u .GenerateEmailActivateCode (email .Email ),
104105 "Email" : email .Email ,
106+ "i18n" : locale ,
107+ "Language" : locale .Language (),
105108 }
106109
107110 var content bytes.Buffer
108111
112+ // TODO: i18n templates?
109113 if err := bodyTemplates .ExecuteTemplate (& content , string (mailAuthActivateEmail ), data ); err != nil {
110114 log .Error ("Template: %v" , err )
111115 return
@@ -118,19 +122,19 @@ func SendActivateEmailMail(locale Locale, u *models.User, email *models.EmailAdd
118122}
119123
120124// SendRegisterNotifyMail triggers a notify e-mail by admin created a account.
121- func SendRegisterNotifyMail (locale Locale , u * models.User ) {
122- if setting .MailService == nil {
123- log .Warn ("SendRegisterNotifyMail is being invoked but mail service hasn't been initialized" )
124- return
125- }
125+ func SendRegisterNotifyMail (u * models.User ) {
126+ locale := translation .NewLocale (u .Language )
126127
127128 data := map [string ]interface {}{
128129 "DisplayName" : u .DisplayName (),
129130 "Username" : u .Name ,
131+ "i18n" : locale ,
132+ "Language" : locale .Language (),
130133 }
131134
132135 var content bytes.Buffer
133136
137+ // TODO: i18n templates?
134138 if err := bodyTemplates .ExecuteTemplate (& content , string (mailAuthRegisterNotify ), data ); err != nil {
135139 log .Error ("Template: %v" , err )
136140 return
@@ -144,17 +148,21 @@ func SendRegisterNotifyMail(locale Locale, u *models.User) {
144148
145149// SendCollaboratorMail sends mail notification to new collaborator.
146150func SendCollaboratorMail (u , doer * models.User , repo * models.Repository ) {
151+ locale := translation .NewLocale (u .Language )
147152 repoName := repo .FullName ()
148- subject := fmt .Sprintf ("%s added you to %s" , doer .DisplayName (), repoName )
149153
154+ subject := locale .Tr ("mail.repo.collaborator.added.subject" , doer .DisplayName (), repoName )
150155 data := map [string ]interface {}{
151156 "Subject" : subject ,
152157 "RepoName" : repoName ,
153158 "Link" : repo .HTMLURL (),
159+ "i18n" : locale ,
160+ "Language" : locale .Language (),
154161 }
155162
156163 var content bytes.Buffer
157164
165+ // TODO: i18n templates?
158166 if err := bodyTemplates .ExecuteTemplate (& content , string (mailNotifyCollaborator ), data ); err != nil {
159167 log .Error ("Template: %v" , err )
160168 return
@@ -166,7 +174,7 @@ func SendCollaboratorMail(u, doer *models.User, repo *models.Repository) {
166174 SendAsync (msg )
167175}
168176
169- func composeIssueCommentMessages (ctx * mailCommentContext , tos []string , fromMention bool , info string ) []* Message {
177+ func composeIssueCommentMessages (ctx * mailCommentContext , lang string , tos []string , fromMention bool , info string ) []* Message {
170178
171179 var (
172180 subject string
@@ -192,7 +200,6 @@ func composeIssueCommentMessages(ctx *mailCommentContext, tos []string, fromMent
192200
193201 // This is the body of the new issue or comment, not the mail body
194202 body := string (markup .RenderByType (markdown .MarkupName , []byte (ctx .Content ), ctx .Issue .Repo .HTMLURL (), ctx .Issue .Repo .ComposeMetas ()))
195-
196203 actType , actName , tplName := actionToTemplate (ctx .Issue , ctx .ActionType , commentType , reviewType )
197204
198205 if actName != "new" {
@@ -208,6 +215,7 @@ func composeIssueCommentMessages(ctx *mailCommentContext, tos []string, fromMent
208215 }
209216 }
210217 }
218+ locale := translation .NewLocale (lang )
211219
212220 mailMeta := map [string ]interface {}{
213221 "FallbackSubject" : fallback ,
@@ -224,13 +232,16 @@ func composeIssueCommentMessages(ctx *mailCommentContext, tos []string, fromMent
224232 "ActionType" : actType ,
225233 "ActionName" : actName ,
226234 "ReviewComments" : reviewComments ,
235+ "i18n" : locale ,
236+ "Language" : locale .Language (),
227237 }
228238
229239 var mailSubject bytes.Buffer
240+ // TODO: i18n templates?
230241 if err := subjectTemplates .ExecuteTemplate (& mailSubject , string (tplName ), mailMeta ); err == nil {
231242 subject = sanitizeSubject (mailSubject .String ())
232243 } else {
233- log .Error ("ExecuteTemplate [%s]: %v" , string ( tplName ) + "/subject" , err )
244+ log .Error ("ExecuteTemplate [%s]: %v" , tplName + "/subject" , err )
234245 }
235246
236247 if subject == "" {
@@ -243,6 +254,7 @@ func composeIssueCommentMessages(ctx *mailCommentContext, tos []string, fromMent
243254
244255 var mailBody bytes.Buffer
245256
257+ // TODO: i18n templates?
246258 if err := bodyTemplates .ExecuteTemplate (& mailBody , string (tplName ), mailMeta ); err != nil {
247259 log .Error ("ExecuteTemplate [%s]: %v" , string (tplName )+ "/body" , err )
248260 }
@@ -276,14 +288,21 @@ func sanitizeSubject(subject string) string {
276288}
277289
278290// SendIssueAssignedMail composes and sends issue assigned email
279- func SendIssueAssignedMail (issue * models.Issue , doer * models.User , content string , comment * models.Comment , tos []string ) {
280- SendAsyncs (composeIssueCommentMessages (& mailCommentContext {
281- Issue : issue ,
282- Doer : doer ,
283- ActionType : models .ActionType (0 ),
284- Content : content ,
285- Comment : comment ,
286- }, tos , false , "issue assigned" ))
291+ func SendIssueAssignedMail (issue * models.Issue , doer * models.User , content string , comment * models.Comment , recipients []* models.User ) {
292+ langMap := make (map [string ][]string )
293+ for _ , user := range recipients {
294+ langMap [user .Language ] = append (langMap [user .Language ], user .Email )
295+ }
296+
297+ for lang , tos := range langMap {
298+ SendAsyncs (composeIssueCommentMessages (& mailCommentContext {
299+ Issue : issue ,
300+ Doer : doer ,
301+ ActionType : models .ActionType (0 ),
302+ Content : content ,
303+ Comment : comment ,
304+ }, lang , tos , false , "issue assigned" ))
305+ }
287306}
288307
289308// actionToTemplate returns the type and name of the action facing the user
0 commit comments