Better translate HELP entries and indexes

This commit is contained in:
Daniel Oaks 2018-01-23 21:17:14 +10:00
parent 6a28277ba4
commit 638b0c03fc
2 changed files with 81 additions and 45 deletions

View File

@ -16,19 +16,20 @@ type HelpEntryType int
const ( const (
// CommandHelpEntry is a help entry explaining a client command. // CommandHelpEntry is a help entry explaining a client command.
CommandHelpEntry HelpEntryType = 0 CommandHelpEntry HelpEntryType = iota
// InformationHelpEntry is a help entry explaining general server info. // InformationHelpEntry is a help entry explaining general server info.
InformationHelpEntry HelpEntryType = 1 InformationHelpEntry
// ISupportHelpEntry is a help entry explaining a specific RPL_ISUPPORT token. // ISupportHelpEntry is a help entry explaining a specific RPL_ISUPPORT token.
ISupportHelpEntry HelpEntryType = 2 ISupportHelpEntry
) )
// HelpEntry represents an entry in the Help map. // HelpEntry represents an entry in the Help map.
type HelpEntry struct { type HelpEntry struct {
oper bool oper bool
text string text string
helpType HelpEntryType textGenerator func(*Client) string
duplicate bool helpType HelpEntryType
duplicate bool
} }
// used for duplicates // used for duplicates
@ -508,8 +509,8 @@ Returns historical information on the last user with the given nickname.`,
// Informational // Informational
"modes": { "modes": {
text: cmodeHelpText + "\n\n" + umodeHelpText, textGenerator: modesTextGenerator,
helpType: InformationHelpEntry, helpType: InformationHelpEntry,
}, },
"cmode": { "cmode": {
text: cmodeHelpText, text: cmodeHelpText,
@ -564,26 +565,21 @@ Oragono supports the following channel membership prefixes:
}, },
} }
// modesTextGenerator generates the text for the 'modes' help entry.
// it exists only so we can translate this entry appropriately.
func modesTextGenerator(client *Client) string {
return client.t(cmodeHelpText) + "\n\n" + client.t(umodeHelpText)
}
// HelpIndex contains the list of all help topics for regular users. // HelpIndex contains the list of all help topics for regular users.
var HelpIndex string var HelpIndex map[string]string
// HelpIndexOpers contains the list of all help topics for opers. // HelpIndexOpers contains the list of all help topics for opers.
var HelpIndexOpers string var HelpIndexOpers map[string]string
// GenerateHelpIndex is used to generate HelpIndex. // GenerateHelpIndex is used to generate HelpIndex.
func GenerateHelpIndex(forOpers bool) string { func GenerateHelpIndex(lm *LanguageManager, forOpers bool) map[string]string {
newHelpIndex := `= Help Topics = // generate the help entry lists
Commands:
%s
RPL_ISUPPORT Tokens:
%s
Information:
%s`
// generate them
var commands, isupport, information []string var commands, isupport, information []string
var line string var line string
@ -606,34 +602,58 @@ Information:
} }
} }
// sort the lines // create the strings
sort.Strings(commands) sort.Strings(commands)
commandsString := strings.Join(commands, "\n")
sort.Strings(isupport) sort.Strings(isupport)
isupportString := strings.Join(isupport, "\n")
sort.Strings(information) sort.Strings(information)
informationString := strings.Join(information, "\n")
// sub them in // sub them in
newHelpIndex = fmt.Sprintf(newHelpIndex, strings.Join(commands, "\n"), strings.Join(isupport, "\n"), strings.Join(information, "\n")) defaultHelpIndex := `= Help Topics =
Commands:
%s
RPL_ISUPPORT Tokens:
%s
Information:
%s`
newHelpIndex := make(map[string]string)
newHelpIndex["en"] = fmt.Sprintf(defaultHelpIndex, commandsString, isupportString, informationString)
lm.RLock()
defer lm.RUnlock()
for langCode := range lm.Info {
translatedHelpIndex := lm.Translate([]string{langCode}, defaultHelpIndex)
if translatedHelpIndex != defaultHelpIndex {
newHelpIndex[langCode] = fmt.Sprintf(translatedHelpIndex, commandsString, isupportString, informationString)
}
}
return newHelpIndex return newHelpIndex
} }
// GenerateHelpIndices generates our help indexes and confirms we have HELP entries for every command. // GenerateHelpIndices generates our help indexes and confirms we have HELP entries for every command.
func GenerateHelpIndices() error { func GenerateHelpIndices(lm *LanguageManager) error {
if HelpIndex != "" && HelpIndexOpers != "" {
return nil
}
// startup check that we have HELP entries for every command // startup check that we have HELP entries for every command
for name := range Commands { if len(HelpIndex) == 0 && len(HelpIndexOpers) == 0 {
_, exists := Help[strings.ToLower(name)] for name := range Commands {
if !exists { _, exists := Help[strings.ToLower(name)]
return fmt.Errorf("Help entry does not exist for command %s", name) if !exists {
return fmt.Errorf("Help entry does not exist for command %s", name)
}
} }
} }
// generate help indexes // generate help indexes
HelpIndex = GenerateHelpIndex(false) HelpIndex = GenerateHelpIndex(lm, false)
HelpIndexOpers = GenerateHelpIndex(true) HelpIndexOpers = GenerateHelpIndex(lm, true)
return nil return nil
} }
@ -656,6 +676,18 @@ func (client *Client) sendHelp(name string, text string) {
client.Send(nil, client.server.name, RPL_ENDOFHELP, args...) client.Send(nil, client.server.name, RPL_ENDOFHELP, args...)
} }
// GetHelpIndex returns the help index for the given language.
func GetHelpIndex(languages []string, helpIndex map[string]string) string {
for _, lang := range languages {
index, exists := helpIndex[lang]
if exists {
return index
}
}
// 'en' always exists
return helpIndex["en"]
}
// helpHandler returns the appropriate help for the given query. // helpHandler returns the appropriate help for the given query.
func helpHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { func helpHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
argument := strings.ToLower(strings.TrimSpace(strings.Join(msg.Params, " "))) argument := strings.ToLower(strings.TrimSpace(strings.Join(msg.Params, " ")))
@ -670,9 +702,9 @@ Get an explanation of <argument>, or "index" for a list of help topics.`))
// handle index // handle index
if argument == "index" { if argument == "index" {
if client.flags[Operator] { if client.flags[Operator] {
client.sendHelp("HELP", HelpIndexOpers) client.sendHelp("HELP", GetHelpIndex(client.languages, HelpIndexOpers))
} else { } else {
client.sendHelp("HELP", HelpIndex) client.sendHelp("HELP", GetHelpIndex(client.languages, HelpIndex))
} }
return false return false
} }
@ -680,7 +712,11 @@ Get an explanation of <argument>, or "index" for a list of help topics.`))
helpHandler, exists := Help[argument] helpHandler, exists := Help[argument]
if exists && (!helpHandler.oper || (helpHandler.oper && client.flags[Operator])) { if exists && (!helpHandler.oper || (helpHandler.oper && client.flags[Operator])) {
client.sendHelp(strings.ToUpper(argument), helpHandler.text) if helpHandler.textGenerator != nil {
client.sendHelp(strings.ToUpper(argument), client.t(helpHandler.textGenerator(client)))
} else {
client.sendHelp(strings.ToUpper(argument), client.t(helpHandler.text))
}
} else { } else {
args := msg.Params args := msg.Params
args = append(args, client.t("Help not found")) args = append(args, client.t("Help not found"))

View File

@ -135,11 +135,6 @@ type clientConn struct {
// NewServer returns a new Oragono server. // NewServer returns a new Oragono server.
func NewServer(config *Config, logger *logger.Manager) (*Server, error) { func NewServer(config *Config, logger *logger.Manager) (*Server, error) {
// TODO move this to main?
if err := GenerateHelpIndices(); err != nil {
return nil, err
}
// initialize data structures // initialize data structures
server := &Server{ server := &Server{
accounts: make(map[string]*ClientAccount), accounts: make(map[string]*ClientAccount),
@ -161,6 +156,11 @@ func NewServer(config *Config, logger *logger.Manager) (*Server, error) {
return nil, err return nil, err
} }
// generate help info
if err := GenerateHelpIndices(server.languages); err != nil {
return nil, err
}
// Attempt to clean up when receiving these signals. // Attempt to clean up when receiving these signals.
signal.Notify(server.signals, ServerExitSignals...) signal.Notify(server.signals, ServerExitSignals...)
signal.Notify(server.rehashSignal, syscall.SIGHUP) signal.Notify(server.rehashSignal, syscall.SIGHUP)