Merge pull request #510 from dweymouth/feat/choose-language
Add option to override app language detection
This commit is contained in:
+4
-2
@@ -48,7 +48,8 @@ type AppConfig struct {
|
||||
ShowTrackChangeNotification bool
|
||||
EnableLrcLib bool
|
||||
SkipSSLVerify bool
|
||||
EnqueueBatchSize int
|
||||
EnqueueBatchSize int
|
||||
Language string
|
||||
|
||||
// Experimental - may be removed in future
|
||||
FontNormalTTF string
|
||||
@@ -174,7 +175,8 @@ func DefaultConfig(appVersionTag string) *Config {
|
||||
ShowTrackChangeNotification: false,
|
||||
EnableLrcLib: true,
|
||||
SkipSSLVerify: false,
|
||||
EnqueueBatchSize: 100,
|
||||
EnqueueBatchSize: 100,
|
||||
Language: "auto",
|
||||
},
|
||||
AlbumPage: AlbumPageConfig{
|
||||
TracklistColumns: []string{"Artist", "Time", "Plays", "Favorite", "Rating"},
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"slices"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -46,7 +47,30 @@ func main() {
|
||||
os.Setenv("FYNE_SCALE", "1.1")
|
||||
}
|
||||
|
||||
lang.AddTranslationsFS(res.Translations, "translations")
|
||||
// load configured app language, or all otherwise
|
||||
lIdx := slices.IndexFunc(res.TranslationsInfo, func(t res.TranslationInfo) bool {
|
||||
return t.Name == myApp.Config.Application.Language
|
||||
})
|
||||
success := false
|
||||
if lIdx >= 0 {
|
||||
tr := res.TranslationsInfo[lIdx]
|
||||
content, err := res.Translations.ReadFile("translations/" + tr.TranslationFileName)
|
||||
if err == nil {
|
||||
// "trick" Fyne into loading translations for configured language
|
||||
// by pretending it's the translation for the system locale
|
||||
name := lang.SystemLocale().LanguageString()
|
||||
lang.AddTranslations(fyne.NewStaticResource(name+".json", content))
|
||||
success = true
|
||||
} else {
|
||||
log.Printf("Error loading translation file %s: %s\n", tr.TranslationFileName, err.Error())
|
||||
}
|
||||
}
|
||||
if !success {
|
||||
if err := lang.AddTranslationsFS(res.Translations, "translations"); err != nil {
|
||||
log.Printf("Error loading translations: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
fyneApp := app.New()
|
||||
fyneApp.SetIcon(res.ResAppicon256Png)
|
||||
|
||||
|
||||
@@ -4,3 +4,23 @@ import "embed"
|
||||
|
||||
//go:embed translations
|
||||
var Translations embed.FS
|
||||
|
||||
type TranslationInfo struct {
|
||||
Name string
|
||||
DisplayName string
|
||||
TranslationFileName string
|
||||
}
|
||||
|
||||
var TranslationsInfo = []TranslationInfo{
|
||||
{Name: "de", DisplayName: "Deutsch", TranslationFileName: "de.json"},
|
||||
{Name: "en", DisplayName: "English", TranslationFileName: "en.json"},
|
||||
{Name: "es", DisplayName: "Español", TranslationFileName: "es.json"},
|
||||
{Name: "fr", DisplayName: "François", TranslationFileName: "fr.json"},
|
||||
{Name: "it", DisplayName: "Italiano", TranslationFileName: "it.json"},
|
||||
{Name: "ja", DisplayName: "日本語", TranslationFileName: "ja.json"},
|
||||
{Name: "pl", DisplayName: "Polski", TranslationFileName: "pl.json"},
|
||||
{Name: "pt_BR", DisplayName: "Português (BR)", TranslationFileName: "pt_BR.json"},
|
||||
{Name: "ro", DisplayName: "Română", TranslationFileName: "ro.json"},
|
||||
{Name: "zhHans", DisplayName: "中文", TranslationFileName: "zhHans.json"},
|
||||
{Name: "zhHant", DisplayName: "中文 (trad.)", TranslationFileName: "zhHant.json"},
|
||||
}
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
"Interview": "Interview",
|
||||
"Is favorite": "Is favorite",
|
||||
"Is not favorite": "Is not favorite",
|
||||
"Language": "Language",
|
||||
"Last played": "Last played",
|
||||
"Live": "Live",
|
||||
"Locally": "Locally",
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
"Interview": "Entrevista",
|
||||
"Is favorite": "Es favorito",
|
||||
"Is not favorite": "No es favorito",
|
||||
"Language": "Idioma",
|
||||
"Last played": "Última reproducción",
|
||||
"Live": "En vivo",
|
||||
"Locally": "Localmente",
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
"Interview": "Interview",
|
||||
"Is favorite": "Favoris",
|
||||
"Is not favorite": "Non favoris",
|
||||
"Language": "Langue",
|
||||
"Last played": "Dernière lecture",
|
||||
"Live": "Live",
|
||||
"Locally": "En local",
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
"Interview": "Interview",
|
||||
"Is favorite": "Nei preferiti",
|
||||
"Is not favorite": "Non nei preferiti",
|
||||
"Language": "Lingua",
|
||||
"Last played": "Ultimo ascolto",
|
||||
"Live": "Live",
|
||||
"Locally": "Localmente",
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
"Interview": "インタビュー",
|
||||
"Is favorite": "お気に入り",
|
||||
"Is not favorite": "お気に入りでない",
|
||||
"Language": "言語",
|
||||
"Last played": "最後の再生",
|
||||
"Live": "ライブ",
|
||||
"Locally": "ローカル",
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
"Interview": "Wywiad",
|
||||
"Is favorite": "Jest ulubione",
|
||||
"Is not favorite": "Nie jest ulubione",
|
||||
"Language": "Język",
|
||||
"Last played": "Ostatnio odtwarzane",
|
||||
"Live": "Live",
|
||||
"Locally": "Lokalnie",
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
"Interview": "Entrevista",
|
||||
"Is favorite": "É favorito",
|
||||
"Is not favorite": "Não é favorito",
|
||||
"Language": "Linguagem",
|
||||
"Last played": "Tocados recentemente",
|
||||
"Live": "Ao Vivo",
|
||||
"Locally": "Localmente",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"Interview": "Interviu",
|
||||
"Is favorite": "Este favorit",
|
||||
"Is not favorite": "Nu este favorit",
|
||||
"Language": "Limbă",
|
||||
"Last played": "Ultimul redat",
|
||||
"Live": "Live",
|
||||
"Locally": "Local",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"Interview": "采访",
|
||||
"Is favorite": "已收藏",
|
||||
"Is not favorite": "未收藏",
|
||||
"Language": "语言",
|
||||
"Last played": "上次播放",
|
||||
"Live": "现场",
|
||||
"To server": "到服务器",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"Interview": "采访",
|
||||
"Is favorite": "已收藏",
|
||||
"Is not favorite": "未收藏",
|
||||
"Language": "语言",
|
||||
"Last played": "上次播放",
|
||||
"Live": "现场",
|
||||
"Locally": "到本地",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"Interview": "訪談",
|
||||
"Is favorite": "已收藏",
|
||||
"Is not favorite": "未收藏",
|
||||
"Language": "語言",
|
||||
"Last played": "上次播放",
|
||||
"Live": "現場",
|
||||
"Locally": "到本地",
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/dweymouth/supersonic/backend"
|
||||
"github.com/dweymouth/supersonic/backend/player/mpv"
|
||||
"github.com/dweymouth/supersonic/res"
|
||||
myTheme "github.com/dweymouth/supersonic/ui/theme"
|
||||
"github.com/dweymouth/supersonic/ui/util"
|
||||
"github.com/dweymouth/supersonic/ui/widgets"
|
||||
@@ -146,6 +147,28 @@ func (s *SettingsDialog) createGeneralTab(canSaveQueueToServer bool) *container.
|
||||
if startupPage.Selected == "" {
|
||||
startupPage.SetSelectedIndex(0)
|
||||
}
|
||||
|
||||
languageList := make([]string, len(res.TranslationsInfo)+1)
|
||||
languageList[0] = lang.L("Auto")
|
||||
var langSelIndex int
|
||||
for i, tr := range res.TranslationsInfo {
|
||||
languageList[i+1] = tr.DisplayName
|
||||
if tr.Name == s.config.Application.Language {
|
||||
langSelIndex = i + 1
|
||||
}
|
||||
}
|
||||
|
||||
languageSelect := widget.NewSelect(languageList, nil)
|
||||
languageSelect.SetSelectedIndex(langSelIndex)
|
||||
languageSelect.OnChanged = func(_ string) {
|
||||
lang := "auto"
|
||||
if i := languageSelect.SelectedIndex(); i > 0 {
|
||||
lang = res.TranslationsInfo[i-1].Name
|
||||
}
|
||||
s.config.Application.Language = lang
|
||||
s.setRestartRequired()
|
||||
}
|
||||
|
||||
closeToTray := widget.NewCheckWithData(lang.L("Close to system tray"),
|
||||
binding.BindBool(&s.config.Application.CloseToSystemTray))
|
||||
if !s.config.Application.EnableSystemTray {
|
||||
@@ -285,8 +308,9 @@ func (s *SettingsDialog) createGeneralTab(canSaveQueueToServer bool) *container.
|
||||
scrobbleEnabled.Checked = s.config.Scrobbling.Enabled
|
||||
|
||||
return container.NewTabItem(lang.L("General"), container.NewVBox(
|
||||
container.NewHBox(widget.NewLabel(lang.L("Language")), languageSelect),
|
||||
container.NewBorder(nil, nil, widget.NewLabel(lang.L("Theme")), /*left*/
|
||||
container.NewHBox(widget.NewLabel("Mode"), themeModeSelect, util.NewHSpace(5)), // right
|
||||
container.NewHBox(widget.NewLabel(lang.L("Mode")), themeModeSelect, util.NewHSpace(5)), // right
|
||||
themeFileSelect, // center
|
||||
),
|
||||
container.NewHBox(
|
||||
|
||||
Reference in New Issue
Block a user