2018-01-21 07:49:17 +01:00
|
|
|
// Copyright (c) 2018 Daniel Oaks <daniel@danieloaks.net>
|
|
|
|
// released under the MIT license
|
|
|
|
|
2018-02-03 10:46:14 +01:00
|
|
|
package languages
|
2018-01-21 07:49:17 +01:00
|
|
|
|
|
|
|
import (
|
2018-01-25 10:51:02 +01:00
|
|
|
"fmt"
|
|
|
|
"sort"
|
2018-01-22 08:30:31 +01:00
|
|
|
"strings"
|
2018-01-21 07:49:17 +01:00
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
2018-02-03 10:46:14 +01:00
|
|
|
// LangData is the data contained in a language file.
|
|
|
|
type LangData struct {
|
|
|
|
Name string
|
|
|
|
Code string
|
|
|
|
Contributors string
|
|
|
|
Incomplete bool
|
|
|
|
Translations map[string]string
|
|
|
|
}
|
|
|
|
|
|
|
|
// Manager manages our languages and provides translation abilities.
|
|
|
|
type Manager struct {
|
2018-01-21 07:49:17 +01:00
|
|
|
sync.RWMutex
|
2018-01-22 08:30:31 +01:00
|
|
|
Info map[string]LangData
|
|
|
|
translations map[string]map[string]string
|
2018-01-22 12:30:28 +01:00
|
|
|
defaultLang string
|
2018-01-21 07:49:17 +01:00
|
|
|
}
|
|
|
|
|
2018-02-03 10:46:14 +01:00
|
|
|
// NewManager returns a new Manager.
|
|
|
|
func NewManager(defaultLang string, languageData map[string]LangData) *Manager {
|
|
|
|
lm := Manager{
|
2018-01-22 08:30:31 +01:00
|
|
|
Info: make(map[string]LangData),
|
|
|
|
translations: make(map[string]map[string]string),
|
2018-01-22 12:30:28 +01:00
|
|
|
defaultLang: defaultLang,
|
2018-01-21 07:49:17 +01:00
|
|
|
}
|
|
|
|
|
2018-01-22 08:30:31 +01:00
|
|
|
// make fake "en" info
|
|
|
|
lm.Info["en"] = LangData{
|
2018-01-23 07:50:19 +01:00
|
|
|
Code: "en",
|
|
|
|
Name: "English",
|
|
|
|
Contributors: "Oragono contributors and the IRC community",
|
2018-01-22 08:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// load language data
|
|
|
|
for name, data := range languageData {
|
|
|
|
lm.Info[name] = data
|
2018-01-23 06:06:55 +01:00
|
|
|
|
|
|
|
// make sure we don't include empty translations
|
|
|
|
lm.translations[name] = make(map[string]string)
|
|
|
|
for key, value := range data.Translations {
|
|
|
|
if strings.TrimSpace(value) == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
lm.translations[name][key] = value
|
|
|
|
}
|
2018-01-22 08:30:31 +01:00
|
|
|
}
|
2018-01-21 07:49:17 +01:00
|
|
|
|
|
|
|
return &lm
|
|
|
|
}
|
|
|
|
|
2018-01-22 12:30:28 +01:00
|
|
|
// Default returns the default languages.
|
2018-02-03 10:46:14 +01:00
|
|
|
func (lm *Manager) Default() []string {
|
2018-01-22 12:30:28 +01:00
|
|
|
lm.RLock()
|
|
|
|
defer lm.RUnlock()
|
|
|
|
|
|
|
|
if lm.defaultLang == "" {
|
|
|
|
return []string{}
|
|
|
|
}
|
|
|
|
return []string{lm.defaultLang}
|
|
|
|
}
|
|
|
|
|
2018-01-22 08:30:31 +01:00
|
|
|
// Count returns how many languages we have.
|
2018-02-03 10:46:14 +01:00
|
|
|
func (lm *Manager) Count() int {
|
2018-01-22 08:30:31 +01:00
|
|
|
lm.RLock()
|
|
|
|
defer lm.RUnlock()
|
|
|
|
|
|
|
|
return len(lm.Info)
|
|
|
|
}
|
|
|
|
|
2018-01-25 10:51:02 +01:00
|
|
|
// Translators returns the languages we have and the translators.
|
2018-02-03 10:46:14 +01:00
|
|
|
func (lm *Manager) Translators() []string {
|
2018-01-25 10:51:02 +01:00
|
|
|
lm.RLock()
|
|
|
|
defer lm.RUnlock()
|
|
|
|
|
|
|
|
var tlist sort.StringSlice
|
|
|
|
|
|
|
|
for _, info := range lm.Info {
|
|
|
|
if info.Code == "en" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
tlist = append(tlist, fmt.Sprintf("%s (%s): %s", info.Name, info.Code, info.Contributors))
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Sort(tlist)
|
|
|
|
return tlist
|
|
|
|
}
|
|
|
|
|
2018-01-22 08:30:31 +01:00
|
|
|
// Codes returns the proper language codes for the given casefolded language codes.
|
2018-02-03 10:46:14 +01:00
|
|
|
func (lm *Manager) Codes(codes []string) []string {
|
2018-01-22 08:30:31 +01:00
|
|
|
lm.RLock()
|
|
|
|
defer lm.RUnlock()
|
|
|
|
|
|
|
|
var newCodes []string
|
|
|
|
for _, code := range codes {
|
|
|
|
info, exists := lm.Info[code]
|
|
|
|
if exists {
|
|
|
|
newCodes = append(newCodes, info.Code)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(newCodes) == 0 {
|
|
|
|
newCodes = []string{"en"}
|
|
|
|
}
|
|
|
|
|
|
|
|
return newCodes
|
|
|
|
}
|
|
|
|
|
2018-01-21 07:49:17 +01:00
|
|
|
// Translate returns the given string, translated into the given language.
|
2018-02-03 10:46:14 +01:00
|
|
|
func (lm *Manager) Translate(languages []string, originalString string) string {
|
2018-01-21 07:49:17 +01:00
|
|
|
// not using any special languages
|
2018-01-22 08:30:31 +01:00
|
|
|
if len(languages) == 0 || languages[0] == "en" || len(lm.translations) == 0 {
|
2018-01-21 07:49:17 +01:00
|
|
|
return originalString
|
|
|
|
}
|
|
|
|
|
|
|
|
lm.RLock()
|
|
|
|
defer lm.RUnlock()
|
|
|
|
|
|
|
|
for _, lang := range languages {
|
2018-01-22 08:30:31 +01:00
|
|
|
lang = strings.ToLower(lang)
|
|
|
|
if lang == "en" {
|
|
|
|
return originalString
|
|
|
|
}
|
|
|
|
|
|
|
|
translations, exists := lm.translations[lang]
|
2018-01-21 07:49:17 +01:00
|
|
|
if !exists {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2018-01-22 08:30:31 +01:00
|
|
|
newString, exists := translations[originalString]
|
2018-01-21 07:49:17 +01:00
|
|
|
if !exists {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// found a valid translation!
|
|
|
|
return newString
|
|
|
|
}
|
|
|
|
|
|
|
|
// didn't find any translation
|
|
|
|
return originalString
|
|
|
|
}
|