1
0
mirror of https://github.com/hrfee/jfa-go.git synced 2024-12-28 03:50:10 +00:00

Compare commits

...

6 Commits

Author SHA1 Message Date
75796a3981
add optional tls/http2 support
Allows for http2 server push, see the advanced section.
2021-01-15 14:41:44 +00:00
781047058f
update CONTRIBUTING.md 2021-01-15 13:40:42 +00:00
0ac61a59b2
fix display of username box on add account modal 2021-01-15 13:37:09 +00:00
732ed5b0b8
add finished french for admin 2021-01-15 13:30:29 +00:00
42ddbab6cf
fix spelling in french email 2021-01-14 21:39:06 +00:00
432d795880
Fix email language selection, add finished french emails 2021-01-14 20:24:28 +00:00
8 changed files with 155 additions and 15 deletions

3
.gitignore vendored
View File

@ -9,3 +9,6 @@ docs/*
lang/langtostruct.py
config-payload.json
!docs/go.mod
server.key
server.pem
server.crt

View File

@ -1,5 +1,5 @@
#### Translation
Currently only the account creation form can be translated. Strings are defined in `lang/form/<country-code>.json` (country code as in `en-us`, `fr-fr`, e.g). You can see the existing ones [here](https://github.com/hrfee/jfa-go/tree/main/lang/form).
Currently the admin page, account creation form and emails can be translated. Strings are defined in `lang/<admin/form/email>/<country-code>.json` (country code as in `en-us`, `fr-fr`, e.g). You can see the existing ones [here](https://github.com/hrfee/jfa-go/tree/main/lang).
Make sure to define `name` in the `meta` section, and you can optionally add an `author` value there as well. If you can, make a pull request with your new file. If not, email me or create an issue.
#### Code

27
api.go
View File

@ -1087,7 +1087,7 @@ func (app *appContext) GetConfig(gc *gin.Context) {
// 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")
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 {
@ -1096,14 +1096,25 @@ func (app *appContext) GetConfig(gc *gin.Context) {
}
return chosenLangName, langOptions
}
formChosen, formOptions := loadLangs(&app.storage.lang.Form, "form")
formChosen, formOptions := loadLangs(&app.storage.lang.Form, "-form")
fl := resp.Sections["ui"].Settings["language-form"]
fl.Options = formOptions
fl.Value = formChosen
adminChosen, adminOptions := loadLangs(&app.storage.lang.Admin, "admin")
adminChosen, adminOptions := loadLangs(&app.storage.lang.Admin, "-admin")
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++
}
el := resp.Sections["email"].Settings["language"]
el.Options = emailOptions
el.Value = emailChosen
for sectName, section := range resp.Sections {
for settingName, setting := range section.Settings {
val := app.config.Section(sectName).Key(settingName)
@ -1121,10 +1132,11 @@ func (app *appContext) GetConfig(gc *gin.Context) {
}
resp.Sections["ui"].Settings["language-form"] = fl
resp.Sections["ui"].Settings["language-admin"] = al
resp.Sections["email"].Settings["language"] = el
t := resp.Sections["jellyfin"].Settings["type"]
opts := make([]string, len(serverTypes))
i := 0
i = 0
for _, v := range serverTypes {
opts[i] = v
i++
@ -1169,6 +1181,13 @@ func (app *appContext) ModifyConfig(gc *gin.Context) {
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) {
tempConfig.Section("email").Key("language").SetValue(key)
break
}
}
} else if section == "jellyfin" && setting == "type" {
for k, v := range serverTypes {
if v == value.(string) {

View File

@ -219,6 +219,50 @@
}
}
},
"advanced": {
"order": [],
"meta": {
"name": "Advanced",
"description": "Advanced settings."
},
"settings": {
"tls": {
"name": "TLS/HTTP2",
"required": false,
"requires_restart": true,
"type": "bool",
"value": false,
"description": "Enable TLS, and by extension HTTP2. This enables server push, where required files are pushed to the web browser before they request them, allowing quicker page loads."
},
"tls_port": {
"name": "TLS Port",
"depends_true": "tls",
"required": false,
"requires_restart": true,
"type": "number",
"value": 8057,
"description": "Port to run TLS server on"
},
"tls_cert": {
"name": "Path to TLS Certificate",
"depends_true": "tls",
"required": false,
"requires_restart": true,
"type": "text",
"value": "",
"description": "Path to .crt file. See jfa-go wiki for more info."
},
"tls_key": {
"name": "Path to TLS Key file",
"depends_true": "tls",
"required": false,
"requires_restart": true,
"type": "text",
"value": "",
"description": "Path to .key file. See jfa-go wiki for more info."
}
}
},
"password_validation": {
"order": [],
"meta": {

View File

@ -8,7 +8,7 @@
window.notificationsEnabled = {{ .notifications }};
window.emailEnabled = {{ .email_enabled }};
window.ombiEnabled = {{ .ombiEnabled }};
window.usernamesEnabled = {{ .username }};
window.usernameEnabled = {{ .username }};
window.langFile = JSON.parse({{ .language }});
</script>
{{ template "header.html" . }}
@ -99,7 +99,7 @@
<span class="heading">{{ .strings.settingsRestartRequired }} <span class="modal-close">&times;</span></span>
<p class="content pb-1">{{ .strings.settingsRestartRequiredDescription }}</p>
<div class="fr">
<span class="button ~info !normal" id="settings-apply-no-restart">{{ .strings.settingsApplyRestartLater }}</span>
<span class="button ~info !normal mb-half" id="settings-apply-no-restart">{{ .strings.settingsApplyRestartLater }}</span>
<span class="button ~critical !normal" id="settings-apply-restart">{{ .strings.settingsApplyRestartNow }}</span>
</div>
</div>

View File

@ -22,17 +22,21 @@
"delete": "Effacer",
"submit": "Soumettre",
"name": "Nom",
"date": "Date",
"username": "Nom d'utilisateur",
"password": "Mot de passe",
"emailAddress": "Addresse Email",
"lastActiveTime": "Dernière activité",
"from": "De",
"user": "Utilisateur",
"aboutProgram": "A propros",
"aboutProgram": "A propos",
"version": "Version",
"commitNoun": "Commettre",
"newUser": "Nouvel utilisateur",
"profile": "Profil",
"success": "Succès",
"error": "Erreur",
"unknown": "Inconnu",
"modifySettings": "Modifier les paramètres",
"modifySettingsDescription": "Appliquez les paramètres à partir d'un profil existant ou obtenez-les directement auprès d'un utilisateur.",
"applyHomescreenLayout": "Appliquer la disposition de l'écran d'accueil",
@ -55,7 +59,47 @@
"addProfile": "Ajouter un profil",
"addProfileDescription": "Créez un utilisateur Jellyfin et configurez-le, puis sélectionnez-le ci-dessous. Lorsque ce profil est appliqué à une invitation, de nouveaux utilisateurs seront créés avec les paramètres. ",
"addProfileNameOf": "Nom de profil",
"addProfileStoreHomescreenLayout": "Enregistrer la disposition de l'écran d'accueil"
"addProfileStoreHomescreenLayout": "Enregistrer la disposition de l'écran d'accueil",
"inviteNoUsersCreated": "Aucun pour l'instant!",
"inviteUsersCreated": "Utilisateurs créer",
"inviteNoProfile": "Aucun profil",
"copy": "Copier",
"inviteDateCreated": "Créer",
"inviteRemainingUses": "Utilisations restantes",
"inviteNoInvites": "Aucune",
"inviteExpiresInTime": "Expires dans {n}",
"notifyEvent": "Notifier sur:",
"notifyInviteExpiry": "À l'expiration",
"notifyUserCreation": "à la création de l'utilisateur"
},
"notifications": {
"changedEmailAddress": "Adresse e-mail modifiée de {n}.",
"userCreated": "L'utilisateur {n} a été créé.",
"createProfile": "Profil créé {n}.",
"saveSettings": "Les paramètres ont été enregistrés",
"setOmbiDefaults": "Valeurs par défaut de Ombi.",
"errorConnection": "Impossible de se connecter à jfa-go.",
"error401Unauthorized": "Non autorisé. Essayez d'actualiser la page.",
"errorSettingsAppliedNoHomescreenLayout": "Les paramètres ont été appliqués, mais l'application de la disposition de l'écran d'accueil a peut-être échoué.",
"errorHomescreenAppliedNoSettings": "La disposition de l'écran d'accueil a été appliquée, mais l'application des paramètres a peut-être échoué.",
"errorSettingsFailed": "L'application a échoué.",
"errorLoginBlank": "Le nom d'utilisateur et / ou le mot de passe sont vides",
"errorUnknown": "Erreur inconnue.",
"errorBlankFields": "Les champs sont vides",
"errorDeleteProfile": "Échec de la suppression du profil {n}",
"errorLoadProfiles": "Échec du chargement des profils.",
"errorCreateProfile": "Échec de la création du profil {n}",
"errorSetDefaultProfile": "Échec de la définition du profil par défaut",
"errorLoadUsers": "Échec du chargement des utilisateurs.",
"errorSaveSettings": "Impossible d'enregistrer les paramètres.",
"errorLoadSettings": "Échec du chargement des paramètres.",
"errorSetOmbiDefaults": "Impossible de stocker les valeurs par défaut d'Ombi.",
"errorLoadOmbiUsers": "Échec du chargement des utilisateurs Ombi.",
"errorChangedEmailAddress": "Impossible de modifier l'adresse e-mail de {n}.",
"errorFailureCheckLogs": "Échec (vérifier la console / les journaux)",
"errorPartialFailureCheckLogs": "Panne partielle (vérifier la console / les journaux)"
},
"quantityStrings": {
"modifySettingsFor": {
@ -73,6 +117,14 @@
"deleteUser": {
"singular": "Supprimer l'utilisateur",
"plural": "Supprimer les utilisateurs"
},
"deletedUser": {
"singular": "Supprimer {n} utilisateur.",
"plural": "Supprimer {n} utilisateurs."
},
"appliedSettings": {
"singular": "Appliquer le paramètre {n} utilisteur.",
"plural": "Appliquer les paramètres {n} utilisteurs."
}
}
}

View File

@ -4,13 +4,21 @@
"author": "https://github.com/Cornichon420"
},
"userCreated": {
"title": "Notification : Utilisateur créé",
"aUserWasCreated": "Un utilisateur a été créé avec ce code {n}",
"name": "Nom",
"emailAddress": "Adresse",
"time": "Date",
"notificationNotice": ""
},
"inviteExpiry": {
"title": "Notification : Invitation expirée",
"inviteExpired": "Invitation expirée.",
"expiredAt": "Le code {n} a expiré à {n}.",
"notificationNotice": ""
},
"passwordReset": {
"title": "Réinitialisation de mot du passe demandée - Jellyfin",
"helloUser": "Salut {n},",
"someoneHasRequestedReset": "Quelqu'un vient de demander une réinitialisation du mot de passe via Jellyfin.",
"ifItWasYou": "Si c'était bien toi, renseigne le code PIN en dessous.",
@ -19,14 +27,16 @@
"pin": "PIN"
},
"userDeleted": {
"title": "Ton compte a été désactivé - Jellyfin",
"yourAccountWasDeleted": "Ton compte Jellyfin a été supprimé.",
"reason": "Motif"
},
"inviteEmail": {
"title": "Invitation - Jellyfin",
"hello": "Salut",
"youHaveBeenInvited": "Tu a été invité à rejoindre Jellyfin.",
"youHaveBeenInvited": "Tu as été invité à rejoindre Jellyfin.",
"toJoin": "Pour continuer, suis le lien en dessous.",
"inviteExpiry": "L'invitation expirera le {n}, à {n}, sout dans {n}, alors fais vite !",
"inviteExpiry": "L'invitation expirera le {n}, à {n}, soit dans {n}, alors fais vite !",
"linkButton": "Lien"
}
}

20
main.go
View File

@ -331,7 +331,12 @@ func start(asDaemon, firstCall bool) {
if !firstRun {
app.host = app.config.Section("ui").Key("host").String()
app.port = app.config.Section("ui").Key("port").MustInt(8056)
if app.config.Section("advanced").Key("tls").MustBool(false) {
app.info.Println("Using TLS/HTTP2")
app.port = app.config.Section("advanced").Key("tls_port").MustInt(8057)
} else {
app.port = app.config.Section("ui").Key("port").MustInt(8056)
}
if *HOST != app.host && *HOST != "" {
app.host = *HOST
@ -350,7 +355,6 @@ func start(asDaemon, firstCall bool) {
}
}
}
address = fmt.Sprintf("%s:%d", app.host, app.port)
app.debug.Printf("Loaded config file \"%s\"", app.configPath)
@ -625,8 +629,16 @@ func start(asDaemon, firstCall bool) {
Handler: router,
}
go func() {
if err := SRV.ListenAndServe(); err != nil {
app.err.Printf("Failure serving: %s", err)
if app.config.Section("advanced").Key("tls").MustBool(false) {
cert := app.config.Section("advanced").Key("tls_cert").MustString("")
key := app.config.Section("advanced").Key("tls_key").MustString("")
if err := SRV.ListenAndServeTLS(cert, key); err != nil {
app.err.Printf("Failure serving: %s", err)
}
} else {
if err := SRV.ListenAndServe(); err != nil {
app.err.Printf("Failure serving: %s", err)
}
}
}()
app.quit = make(chan os.Signal)