🌐 Fully localized notification

This commit is contained in:
LittleSheep 2025-02-01 17:59:58 +08:00
parent d7ee87433f
commit b68aed0284
5 changed files with 48 additions and 64 deletions

88
.idea/workspace.xml generated
View File

@ -4,29 +4,12 @@
<option name="autoReloadType" value="ALL" /> <option name="autoReloadType" value="ALL" />
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="3fefb2c4-b6f9-466b-a523-53352e8d6f95" name="更改" comment=":sparkles: Account preferred language"> <list default="true" id="3fefb2c4-b6f9-466b-a523-53352e8d6f95" name="更改" comment=":sparkles: Push email &amp; notification localization">
<change afterPath="$PROJECT_DIR$/locales/en-US.json" afterDir="false" />
<change afterPath="$PROJECT_DIR$/locales/zh-CN.json" afterDir="false" />
<change afterPath="$PROJECT_DIR$/pkg/internal/services/i18n.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/email/en-US/confirm-deletion.tmpl" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/email/en-US/email-otp.tmpl" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/email/en-US/register-confirm.tmpl" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/email/en-US/reset-password.tmpl" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/email/zh-CN/confirm-deletion.tmpl" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/email/zh-CN/email-otp.tmpl" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/email/zh-CN/register-confirm.tmpl" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/email/zh-CN/reset-password.tmpl" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/dataSources.local.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/dataSources.local.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Dockerfile" beforeDir="false" afterPath="$PROJECT_DIR$/Dockerfile" afterDir="false" /> <change beforePath="$PROJECT_DIR$/locales/en-US.json" beforeDir="false" afterPath="$PROJECT_DIR$/locales/en-US.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/go.mod" beforeDir="false" afterPath="$PROJECT_DIR$/go.mod" afterDir="false" /> <change beforePath="$PROJECT_DIR$/locales/zh-CN.json" beforeDir="false" afterPath="$PROJECT_DIR$/locales/zh-CN.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/go.sum" beforeDir="false" afterPath="$PROJECT_DIR$/go.sum" afterDir="false" /> <change beforePath="$PROJECT_DIR$/pkg/internal/services/reports.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/internal/services/reports.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pkg/internal/http/api/accounts_api.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/internal/http/api/accounts_api.go" afterDir="false" /> <change beforePath="$PROJECT_DIR$/pkg/internal/services/ticket.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/internal/services/ticket.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pkg/internal/http/api/factors_api.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/internal/http/api/factors_api.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pkg/internal/services/factors.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/internal/services/factors.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pkg/internal/services/tokens.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/internal/services/tokens.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pkg/main.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/main.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/settings.toml" beforeDir="false" afterPath="$PROJECT_DIR$/settings.toml" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -65,35 +48,35 @@
<option name="hideEmptyMiddlePackages" value="true" /> <option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" /> <option name="showLibraryContents" value="true" />
</component> </component>
<component name="PropertiesComponent">{ <component name="PropertiesComponent"><![CDATA[{
&quot;keyToString&quot;: { "keyToString": {
&quot;DefaultGoTemplateProperty&quot;: &quot;Go File&quot;, "DefaultGoTemplateProperty": "Go File",
&quot;Go Build.Backend.executor&quot;: &quot;Debug&quot;, "Go Build.Backend.executor": "Run",
&quot;Go 构建.Backend.executor&quot;: &quot;Run&quot;, "Go 构建.Backend.executor": "Run",
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;, "RunOnceActivity.ShowReadmeOnStart": "true",
&quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;, "RunOnceActivity.git.unshallow": "true",
&quot;RunOnceActivity.go.formatter.settings.were.checked&quot;: &quot;true&quot;, "RunOnceActivity.go.formatter.settings.were.checked": "true",
&quot;RunOnceActivity.go.migrated.go.modules.settings&quot;: &quot;true&quot;, "RunOnceActivity.go.migrated.go.modules.settings": "true",
&quot;RunOnceActivity.go.modules.automatic.dependencies.download&quot;: &quot;true&quot;, "RunOnceActivity.go.modules.automatic.dependencies.download": "true",
&quot;RunOnceActivity.go.modules.go.list.on.any.changes.was.set&quot;: &quot;true&quot;, "RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true",
&quot;git-widget-placeholder&quot;: &quot;master&quot;, "git-widget-placeholder": "master",
&quot;go.import.settings.migrated&quot;: &quot;true&quot;, "go.import.settings.migrated": "true",
&quot;go.sdk.automatically.set&quot;: &quot;true&quot;, "go.sdk.automatically.set": "true",
&quot;last_opened_file_path&quot;: &quot;/Users/littlesheep/Documents/Projects/Hypernet/Passport&quot;, "last_opened_file_path": "/Users/littlesheep/Documents/Projects/Hypernet/Passport",
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;, "node.js.detected.package.eslint": "true",
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;, "node.js.selected.package.eslint": "(autodetect)",
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;, "nodejs_package_manager_path": "npm",
&quot;run.code.analysis.last.selected.profile&quot;: &quot;pProject Default&quot;, "run.code.analysis.last.selected.profile": "pProject Default",
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.intentionPowerPack&quot;, "settings.editor.selected.configurable": "preferences.intentionPowerPack",
&quot;ts.external.directory.path&quot;: &quot;/Users/littlesheep/Documents/Projects/Hydrogen/Passport/web/node_modules/typescript/lib&quot;, "ts.external.directory.path": "/Users/littlesheep/Documents/Projects/Hydrogen/Passport/web/node_modules/typescript/lib",
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot; "vue.rearranger.settings.migration": "true"
}, },
&quot;keyToStringList&quot;: { "keyToStringList": {
&quot;DatabaseDriversLRU&quot;: [ "DatabaseDriversLRU": [
&quot;postgresql&quot; "postgresql"
] ]
} }
}</component> }]]></component>
<component name="RecentsManager"> <component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS"> <key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/keys" /> <recent name="$PROJECT_DIR$/keys" />
@ -179,7 +162,6 @@
</component> </component>
<component name="VcsManagerConfiguration"> <component name="VcsManagerConfiguration">
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="false" /> <option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="false" />
<MESSAGE value=":loud_sound: Add verbose permission logging" />
<MESSAGE value=":bug: Fix group permission didn't extend properly" /> <MESSAGE value=":bug: Fix group permission didn't extend properly" />
<MESSAGE value=":mute: Remove authenticate result logging" /> <MESSAGE value=":mute: Remove authenticate result logging" />
<MESSAGE value=":truck: Rename daily-sign to check-in" /> <MESSAGE value=":truck: Rename daily-sign to check-in" />
@ -204,7 +186,8 @@
<MESSAGE value=":bug: Bug fixes on notifications" /> <MESSAGE value=":bug: Bug fixes on notifications" />
<MESSAGE value=":bug: Fix list user relative return wrong data" /> <MESSAGE value=":bug: Fix list user relative return wrong data" />
<MESSAGE value=":sparkles: Account preferred language" /> <MESSAGE value=":sparkles: Account preferred language" />
<option name="LAST_COMMIT_MESSAGE" value=":sparkles: Account preferred language" /> <MESSAGE value=":sparkles: Push email &amp; notification localization" />
<option name="LAST_COMMIT_MESSAGE" value=":sparkles: Push email &amp; notification localization" />
<option name="GROUP_MULTIFILE_MERGE_BY_DIRECTORY" value="true" /> <option name="GROUP_MULTIFILE_MERGE_BY_DIRECTORY" value="true" />
</component> </component>
<component name="VgoProject"> <component name="VgoProject">
@ -218,11 +201,6 @@
<line>93</line> <line>93</line>
<option name="timeStamp" value="3" /> <option name="timeStamp" value="3" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
<url>file://$PROJECT_DIR$/pkg/internal/services/notifications.go</url>
<line>73</line>
<option name="timeStamp" value="4" />
</line-breakpoint>
</breakpoints> </breakpoints>
</breakpoint-manager> </breakpoint-manager>
</component> </component>

View File

@ -3,5 +3,9 @@
"shortBodyLoginOneTimePassword": "%s is your login verification code. It will expires in 30 minutes.", "shortBodyLoginOneTimePassword": "%s is your login verification code. It will expires in 30 minutes.",
"subjectConfirmRegistration": "Confirm your registration", "subjectConfirmRegistration": "Confirm your registration",
"subjectResetPassword": "Reset your password", "subjectResetPassword": "Reset your password",
"subjectDeleteAccount": "Confirm your account deletion" "subjectDeleteAccount": "Confirm your account deletion",
"subjectLoginAlert": "Login alert",
"shortBodyLoginAlert": "Your account got logged in from %s. If it's not your device, please deal with it immediately.",
"subjectAbuseReportUpdated": "Abuse report status has been changed",
"shortBodyAbuseReportUpdated": "Report #%d has been changed to %s. Moderator message: %s"
} }

View File

@ -3,5 +3,9 @@
"shortBodyLoginOneTimePassword": "%s 是您的登录验证码,它将在 30 分钟后过期。", "shortBodyLoginOneTimePassword": "%s 是您的登录验证码,它将在 30 分钟后过期。",
"subjectConfirmRegistration": "确认您的注册", "subjectConfirmRegistration": "确认您的注册",
"subjectResetPassword": "重置您的密码", "subjectResetPassword": "重置您的密码",
"subjectDeleteAccount": "确认您的帐户删除" "subjectDeleteAccount": "确认您的帐户删除",
"subjectLoginAlert": "登陆提醒",
"shortBodyLoginAlert": "您的帐户在 %s 登录,若它不是你的设备,请立即处理。",
"subjectAbuseReportUpdated": "举报状态已更新",
"shortBodyAbuseReportUpdated": "举报 #%d 已更新为 %s。管理员回复%s"
} }

View File

@ -42,9 +42,8 @@ func UpdateAbuseReportStatus(id uint, status, message string) error {
_ = NewNotification(models.Notification{ _ = NewNotification(models.Notification{
Topic: "reports.feedback", Topic: "reports.feedback",
Title: "Abuse report status has been changed.", Title: GetLocalizedString("subjectAbuseReportUpdated", account.Language),
Subtitle: fmt.Sprintf("The report #%d's status updated", id), Body: fmt.Sprintf(GetLocalizedString("shortBodyAbuseReportUpdated", account.Language), id, status, message),
Body: fmt.Sprintf("The report created by you with ID #%d's status has been changed to %s. Moderator message: %s", id, status, message),
Account: account, Account: account,
AccountID: account.ID, AccountID: account.ID,
}) })

View File

@ -129,10 +129,9 @@ func ActiveTicket(ticket models.AuthTicket) (models.AuthTicket, error) {
return ticket, err return ticket, err
} else { } else {
_ = NewNotification(models.Notification{ _ = NewNotification(models.Notification{
Topic: "passport.security.alert", Topic: "passport.security.alert",
Title: "New sign in alert", Title: GetLocalizedString("subjectLoginAlert", ticket.Account.Language),
Subtitle: fmt.Sprintf("New sign in from %s", ticket.IpAddress), Body: fmt.Sprintf(GetLocalizedString("shortBodyLoginAlert", ticket.Account.Language), ticket.IpAddress),
Body: fmt.Sprintf("Your account just got a new sign in from %s. Make sure you recongize this device, or sign out it immediately and reset password.", ticket.IpAddress),
Metadata: datatypes.JSONMap{ Metadata: datatypes.JSONMap{
"ip_address": ticket.IpAddress, "ip_address": ticket.IpAddress,
"created_at": ticket.CreatedAt, "created_at": ticket.CreatedAt,