diff --git a/api.go b/api.go index d1c382b..ecb47bb 100644 --- a/api.go +++ b/api.go @@ -1085,33 +1085,15 @@ func (app *appContext) GetConfig(gc *gin.Context) { app.info.Println("Config requested") resp := app.configBase // Load language options - loadLangs := func(langs *map[string]map[string]interface{}, settingsKey string) (string, []string) { - langOptions := make([]string, len(*langs)) - chosenLang := app.config.Section("ui").Key("language" + settingsKey).MustString("en-us") - chosenLangName := (*langs)[chosenLang]["meta"].(map[string]interface{})["name"].(string) - i := 0 - for _, lang := range *langs { - langOptions[i] = lang["meta"].(map[string]interface{})["name"].(string) - i++ - } - return chosenLangName, langOptions - } - formChosen, formOptions := loadLangs(&app.storage.lang.Form, "-form") + formChosen, formOptions := app.storage.lang.Form.getOptions(app.config.Section("ui").Key("language-form").MustString("en-us")) fl := resp.Sections["ui"].Settings["language-form"] fl.Options = formOptions fl.Value = formChosen - adminChosen, adminOptions := loadLangs(&app.storage.lang.Admin, "-admin") + adminChosen, adminOptions := app.storage.lang.Admin.getOptions(app.config.Section("ui").Key("language-admin").MustString("en-us")) al := resp.Sections["ui"].Settings["language-admin"] al.Options = adminOptions al.Value = adminChosen - emailOptions := make([]string, len(app.storage.lang.Email)) - chosenLang := app.config.Section("email").Key("language").MustString("en-us") - emailChosen := app.storage.lang.Email.get(chosenLang, "meta", "name") - i := 0 - for langName := range app.storage.lang.Email { - emailOptions[i] = app.storage.lang.Email.get(langName, "meta", "name") - i++ - } + emailChosen, emailOptions := app.storage.lang.Email.getOptions(app.config.Section("email").Key("language").MustString("en-us")) el := resp.Sections["email"].Settings["language"] el.Options = emailOptions el.Value = emailChosen @@ -1136,7 +1118,7 @@ func (app *appContext) GetConfig(gc *gin.Context) { t := resp.Sections["jellyfin"].Settings["type"] opts := make([]string, len(serverTypes)) - i = 0 + i := 0 for _, v := range serverTypes { opts[i] = v i++ @@ -1169,21 +1151,21 @@ func (app *appContext) ModifyConfig(gc *gin.Context) { for setting, value := range settings.(map[string]interface{}) { if section == "ui" && setting == "language-form" { for key, lang := range app.storage.lang.Form { - if lang["meta"].(map[string]interface{})["name"].(string) == value.(string) { + if lang.Meta.Name == value.(string) { tempConfig.Section("ui").Key("language-form").SetValue(key) break } } } else if section == "ui" && setting == "language-admin" { for key, lang := range app.storage.lang.Admin { - if lang["meta"].(map[string]interface{})["name"].(string) == value.(string) { + if lang.Meta.Name == value.(string) { tempConfig.Section("ui").Key("language-admin").SetValue(key) break } } } else if section == "email" && setting == "language" { - for key := range app.storage.lang.Email { - if app.storage.lang.Email.get(key, "meta", "name") == value.(string) { + for key, lang := range app.storage.lang.Email { + if lang.Meta.Name == value.(string) { tempConfig.Section("email").Key("language").SetValue(key) break } @@ -1260,11 +1242,11 @@ func (app *appContext) GetLanguages(gc *gin.Context) { resp := langDTO{} if page == "form" { for key, lang := range app.storage.lang.Form { - resp[key] = lang["meta"].(map[string]interface{})["name"].(string) + resp[key] = lang.Meta.Name } } else if page == "admin" { for key, lang := range app.storage.lang.Admin { - resp[key] = lang["meta"].(map[string]interface{})["name"].(string) + resp[key] = lang.Meta.Name } } if len(resp) == 0 { @@ -1274,6 +1256,19 @@ func (app *appContext) GetLanguages(gc *gin.Context) { gc.JSON(200, resp) } +func (app *appContext) ServeLang(gc *gin.Context) { + page := gc.Param("page") + lang := strings.Replace(gc.Param("file"), ".json", "", 1) + if page == "admin" { + gc.JSON(200, app.storage.lang.Admin[lang]) + return + } else if page == "form" { + gc.JSON(200, app.storage.lang.Form[lang]) + return + } + respondBool(400, false, gc) +} + // func Restart() error { // defer func() { // if r := recover(); r != nil { diff --git a/email.go b/email.go index 27b411e..505bcf6 100644 --- a/email.go +++ b/email.go @@ -73,8 +73,7 @@ func (sm *SMTP) send(address, fromName, fromAddr string, email *Email) error { // Emailer contains the email sender, email content, and methods to construct message content. type Emailer struct { fromAddr, fromName string - lang *EmailLang - cLang string + lang emailLang sender emailClient } @@ -110,8 +109,7 @@ func NewEmailer(app *appContext) *Emailer { emailer := &Emailer{ fromAddr: app.config.Section("email").Key("address").String(), fromName: app.config.Section("email").Key("from").String(), - lang: &(app.storage.lang.Email), - cLang: app.storage.lang.chosenEmailLang, + lang: app.storage.lang.Email[app.storage.lang.chosenEmailLang], } method := app.config.Section("email").Key("method").String() if method == "smtp" { @@ -137,7 +135,7 @@ func (emailer *Emailer) NewMailgun(url, key string) { sender := &Mailgun{ client: mailgun.NewMailgun(strings.Split(emailer.fromAddr, "@")[1], key), } - // Mailgun client takes the base url, so we need to trim off the end (e.g 'v3/messages' + // Mailgun client takes the base url, so we need to trim off the end (e.g 'v3/messages') if strings.Contains(url, "messages") { url = url[0:strings.LastIndex(url, "/")] url = url[0:strings.LastIndex(url, "/")] @@ -157,9 +155,8 @@ func (emailer *Emailer) NewSMTP(server string, port int, username, password stri } func (emailer *Emailer) constructInvite(code string, invite Invite, app *appContext) (*Email, error) { - lang := emailer.cLang email := &Email{ - subject: app.config.Section("invite_emails").Key("subject").MustString(emailer.lang.get(lang, "inviteEmail", "title")), + subject: app.config.Section("invite_emails").Key("subject").MustString(emailer.lang.InviteEmail.get("title")), } expiry := invite.ValidTill d, t, expiresIn := emailer.formatExpiry(expiry, false, app.datePattern, app.timePattern) @@ -175,11 +172,11 @@ func (emailer *Emailer) constructInvite(code string, invite Invite, app *appCont } var tplData bytes.Buffer err = tpl.Execute(&tplData, map[string]string{ - "hello": emailer.lang.get(lang, "inviteEmail", "hello"), - "youHaveBeenInvited": emailer.lang.get(lang, "inviteEmail", "youHaveBeenInvited"), - "toJoin": emailer.lang.get(lang, "inviteEmail", "toJoin"), - "inviteExpiry": emailer.lang.format(lang, "inviteEmail", "inviteExpiry", d, t, expiresIn), - "linkButton": emailer.lang.get(lang, "inviteEmail", "linkButton"), + "hello": emailer.lang.InviteEmail.get("hello"), + "youHaveBeenInvited": emailer.lang.InviteEmail.get("youHaveBeenInvited"), + "toJoin": emailer.lang.InviteEmail.get("toJoin"), + "inviteExpiry": emailer.lang.InviteEmail.format("inviteExpiry", d, t, expiresIn), + "linkButton": emailer.lang.InviteEmail.get("linkButton"), "invite_link": inviteLink, "message": message, }) @@ -196,9 +193,8 @@ func (emailer *Emailer) constructInvite(code string, invite Invite, app *appCont } func (emailer *Emailer) constructExpiry(code string, invite Invite, app *appContext) (*Email, error) { - lang := emailer.cLang email := &Email{ - subject: emailer.lang.get(lang, "inviteExpiry", "title"), + subject: emailer.lang.InviteExpiry.get("title"), } expiry := app.formatDatetime(invite.ValidTill) for _, key := range []string{"html", "text"} { @@ -209,9 +205,9 @@ func (emailer *Emailer) constructExpiry(code string, invite Invite, app *appCont } var tplData bytes.Buffer err = tpl.Execute(&tplData, map[string]string{ - "inviteExpired": emailer.lang.get(lang, "inviteExpiry", "inviteExpired"), - "expiredAt": emailer.lang.format(lang, "inviteExpiry", "expiredAt", "\""+code+"\"", expiry), - "notificationNotice": emailer.lang.get(lang, "inviteExpiry", "notificationNotice"), + "inviteExpired": emailer.lang.InviteExpiry.get("inviteExpired"), + "expiredAt": emailer.lang.InviteExpiry.format("expiredAt", "\""+code+"\"", expiry), + "notificationNotice": emailer.lang.InviteExpiry.get("notificationNotice"), }) if err != nil { return nil, err @@ -226,9 +222,8 @@ func (emailer *Emailer) constructExpiry(code string, invite Invite, app *appCont } func (emailer *Emailer) constructCreated(code, username, address string, invite Invite, app *appContext) (*Email, error) { - lang := emailer.cLang email := &Email{ - subject: emailer.lang.get(lang, "userCreated", "title"), + subject: emailer.lang.UserCreated.get("title"), } created := app.formatDatetime(invite.Created) var tplAddress string @@ -245,14 +240,14 @@ func (emailer *Emailer) constructCreated(code, username, address string, invite } var tplData bytes.Buffer err = tpl.Execute(&tplData, map[string]string{ - "aUserWasCreated": emailer.lang.format(lang, "userCreated", "aUserWasCreated", "\""+code+"\""), - "name": emailer.lang.get(lang, "userCreated", "name"), - "address": emailer.lang.get(lang, "userCreated", "emailAddress"), - "time": emailer.lang.get(lang, "userCreated", "time"), + "aUserWasCreated": emailer.lang.UserCreated.format("aUserWasCreated", "\""+code+"\""), + "name": emailer.lang.UserCreated.get("name"), + "address": emailer.lang.UserCreated.get("emailAddress"), + "time": emailer.lang.UserCreated.get("time"), "nameVal": username, "addressVal": tplAddress, "timeVal": created, - "notificationNotice": emailer.lang.get(lang, "userCreated", "notificationNotice"), + "notificationNotice": emailer.lang.UserCreated.get("notificationNotice"), }) if err != nil { return nil, err @@ -267,9 +262,8 @@ func (emailer *Emailer) constructCreated(code, username, address string, invite } func (emailer *Emailer) constructReset(pwr PasswordReset, app *appContext) (*Email, error) { - lang := emailer.cLang email := &Email{ - subject: emailer.lang.get(lang, "passwordReset", "title"), + subject: emailer.lang.PasswordReset.get("title"), } d, t, expiresIn := emailer.formatExpiry(pwr.Expiry, true, app.datePattern, app.timePattern) message := app.config.Section("email").Key("message").String() @@ -281,12 +275,12 @@ func (emailer *Emailer) constructReset(pwr PasswordReset, app *appContext) (*Ema } var tplData bytes.Buffer err = tpl.Execute(&tplData, map[string]string{ - "helloUser": emailer.lang.format(lang, "passwordReset", "helloUser", pwr.Username), - "someoneHasRequestedReset": emailer.lang.get(lang, "passwordReset", "someoneHasRequestedReset"), - "ifItWasYou": emailer.lang.get(lang, "passwordReset", "ifItWasYou"), - "codeExpiry": emailer.lang.format(lang, "passwordReset", "codeExpiry", d, t, expiresIn), - "ifItWasNotYou": emailer.lang.get(lang, "passwordReset", "ifItWasNotYou"), - "pin": emailer.lang.get(lang, "passwordReset", "pin"), + "helloUser": emailer.lang.PasswordReset.format("helloUser", pwr.Username), + "someoneHasRequestedReset": emailer.lang.PasswordReset.get("someoneHasRequestedReset"), + "ifItWasYou": emailer.lang.PasswordReset.get("ifItWasYou"), + "codeExpiry": emailer.lang.PasswordReset.format("codeExpiry", d, t, expiresIn), + "ifItWasNotYou": emailer.lang.PasswordReset.get("ifItWasNotYou"), + "pin": emailer.lang.PasswordReset.get("pin"), "pinVal": pwr.Pin, "message": message, }) @@ -303,9 +297,8 @@ func (emailer *Emailer) constructReset(pwr PasswordReset, app *appContext) (*Ema } func (emailer *Emailer) constructDeleted(reason string, app *appContext) (*Email, error) { - lang := emailer.cLang email := &Email{ - subject: emailer.lang.get(lang, "userDeleted", "title"), + subject: emailer.lang.UserDeleted.get("title"), } for _, key := range []string{"html", "text"} { fpath := app.config.Section("deletion").Key("email_" + key).String() @@ -315,8 +308,8 @@ func (emailer *Emailer) constructDeleted(reason string, app *appContext) (*Email } var tplData bytes.Buffer err = tpl.Execute(&tplData, map[string]string{ - "yourAccountWasDeleted": emailer.lang.get(lang, "userDeleted", "yourAccountWasDeleted"), - "reason": emailer.lang.get(lang, "userDeleted", "reason"), + "yourAccountWasDeleted": emailer.lang.UserDeleted.get("yourAccountWasDeleted"), + "reason": emailer.lang.UserDeleted.get("reason"), "reasonVal": reason, }) if err != nil { diff --git a/html/admin.html b/html/admin.html index 1fea414..519b821 100644 --- a/html/admin.html +++ b/html/admin.html @@ -253,9 +253,9 @@
{{ .strings.accounts }}
- {{ .quantityStrings.addUser.singular }} + {{ .quantityStrings.addUser.Singular }} {{ .strings.modifySettings }} - {{ .quantityStrings.deleteUser.singular }} + {{ .quantityStrings.deleteUser.Singular }}
diff --git a/lang.go b/lang.go index c5b7b90..a8c1495 100644 --- a/lang.go +++ b/lang.go @@ -1,5 +1,7 @@ package main +import "strings" + type langMeta struct { Name string `json:"name"` } @@ -9,14 +11,80 @@ type quantityString struct { Plural string `json:"plural"` } +type adminLangs map[string]adminLang + +func (ls *adminLangs) getOptions(chosen string) (string, []string) { + opts := make([]string, len(*ls)) + chosenLang := (*ls)[chosen].Meta.Name + i := 0 + for _, lang := range *ls { + opts[i] = lang.Meta.Name + } + return chosenLang, opts +} + type adminLang struct { Meta langMeta `json:"meta"` - Strings map[string]string `json:"strings"` - Notifications map[string]string `json:"notifications"` + Strings langSection `json:"strings"` + Notifications langSection `json:"notifications"` QuantityStrings map[string]quantityString `json:"quantityStrings"` + JSON string +} + +type formLangs map[string]formLang + +func (ls *formLangs) getOptions(chosen string) (string, []string) { + opts := make([]string, len(*ls)) + chosenLang := (*ls)[chosen].Meta.Name + i := 0 + for _, lang := range *ls { + opts[i] = lang.Meta.Name + } + return chosenLang, opts } type formLang struct { - Strings map[string]string `json:"strings"` - ValidationStrings map[string]quantityString `json:"validationStrings"` + Meta langMeta `json:"meta"` + Strings langSection `json:"strings"` + ValidationStrings map[string]quantityString `json:"validationStrings"` + validationStringsJSON string +} + +type emailLangs map[string]emailLang + +func (ls *emailLangs) getOptions(chosen string) (string, []string) { + opts := make([]string, len(*ls)) + chosenLang := (*ls)[chosen].Meta.Name + i := 0 + for _, lang := range *ls { + opts[i] = lang.Meta.Name + } + return chosenLang, opts +} + +type emailLang struct { + Meta langMeta `json:"meta"` + UserCreated langSection `json:"userCreated"` + InviteExpiry langSection `json:"inviteExpiry"` + PasswordReset langSection `json:"passwordReset"` + UserDeleted langSection `json:"userDeleted"` + InviteEmail langSection `json:"inviteEmail"` +} + +type langSection map[string]string + +func (el *langSection) format(field string, vals ...string) string { + text := el.get(field) + for _, val := range vals { + text = strings.Replace(text, "{n}", val, 1) + } + return text +} + +func (el *langSection) get(field string) string { + t, ok := (*el)[field] + if !ok { + return "" + } + return t } diff --git a/main.go b/main.go index eff777b..a1d5937 100644 --- a/main.go +++ b/main.go @@ -569,7 +569,6 @@ func start(asDaemon, firstCall bool) { router.Use(gin.Recovery()) router.Use(static.Serve("/", static.LocalFile(filepath.Join(app.localPath, "web"), false))) - router.Use(static.Serve("/lang/", static.LocalFile(filepath.Join(app.localPath, "lang"), false))) app.loadHTML(router) router.NoRoute(app.NoRouteHandler) if debugMode { @@ -580,7 +579,7 @@ func start(asDaemon, firstCall bool) { router.GET("/", app.AdminPage) router.GET("/accounts", app.AdminPage) router.GET("/settings", app.AdminPage) - + router.GET("/lang/:page/:file", app.ServeLang) router.GET("/lang/:page", app.GetLanguages) router.GET("/token/login", app.getTokenLogin) router.GET("/token/refresh", app.getTokenRefresh) diff --git a/storage.go b/storage.go index 4dcbe6c..aa64cc3 100644 --- a/storage.go +++ b/storage.go @@ -20,36 +20,6 @@ type Storage struct { lang Lang } -type EmailLang map[string]map[string]map[string]interface{} // Map of lang codes to email name to fields - -func (el *EmailLang) format(lang, email, field string, vals ...string) string { - text := el.get(lang, email, field) - for _, val := range vals { - text = strings.Replace(text, "{n}", val, 1) - } - return text -} -func (el *EmailLang) get(lang, email, field string) string { - t, ok := (*el)[lang][email][field] - if !ok { - t = (*el)["en-us"][email][field] - } - return t.(string) -} - -type Lang struct { - chosenFormLang string - chosenAdminLang string - chosenEmailLang string - AdminPath string - Admin map[string]map[string]interface{} - AdminJSON map[string]string - FormPath string - Form map[string]map[string]interface{} - EmailPath string - Email EmailLang -} - // timePattern: %Y-%m-%dT%H:%M:%S.%f type Profile struct { @@ -73,6 +43,202 @@ type Invite struct { Profile string `json:"profile"` } +type Lang struct { + chosenFormLang string + chosenAdminLang string + chosenEmailLang string + AdminPath string + Admin adminLangs + AdminJSON map[string]string + FormPath string + Form formLangs + EmailPath string + Email emailLangs +} + +func (st *Storage) loadLang() (err error) { + err = st.loadLangAdmin() + if err != nil { + return + } + err = st.loadLangForm() + if err != nil { + return + } + err = st.loadLangEmail() + return +} + +// If a given language has missing values, fill it in with the english value. +func patchLang(english, other *langSection) { + for n, ev := range *english { + if v, ok := (*other)[n]; !ok || v == "" { + (*other)[n] = ev + } + } +} + +func patchQuantityStrings(english, other *map[string]quantityString) { + for n, ev := range *english { + qs, ok := (*other)[n] + if !ok { + (*other)[n] = ev + return + } else if qs.Singular == "" { + qs.Singular = ev.Singular + } else if (*other)[n].Plural == "" { + qs.Plural = ev.Plural + } + (*other)[n] = qs + } +} + +func (st *Storage) loadLangAdmin() error { + st.lang.Admin = map[string]adminLang{} + var english adminLang + load := func(fname string) error { + index := strings.TrimSuffix(fname, filepath.Ext(fname)) + lang := adminLang{} + f, err := ioutil.ReadFile(filepath.Join(st.lang.AdminPath, fname)) + if err != nil { + return err + } + if substituteStrings != "" { + f = []byte(strings.ReplaceAll(string(f), "Jellyfin", substituteStrings)) + } + err = json.Unmarshal(f, &lang) + if err != nil { + return err + } + if fname != "en-us.json" { + patchLang(&english.Strings, &lang.Strings) + patchLang(&english.Notifications, &lang.Notifications) + patchQuantityStrings(&english.QuantityStrings, &lang.QuantityStrings) + } + stringAdmin, err := json.Marshal(lang) + if err != nil { + return err + } + lang.JSON = string(stringAdmin) + st.lang.Admin[index] = lang + return nil + } + err := load("en-us.json") + if err != nil { + return err + } + english = st.lang.Admin["en-us"] + files, err := ioutil.ReadDir(st.lang.AdminPath) + if err != nil { + return err + } + for _, f := range files { + if f.Name() != "en-us.json" { + err = load(f.Name()) + if err != nil { + return err + } + } + } + return nil +} + +func (st *Storage) loadLangForm() error { + st.lang.Form = map[string]formLang{} + var english formLang + load := func(fname string) error { + index := strings.TrimSuffix(fname, filepath.Ext(fname)) + lang := formLang{} + f, err := ioutil.ReadFile(filepath.Join(st.lang.FormPath, fname)) + if err != nil { + return err + } + if substituteStrings != "" { + f = []byte(strings.ReplaceAll(string(f), "Jellyfin", substituteStrings)) + } + err = json.Unmarshal(f, &lang) + if err != nil { + return err + } + if fname != "en-us.json" { + patchLang(&english.Strings, &lang.Strings) + patchQuantityStrings(&english.ValidationStrings, &lang.ValidationStrings) + } + validationStrings, err := json.Marshal(lang.ValidationStrings) + if err != nil { + return err + } + lang.validationStringsJSON = string(validationStrings) + st.lang.Form[index] = lang + return nil + } + err := load("en-us.json") + if err != nil { + return err + } + english = st.lang.Form["en-us"] + files, err := ioutil.ReadDir(st.lang.FormPath) + if err != nil { + return err + } + for _, f := range files { + if f.Name() != "en-us.json" { + err = load(f.Name()) + if err != nil { + return err + } + } + } + return nil +} + +func (st *Storage) loadLangEmail() error { + st.lang.Email = map[string]emailLang{} + var english emailLang + load := func(fname string) error { + index := strings.TrimSuffix(fname, filepath.Ext(fname)) + lang := emailLang{} + f, err := ioutil.ReadFile(filepath.Join(st.lang.EmailPath, fname)) + if err != nil { + return err + } + if substituteStrings != "" { + f = []byte(strings.ReplaceAll(string(f), "Jellyfin", substituteStrings)) + } + err = json.Unmarshal(f, &lang) + if err != nil { + return err + } + if fname != "en-us.json" { + patchLang(&english.UserCreated, &lang.UserCreated) + patchLang(&english.InviteExpiry, &lang.InviteExpiry) + patchLang(&english.PasswordReset, &lang.PasswordReset) + patchLang(&english.UserDeleted, &lang.UserDeleted) + patchLang(&english.InviteEmail, &lang.InviteEmail) + } + st.lang.Email[index] = lang + return nil + } + err := load("en-us.json") + if err != nil { + return err + } + english = st.lang.Email["en-us"] + files, err := ioutil.ReadDir(st.lang.EmailPath) + if err != nil { + return err + } + for _, f := range files { + if f.Name() != "en-us.json" { + err = load(f.Name()) + if err != nil { + return err + } + } + } + return nil +} + type Invites map[string]Invite func (st *Storage) loadInvites() error { @@ -83,75 +249,75 @@ func (st *Storage) storeInvites() error { return storeJSON(st.invite_path, st.invites) } -func (st *Storage) loadLang() error { - loadData := func(path string, stringJson bool) (map[string]string, map[string]map[string]interface{}, error) { - files, err := ioutil.ReadDir(path) - outString := map[string]string{} - out := map[string]map[string]interface{}{} - if err != nil { - return nil, nil, err - } - for _, f := range files { - index := strings.TrimSuffix(f.Name(), filepath.Ext(f.Name())) - var data map[string]interface{} - var file []byte - var err error - file, err = ioutil.ReadFile(filepath.Join(path, f.Name())) - if err != nil { - file = []byte("{}") - } - // Replace Jellyfin with something if necessary - if substituteStrings != "" { - fileString := strings.ReplaceAll(string(file), "Jellyfin", substituteStrings) - file = []byte(fileString) - } - err = json.Unmarshal(file, &data) - if err != nil { - log.Printf("ERROR: Failed to read \"%s\": %s", path, err) - return nil, nil, err - } - if stringJson { - stringJSON, err := json.Marshal(data) - if err != nil { - return nil, nil, err - } - outString[index] = string(stringJSON) - } - out[index] = data - - } - return outString, out, nil - } - _, form, err := loadData(st.lang.FormPath, false) - if err != nil { - return err - } - for index, lang := range form { - validationStrings := lang["validationStrings"].(map[string]interface{}) - vS, err := json.Marshal(validationStrings) - if err != nil { - return err - } - lang["validationStrings"] = string(vS) - form[index] = lang - } - st.lang.Form = form - adminJSON, admin, err := loadData(st.lang.AdminPath, true) - st.lang.Admin = admin - st.lang.AdminJSON = adminJSON - - _, emails, err := loadData(st.lang.EmailPath, false) - fixedEmails := map[string]map[string]map[string]interface{}{} - for lang, e := range emails { - f := map[string]map[string]interface{}{} - for field, vals := range e { - f[field] = vals.(map[string]interface{}) - } - fixedEmails[lang] = f - } - st.lang.Email = fixedEmails - return err -} +// func (st *Storage) loadLang() error { +// loadData := func(path string, stringJson bool) (map[string]string, map[string]map[string]interface{}, error) { +// files, err := ioutil.ReadDir(path) +// outString := map[string]string{} +// out := map[string]map[string]interface{}{} +// if err != nil { +// return nil, nil, err +// } +// for _, f := range files { +// index := strings.TrimSuffix(f.Name(), filepath.Ext(f.Name())) +// var data map[string]interface{} +// var file []byte +// var err error +// file, err = ioutil.ReadFile(filepath.Join(path, f.Name())) +// if err != nil { +// file = []byte("{}") +// } +// // Replace Jellyfin with something if necessary +// if substituteStrings != "" { +// fileString := strings.ReplaceAll(string(file), "Jellyfin", substituteStrings) +// file = []byte(fileString) +// } +// err = json.Unmarshal(file, &data) +// if err != nil { +// log.Printf("ERROR: Failed to read \"%s\": %s", path, err) +// return nil, nil, err +// } +// if stringJson { +// stringJSON, err := json.Marshal(data) +// if err != nil { +// return nil, nil, err +// } +// outString[index] = string(stringJSON) +// } +// out[index] = data +// +// } +// return outString, out, nil +// } +// _, form, err := loadData(st.lang.FormPath, false) +// if err != nil { +// return err +// } +// for index, lang := range form { +// validationStrings := lang["validationStrings"].(map[string]interface{}) +// vS, err := json.Marshal(validationStrings) +// if err != nil { +// return err +// } +// lang["validationStrings"] = string(vS) +// form[index] = lang +// } +// st.lang.Form = form +// adminJSON, admin, err := loadData(st.lang.AdminPath, true) +// st.lang.Admin = admin +// st.lang.AdminJSON = adminJSON +// +// _, emails, err := loadData(st.lang.EmailPath, false) +// fixedEmails := map[string]map[string]map[string]interface{}{} +// for lang, e := range emails { +// f := map[string]map[string]interface{}{} +// for field, vals := range e { +// f[field] = vals.(map[string]interface{}) +// } +// fixedEmails[lang] = f +// } +// st.lang.Email = fixedEmails +// return err +// } func (st *Storage) loadEmails() error { return loadJSON(st.emails_path, &st.emails) diff --git a/views.go b/views.go index 77a07d4..da02507 100644 --- a/views.go +++ b/views.go @@ -45,7 +45,7 @@ func (app *appContext) AdminPage(gc *gin.Context) { lang := gc.Query("lang") if lang == "" { lang = app.storage.lang.chosenAdminLang - } else if _, ok := app.storage.lang.Form[lang]; !ok { + } else if _, ok := app.storage.lang.Admin[lang]; !ok { lang = app.storage.lang.chosenAdminLang } emailEnabled, _ := app.config.Section("invite_emails").Key("enabled").Bool() @@ -61,9 +61,9 @@ func (app *appContext) AdminPage(gc *gin.Context) { "commit": COMMIT, "ombiEnabled": ombiEnabled, "username": !app.config.Section("email").Key("no_username").MustBool(false), - "strings": app.storage.lang.Admin[lang]["strings"], - "quantityStrings": app.storage.lang.Admin[lang]["quantityStrings"], - "language": app.storage.lang.AdminJSON[lang], + "strings": app.storage.lang.Admin[lang].Strings, + "quantityStrings": app.storage.lang.Admin[lang].QuantityStrings, + "language": app.storage.lang.Admin[lang].JSON, }) } @@ -94,8 +94,8 @@ func (app *appContext) InviteProxy(gc *gin.Context) { "requirements": app.validator.getCriteria(), "email": email, "username": !app.config.Section("email").Key("no_username").MustBool(false), - "strings": app.storage.lang.Form[lang]["strings"], - "validationStrings": app.storage.lang.Form[lang]["validationStrings"], + "strings": app.storage.lang.Form[lang].Strings, + "validationStrings": app.storage.lang.Form[lang].validationStringsJSON, "code": code, }) } else {