Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make time diff translatable #2057

Merged
merged 1 commit into from
Jun 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions models/mail.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down Expand Up @@ -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,
}
Expand Down
93 changes: 30 additions & 63 deletions modules/base/tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,84 +219,84 @@ 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
}

// 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
Expand All @@ -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
Expand Down
16 changes: 7 additions & 9 deletions modules/base/tool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down
33 changes: 17 additions & 16 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1385,23 +1385,24 @@ push_tag = pushed tag <a href="%s/src/%s">%[2]s</a> to <a href="%[1]s">%[3]s</a>
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
Expand Down
2 changes: 1 addition & 1 deletion routers/admin/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions routers/dev/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -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("*")))
Expand Down
10 changes: 5 additions & 5 deletions routers/user/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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)
}
Expand Down
2 changes: 1 addition & 1 deletion routers/user/auth_openid.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion routers/user/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
}
Expand Down