Phrases are now stored in JSON files.

We now use a sync.Map for language packs for better concurrency.
This commit is contained in:
Azareal 2017-09-11 01:56:09 +01:00
parent b289b52210
commit ab0776c52b
4 changed files with 121 additions and 61 deletions

View File

@ -52,6 +52,11 @@ func gloinit() error {
return err
}
err = initPhrases()
if err != nil {
log.Fatal(err)
}
if config.CacheTopicUser == CACHE_STATIC {
users = NewMemoryUserStore(config.UserCacheCapacity)
topics = NewMemoryTopicStore(config.TopicCacheCapacity)

43
langs/english.json Normal file
View File

@ -0,0 +1,43 @@
{
"Name": "english",
"Levels": {
"Level": "Level {0}",
"LevelMax": ""
},
"GlobalPerms": {
"BanUsers": "Can ban users",
"ActivateUsers": "Can activate users",
"EditUser": "Can edit users",
"EditUserEmail": "Can change a user's email",
"EditUserPassword": "Can change a user's password",
"EditUserGroup": "Can change a user's group",
"EditUserGroupSuperMod": "Can edit super-mods",
"EditUserGroupAdmin": "Can edit admins",
"EditGroup": "Can edit groups",
"EditGroupLocalPerms": "Can edit a group's minor perms",
"EditGroupGlobalPerms": "Can edit a group's global perms",
"EditGroupSuperMod": "Can edit super-mod groups",
"EditGroupAdmin": "Can edit admin groups",
"ManageForums": "Can manage forums",
"EditSettings": "Can edit settings",
"ManageThemes": "Can manage themes",
"ManagePlugins": "Can manage plugins",
"ViewAdminLogs": "Can view the administrator action logs",
"ViewIPs": "Can view IP addresses"
},
"LocalPerms": {
"ViewTopic": "Can view topics",
"LikeItem": "Can like items",
"CreateTopic": "Can create topics",
"EditTopic": "Can edit topics",
"DeleteTopic": "Can delete topics",
"CreateReply": "Can create replies",
"EditReply": "Can edit replies",
"DeleteReply": "Can delete replies",
"PinTopic": "Can pin topics",
"CloseTopic": "Can lock topics"
},
"SettingLabels": {
"activation_type": "Activate All,Email Activation,Admin Approval"
}
}

View File

@ -31,6 +31,8 @@ var enableWebsockets = false // Don't change this, the value is overwritten by a
var router *GenRouter
var startTime time.Time
// ? - Make this more customisable?
var externalSites = map[string]string{
"YT": "https://www.youtube.com/",
}
@ -133,6 +135,11 @@ func main() {
log.Fatal(err)
}
err = initPhrases()
if err != nil {
log.Fatal(err)
}
if config.CacheTopicUser == CACHE_STATIC {
users = NewMemoryUserStore(config.UserCacheCapacity)
topics = NewMemoryTopicStore(config.TopicCacheCapacity)

View File

@ -7,19 +7,26 @@
package main
import (
"encoding/json"
"errors"
"io/ioutil"
"log"
"os"
"path/filepath"
"sync"
"sync/atomic"
)
// TODO: Let the admin edit phrases from inside the Control Panel? How should we persist these? Should we create a copy of the langpack or edit the primaries? Use the changeLangpack mutex for this?
// nolint Be quiet megacheck, this *is* used
var changeLangpackMutex sync.Mutex
var currentLanguage = "english"
var currentLangPack atomic.Value
var langpackCount int // TODO: Use atomics for this
// We'll be implementing the level phrases in the software proper very very soon!
type LevelPhrases struct {
Level string
LevelMax string
LevelMax string // ? Add a max level setting?
// Override the phrase for individual levels, if the phrases exist
Levels []string // index = level
@ -28,67 +35,68 @@ type LevelPhrases struct {
type LanguagePack struct {
Name string
Phrases map[string]string // Should we use a sync map or a struct for these? It would be nice, if we could keep all the phrases consistent.
LevelPhrases LevelPhrases
GlobalPermPhrases map[string]string
LocalPermPhrases map[string]string
Levels LevelPhrases
GlobalPerms map[string]string
LocalPerms map[string]string
SettingLabels map[string]string
}
// TODO: Add the ability to edit language JSON files from the Control Panel and automatically scan the files for changes
// TODO: Move the english language pack into a JSON file and load that on start-up
var langpacks = map[string]*LanguagePack{
"english": &LanguagePack{
Name: "english",
////var langpacks = map[string]*LanguagePack
var langpacks sync.Map // nolint it is used
// We'll be implementing the level phrases in the software proper very very soon!
LevelPhrases: LevelPhrases{
Level: "Level {0}",
LevelMax: "", // Add a max level setting?
},
GlobalPermPhrases: map[string]string{
"BanUsers": "Can ban users",
"ActivateUsers": "Can activate users",
"EditUser": "Can edit users",
"EditUserEmail": "Can change a user's email",
"EditUserPassword": "Can change a user's password",
"EditUserGroup": "Can change a user's group",
"EditUserGroupSuperMod": "Can edit super-mods",
"EditUserGroupAdmin": "Can edit admins",
"EditGroup": "Can edit groups",
"EditGroupLocalPerms": "Can edit a group's minor perms",
"EditGroupGlobalPerms": "Can edit a group's global perms",
"EditGroupSuperMod": "Can edit super-mod groups",
"EditGroupAdmin": "Can edit admin groups",
"ManageForums": "Can manage forums",
"EditSettings": "Can edit settings",
"ManageThemes": "Can manage themes",
"ManagePlugins": "Can manage plugins",
"ViewAdminLogs": "Can view the administrator action logs",
"ViewIPs": "Can view IP addresses",
},
LocalPermPhrases: map[string]string{
"ViewTopic": "Can view topics",
"LikeItem": "Can like items",
"CreateTopic": "Can create topics",
"EditTopic": "Can edit topics",
"DeleteTopic": "Can delete topics",
"CreateReply": "Can create replies",
"EditReply": "Can edit replies",
"DeleteReply": "Can delete replies",
"PinTopic": "Can pin topics",
"CloseTopic": "Can lock topics",
},
SettingLabels: map[string]string{
"activation_type": "Activate All,Email Activation,Admin Approval",
},
},
func initPhrases() error {
log.Print("Loading the language packs")
err := filepath.Walk("./langs", func(path string, f os.FileInfo, err error) error {
if f.IsDir() {
return nil
}
func init() {
currentLangPack.Store(langpacks[currentLanguage])
data, err := ioutil.ReadFile(path)
if err != nil {
return err
}
var ext = filepath.Ext("/langs/" + path)
if ext != ".json" {
if dev.DebugMode {
log.Print("Found a " + ext + "in /langs/")
}
return nil
}
var langPack LanguagePack
err = json.Unmarshal(data, &langPack)
if err != nil {
return err
}
log.Print("Adding the '" + langPack.Name + "' language pack")
langpacks.Store(langPack.Name, &langPack)
langpackCount++
return nil
})
if err != nil {
return err
}
if langpackCount == 0 {
return errors.New("You don't have any language packs")
}
langPack, ok := langpacks.Load(currentLanguage)
if !ok {
return errors.New("Couldn't find the " + currentLanguage + " language pack")
}
currentLangPack.Store(langPack)
return nil
}
func LoadLangPack(name string) error {
_ = name
return nil
}
// We might not need to use a mutex for this, we shouldn't need to change the phrases after start-up, and when we do we could overwrite the entire map
@ -98,7 +106,7 @@ func GetPhrase(name string) (string, bool) {
}
func GetGlobalPermPhrase(name string) string {
res, ok := currentLangPack.Load().(*LanguagePack).GlobalPermPhrases[name]
res, ok := currentLangPack.Load().(*LanguagePack).GlobalPerms[name]
if !ok {
return "{name}"
}
@ -106,7 +114,7 @@ func GetGlobalPermPhrase(name string) string {
}
func GetLocalPermPhrase(name string) string {
res, ok := currentLangPack.Load().(*LanguagePack).LocalPermPhrases[name]
res, ok := currentLangPack.Load().(*LanguagePack).LocalPerms[name]
if !ok {
return "{name}"
}
@ -140,13 +148,10 @@ func DeletePhrase() {
// TODO: Use atomics to store the pointer of the current active langpack?
// nolint
func ChangeLanguagePack(name string) (exists bool) {
changeLangpackMutex.Lock()
pack, ok := langpacks[name]
pack, ok := langpacks.Load(name)
if !ok {
changeLangpackMutex.Unlock()
return false
}
currentLangPack.Store(pack)
changeLangpackMutex.Unlock()
return true
}