Refactor i18n name and fix the L() function in public HTML templates
This commit is contained in:
parent
4cd5e6ebeb
commit
ee4fb7182f
14 changed files with 111 additions and 71 deletions
15
cmd/init.go
15
cmd/init.go
|
@ -258,13 +258,13 @@ func initConstants() *constants {
|
|||
|
||||
// initI18n initializes a new i18n instance with the selected language map
|
||||
// loaded from the filesystem.
|
||||
func initI18n(lang string, fs stuffbin.FileSystem) *i18n.I18nLang {
|
||||
func initI18n(lang string, fs stuffbin.FileSystem) *i18n.I18n {
|
||||
b, err := fs.Read(fmt.Sprintf("/i18n/%s.json", lang))
|
||||
if err != nil {
|
||||
lo.Fatalf("error loading i18n language file: %v", err)
|
||||
}
|
||||
|
||||
i, err := i18n.New(lang, b)
|
||||
i, err := i18n.New(b)
|
||||
if err != nil {
|
||||
lo.Fatalf("error unmarshalling i18n language: %v", err)
|
||||
}
|
||||
|
@ -298,7 +298,7 @@ func initCampaignManager(q *Queries, cs *constants, app *App) *manager.Manager {
|
|||
ViewTrackURL: cs.ViewTrackURL,
|
||||
MessageURL: cs.MessageURL,
|
||||
UnsubHeader: ko.Bool("privacy.unsubscribe_header"),
|
||||
}, newManagerDB(q), campNotifCB, lo)
|
||||
}, newManagerDB(q), campNotifCB, app.i18n, lo)
|
||||
|
||||
}
|
||||
|
||||
|
@ -428,7 +428,7 @@ func initMediaStore() media.Store {
|
|||
|
||||
// initNotifTemplates compiles and returns e-mail notification templates that are
|
||||
// used for sending ad-hoc notifications to admins and subscribers.
|
||||
func initNotifTemplates(path string, fs stuffbin.FileSystem, i *i18n.I18nLang, cs *constants) *template.Template {
|
||||
func initNotifTemplates(path string, fs stuffbin.FileSystem, i *i18n.I18n, cs *constants) *template.Template {
|
||||
// Register utility functions that the e-mail templates can use.
|
||||
funcs := template.FuncMap{
|
||||
"RootURL": func() string {
|
||||
|
@ -437,7 +437,7 @@ func initNotifTemplates(path string, fs stuffbin.FileSystem, i *i18n.I18nLang, c
|
|||
"LogoURL": func() string {
|
||||
return cs.LogoURL
|
||||
},
|
||||
"L": func() *i18n.I18nLang {
|
||||
"L": func() *i18n.I18n {
|
||||
return i
|
||||
},
|
||||
}
|
||||
|
@ -464,7 +464,10 @@ func initHTTPServer(app *App) *echo.Echo {
|
|||
})
|
||||
|
||||
// Parse and load user facing templates.
|
||||
tpl, err := stuffbin.ParseTemplatesGlob(nil, app.fs, "/public/templates/*.html")
|
||||
tpl, err := stuffbin.ParseTemplatesGlob(template.FuncMap{
|
||||
"L": func() *i18n.I18n {
|
||||
return app.i18n
|
||||
}}, app.fs, "/public/templates/*.html")
|
||||
if err != nil {
|
||||
lo.Fatalf("error parsing public templates: %v", err)
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ type App struct {
|
|||
importer *subimporter.Importer
|
||||
messengers map[string]messenger.Messenger
|
||||
media media.Store
|
||||
i18n *i18n.I18nLang
|
||||
i18n *i18n.I18n
|
||||
notifTpls *template.Template
|
||||
log *log.Logger
|
||||
bufLog *buflog.BufLog
|
||||
|
|
|
@ -39,7 +39,7 @@ type tplData struct {
|
|||
LogoURL string
|
||||
FaviconURL string
|
||||
Data interface{}
|
||||
L *i18n.I18nLang
|
||||
L *i18n.I18n
|
||||
}
|
||||
|
||||
type publicTpl struct {
|
||||
|
|
14
i18n/en.json
14
i18n/en.json
|
@ -83,6 +83,7 @@
|
|||
"globals.buttons.cancel": "Cancel",
|
||||
"globals.buttons.clone": "Clone",
|
||||
"globals.buttons.close": "Close",
|
||||
"globals.buttons.continue": "Continue",
|
||||
"globals.buttons.delete": "Delete",
|
||||
"globals.buttons.edit": "Edit",
|
||||
"globals.buttons.enabled": "Enabled",
|
||||
|
@ -188,14 +189,25 @@
|
|||
"menu.media": "Media",
|
||||
"menu.newCampaign": "Create new",
|
||||
"menu.settings": "Settings",
|
||||
"public.subNotFound": "Subscription not found.",
|
||||
"public.campaignNotFound": "The e-mail message was not found.",
|
||||
"public.unsubTitle": "Unsubscribe",
|
||||
"public.unsubHelp": "Do you want to unsubscribe from this mailing list?",
|
||||
"public.unsubFull": "Also unsubscribe from all future e-mails.",
|
||||
"public.unsub": "Unsubscribe",
|
||||
"public.privacyTitle": "Privacy and data",
|
||||
"public.privacyExport": "Export your data",
|
||||
"public.privacyExportHelp": "A copy of your data will be e-mailed to you.",
|
||||
"public.privacyWipe": "Wipe your data",
|
||||
"public.privacyWipeHelp": "Delete all your subscriptions and related data from the database permanently.",
|
||||
"public.privacyConfirmWipe": "Are you sure you want to delete all your subscription data permanently?",
|
||||
"public.confirmOptinSubTitle": "Confirm subscription",
|
||||
"public.confirmSub": "Confirm subscription",
|
||||
"public.confirmSubInfo": "You have been added to the following lists:",
|
||||
"public.confirmSubTitle": "Confirm",
|
||||
"public.dataRemoved": "Your subscriptions and all associated data has been removed.",
|
||||
"public.dataRemovedTitle": "Data removed",
|
||||
"public.dataSent": "Your data has been e-mailed to you as an attachment",
|
||||
"public.dataSent": "Your data has been e-mailed to you as an attachment.",
|
||||
"public.dataSentTitle": "Data e-mailed",
|
||||
"public.errorFetchingCampaign": "Error fetching e-mail message",
|
||||
"public.errorFetchingEmail": "E-mail message not found",
|
||||
|
|
|
@ -1,48 +1,66 @@
|
|||
// i18n is a simple package that translates strings using a language map.
|
||||
// It mimicks some functionality of the vue-i18n library so that the same JSON
|
||||
// language map may be used in the JS frontent and the Go backend.
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Lang represents a loaded language.
|
||||
type Lang struct {
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
langMap map[string]string
|
||||
}
|
||||
|
||||
// I18nLang is a simple i18n library that translates strings using a language map.
|
||||
// It mimicks some functionality of the vue-i18n library so that the same JSON
|
||||
// language map may be used in the JS frontent and the Go backend.
|
||||
type I18nLang struct {
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
// I18n offers translation functions over a language map.
|
||||
type I18n struct {
|
||||
code string `json:"code"`
|
||||
name string `json:"name"`
|
||||
langMap map[string]string
|
||||
}
|
||||
|
||||
var reParam = regexp.MustCompile(`(?i)\{([a-z0-9-.]+)\}`)
|
||||
|
||||
// New returns an I18n instance.
|
||||
func New(code string, b []byte) (*I18nLang, error) {
|
||||
func New(b []byte) (*I18n, error) {
|
||||
var l map[string]string
|
||||
if err := json.Unmarshal(b, &l); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &I18nLang{
|
||||
|
||||
code, ok := l["_.code"]
|
||||
if !ok {
|
||||
return nil, errors.New("missing _.code field in language file")
|
||||
}
|
||||
|
||||
name, ok := l["_.name"]
|
||||
if !ok {
|
||||
return nil, errors.New("missing _.name field in language file")
|
||||
}
|
||||
|
||||
return &I18n{
|
||||
langMap: l,
|
||||
code: code,
|
||||
name: name,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Name returns the canonical name of the language.
|
||||
func (i *I18n) Name() string {
|
||||
return i.name
|
||||
}
|
||||
|
||||
// Code returns the ISO code of the language.
|
||||
func (i *I18n) Code() string {
|
||||
return i.code
|
||||
}
|
||||
|
||||
// JSON returns the languagemap as raw JSON.
|
||||
func (i *I18nLang) JSON() []byte {
|
||||
func (i *I18n) JSON() []byte {
|
||||
b, _ := json.Marshal(i.langMap)
|
||||
return b
|
||||
}
|
||||
|
||||
// T returns the translation for the given key similar to vue i18n's t().
|
||||
func (i *I18nLang) T(key string) string {
|
||||
func (i *I18n) T(key string) string {
|
||||
s, ok := i.langMap[key]
|
||||
if !ok {
|
||||
return key
|
||||
|
@ -59,7 +77,7 @@ func (i *I18nLang) T(key string) string {
|
|||
// eg: Ts("globals.message.notFound",
|
||||
// "name", "campaigns",
|
||||
// "error", err)
|
||||
func (i *I18nLang) Ts(key string, params ...string) string {
|
||||
func (i *I18n) Ts(key string, params ...string) string {
|
||||
if len(params)%2 != 0 {
|
||||
return key + `: Invalid arguments`
|
||||
}
|
||||
|
@ -82,7 +100,7 @@ func (i *I18nLang) Ts(key string, params ...string) string {
|
|||
// Tc returns the translation for the given key similar to vue i18n's tc().
|
||||
// It expects the language string in the map to be of the form `Singular | Plural` and
|
||||
// returns `Plural` if n > 1, or `Singular` otherwise.
|
||||
func (i *I18nLang) Tc(key string, n int) string {
|
||||
func (i *I18n) Tc(key string, n int) string {
|
||||
s, ok := i.langMap[key]
|
||||
if !ok {
|
||||
return key
|
||||
|
@ -98,7 +116,7 @@ func (i *I18nLang) Tc(key string, n int) string {
|
|||
|
||||
// getSingular returns the singular term from the vuei18n pipe separated value.
|
||||
// singular term | plural term
|
||||
func (i *I18nLang) getSingular(s string) string {
|
||||
func (i *I18n) getSingular(s string) string {
|
||||
if !strings.Contains(s, "|") {
|
||||
return s
|
||||
}
|
||||
|
@ -108,7 +126,7 @@ func (i *I18nLang) getSingular(s string) string {
|
|||
|
||||
// getSingular returns the plural term from the vuei18n pipe separated value.
|
||||
// singular term | plural term
|
||||
func (i *I18nLang) getPlural(s string) string {
|
||||
func (i *I18n) getPlural(s string) string {
|
||||
if !strings.Contains(s, "|") {
|
||||
return s
|
||||
}
|
||||
|
@ -122,7 +140,7 @@ func (i *I18nLang) getPlural(s string) string {
|
|||
}
|
||||
|
||||
// subAllParams recursively resolves and replaces all {params} in a string.
|
||||
func (i *I18nLang) subAllParams(s string) string {
|
||||
func (i *I18n) subAllParams(s string) string {
|
||||
if !strings.Contains(s, `{`) {
|
||||
return s
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/knadh/listmonk/internal/i18n"
|
||||
"github.com/knadh/listmonk/internal/messenger"
|
||||
"github.com/knadh/listmonk/models"
|
||||
)
|
||||
|
@ -40,6 +41,7 @@ type DataSource interface {
|
|||
type Manager struct {
|
||||
cfg Config
|
||||
src DataSource
|
||||
i18n *i18n.I18n
|
||||
messengers map[string]messenger.Messenger
|
||||
notifCB models.AdminNotifCallback
|
||||
logger *log.Logger
|
||||
|
@ -108,7 +110,7 @@ type msgError struct {
|
|||
}
|
||||
|
||||
// New returns a new instance of Mailer.
|
||||
func New(cfg Config, src DataSource, notifCB models.AdminNotifCallback, l *log.Logger) *Manager {
|
||||
func New(cfg Config, src DataSource, notifCB models.AdminNotifCallback, i *i18n.I18n, l *log.Logger) *Manager {
|
||||
if cfg.BatchSize < 1 {
|
||||
cfg.BatchSize = 1000
|
||||
}
|
||||
|
@ -122,6 +124,7 @@ func New(cfg Config, src DataSource, notifCB models.AdminNotifCallback, l *log.L
|
|||
return &Manager{
|
||||
cfg: cfg,
|
||||
src: src,
|
||||
i18n: i,
|
||||
notifCB: notifCB,
|
||||
logger: l,
|
||||
messengers: make(map[string]messenger.Messenger),
|
||||
|
@ -334,6 +337,9 @@ func (m *Manager) TemplateFuncs(c *models.Campaign) template.FuncMap {
|
|||
}
|
||||
return time.Now().Format(layout)
|
||||
},
|
||||
"L": func() *i18n.I18n {
|
||||
return m.i18n
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
{{ define "campaign-status" }}
|
||||
{{ template "header" . }}
|
||||
<h2>{{ .L.T "email.status.campaignUpdate" }}</h2>
|
||||
<h2>{{ L.Ts "email.status.campaignUpdate" }}</h2>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="30%"><strong>{{ .L.T "globa.L.Terms.campaign" }}</strong></td>
|
||||
<td width="30%"><strong>{{ L.Ts "globa.L.Terms.campaign" }}</strong></td>
|
||||
<td><a href="{{ index . "RootURL" }}/campaigns/{{ index . "ID" }}">{{ index . "Name" }}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="30%"><strong>{{ .L.T "email.status.status" }}</strong></td>
|
||||
<td width="30%"><strong>{{ L.Ts "email.status.status" }}</strong></td>
|
||||
<td>{{ index . "Status" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="30%"><strong>{{ .L.T "email.status.campaignSent" }}</strong></td>
|
||||
<td width="30%"><strong>{{ L.Ts "email.status.campaignSent" }}</strong></td>
|
||||
<td>{{ index . "Sent" }} / {{ index . "ToSend" }}</td>
|
||||
</tr>
|
||||
{{ if ne (index . "Reason") "" }}
|
||||
<tr>
|
||||
<td width="30%"><strong>{{ .L.T "email.status.campaignReason" }}</strong></td>
|
||||
<td width="30%"><strong>{{ L.Ts "email.status.campaignReason" }}</strong></td>
|
||||
<td>{{ index . "Reason" }}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
|
|
|
@ -77,8 +77,8 @@
|
|||
|
||||
<div class="footer" style="text-align: center;font-size: 12px;color: #888;">
|
||||
<p>
|
||||
{{ I18n.T "email.unsubHelp" }}
|
||||
<a href="{{ UnsubscribeURL }}" style="color: #888;">{{ I18n.T "email.unsub" }}</a>
|
||||
{{ L.T "email.unsubHelp" }}
|
||||
<a href="{{ UnsubscribeURL }}" style="color: #888;">{{ L.T "email.unsub" }}</a>
|
||||
</p>
|
||||
<p>Powered by <a href="https://listmonk.app" target="_blank" style="color: #888;">listmonk</a></p>
|
||||
</div>
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
{{ define "import-status" }}
|
||||
{{ template "header" . }}
|
||||
<h2>{{ .L.T "email.status.importTitle" }}</h2>
|
||||
<h2>{{ L.Ts "email.status.importTitle" }}</h2>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td width="30%"><strong>{{ .L.T "email.status.importFile" }}</strong></td>
|
||||
<td width="30%"><strong>{{ L.Ts "email.status.importFile" }}</strong></td>
|
||||
<td><a href="{{ RootURL }}/subscribers/import">{{ .Name }}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="30%"><strong>{{ .L.T "email.status.status" }}</strong></td>
|
||||
<td width="30%"><strong>{{ L.Ts "email.status.status" }}</strong></td>
|
||||
<td>{{ .Status }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="30%"><strong>{{ .L.T "email.status.importRecords" }}</strong></td>
|
||||
<td width="30%"><strong>{{ L.Ts "email.status.importRecords" }}</strong></td>
|
||||
<td>{{ .Imported }} / {{ .Total }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{{ define "subscriber-data" }}
|
||||
{{ template "header" . }}
|
||||
<h2>{{ .L.T "email.data.title" }}</h2>
|
||||
<h2>{{ L.Ts "email.data.title" }}</h2>
|
||||
<p>
|
||||
{{ .L.T "email.data.info" }}
|
||||
{{ L.Ts "email.data.info" }}
|
||||
</p>
|
||||
{{ template "footer" }}
|
||||
{{ end }}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
{{ define "optin-campaign" }}
|
||||
|
||||
<p>{{ .L.Ts "email.optin.confirmSubWelcome" "name" .Subscriber.FirstName }}</p>
|
||||
<p>{{ .L.T "email.optin.confirmSubInfo" }}</p>
|
||||
<p>{{ L.Ts "email.optin.confirmSubWelcome" "name" .Subscriber.FirstName }}</p>
|
||||
<p>{{ L.Ts "email.optin.confirmSubInfo" }}</p>
|
||||
<ul>
|
||||
{{ range $i, $l := .Lists }}
|
||||
{{ if eq .Type "public" }}
|
||||
<li>{{ .Name }}</li>
|
||||
{{ else }}
|
||||
<li>{{ .L.T "email.optin.privateList" }}</li>
|
||||
<li>{{ L.Ts "email.optin.privateList" }}</li>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</ul>
|
||||
<p>
|
||||
<a class="button" {{ .OptinURLAttr }} class="button">{{ .L.T "email.optin.confirmSub" }}</a>
|
||||
<a class="button" {{ .OptinURLAttr }} class="button">{{ L.Ts "email.optin.confirmSub" }}</a>
|
||||
</p>
|
||||
{{ end }}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
{{ define "subscriber-optin" }}
|
||||
{{ template "header" . }}
|
||||
<h2>{{ .L.T "email.optin.confirmSubTitle" }}</h2>
|
||||
<p>{{ .L.Ts "email.optin.confirmSubWelcome" "name" .Subscriber.FirstName }}</p>
|
||||
<p>{{ .L.T "email.optin.confirmSubInfo" }}</p>
|
||||
<h2>{{ L.Ts "email.optin.confirmSubTitle" }}</h2>
|
||||
<p>{{ L.Ts "email.optin.confirmSubWelcome" "name" .Subscriber.FirstName }}</p>
|
||||
<p>{{ L.Ts "email.optin.confirmSubInfo" }}</p>
|
||||
<ul>
|
||||
{{ range $i, $l := .Lists }}
|
||||
{{ if eq .Type "public" }}
|
||||
<li>{{ .Name }}</li>
|
||||
{{ else }}
|
||||
<li>{{ .L.T "email.optin.privateList" }}</li>
|
||||
<li>{{ L.Ts "email.optin.privateList" }}</li>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</ul>
|
||||
<p>{{ .L.T "email.optin.confirmSubHelp" }}</p>
|
||||
<p>{{ L.Ts "email.optin.confirmSubHelp" }}</p>
|
||||
<p>
|
||||
<a href="{{ .OptinURL }}" class="button">{{ .L.T "email.optin.confirmSub" }}</a>
|
||||
<a href="{{ .OptinURL }}" class="button">{{ L.Ts "email.optin.confirmSub" }}</a>
|
||||
</p>
|
||||
|
||||
{{ template "footer" }}
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
{{ define "optin" }}
|
||||
{{ template "header" .}}
|
||||
<section>
|
||||
<h2>{{ .L.T "public.confirmSubTitle" }}</h2>
|
||||
<h2>{{ L.T "public.confirmSubTitle" }}</h2>
|
||||
<p>
|
||||
{{ .L.T "public.confirmSubInfo" }}
|
||||
{{ L.T "public.confirmSubInfo" }}
|
||||
</p>
|
||||
|
||||
<form method="post">
|
||||
<ul>
|
||||
{{ range $i, $l := .Data.Lists }}
|
||||
<input type="hidden" name="l" value="{{ $l.UUID }}" />
|
||||
{{ if eq $.L.Type "public" }}
|
||||
{{ if eq $l.Type "public" }}
|
||||
<li>{{ $l.Name }}</li>
|
||||
{{ else }}
|
||||
<li>{{ .L.T "public.subPrivateList" }}</li>
|
||||
<li>{{ L.Ts "public.subPrivateList" }}</li>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</ul>
|
||||
<p>
|
||||
<input type="hidden" name="confirm" value="true" />
|
||||
<button type="submit" class="button" id="btn-unsub">
|
||||
{{ .L.T "public.confirmSub" }}
|
||||
{{ L.Ts "public.confirmSub" }}
|
||||
</button>
|
||||
</p>
|
||||
</form>
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
{{ define "subscription" }}
|
||||
{{ template "header" .}}
|
||||
<section>
|
||||
<h2>Unsubscribe</h2>
|
||||
<p>Do you wish to unsubscribe from this mailing list?</p>
|
||||
<h2>{{ L.T "public.unsubTitle" }}</h2>
|
||||
<p>{{ L.T "public.unsubHelp" }}</p>
|
||||
<form method="post">
|
||||
<div>
|
||||
{{ if .Data.AllowBlocklist }}
|
||||
<p>
|
||||
<input id="privacy-blocklist" type="checkbox" name="blocklist" value="true" /> <label for="privacy-blocklist">Also unsubscribe from all future e-mails.</label>
|
||||
<input id="privacy-blocklist" type="checkbox" name="blocklist" value="true" />
|
||||
<label for="privacy-blocklist">{{ L.T "public.unsubFull" }}</label>
|
||||
</p>
|
||||
{{ end }}
|
||||
|
||||
<p>
|
||||
<button type="submit" class="button" id="btn-unsub">Unsubscribe</button>
|
||||
<button type="submit" class="button" id="btn-unsub">{{ L.T "public.unsub" }}</button>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -21,16 +22,16 @@
|
|||
{{ if or .Data.AllowExport .Data.AllowWipe }}
|
||||
<form id="data-form" method="post" action="" onsubmit="return handleData()">
|
||||
<section>
|
||||
<h2>Privacy and data</h2>
|
||||
<h2>{{ L.T "public.privacyTitle" }}</h2>
|
||||
{{ if .Data.AllowExport }}
|
||||
<div class="row">
|
||||
<div class="one columns">
|
||||
<input id="privacy-export" type="radio" name="data-action" value="export" required />
|
||||
</div>
|
||||
<div class="ten columns">
|
||||
<label for="privacy-export"><strong>Export your data</strong></label>
|
||||
<label for="privacy-export"><strong>{{ L.T "public.privacyExport" }}</strong></label>
|
||||
<br />
|
||||
A copy of your data will be e-mailed to you.
|
||||
{{ L.T "public.privacyExportHelp" }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
@ -41,14 +42,14 @@
|
|||
<input id="privacy-wipe" type="radio" name="data-action" value="wipe" required />
|
||||
</div>
|
||||
<div class="ten columns">
|
||||
<label for="privacy-wipe"><strong>Wipe your data</strong></label>
|
||||
<label for="privacy-wipe"><strong>{{ L.T "public.privacyWipe" }}</strong></label>
|
||||
<br />
|
||||
Delete all your subscriptions and related data from our database permanently.
|
||||
{{ L.T "public.privacyWipeHelp" }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
<p>
|
||||
<input type="submit" value="Continue" class="button button-outline" />
|
||||
<input type="submit" value="{{ L.T "globals.buttons.continue" }}" class="button button-outline" />
|
||||
</p>
|
||||
</section>
|
||||
</form>
|
||||
|
@ -59,7 +60,7 @@
|
|||
if (a == "export") {
|
||||
f.action = "/subscription/export/{{ .Data.SubUUID }}";
|
||||
return true;
|
||||
} else if (confirm("Are you sure you want to delete all your subscription data permanently?")) {
|
||||
} else if (confirm("{{ L.T "public.privacyConfirmWipe" }}")) {
|
||||
f.action = "/subscription/wipe/{{ .Data.SubUUID }}";
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue