2017-05-07 02:32:32 +02:00
package languages
import (
2017-05-09 01:44:41 +02:00
"fmt"
2017-05-13 22:52:10 +02:00
"html/template"
"net/http"
"path"
"path/filepath"
"github.com/ewhal/nyaa/config"
2017-05-10 21:45:39 +02:00
"github.com/ewhal/nyaa/service/user"
2017-05-11 15:12:19 +02:00
"github.com/nicksnyder/go-i18n/i18n"
2017-05-13 00:17:34 +02:00
"github.com/nicksnyder/go-i18n/i18n/language"
2017-05-07 23:05:41 +02:00
)
2017-05-07 02:32:32 +02:00
2017-05-13 22:52:10 +02:00
// Initialize the languages translation
func InitI18n ( conf config . I18nConfig ) error {
defaultFilepath := path . Join ( conf . TranslationsDirectory , conf . DefaultLanguage + ".all.json" )
err := i18n . LoadTranslationFile ( defaultFilepath )
if err != nil {
panic ( fmt . Sprintf ( "failed to load default translation file '%s': %v" , defaultFilepath , err ) )
}
paths , err := filepath . Glob ( path . Join ( conf . TranslationsDirectory , "*.json" ) )
if err != nil {
return fmt . Errorf ( "failed to get translation files: %v" , err )
}
for _ , path := range paths {
err := i18n . LoadTranslationFile ( path )
if err != nil {
return fmt . Errorf ( "failed to load translation file '%s': %v" , path , err )
}
}
return nil
}
2017-05-09 20:24:37 +02:00
// When go-i18n finds a language with >0 translations, it uses it as the Tfunc
// However, if said language has a missing translation, it won't fallback to the "main" language
2017-05-13 00:17:34 +02:00
func TfuncAndLanguageWithFallback ( language string , languages ... string ) ( i18n . TranslateFunc , * language . Language , error ) {
2017-05-09 20:24:37 +02:00
// Use the last language on the args as the fallback one.
fallbackLanguage := language
if languages != nil {
fallbackLanguage = languages [ len ( languages ) - 1 ]
}
2017-05-13 00:17:34 +02:00
T , Tlang , err1 := i18n . TfuncAndLanguage ( language , languages ... )
fallbackT , fallbackTlang , err2 := i18n . TfuncAndLanguage ( fallbackLanguage )
2017-05-09 20:24:37 +02:00
if err1 != nil && err2 != nil {
// fallbackT is still a valid function even with the error, it returns translationID.
2017-05-13 00:17:34 +02:00
return fallbackT , fallbackTlang , err2
2017-05-09 20:24:37 +02:00
}
return func ( translationID string , args ... interface { } ) string {
if translated := T ( translationID , args ... ) ; translated != translationID {
return translated
}
return fallbackT ( translationID , args ... )
2017-05-13 00:17:34 +02:00
} , Tlang , nil
2017-05-09 20:24:37 +02:00
}
2017-05-10 21:45:39 +02:00
func GetAvailableLanguages ( ) ( languages map [ string ] string ) {
languages = make ( map [ string ] string )
var T i18n . TranslateFunc
for _ , languageTag := range i18n . LanguageTags ( ) {
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" {
2017-05-11 15:12:19 +02:00
languages [ languageTag ] = languageName
2017-05-10 21:45:39 +02:00
} else {
languages [ languageTag ] = languageTag
}
}
return
}
2017-05-13 00:17:34 +02:00
func setTranslation ( tmpl * template . Template , T i18n . TranslateFunc ) {
2017-05-07 23:05:41 +02:00
tmpl . Funcs ( map [ string ] interface { } {
2017-05-09 01:44:41 +02:00
"T" : func ( str string , args ... interface { } ) template . HTML {
return template . HTML ( fmt . Sprintf ( T ( str ) , args ... ) )
2017-05-07 23:05:41 +02:00
} ,
2017-05-11 13:15:52 +02:00
"Ts" : func ( str string , args ... interface { } ) string {
return fmt . Sprintf ( T ( str ) , args ... )
} ,
2017-05-07 23:05:41 +02:00
} )
}
2017-05-13 00:17:34 +02:00
func GetTfuncAndLanguageFromRequest ( r * http . Request , defaultLanguage string ) ( T i18n . TranslateFunc , Tlang * language . Language ) {
2017-05-10 21:45:39 +02:00
userLanguage := ""
user , _ , err := userService . RetrieveCurrentUser ( r )
if err == nil {
2017-05-11 15:12:19 +02:00
userLanguage = user . Language
2017-05-10 21:45:39 +02:00
}
2017-05-07 23:05:41 +02:00
cookie , err := r . Cookie ( "lang" )
cookieLanguage := ""
if err == nil {
cookieLanguage = cookie . Value
}
2017-05-10 21:45:39 +02:00
2017-05-07 23:05:41 +02:00
// go-i18n supports the format of the Accept-Language header, thankfully.
headerLanguage := r . Header . Get ( "Accept-Language" )
2017-05-13 00:17:34 +02:00
T , Tlang , _ = TfuncAndLanguageWithFallback ( userLanguage , cookieLanguage , headerLanguage , defaultLanguage )
return
}
func SetTranslationFromRequest ( tmpl * template . Template , r * http . Request , defaultLanguage string ) i18n . TranslateFunc {
2017-05-11 15:12:19 +02:00
r . Header . Add ( "Vary" , "Accept-Encoding" )
2017-05-13 00:17:34 +02:00
T , _ := GetTfuncAndLanguageFromRequest ( r , defaultLanguage )
setTranslation ( tmpl , T )
return T
2017-05-07 23:05:41 +02:00
}