From a60e8be8d15e90a44f2a746a4e8d81a81e03d2db Mon Sep 17 00:00:00 2001 From: wxiaoguang 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 = "" + actionTextDeleted + "" } 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 @@
{{.Process.Description}}
-
{{TimeSince .Process.Start .root.Lang}}
+
{{TimeSince .Process.Start .root.i18n.Lang}}
{{svg "octicon-trash" 16 "text-red"}} 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}} 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 @@ - + 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}} {{.Title | RenderEmoji}} {{end}} - {{TimeSinceUnix .CreatedUnix $.Lang}} + {{TimeSinceUnix .CreatedUnix $.i18n.Lang}}

{{end}}
@@ -150,7 +150,7 @@

{{$.i18n.Tr "repo.activity.merged_prs_label"}} #{{.Index}} {{.Issue.Title | RenderEmoji}} - {{TimeSinceUnix .MergedUnix $.Lang}} + {{TimeSinceUnix .MergedUnix $.i18n.Lang}}

{{end}}
@@ -169,7 +169,7 @@

{{$.i18n.Tr "repo.activity.opened_prs_label"}} #{{.Index}} {{.Issue.Title | RenderEmoji}} - {{TimeSinceUnix .Issue.CreatedUnix $.Lang}} + {{TimeSinceUnix .Issue.CreatedUnix $.i18n.Lang}}

{{end}} @@ -188,7 +188,7 @@

{{$.i18n.Tr "repo.activity.closed_issue_label"}} #{{.Index}} {{.Title | RenderEmoji}} - {{TimeSinceUnix .ClosedUnix $.Lang}} + {{TimeSinceUnix .ClosedUnix $.i18n.Lang}}

{{end}} @@ -207,7 +207,7 @@

{{$.i18n.Tr "repo.activity.new_issue_label"}} #{{.Index}} {{.Title | RenderEmoji}} - {{TimeSinceUnix .CreatedUnix $.Lang}} + {{TimeSinceUnix .CreatedUnix $.i18n.Lang}}

{{end}} @@ -231,7 +231,7 @@ {{else}} {{.Title | RenderEmoji}} {{end}} - {{TimeSinceUnix .UpdatedUnix $.Lang}} + {{TimeSinceUnix .UpdatedUnix $.i18n.Lang}}

{{end}} 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"}} {{.Commit.Author.Name}} {{end}} - {{TimeSince .Commit.Author.When $.Lang}} + {{TimeSince .Commit.Author.When $.i18n.Lang}} {{if or (ne .Commit.Committer.Name .Commit.Author.Name) (ne .Commit.Committer.Email .Commit.Author.Email)}} {{.i18n.Tr "repo.diff.committed_by"}} {{if ne .Verification.CommittingUser.ID 0}} @@ -169,7 +169,7 @@ {{else}} {{.NoteCommit.Author.Name}} {{end}} - {{TimeSince .NoteCommit.Author.When $.Lang}} + {{TimeSince .NoteCommit.Author.When $.i18n.Lang}}
{{RenderNote $.Context .Note $.RepoLink $.Repository.ComposeMetas}}
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}} {{if .Committer}} - {{TimeSince .Committer.When $.Lang}} + {{TimeSince .Committer.When $.i18n.Lang}} {{else}} - {{TimeSince .Author.When $.Lang}} + {{TimeSince .Author.When $.i18n.Lang}} {{end}} {{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 }}
{{if .OriginalAuthor }} 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 @@
- {{ $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 @@
- {{ $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 @@ - {{ $createdStr:= TimeSinceUnix .Issue.CreatedUnix $.Lang }} + {{ $createdStr:= TimeSinceUnix .Issue.CreatedUnix $.i18n.Lang }}
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 }}