From 32fc44aa83e61acb93dbdcf6d47dfadc69f5c044 Mon Sep 17 00:00:00 2001 From: Lauris BH Date: Wed, 28 Jun 2017 08:43:28 +0300 Subject: [PATCH] Make time diff translatable (#2057) --- models/mail.go | 6 +-- modules/base/tool.go | 93 +++++++++++---------------------- modules/base/tool_test.go | 16 +++--- options/locale/locale_en-US.ini | 33 ++++++------ routers/admin/admin.go | 2 +- routers/dev/template.go | 4 +- routers/user/auth.go | 10 ++-- routers/user/auth_openid.go | 2 +- routers/user/setting.go | 2 +- 9 files changed, 67 insertions(+), 101 deletions(-) diff --git a/models/mail.go b/models/mail.go index 7ef73fc11..41fddad2b 100644 --- a/models/mail.go +++ b/models/mail.go @@ -47,8 +47,8 @@ func SendTestMail(email string) error { func SendUserMail(c *macaron.Context, u *User, tpl base.TplName, code, subject, info string) { data := map[string]interface{}{ "Username": u.DisplayName(), - "ActiveCodeLives": base.MinutesToFriendly(setting.Service.ActiveCodeLives), - "ResetPwdCodeLives": base.MinutesToFriendly(setting.Service.ResetPwdCodeLives), + "ActiveCodeLives": base.MinutesToFriendly(setting.Service.ActiveCodeLives, c.Locale.Language()), + "ResetPwdCodeLives": base.MinutesToFriendly(setting.Service.ResetPwdCodeLives, c.Locale.Language()), "Code": code, } @@ -79,7 +79,7 @@ func SendResetPasswordMail(c *macaron.Context, u *User) { func SendActivateEmailMail(c *macaron.Context, u *User, email *EmailAddress) { data := map[string]interface{}{ "Username": u.DisplayName(), - "ActiveCodeLives": base.MinutesToFriendly(setting.Service.ActiveCodeLives), + "ActiveCodeLives": base.MinutesToFriendly(setting.Service.ActiveCodeLives, c.Locale.Language()), "Code": u.GenerateEmailActivateCode(email.Email), "Email": email.Email, } diff --git a/modules/base/tool.go b/modules/base/tool.go index 3fe5a3d84..8952e7a8c 100644 --- a/modules/base/tool.go +++ b/modules/base/tool.go @@ -219,59 +219,59 @@ const ( Year = 12 * Month ) -func computeTimeDiff(diff int64) (int64, string) { +func computeTimeDiff(diff int64, lang string) (int64, string) { diffStr := "" switch { case diff <= 0: diff = 0 - diffStr = "now" + diffStr = i18n.Tr(lang, "tool.now") case diff < 2: diff = 0 - diffStr = "1 second" + diffStr = i18n.Tr(lang, "tool.1s") case diff < 1*Minute: - diffStr = fmt.Sprintf("%d seconds", diff) + diffStr = i18n.Tr(lang, "tool.seconds", diff) diff = 0 case diff < 2*Minute: diff -= 1 * Minute - diffStr = "1 minute" + diffStr = i18n.Tr(lang, "tool.1m") case diff < 1*Hour: - diffStr = fmt.Sprintf("%d minutes", diff/Minute) + diffStr = i18n.Tr(lang, "tool.minutes", diff/Minute) diff -= diff / Minute * Minute case diff < 2*Hour: diff -= 1 * Hour - diffStr = "1 hour" + diffStr = i18n.Tr(lang, "tool.1h") case diff < 1*Day: - diffStr = fmt.Sprintf("%d hours", diff/Hour) + diffStr = i18n.Tr(lang, "tool.hours", diff/Hour) diff -= diff / Hour * Hour case diff < 2*Day: diff -= 1 * Day - diffStr = "1 day" + diffStr = i18n.Tr(lang, "tool.1d") case diff < 1*Week: - diffStr = fmt.Sprintf("%d days", diff/Day) + diffStr = i18n.Tr(lang, "tool.days", diff/Day) diff -= diff / Day * Day case diff < 2*Week: diff -= 1 * Week - diffStr = "1 week" + diffStr = i18n.Tr(lang, "tool.1w") case diff < 1*Month: - diffStr = fmt.Sprintf("%d weeks", diff/Week) + diffStr = i18n.Tr(lang, "tool.weeks", diff/Week) diff -= diff / Week * Week case diff < 2*Month: diff -= 1 * Month - diffStr = "1 month" + diffStr = i18n.Tr(lang, "tool.1mon") case diff < 1*Year: - diffStr = fmt.Sprintf("%d months", diff/Month) + diffStr = i18n.Tr(lang, "tool.months", diff/Month) diff -= diff / Month * Month case diff < 2*Year: diff -= 1 * Year - diffStr = "1 year" + diffStr = i18n.Tr(lang, "tool.1y") default: - diffStr = fmt.Sprintf("%d years", diff/Year) + diffStr = i18n.Tr(lang, "tool.years", diff/Year) diff -= (diff / Year) * Year } return diff, diffStr @@ -279,24 +279,24 @@ func computeTimeDiff(diff int64) (int64, string) { // MinutesToFriendly returns a user friendly string with number of minutes // converted to hours and minutes. -func MinutesToFriendly(minutes int) string { +func MinutesToFriendly(minutes int, lang string) string { duration := time.Duration(minutes) * time.Minute - return TimeSincePro(time.Now().Add(-duration)) + return TimeSincePro(time.Now().Add(-duration), lang) } // TimeSincePro calculates the time interval and generate full user-friendly string. -func TimeSincePro(then time.Time) string { - return timeSincePro(then, time.Now()) +func TimeSincePro(then time.Time, lang string) string { + return timeSincePro(then, time.Now(), lang) } -func timeSincePro(then, now time.Time) string { +func timeSincePro(then, now time.Time, lang string) string { diff := now.Unix() - then.Unix() if then.After(now) { - return "future" + return i18n.Tr(lang, "tool.future") } if diff == 0 { - return "now" + return i18n.Tr(lang, "tool.now") } var timeStr, diffStr string @@ -305,58 +305,25 @@ func timeSincePro(then, now time.Time) string { break } - diff, diffStr = computeTimeDiff(diff) + diff, diffStr = computeTimeDiff(diff, lang) timeStr += ", " + diffStr } return strings.TrimPrefix(timeStr, ", ") } func timeSince(then, now time.Time, lang string) string { - lbl := i18n.Tr(lang, "tool.ago") + lbl := "tool.ago" diff := now.Unix() - then.Unix() if then.After(now) { - lbl = i18n.Tr(lang, "tool.from_now") + lbl = "tool.from_now" diff = then.Unix() - now.Unix() } - - switch { - case diff <= 0: + if diff <= 0 { return i18n.Tr(lang, "tool.now") - case diff <= 1: - return i18n.Tr(lang, "tool.1s", lbl) - case diff < 1*Minute: - return i18n.Tr(lang, "tool.seconds", diff, lbl) - - case diff < 2*Minute: - return i18n.Tr(lang, "tool.1m", lbl) - case diff < 1*Hour: - return i18n.Tr(lang, "tool.minutes", diff/Minute, lbl) - - case diff < 2*Hour: - return i18n.Tr(lang, "tool.1h", lbl) - case diff < 1*Day: - return i18n.Tr(lang, "tool.hours", diff/Hour, lbl) - - case diff < 2*Day: - return i18n.Tr(lang, "tool.1d", lbl) - case diff < 1*Week: - return i18n.Tr(lang, "tool.days", diff/Day, lbl) - - case diff < 2*Week: - return i18n.Tr(lang, "tool.1w", lbl) - case diff < 1*Month: - return i18n.Tr(lang, "tool.weeks", diff/Week, lbl) - - case diff < 2*Month: - return i18n.Tr(lang, "tool.1mon", lbl) - case diff < 1*Year: - return i18n.Tr(lang, "tool.months", diff/Month, lbl) - - case diff < 2*Year: - return i18n.Tr(lang, "tool.1y", lbl) - default: - return i18n.Tr(lang, "tool.years", diff/Year, lbl) } + + _, diffStr := computeTimeDiff(diff, lang) + return i18n.Tr(lang, lbl, diffStr) } // RawTimeSince retrieves i18n key of time since t diff --git a/modules/base/tool_test.go b/modules/base/tool_test.go index bd9c6e276..f3e787dd1 100644 --- a/modules/base/tool_test.go +++ b/modules/base/tool_test.go @@ -145,7 +145,7 @@ func TestComputeTimeDiff(t *testing.T) { // computeTimeDiff(base + offset) == (offset, str) test := func(base int64, str string, offsets ...int64) { for _, offset := range offsets { - diff, diffStr := computeTimeDiff(base + offset) + diff, diffStr := computeTimeDiff(base+offset, "en") assert.Equal(t, offset, diff) assert.Equal(t, str, diffStr) } @@ -170,7 +170,7 @@ func TestComputeTimeDiff(t *testing.T) { func TestMinutesToFriendly(t *testing.T) { // test that a number of minutes yields the expected string test := func(expected string, minutes int) { - actual := MinutesToFriendly(minutes) + actual := MinutesToFriendly(minutes, "en") assert.Equal(t, expected, actual) } test("1 minute", 1) @@ -186,13 +186,11 @@ func TestTimeSince(t *testing.T) { // test that each diff in `diffs` yields the expected string test := func(expected string, diffs ...time.Duration) { - ago := i18n.Tr("en", "tool.ago") - fromNow := i18n.Tr("en", "tool.from_now") for _, diff := range diffs { actual := timeSince(BaseDate, BaseDate.Add(diff), "en") - assert.Equal(t, expected+" "+ago, actual) + assert.Equal(t, i18n.Tr("en", "tool.ago", expected), actual) actual = timeSince(BaseDate.Add(diff), BaseDate, "en") - assert.Equal(t, expected+" "+fromNow, actual) + assert.Equal(t, i18n.Tr("en", "tool.from_now", expected), actual) } } test("1 second", time.Second, time.Second+50*time.Millisecond) @@ -212,13 +210,13 @@ func TestTimeSince(t *testing.T) { } func TestTimeSincePro(t *testing.T) { - assert.Equal(t, "now", timeSincePro(BaseDate, BaseDate)) + assert.Equal(t, "now", timeSincePro(BaseDate, BaseDate, "en")) // test that a difference of `diff` yields the expected string test := func(expected string, diff time.Duration) { - actual := timeSincePro(BaseDate, BaseDate.Add(diff)) + actual := timeSincePro(BaseDate, BaseDate.Add(diff), "en") assert.Equal(t, expected, actual) - assert.Equal(t, "future", timeSincePro(BaseDate.Add(diff), BaseDate)) + assert.Equal(t, "future", timeSincePro(BaseDate.Add(diff), BaseDate, "en")) } test("1 second", time.Second) test("2 seconds", 2*time.Second) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 0cbb32df1..b74921b02 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1385,23 +1385,24 @@ push_tag = pushed tag %[2]s to %[3]s compare_commits = Compare %d commits [tool] -ago = ago -from_now = from now +ago = %s ago +from_now = %s from now now = now -1s = 1 second %s -1m = 1 minute %s -1h = 1 hour %s -1d = 1 day %s -1w = 1 week %s -1mon = 1 month %s -1y = 1 year %s -seconds = %d seconds %s -minutes = %d minutes %s -hours = %d hours %s -days = %d days %s -weeks = %d weeks %s -months = %d months %s -years = %d years %s +future = future +1s = 1 second +1m = 1 minute +1h = 1 hour +1d = 1 day +1w = 1 week +1mon = 1 month +1y = 1 year +seconds = %d seconds +minutes = %d minutes +hours = %d hours +days = %d days +weeks = %d weeks +months = %d months +years = %d years raw_seconds = seconds raw_minutes = minutes diff --git a/routers/admin/admin.go b/routers/admin/admin.go index 3ce194f2b..d439544c8 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -73,7 +73,7 @@ var sysStatus struct { } func updateSystemStatus() { - sysStatus.Uptime = base.TimeSincePro(startTime) + sysStatus.Uptime = base.TimeSincePro(startTime, "en") m := new(runtime.MemStats) runtime.ReadMemStats(m) diff --git a/routers/dev/template.go b/routers/dev/template.go index fc3ef9942..ad0d2c1cd 100644 --- a/routers/dev/template.go +++ b/routers/dev/template.go @@ -18,8 +18,8 @@ func TemplatePreview(ctx *context.Context) { ctx.Data["AppVer"] = setting.AppVer ctx.Data["AppUrl"] = setting.AppURL ctx.Data["Code"] = "2014031910370000009fff6782aadb2162b4a997acb69d4400888e0b9274657374" - ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives) - ctx.Data["ResetPwdCodeLives"] = base.MinutesToFriendly(setting.Service.ResetPwdCodeLives) + ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) + ctx.Data["ResetPwdCodeLives"] = base.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language()) ctx.Data["CurDbValue"] = "" ctx.HTML(200, base.TplName(ctx.Params("*"))) diff --git a/routers/user/auth.go b/routers/user/auth.go index d1a6fc8a9..f1aa9d26a 100644 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -677,7 +677,7 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au models.SendActivateAccountMail(ctx.Context, u) ctx.Data["IsSendRegisterMail"] = true ctx.Data["Email"] = u.Email - ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives) + ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) ctx.HTML(200, TplActivate) if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { @@ -792,7 +792,7 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo models.SendActivateAccountMail(ctx.Context, u) ctx.Data["IsSendRegisterMail"] = true ctx.Data["Email"] = u.Email - ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives) + ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) ctx.HTML(200, TplActivate) if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { @@ -818,7 +818,7 @@ func Activate(ctx *context.Context) { if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) { ctx.Data["ResendLimited"] = true } else { - ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives) + ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) models.SendActivateAccountMail(ctx.Context, ctx.User) if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { @@ -913,7 +913,7 @@ func ForgotPasswdPost(ctx *context.Context) { u, err := models.GetUserByEmail(email) if err != nil { if models.IsErrUserNotExist(err) { - ctx.Data["ResetPwdCodeLives"] = base.MinutesToFriendly(setting.Service.ResetPwdCodeLives) + ctx.Data["ResetPwdCodeLives"] = base.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language()) ctx.Data["IsResetSent"] = true ctx.HTML(200, tplForgotPassword) return @@ -940,7 +940,7 @@ func ForgotPasswdPost(ctx *context.Context) { log.Error(4, "Set cache(MailResendLimit) fail: %v", err) } - ctx.Data["ResetPwdCodeLives"] = base.MinutesToFriendly(setting.Service.ResetPwdCodeLives) + ctx.Data["ResetPwdCodeLives"] = base.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language()) ctx.Data["IsResetSent"] = true ctx.HTML(200, tplForgotPassword) } diff --git a/routers/user/auth_openid.go b/routers/user/auth_openid.go index 15bbe41c1..ff03e538f 100644 --- a/routers/user/auth_openid.go +++ b/routers/user/auth_openid.go @@ -415,7 +415,7 @@ func RegisterOpenIDPost(ctx *context.Context, cpt *captcha.Captcha, form auth.Si models.SendActivateAccountMail(ctx.Context, u) ctx.Data["IsSendRegisterMail"] = true ctx.Data["Email"] = u.Email - ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives) + ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) ctx.HTML(200, TplActivate) if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { diff --git a/routers/user/setting.go b/routers/user/setting.go index 1cc601282..b6bd4ed5c 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -298,7 +298,7 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) { if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { log.Error(4, "Set cache(MailResendLimit) fail: %v", err) } - ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", email.Email, base.MinutesToFriendly(setting.Service.ActiveCodeLives))) + ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", email.Email, base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()))) } else { ctx.Flash.Success(ctx.Tr("settings.add_email_success")) }