From b58f9c55b54dea4a9a39f3d64fb553c74d0f4e79 Mon Sep 17 00:00:00 2001 From: akuma06 Date: Tue, 11 Jul 2017 21:34:06 +0200 Subject: [PATCH] Refactor Language Packages --- utils/publicSettings/publicSettings.go | 61 ++++++++++++++----- utils/publicSettings/publicSettings_test.go | 34 +++++++++++ utils/torrentLanguages/torrent_languages.go | 41 ++++++------- .../torrent_languages_test.go | 12 +++- 4 files changed, 110 insertions(+), 38 deletions(-) diff --git a/utils/publicSettings/publicSettings.go b/utils/publicSettings/publicSettings.go index 7053262a..31fd3705 100644 --- a/utils/publicSettings/publicSettings.go +++ b/utils/publicSettings/publicSettings.go @@ -6,6 +6,7 @@ import ( "html/template" "path" "path/filepath" + "strings" "sort" @@ -14,6 +15,9 @@ import ( "github.com/gin-gonic/gin" "github.com/nicksnyder/go-i18n/i18n" "github.com/nicksnyder/go-i18n/i18n/language" + + glang "golang.org/x/text/language" + "golang.org/x/text/language/display" ) // UserRetriever : this interface is required to prevent a cyclic import between the languages and userService package. @@ -24,6 +28,7 @@ type UserRetriever interface { type Language struct { Name string Code string + Tag string } type Languages []Language @@ -98,27 +103,33 @@ func GetAvailableLanguages() Languages { if len(languages) > 0 { return languages } - var T i18n.TranslateFunc - // Need this to sort out languages alphabetically by language tag var codes []string for _, languageTag := range i18n.LanguageTags() { codes = append(codes, languageTag) } - sort.Strings(codes) + languages = ParseLanguages(codes) + return languages +} +func getParentTag(languageTag string) glang.Tag { + lang := glang.Make(languageTag) + for !lang.Parent().IsRoot() { + lang = lang.Parent() + } + return lang +} + +// ParseLanguages takes a list of language codes and convert them in languages object +func ParseLanguages(codes []string) Languages { + var langs Languages + sort.Strings(codes) // Now build languages array for _, languageTag := range codes { - T, _ = i18n.Tfunc(languageTag) - /* Translation files should have an ID with the translated language name. - If they don't, just use the languageTag */ - if languageName := T("language_name"); languageName != "language_name" { - languages = append(languages, Language{languageName, languageTag}) - } else { - languages = append(languages, Language{languageName, languageTag}) - } + lang := getParentTag(languageTag) + langs = append(langs, Language{strings.Title(display.Self.Name(glang.Make(languageTag))), lang.String(), languageTag}) } - return languages + return langs } // GetDefaultTfunc : Gets T func from default language @@ -154,7 +165,7 @@ func GetTfuncFromRequest(c *gin.Context) TemplateTfunc { } } -// GetThemeFromRequest: Gets the user selected theme from the request +// GetThemeFromRequest : Gets the user selected theme from the request func GetThemeFromRequest(c *gin.Context) string { user, _ := getCurrentUser(c) if user.ID > 0 { @@ -167,7 +178,7 @@ func GetThemeFromRequest(c *gin.Context) string { return "" } -// GetThemeFromRequest: Gets the user selected theme from the request +// GetMascotFromRequest : Gets the user selected theme from the request func GetMascotFromRequest(c *gin.Context) string { user, _ := getCurrentUser(c) if user.ID > 0 { @@ -180,7 +191,7 @@ func GetMascotFromRequest(c *gin.Context) string { return "show" } -// GetMascotUrlFromRequest: Get the user selected mascot url from the request. +// GetMascotUrlFromRequest : Get the user selected mascot url from the request. // Returns an empty string if not set. func GetMascotUrlFromRequest(c *gin.Context) string { user, _ := getCurrentUser(c) @@ -203,8 +214,8 @@ func getCurrentUser(c *gin.Context) (*models.User, error) { return userRetriever.RetrieveCurrentUser(c) } +// Exist evaluate if a language exists or not (language code or language name) func (langs Languages) Exist(name string) bool { - for _, language := range langs { if language.Code == name || language.Name == name { return true @@ -213,3 +224,21 @@ func (langs Languages) Exist(name string) bool { return false } + +// Translate accepts a languageCode in string and translate the language to the language from the language code +func (lang *Language) Translate(languageCode template.HTML) string { + langTranslate := display.Tags(getParentTag(string(languageCode))) + return langTranslate.Name(lang) +} + +// Flag reads the language's country code and return the country's flag if national true or the international flag for the language +func (lang *Language) Flag(national bool) string { + if national { + languageSplit := strings.Split(lang.Tag, "-") + if len(languageSplit) > 1 { + return languageSplit[1] + } + return lang.Tag + } + return lang.Code +} diff --git a/utils/publicSettings/publicSettings_test.go b/utils/publicSettings/publicSettings_test.go index 1f015bb9..265a1eb8 100644 --- a/utils/publicSettings/publicSettings_test.go +++ b/utils/publicSettings/publicSettings_test.go @@ -4,6 +4,14 @@ import ( "path" "testing" + "github.com/nicksnyder/go-i18n/i18n" + "golang.org/x/text/language" + "golang.org/x/text/language/display" + + "fmt" + + "strings" + "github.com/NyaaPantsu/nyaa/config" ) @@ -25,3 +33,29 @@ func TestInitI18n(t *testing.T) { t.Errorf("failed to initialize language translations: %v", err) } } + +func TestLanguages(t *testing.T) { + conf := config.Get().I18n + conf.Directory = path.Join("..", "..", conf.Directory) + var retriever UserRetriever // not required during initialization + err := InitI18n(conf, retriever) + if err != nil { + t.Errorf("failed to initialize language translations: %v", err) + } + displayLang := language.Make(conf.DefaultLanguage) + if displayLang.String() == "und" { + t.Errorf("Couldn't find the language display for the language %s", displayLang.String()) + } + n := display.Tags(displayLang) + + tags := i18n.LanguageTags() + for _, languageTag := range tags { + // The matcher will match Swiss German to German. + lang := getParentTag(languageTag) + if lang.String() == "und" { + t.Errorf("Couldn't find the language root for the language %s", languageTag) + } + fmt.Printf("Name of the language natively: %s\n", strings.Title(display.Self.Name(lang))) + fmt.Printf("Name of the language in %s: %s\n", displayLang.String(), n.Name(lang)) + } +} diff --git a/utils/torrentLanguages/torrent_languages.go b/utils/torrentLanguages/torrent_languages.go index 3f94a89a..48e4bcfc 100644 --- a/utils/torrentLanguages/torrent_languages.go +++ b/utils/torrentLanguages/torrent_languages.go @@ -3,29 +3,38 @@ package torrentLanguages import ( "strings" - "sort" - "github.com/NyaaPantsu/nyaa/config" "github.com/NyaaPantsu/nyaa/utils/publicSettings" ) -var torrentLanguages []string +var torrentLanguages publicSettings.Languages func initTorrentLanguages() { languages := publicSettings.GetAvailableLanguages() - + var langSort []string for _, lang := range languages { - torrentLanguages = append(torrentLanguages, lang.Code) + langSort = append(langSort, lang.Code) } // Also support languages we don't have a translation - torrentLanguages = append(torrentLanguages, config.Get().Torrents.AdditionalLanguages...) + langSorted := publicSettings.ParseLanguages(append(langSort, config.Get().Torrents.AdditionalLanguages...)) - sort.Strings(torrentLanguages) + prevLang := "" + for _, lang := range langSorted { + if prevLang == lang.Code { + last := len(torrentLanguages) - 1 + if last > 0 && !strings.Contains(torrentLanguages[last].Name, lang.Name) { + torrentLanguages[last].Name += ", " + lang.Name + } + } else { + prevLang = lang.Code + torrentLanguages = append(torrentLanguages, lang) + } + } } // GetTorrentLanguages returns a list of available torrent languages. -func GetTorrentLanguages() []string { +func GetTorrentLanguages() publicSettings.Languages { if torrentLanguages == nil { initTorrentLanguages() } @@ -34,23 +43,13 @@ func GetTorrentLanguages() []string { } // LanguageExists check if said language is available for torrents -func LanguageExists(lang string) bool { +func LanguageExists(languageCode string) bool { langs := GetTorrentLanguages() - for _, code := range langs { - if code == lang { + for _, lang := range langs { + if lang.Tag == languageCode { return true } } return false } - -// FlagFromLanguage reads the language's country code. -func FlagFromLanguage(lang string) string { - languageSplit := strings.Split(lang, "-") - if len(languageSplit) > 1 { - return languageSplit[1] - } - - return "" -} diff --git a/utils/torrentLanguages/torrent_languages_test.go b/utils/torrentLanguages/torrent_languages_test.go index 24dc7489..fdc99923 100644 --- a/utils/torrentLanguages/torrent_languages_test.go +++ b/utils/torrentLanguages/torrent_languages_test.go @@ -6,7 +6,10 @@ import ( "strings" "testing" + "fmt" + "github.com/NyaaPantsu/nyaa/config" + "github.com/NyaaPantsu/nyaa/utils/publicSettings" ) // run before config/parse.go:init() @@ -14,10 +17,16 @@ var _ = func() (_ struct{}) { config.ConfigPath = path.Join("..", "..", config.ConfigPath) config.DefaultConfigPath = path.Join("..", "..", config.DefaultConfigPath) config.Reload() + config.Get().I18n.Directory = path.Join("..", "..", config.Get().I18n.Directory) return }() func TestCSSFlags(t *testing.T) { + var retriever publicSettings.UserRetriever // not required during initialization + err := publicSettings.InitI18n(config.Get().I18n, retriever) + if err != nil { + t.Errorf("failed to initialize language translations: %v", err) + } languages := GetTorrentLanguages() flagsCSSPath := path.Join("..", "..", "public", "css", "flags", "flags.css") file, err := ioutil.ReadFile(flagsCSSPath) @@ -28,7 +37,8 @@ func TestCSSFlags(t *testing.T) { contents := string(file) for _, language := range languages { - flag := FlagFromLanguage(language) + flag := language.Flag(false) + fmt.Printf("Finding css class for: %s (%s)\n", flag, language.Name) if !strings.Contains(contents, ".flag-"+flag) { t.Errorf("flags.css does not contains class .flag-%s. You probably need to update it.", flag) }