From a60e8be8d15e90a44f2a746a4e8d81a81e03d2db Mon Sep 17 00:00:00 2001
From: wxiaoguang <wxiaoguang@gmail.com>
Date: Tue, 8 Feb 2022 11:02:30 +0800
Subject: [PATCH] Refactor i18n, use Locale to provide i18n/translation related
 functions (#18648)

* remove unnecessary web context data fields, and unify the i18n/translation related functions to `Locale`
* in development, show an error if a translation key is missing
* remove the unnecessary loops `for _, lang := range translation.AllLangs()` for every request, which improves the performance slightly
* use `ctx.Locale.Language()` instead of `ctx.Data["Lang"].(string)`
* add more comments about how the Locale/LangType fields are used
---
 modules/context/context.go                    |  9 -----
 modules/translation/translation.go            | 38 ++++++++++++++-----
 routers/install/install.go                    | 11 +-----
 routers/web/repo/blame.go                     |  2 +-
 routers/web/repo/issue_content_history.go     | 10 ++---
 templates/admin/process-row.tmpl              |  2 +-
 templates/base/footer_content.tmpl            |  4 +-
 templates/base/head.tmpl                      |  2 +-
 templates/repo/activity.tmpl                  | 12 +++---
 templates/repo/commit_page.tmpl               |  4 +-
 templates/repo/commits_list.tmpl              |  4 +-
 templates/repo/diff/comments.tmpl             |  2 +-
 templates/repo/issue/milestone_issues.tmpl    |  2 +-
 templates/repo/issue/milestones.tmpl          |  2 +-
 templates/repo/issue/view_content.tmpl        |  2 +-
 .../repo/issue/view_content/comments.tmpl     |  6 +--
 templates/repo/issue/view_content/pull.tmpl   |  4 +-
 templates/repo/issue/view_title.tmpl          |  4 +-
 templates/repo/projects/list.tmpl             |  2 +-
 templates/repo/projects/view.tmpl             |  2 +-
 templates/repo/release/list.tmpl              |  4 +-
 templates/repo/settings/lfs.tmpl              |  2 +-
 templates/repo/settings/lfs_file_find.tmpl    |  2 +-
 templates/repo/settings/lfs_locks.tmpl        |  2 +-
 templates/repo/view_list.tmpl                 |  4 +-
 templates/repo/wiki/pages.tmpl                |  2 +-
 templates/repo/wiki/revision.tmpl             |  2 +-
 templates/repo/wiki/view.tmpl                 |  2 +-
 templates/shared/issuelist.tmpl               |  2 +-
 templates/user/dashboard/milestones.tmpl      |  2 +-
 .../user/settings/security/webauthn.tmpl      |  2 +-
 31 files changed, 75 insertions(+), 75 deletions(-)

diff --git a/modules/context/context.go b/modules/context/context.go
index 887cffdbf9..7ae37208e4 100644
--- a/modules/context/context.go
+++ b/modules/context/context.go
@@ -38,7 +38,6 @@ import (
 	"gitea.com/go-chi/session"
 	chi "github.com/go-chi/chi/v5"
 	"github.com/unknwon/com"
-	"github.com/unknwon/i18n"
 	"github.com/unrolled/render"
 	"golang.org/x/crypto/pbkdf2"
 )
@@ -738,15 +737,7 @@ func Contexter() func(next http.Handler) http.Handler {
 			ctx.Data["UnitProjectsGlobalDisabled"] = unit.TypeProjects.UnitGlobalDisabled()
 
 			ctx.Data["i18n"] = locale
-			ctx.Data["Tr"] = i18n.Tr
-			ctx.Data["Lang"] = locale.Language()
 			ctx.Data["AllLangs"] = translation.AllLangs()
-			for _, lang := range translation.AllLangs() {
-				if lang.Lang == locale.Language() {
-					ctx.Data["LangName"] = lang.Name
-					break
-				}
-			}
 
 			next.ServeHTTP(ctx.Resp, ctx.Req)
 
diff --git a/modules/translation/translation.go b/modules/translation/translation.go
index 977f2cdc23..fd38e4d510 100644
--- a/modules/translation/translation.go
+++ b/modules/translation/translation.go
@@ -25,17 +25,18 @@ type Locale interface {
 
 // LangType represents a lang type
 type LangType struct {
-	Lang, Name string
+	Lang, Name string // these fields are used directly in templates: {{range .AllLangs}}{{.Lang}}{{.Name}}{{end}}
 }
 
 var (
 	matcher       language.Matcher
-	allLangs      []LangType
+	allLangs      []*LangType
+	allLangMap    map[string]*LangType
 	supportedTags []language.Tag
 )
 
 // AllLangs returns all supported languages sorted by name
-func AllLangs() []LangType {
+func AllLangs() []*LangType {
 	return allLangs
 }
 
@@ -81,14 +82,17 @@ func InitLocales() {
 	}
 	i18n.SetDefaultLang("en-US")
 
-	allLangs = make([]LangType, 0, i18n.Count()-1)
+	allLangs = make([]*LangType, 0, i18n.Count())
+	allLangMap = map[string]*LangType{}
 	langs := i18n.ListLangs()
-	names := i18n.ListLangDescs()
+	descs := i18n.ListLangDescs()
 	for i, v := range langs {
-		allLangs = append(allLangs, LangType{v, names[i]})
+		l := &LangType{v, descs[i]}
+		allLangs = append(allLangs, l)
+		allLangMap[v] = l
 	}
 
-	// Sort languages case insensitive according to their name - needed for the user settings
+	// Sort languages case-insensitive according to their name - needed for the user settings
 	sort.Slice(allLangs, func(i, j int) bool {
 		return strings.ToLower(allLangs[i].Name) < strings.ToLower(allLangs[j].Name)
 	})
@@ -102,13 +106,18 @@ func Match(tags ...language.Tag) language.Tag {
 
 // locale represents the information of localization.
 type locale struct {
-	Lang string
+	Lang, LangName string // these fields are used directly in templates: .i18n.Lang
 }
 
 // NewLocale return a locale
 func NewLocale(lang string) Locale {
+	langName := "unknown"
+	if l, ok := allLangMap[lang]; ok {
+		langName = l.Name
+	}
 	return &locale{
-		Lang: lang,
+		Lang:     lang,
+		LangName: langName,
 	}
 }
 
@@ -118,7 +127,16 @@ func (l *locale) Language() string {
 
 // Tr translates content to target language.
 func (l *locale) Tr(format string, args ...interface{}) string {
-	return i18n.Tr(l.Lang, format, args...)
+	if setting.IsProd {
+		return i18n.Tr(l.Lang, format, args...)
+	}
+
+	// in development, we should show an error if a translation key is missing
+	s, ok := TryTr(l.Lang, format, args...)
+	if !ok {
+		log.Error("missing i18n translation key: %q", format)
+	}
+	return s
 }
 
 // Language specific rules for translating plural texts
diff --git a/routers/install/install.go b/routers/install/install.go
index eb2cd23463..98eeb5f8a0 100644
--- a/routers/install/install.go
+++ b/routers/install/install.go
@@ -71,25 +71,16 @@ func Init(next http.Handler) http.Handler {
 			Render:  rnd,
 			Session: session.GetSession(req),
 			Data: map[string]interface{}{
+				"i18n":          locale,
 				"Title":         locale.Tr("install.install"),
 				"PageIsInstall": true,
 				"DbTypeNames":   getDbTypeNames(),
-				"i18n":          locale,
-				"Language":      locale.Language(),
-				"Lang":          locale.Language(),
 				"AllLangs":      translation.AllLangs(),
-				"CurrentURL":    setting.AppSubURL + req.URL.RequestURI(),
 				"PageStartTime": startTime,
 
 				"PasswordHashAlgorithms": user_model.AvailableHashAlgorithms,
 			},
 		}
-		for _, lang := range translation.AllLangs() {
-			if lang.Lang == locale.Language() {
-				ctx.Data["LangName"] = lang.Name
-				break
-			}
-		}
 		ctx.Req = context.WithContext(req, &ctx)
 		next.ServeHTTP(resp, ctx.Req)
 	})
diff --git a/routers/web/repo/blame.go b/routers/web/repo/blame.go
index 588e432e3a..e96e2142d2 100644
--- a/routers/web/repo/blame.go
+++ b/routers/web/repo/blame.go
@@ -255,7 +255,7 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m
 				commitCnt++
 
 				// User avatar image
-				commitSince := timeutil.TimeSinceUnix(timeutil.TimeStamp(commit.Author.When.Unix()), ctx.Data["Lang"].(string))
+				commitSince := timeutil.TimeSinceUnix(timeutil.TimeStamp(commit.Author.When.Unix()), ctx.Locale.Language())
 
 				var avatar string
 				if commit.User != nil {
diff --git a/routers/web/repo/issue_content_history.go b/routers/web/repo/issue_content_history.go
index 75951ca25b..5b5aced6ec 100644
--- a/routers/web/repo/issue_content_history.go
+++ b/routers/web/repo/issue_content_history.go
@@ -29,7 +29,7 @@ func GetContentHistoryOverview(ctx *context.Context) {
 		return
 	}
 
-	lang := ctx.Data["Lang"].(string)
+	lang := ctx.Locale.Language()
 	editedHistoryCountMap, _ := issuesModel.QueryIssueContentHistoryEditedCountMap(db.DefaultContext, issue.ID)
 	ctx.JSON(http.StatusOK, map[string]interface{}{
 		"i18n": map[string]interface{}{
@@ -55,17 +55,17 @@ func GetContentHistoryList(ctx *context.Context) {
 	// render history list to HTML for frontend dropdown items: (name, value)
 	// name is HTML of "avatar + userName + userAction + timeSince"
 	// value is historyId
-	lang := ctx.Data["Lang"].(string)
+	lang := ctx.Locale.Language()
 	var results []map[string]interface{}
 	for _, item := range items {
 		var actionText string
 		if item.IsDeleted {
-			actionTextDeleted := i18n.Tr(lang, "repo.issues.content_history.deleted")
+			actionTextDeleted := ctx.Locale.Tr("repo.issues.content_history.deleted")
 			actionText = "<i data-history-is-deleted='1'>" + actionTextDeleted + "</i>"
 		} else if item.IsFirstCreated {
-			actionText = i18n.Tr(lang, "repo.issues.content_history.created")
+			actionText = ctx.Locale.Tr("repo.issues.content_history.created")
 		} else {
-			actionText = i18n.Tr(lang, "repo.issues.content_history.edited")
+			actionText = ctx.Locale.Tr("repo.issues.content_history.edited")
 		}
 		timeSinceText := timeutil.TimeSinceUnix(item.EditedUnix, lang)
 		results = append(results, map[string]interface{}{
diff --git a/templates/admin/process-row.tmpl b/templates/admin/process-row.tmpl
index 814727e7fa..146ecc7b29 100644
--- a/templates/admin/process-row.tmpl
+++ b/templates/admin/process-row.tmpl
@@ -2,7 +2,7 @@
 	<div class="df ac">
 		<div class="content f1">
 			<div class="header">{{.Process.Description}}</div>
-			<div class="description"><span title="{{DateFmtLong .Process.Start}}">{{TimeSince .Process.Start .root.Lang}}</span></div>
+			<div class="description"><span title="{{DateFmtLong .Process.Start}}">{{TimeSince .Process.Start .root.i18n.Lang}}</span></div>
 		</div>
 		<div>
 			<a class="delete-button icon" href="" data-url="{{.root.Link}}/cancel/{{.Process.PID}}" data-id="{{.Process.PID}}" data-name="{{.Process.Description}}">{{svg "octicon-trash" 16 "text-red"}}</a>
diff --git a/templates/base/footer_content.tmpl b/templates/base/footer_content.tmpl
index e30fe70768..979c03146c 100644
--- a/templates/base/footer_content.tmpl
+++ b/templates/base/footer_content.tmpl
@@ -9,10 +9,10 @@
 			{{end}}
 			<div class="ui language bottom floating slide up dropdown link item">
 				{{svg "octicon-globe"}}
-				<div class="text">{{.LangName}}</div>
+				<div class="text">{{.i18n.LangName}}</div>
 				<div class="menu language-menu">
 					{{range .AllLangs}}
-						<a lang="{{.Lang}}" data-url="{{AppSubUrl}}/?lang={{.Lang}}" class="item {{if eq $.Lang .Lang}}active selected{{end}}">{{.Name}}</a>
+						<a lang="{{.Lang}}" data-url="{{AppSubUrl}}/?lang={{.Lang}}" class="item {{if eq $.i18n.Lang .Lang}}active selected{{end}}">{{.Name}}</a>
 					{{end}}
 				</div>
 			</div>
diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl
index 3068dd4cbb..32e206a95d 100644
--- a/templates/base/head.tmpl
+++ b/templates/base/head.tmpl
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<html lang="{{.Lang}}" class="theme-{{.SignedUser.Theme}}">
+<html lang="{{.i18n.Lang}}" class="theme-{{.SignedUser.Theme}}">
 <head>
 	<meta charset="utf-8">
 	<meta name="viewport" content="width=device-width, initial-scale=1">
diff --git a/templates/repo/activity.tmpl b/templates/repo/activity.tmpl
index 3086ca8e8d..36108dddcb 100644
--- a/templates/repo/activity.tmpl
+++ b/templates/repo/activity.tmpl
@@ -131,7 +131,7 @@
 						{{if not .IsTag}}
 							<a class="title" href="{{$.RepoLink}}/src/{{.TagName | PathEscapeSegments}}">{{.Title | RenderEmoji}}</a>
 						{{end}}
-						{{TimeSinceUnix .CreatedUnix $.Lang}}
+						{{TimeSinceUnix .CreatedUnix $.i18n.Lang}}
 					</p>
 				{{end}}
 			</div>
@@ -150,7 +150,7 @@
 					<p class="desc">
 						<span class="ui purple label">{{$.i18n.Tr "repo.activity.merged_prs_label"}}</span>
 						#{{.Index}} <a class="title" href="{{$.RepoLink}}/pulls/{{.Index}}">{{.Issue.Title | RenderEmoji}}</a>
-						{{TimeSinceUnix .MergedUnix $.Lang}}
+						{{TimeSinceUnix .MergedUnix $.i18n.Lang}}
 					</p>
 				{{end}}
 			</div>
@@ -169,7 +169,7 @@
 					<p class="desc">
 						<span class="ui green label">{{$.i18n.Tr "repo.activity.opened_prs_label"}}</span>
 						#{{.Index}} <a class="title" href="{{$.RepoLink}}/pulls/{{.Index}}">{{.Issue.Title | RenderEmoji}}</a>
-						{{TimeSinceUnix .Issue.CreatedUnix $.Lang}}
+						{{TimeSinceUnix .Issue.CreatedUnix $.i18n.Lang}}
 					</p>
 				{{end}}
 			</div>
@@ -188,7 +188,7 @@
 					<p class="desc">
 						<span class="ui red label">{{$.i18n.Tr "repo.activity.closed_issue_label"}}</span>
 						#{{.Index}} <a class="title" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Title | RenderEmoji}}</a>
-						{{TimeSinceUnix .ClosedUnix $.Lang}}
+						{{TimeSinceUnix .ClosedUnix $.i18n.Lang}}
 					</p>
 				{{end}}
 			</div>
@@ -207,7 +207,7 @@
 					<p class="desc">
 						<span class="ui green label">{{$.i18n.Tr "repo.activity.new_issue_label"}}</span>
 						#{{.Index}} <a class="title" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Title | RenderEmoji}}</a>
-						{{TimeSinceUnix .CreatedUnix $.Lang}}
+						{{TimeSinceUnix .CreatedUnix $.i18n.Lang}}
 					</p>
 				{{end}}
 			</div>
@@ -231,7 +231,7 @@
 						{{else}}
 						<a class="title" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Title | RenderEmoji}}</a>
 						{{end}}
-						{{TimeSinceUnix .UpdatedUnix $.Lang}}
+						{{TimeSinceUnix .UpdatedUnix $.i18n.Lang}}
 					</p>
 				{{end}}
 			</div>
diff --git a/templates/repo/commit_page.tmpl b/templates/repo/commit_page.tmpl
index 931201fed6..331c439c02 100644
--- a/templates/repo/commit_page.tmpl
+++ b/templates/repo/commit_page.tmpl
@@ -47,7 +47,7 @@
 						{{avatarByEmail .Commit.Author.Email .Commit.Author.Email 28 "mr-3"}}
 						<strong>{{.Commit.Author.Name}}</strong>
 					{{end}}
-					<span class="text grey ml-3" id="authored-time">{{TimeSince .Commit.Author.When $.Lang}}</span>
+					<span class="text grey ml-3" id="authored-time">{{TimeSince .Commit.Author.When $.i18n.Lang}}</span>
 					{{if or (ne .Commit.Committer.Name .Commit.Author.Name) (ne .Commit.Committer.Email .Commit.Author.Email)}}
 						<span class="text grey mx-3">{{.i18n.Tr "repo.diff.committed_by"}}</span>
 						{{if ne .Verification.CommittingUser.ID 0}}
@@ -169,7 +169,7 @@
 				{{else}}
 					<strong>{{.NoteCommit.Author.Name}}</strong>
 				{{end}}
-				<span class="text grey" id="note-authored-time">{{TimeSince .NoteCommit.Author.When $.Lang}}</span>
+				<span class="text grey" id="note-authored-time">{{TimeSince .NoteCommit.Author.When $.i18n.Lang}}</span>
 			</div>
 			<div class="ui bottom attached info segment git-notes">
 				<pre class="commit-body">{{RenderNote $.Context .Note $.RepoLink $.Repository.ComposeMetas}}</pre>
diff --git a/templates/repo/commits_list.tmpl b/templates/repo/commits_list.tmpl
index e8ac4020f4..86ad835202 100644
--- a/templates/repo/commits_list.tmpl
+++ b/templates/repo/commits_list.tmpl
@@ -76,9 +76,9 @@
 							{{end}}
 						</td>
 						{{if .Committer}}
-							<td class="text right aligned">{{TimeSince .Committer.When $.Lang}}</td>
+							<td class="text right aligned">{{TimeSince .Committer.When $.i18n.Lang}}</td>
 						{{else}}
-							<td class="text right aligned">{{TimeSince .Author.When $.Lang}}</td>
+							<td class="text right aligned">{{TimeSince .Author.When $.i18n.Lang}}</td>
 						{{end}}
 					</tr>
 				{{end}}
diff --git a/templates/repo/diff/comments.tmpl b/templates/repo/diff/comments.tmpl
index 9ec42a8d11..3b8f1c2a9c 100644
--- a/templates/repo/diff/comments.tmpl
+++ b/templates/repo/diff/comments.tmpl
@@ -1,6 +1,6 @@
 {{range .comments}}
 
-{{ $createdStr:= TimeSinceUnix .CreatedUnix $.root.Lang }}
+{{ $createdStr:= TimeSinceUnix .CreatedUnix $.root.i18n.Lang }}
 <div class="comment" id="{{.HashTag}}">
 	{{if .OriginalAuthor }}
 		<span class="avatar"><img src="{{AppSubUrl}}/assets/img/avatar_default.png"></span>
diff --git a/templates/repo/issue/milestone_issues.tmpl b/templates/repo/issue/milestone_issues.tmpl
index 3f4a13570f..cb2779db32 100644
--- a/templates/repo/issue/milestone_issues.tmpl
+++ b/templates/repo/issue/milestone_issues.tmpl
@@ -22,7 +22,7 @@
 		</div>
 		<div class="ui one column stackable grid">
 			<div class="column">
-				{{ $closedDate:= TimeSinceUnix .Milestone.ClosedDateUnix $.Lang }}
+				{{ $closedDate:= TimeSinceUnix .Milestone.ClosedDateUnix $.i18n.Lang }}
 				{{if .IsClosed}}
 					{{svg "octicon-clock"}} {{$.i18n.Tr "repo.milestones.closed" $closedDate|Str2html}}
 				{{else}}
diff --git a/templates/repo/issue/milestones.tmpl b/templates/repo/issue/milestones.tmpl
index 448d758e3e..dc168bdc1a 100644
--- a/templates/repo/issue/milestones.tmpl
+++ b/templates/repo/issue/milestones.tmpl
@@ -68,7 +68,7 @@
 						</div>
 					</div>
 					<div class="meta">
-						{{ $closedDate:= TimeSinceUnix .ClosedDateUnix $.Lang }}
+						{{ $closedDate:= TimeSinceUnix .ClosedDateUnix $.i18n.Lang }}
 						{{if .IsClosed}}
 							{{svg "octicon-clock"}} {{$.i18n.Tr "repo.milestones.closed" $closedDate|Str2html}}
 						{{else}}
diff --git a/templates/repo/issue/view_content.tmpl b/templates/repo/issue/view_content.tmpl
index 86d9e6da84..820055c136 100644
--- a/templates/repo/issue/view_content.tmpl
+++ b/templates/repo/issue/view_content.tmpl
@@ -15,7 +15,7 @@
 	<input type="hidden" id="issueIndex" value="{{.Issue.Index}}"/>
 	<input type="hidden" id="type" value="{{.IssueType}}">
 
-	{{ $createdStr:= TimeSinceUnix .Issue.CreatedUnix $.Lang }}
+	{{ $createdStr:= TimeSinceUnix .Issue.CreatedUnix $.i18n.Lang }}
 	<div class="twelve wide column comment-list prevent-before-timeline">
 		<ui class="ui timeline">
 			<div id="{{.Issue.HashTag}}" class="timeline-item comment first">
diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl
index 03e2728299..7b0941148f 100644
--- a/templates/repo/issue/view_content/comments.tmpl
+++ b/templates/repo/issue/view_content/comments.tmpl
@@ -1,7 +1,7 @@
 {{ template "base/alert" }}
 {{range .Issue.Comments}}
 	{{if call $.ShouldShowCommentType .Type}}
-		{{ $createdStr:= TimeSinceUnix .CreatedUnix $.Lang }}
+		{{ $createdStr:= TimeSinceUnix .CreatedUnix $.i18n.Lang }}
 
 		<!-- 0 = COMMENT, 1 = REOPEN, 2 = CLOSE, 3 = ISSUE_REF, 4 = COMMIT_REF,
 		5 = COMMENT_REF, 6 = PULL_REF, 7 = COMMENT_LABEL, 12 = START_TRACKING,
@@ -146,7 +146,7 @@
 			{{else if eq .RefAction 2 }}
 				{{ $refTr = "repo.issues.ref_reopening_from" }}
 			{{end}}
-			{{ $createdStr:= TimeSinceUnix .CreatedUnix $.Lang }}
+			{{ $createdStr:= TimeSinceUnix .CreatedUnix $.i18n.Lang }}
 			<div class="timeline-item event" id="{{.HashTag}}">
 				<span class="badge">{{svg "octicon-bookmark"}}</span>
 				<a href="{{.Poster.HomeLink}}">
@@ -557,7 +557,7 @@
 									<div id="code-comments-{{(index $comms 0).ID}}" class="comment-code-cloud ui segment{{if $resolved}} hide{{end}}">
 										<div class="ui comments mb-0">
 											{{range $comms}}
-												{{ $createdSubStr:= TimeSinceUnix .CreatedUnix $.Lang }}
+												{{ $createdSubStr:= TimeSinceUnix .CreatedUnix $.i18n.Lang }}
 												<div class="comment code-comment pb-4" id="{{.HashTag}}">
 													<div class="content">
 														<div class="header comment-header">
diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl
index 85076027d1..fef868af1f 100644
--- a/templates/repo/issue/view_content/pull.tmpl
+++ b/templates/repo/issue/view_content/pull.tmpl
@@ -4,7 +4,7 @@
 			<div class="ui segment">
 				<h4>{{$.i18n.Tr "repo.issues.review.reviewers"}}</h4>
 				{{range .PullReviewers}}
-					{{ $createdStr:= TimeSinceUnix .Review.UpdatedUnix $.Lang }}
+					{{ $createdStr:= TimeSinceUnix .Review.UpdatedUnix $.i18n.Lang }}
 					<div class="ui divider"></div>
 					<div class="review-item">
 						<div class="review-item-left">
@@ -82,7 +82,7 @@
 					</div>
 				{{end}}
 				{{range .OriginalReviews}}
-					{{ $createdStr:= TimeSinceUnix .UpdatedUnix $.Lang }}
+					{{ $createdStr:= TimeSinceUnix .UpdatedUnix $.i18n.Lang }}
 					<div class="ui divider"></div>
 					<div class="review-item">
 						<div class="review-item-left">
diff --git a/templates/repo/issue/view_title.tmpl b/templates/repo/issue/view_title.tmpl
index 07c700afea..707b8252f4 100644
--- a/templates/repo/issue/view_title.tmpl
+++ b/templates/repo/issue/view_title.tmpl
@@ -40,7 +40,7 @@
 			{{$baseHref = printf "<a href=\"%s\">%s</a>" (.BaseBranchHTMLURL | Escape) $baseHref}}
 		{{end}}
 		{{if .Issue.PullRequest.HasMerged}}
-			{{ $mergedStr:= TimeSinceUnix .Issue.PullRequest.MergedUnix $.Lang }}
+			{{ $mergedStr:= TimeSinceUnix .Issue.PullRequest.MergedUnix $.i18n.Lang }}
 			{{if .Issue.OriginalAuthor }}
 				{{.Issue.OriginalAuthor}}
 				<span class="pull-desc">{{$.i18n.Tr "repo.pulls.merged_title_desc" .NumCommits $headHref $baseHref $mergedStr | Safe}}</span>
@@ -88,7 +88,7 @@
 			</span>
 		{{end}}
 	{{else}}
-		{{ $createdStr:= TimeSinceUnix .Issue.CreatedUnix $.Lang }}
+		{{ $createdStr:= TimeSinceUnix .Issue.CreatedUnix $.i18n.Lang }}
 		<span class="time-desc">
 			{{if .Issue.OriginalAuthor }}
 				{{$.i18n.Tr "repo.issues.opened_by_fake" $createdStr (.Issue.OriginalAuthor|Escape) | Safe}}
diff --git a/templates/repo/projects/list.tmpl b/templates/repo/projects/list.tmpl
index f152d20915..a8c51d668e 100644
--- a/templates/repo/projects/list.tmpl
+++ b/templates/repo/projects/list.tmpl
@@ -42,7 +42,7 @@
 				<li class="item">
 					{{svg "octicon-project"}} <a href="{{$.RepoLink}}/projects/{{.ID}}">{{.Title}}</a>
 					<div class="meta">
-						{{ $closedDate:= TimeSinceUnix .ClosedDateUnix $.Lang }}
+						{{ $closedDate:= TimeSinceUnix .ClosedDateUnix $.i18n.Lang }}
 						{{if .IsClosed }}
 							{{svg "octicon-clock"}} {{$.i18n.Tr "repo.milestones.closed" $closedDate|Str2html}}
 						{{end}}
diff --git a/templates/repo/projects/view.tmpl b/templates/repo/projects/view.tmpl
index 1db52a3d79..6db1025539 100644
--- a/templates/repo/projects/view.tmpl
+++ b/templates/repo/projects/view.tmpl
@@ -202,7 +202,7 @@
 							<div class="meta my-2">
 								<span class="text light grey">
 									#{{.Index}}
-									{{ $timeStr := TimeSinceUnix .GetLastEventTimestamp $.Lang }}
+									{{ $timeStr := TimeSinceUnix .GetLastEventTimestamp $.i18n.Lang }}
 									{{if .OriginalAuthor }}
 										{{$.i18n.Tr .GetLastEventLabelFake $timeStr (.OriginalAuthor|Escape) | Safe}}
 									{{else if gt .Poster.ID 0}}
diff --git a/templates/repo/release/list.tmpl b/templates/repo/release/list.tmpl
index 01f01cdeff..26d78df3cc 100644
--- a/templates/repo/release/list.tmpl
+++ b/templates/repo/release/list.tmpl
@@ -65,7 +65,7 @@
 				<li class="ui grid">
 					<div class="ui four wide column meta mt-2">
 						{{if .IsTag}}
-							{{if .CreatedUnix}}<span class="time">{{TimeSinceUnix .CreatedUnix $.Lang}}</span>{{end}}
+							{{if .CreatedUnix}}<span class="time">{{TimeSinceUnix .CreatedUnix $.i18n.Lang}}</span>{{end}}
 						{{else}}
 							{{if .IsDraft}}
 								<span class="ui yellow label">{{$.i18n.Tr "repo.release.draft"}}</span>
@@ -132,7 +132,7 @@
 									{{$.i18n.Tr "repo.released_this"}}
 								</span>
 								{{if .CreatedUnix}}
-									<span class="time">{{TimeSinceUnix .CreatedUnix $.Lang}}</span>
+									<span class="time">{{TimeSinceUnix .CreatedUnix $.i18n.Lang}}</span>
 								{{end}}
 								{{if not .IsDraft}}
 									| <span class="ahead"><a href="{{$.RepoLink}}/compare/{{.TagName | PathEscapeSegments}}...{{.Target | PathEscapeSegments}}">{{$.i18n.Tr "repo.release.ahead.commits" .NumCommitsBehind | Str2html}}</a> {{$.i18n.Tr "repo.release.ahead.target" .Target}}</span>
diff --git a/templates/repo/settings/lfs.tmpl b/templates/repo/settings/lfs.tmpl
index 69db43cf6b..9b5c646209 100644
--- a/templates/repo/settings/lfs.tmpl
+++ b/templates/repo/settings/lfs.tmpl
@@ -23,7 +23,7 @@
 							</span>
 						</td>
 						<td>{{FileSize .Size}}</td>
-						<td>{{TimeSince .CreatedUnix.AsTime $.Lang}}</td>
+						<td>{{TimeSince .CreatedUnix.AsTime $.i18n.Lang}}</td>
 						<td class="right aligned">
 							<a class="ui primary show-panel button" href="{{$.Link}}/find?oid={{.Oid}}&size={{.Size}}">{{$.i18n.Tr "repo.settings.lfs_findcommits"}}</a>
 							<button class="ui basic show-modal icon button" data-modal="#delete-{{.Oid}}">
diff --git a/templates/repo/settings/lfs_file_find.tmpl b/templates/repo/settings/lfs_file_find.tmpl
index f5a0e0081c..60caf46fe8 100644
--- a/templates/repo/settings/lfs_file_find.tmpl
+++ b/templates/repo/settings/lfs_file_find.tmpl
@@ -37,7 +37,7 @@
 								{{$.i18n.Tr "repo.diff.commit"}}
 								<a class="ui blue sha label" href="{{$.RepoLink}}/commit/{{.SHA}}">{{ShortSha .SHA}}</a>
 							</td>
-							<td>{{TimeSince .When $.Lang}}</td>
+							<td>{{TimeSince .When $.i18n.Lang}}</td>
 						</tr>
 					{{else}}
 						<tr>
diff --git a/templates/repo/settings/lfs_locks.tmpl b/templates/repo/settings/lfs_locks.tmpl
index 2d311d59ea..6f52358708 100644
--- a/templates/repo/settings/lfs_locks.tmpl
+++ b/templates/repo/settings/lfs_locks.tmpl
@@ -39,7 +39,7 @@
 									{{$lock.Owner.DisplayName}}
 								</a>
 							</td>
-							<td>{{TimeSince .Created $.Lang}}</td>
+							<td>{{TimeSince .Created $.i18n.Lang}}</td>
 							<td class="right aligned">
 								<form action="{{$.LFSFilesLink}}/locks/{{$lock.ID}}/unlock" method="POST">
 									{{$.CsrfTokenHtml}}
diff --git a/templates/repo/view_list.tmpl b/templates/repo/view_list.tmpl
index b123096777..bc56041c7d 100644
--- a/templates/repo/view_list.tmpl
+++ b/templates/repo/view_list.tmpl
@@ -34,7 +34,7 @@
 					</span>
 				{{end}}
 			</th>
-			<th class="text grey right age">{{if .LatestCommit}}{{if .LatestCommit.Committer}}{{TimeSince .LatestCommit.Committer.When $.Lang}}{{end}}{{end}}</th>
+			<th class="text grey right age">{{if .LatestCommit}}{{if .LatestCommit.Committer}}{{TimeSince .LatestCommit.Committer.When $.i18n.Lang}}{{end}}{{end}}</th>
 		</tr>
 	</thead>
 	<tbody>
@@ -87,7 +87,7 @@
 						{{end}}
 					</span>
 				</td>
-				<td class="text right age three wide">{{if $commit}}{{TimeSince $commit.Committer.When $.Lang}}{{end}}</td>
+				<td class="text right age three wide">{{if $commit}}{{TimeSince $commit.Committer.When $.i18n.Lang}}{{end}}</td>
 			</tr>
 		{{end}}
 	</tbody>
diff --git a/templates/repo/wiki/pages.tmpl b/templates/repo/wiki/pages.tmpl
index 43766771bc..74674c6f1c 100644
--- a/templates/repo/wiki/pages.tmpl
+++ b/templates/repo/wiki/pages.tmpl
@@ -20,7 +20,7 @@
 							{{svg "octicon-file"}}
 							<a href="{{$.RepoLink}}/wiki/{{.SubURL}}">{{.Name}}</a>
 						</td>
-						{{$timeSince := TimeSinceUnix .UpdatedUnix $.Lang}}
+						{{$timeSince := TimeSinceUnix .UpdatedUnix $.i18n.Lang}}
 						<td class="text right grey">{{$.i18n.Tr "repo.wiki.last_updated" $timeSince | Safe}}</td>
 					</tr>
 				{{end}}
diff --git a/templates/repo/wiki/revision.tmpl b/templates/repo/wiki/revision.tmpl
index d74c99152a..4e55da82fb 100644
--- a/templates/repo/wiki/revision.tmpl
+++ b/templates/repo/wiki/revision.tmpl
@@ -13,7 +13,7 @@
 				<a class="file-revisions-btn ui basic button" title="{{.i18n.Tr "repo.wiki.back_to_wiki"}}" href="{{.RepoLink}}/wiki/{{.PageURL}}" ><span>{{.revision}}</span> {{svg "octicon-home"}}</a>
 				{{$title}}
 				<div class="ui sub header word-break">
-					{{$timeSince := TimeSince .Author.When $.Lang}}
+					{{$timeSince := TimeSince .Author.When $.i18n.Lang}}
 					{{.i18n.Tr "repo.wiki.last_commit_info" .Author.Name $timeSince | Safe}}
 				</div>
 			</div>
diff --git a/templates/repo/wiki/view.tmpl b/templates/repo/wiki/view.tmpl
index db0ce14878..ce1b00b4f2 100644
--- a/templates/repo/wiki/view.tmpl
+++ b/templates/repo/wiki/view.tmpl
@@ -40,7 +40,7 @@
 					<a class="file-revisions-btn ui basic button" title="{{.i18n.Tr "repo.wiki.file_revision"}}" href="{{.RepoLink}}/wiki/{{.PageURL}}?action=_revision" ><span>{{.CommitCount}}</span> {{svg "octicon-history"}}</a>
 					{{$title}}
 					<div class="ui sub header">
-						{{$timeSince := TimeSince .Author.When $.Lang}}
+						{{$timeSince := TimeSince .Author.When $.i18n.Lang}}
 						{{.i18n.Tr "repo.wiki.last_commit_info" .Author.Name $timeSince | Safe}}
 					</div>
 				</div>
diff --git a/templates/shared/issuelist.tmpl b/templates/shared/issuelist.tmpl
index 687bbdee94..002aa5b5ab 100644
--- a/templates/shared/issuelist.tmpl
+++ b/templates/shared/issuelist.tmpl
@@ -51,7 +51,7 @@
 							#{{.Index}}
 						{{end}}
 					</a>
-					{{ $timeStr := TimeSinceUnix .GetLastEventTimestamp $.Lang }}
+					{{ $timeStr := TimeSinceUnix .GetLastEventTimestamp $.i18n.Lang }}
 					{{if .OriginalAuthor }}
 						{{$.i18n.Tr .GetLastEventLabelFake $timeStr (.OriginalAuthor|Escape) | Safe}}
 					{{else if gt .Poster.ID 0}}
diff --git a/templates/user/dashboard/milestones.tmpl b/templates/user/dashboard/milestones.tmpl
index b006ca5186..a650a5d315 100644
--- a/templates/user/dashboard/milestones.tmpl
+++ b/templates/user/dashboard/milestones.tmpl
@@ -88,7 +88,7 @@
 								</div>
 							</div>
 							<div class="meta">
-								{{ $closedDate:= TimeSinceUnix .ClosedDateUnix $.Lang }}
+								{{ $closedDate:= TimeSinceUnix .ClosedDateUnix $.i18n.Lang }}
 								{{if .IsClosed}}
 									{{svg "octicon-clock"}} {{$.i18n.Tr "repo.milestones.closed" $closedDate|Str2html}}
 								{{else}}
diff --git a/templates/user/settings/security/webauthn.tmpl b/templates/user/settings/security/webauthn.tmpl
index d447ec04b3..51a6deb187 100644
--- a/templates/user/settings/security/webauthn.tmpl
+++ b/templates/user/settings/security/webauthn.tmpl
@@ -14,7 +14,7 @@
 				<div class="content">
 					<strong>{{.Name}}</strong>
 				</div>
-				<span class="time">{{TimeSinceUnix .CreatedUnix $.Lang}}</span>
+				<span class="time">{{TimeSinceUnix .CreatedUnix $.i18n.Lang}}</span>
 			</div>
 		{{end}}
 	</div>