mirror of
https://github.com/AynaLivePlayer/AynaLivePlayer.git
synced 2025-12-06 10:22:50 +08:00
add i18n
This commit is contained in:
@@ -10,4 +10,5 @@ QQ group: 621035845
|
||||
|
||||
```
|
||||
go build -ldflags -H=windowsgui app/gui/main.go
|
||||
|
||||
```
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"AynaLivePlayer/config"
|
||||
"AynaLivePlayer/controller"
|
||||
"AynaLivePlayer/gui"
|
||||
"AynaLivePlayer/i18n"
|
||||
"AynaLivePlayer/logger"
|
||||
"AynaLivePlayer/plugin/diange"
|
||||
"AynaLivePlayer/plugin/qiege"
|
||||
@@ -32,6 +33,7 @@ func main() {
|
||||
defer func() {
|
||||
controller.Destroy()
|
||||
config.SaveToConfigFile(config.CONFIG_PATH)
|
||||
i18n.SaveTranslation()
|
||||
}()
|
||||
gui.Initialize()
|
||||
gui.MainWindow.ShowAndRun()
|
||||
|
||||
220
assets/translation.json
Normal file
220
assets/translation.json
Normal file
@@ -0,0 +1,220 @@
|
||||
{
|
||||
"Languages": [
|
||||
"en",
|
||||
"zh-CN"
|
||||
],
|
||||
"Messages": {
|
||||
"gui.player.button.lrc": {
|
||||
"en": "lrc",
|
||||
"zh-CN": "歌词"
|
||||
},
|
||||
"gui.player.playlist.artist": {
|
||||
"en": "Artist",
|
||||
"zh-CN": "歌手"
|
||||
},
|
||||
"gui.player.playlist.op.delete": {
|
||||
"en": "Delete",
|
||||
"zh-CN": "删除"
|
||||
},
|
||||
"gui.player.playlist.op.top": {
|
||||
"en": "Top",
|
||||
"zh-CN": "置顶"
|
||||
},
|
||||
"gui.player.playlist.ops": {
|
||||
"en": "OPs",
|
||||
"zh-CN": "操作"
|
||||
},
|
||||
"gui.player.playlist.title": {
|
||||
"en": "Title",
|
||||
"zh-CN": "歌名"
|
||||
},
|
||||
"gui.player.playlist.user": {
|
||||
"en": "User",
|
||||
"zh-CN": "用户"
|
||||
},
|
||||
"gui.playlist.add.cancel": {
|
||||
"en": "Cancel",
|
||||
"zh-CN": "取消"
|
||||
},
|
||||
"gui.playlist.add.confirm": {
|
||||
"en": "Confirm",
|
||||
"zh-CN": "确认"
|
||||
},
|
||||
"gui.playlist.add.id_url": {
|
||||
"en": "ID/URL",
|
||||
"zh-CN": "ID/网址"
|
||||
},
|
||||
"gui.playlist.add.prompt": {
|
||||
"en": "Please enter the ID or URL of the song you want to add.",
|
||||
"zh-CN": "输入歌单ID或者歌单网址。"
|
||||
},
|
||||
"gui.playlist.add.title": {
|
||||
"en": "Add Playlist",
|
||||
"zh-CN": "添加歌单"
|
||||
},
|
||||
"gui.playlist.button.add": {
|
||||
"en": "Add",
|
||||
"zh-CN": "添加"
|
||||
},
|
||||
"gui.playlist.button.refresh": {
|
||||
"en": "Refresh",
|
||||
"zh-CN": "刷新"
|
||||
},
|
||||
"gui.playlist.button.remove": {
|
||||
"en": "Remove",
|
||||
"zh-CN": "移除"
|
||||
},
|
||||
"gui.playlist.button.set_as_system": {
|
||||
"en": "SetAsSystem",
|
||||
"zh-CN": "设为默认歌单"
|
||||
},
|
||||
"gui.playlist.current": {
|
||||
"en": "Current: ",
|
||||
"zh-CN": "当前为: "
|
||||
},
|
||||
"gui.playlist.current.none": {
|
||||
"en": "Current: None",
|
||||
"zh-CN": "当前为: 无"
|
||||
},
|
||||
"gui.room.btn.connect": {
|
||||
"en": "Connect",
|
||||
"zh-CN": "连接"
|
||||
},
|
||||
"gui.room.btn.disconnect": {
|
||||
"en": "Disconnect",
|
||||
"zh-CN": "断开"
|
||||
},
|
||||
"gui.room.id": {
|
||||
"en": "Room ID: ",
|
||||
"zh-CN": "房间号: "
|
||||
},
|
||||
"gui.room.status.connected": {
|
||||
"en": "Connected",
|
||||
"zh-CN": "已连接"
|
||||
},
|
||||
"gui.room.status.disconnected": {
|
||||
"en": "Disconnected",
|
||||
"zh-CN": "已断开"
|
||||
},
|
||||
"gui.room.status.failed": {
|
||||
"en": "Set Failed",
|
||||
"zh-CN": "设置失败"
|
||||
},
|
||||
"gui.room.waiting": {
|
||||
"en": "Waiting",
|
||||
"zh-CN": "等待连接"
|
||||
},
|
||||
"gui.search.artist": {
|
||||
"en": "Artist",
|
||||
"zh-CN": "歌手"
|
||||
},
|
||||
"gui.search.filter": {
|
||||
"en": "Source Filter: ",
|
||||
"zh-CN": "选择源: "
|
||||
},
|
||||
"gui.search.operation": {
|
||||
"en": "Operation",
|
||||
"zh-CN": "操作 "
|
||||
},
|
||||
"gui.search.placeholder": {
|
||||
"en": "Keyword",
|
||||
"zh-CN": "Keyword"
|
||||
},
|
||||
"gui.search.search": {
|
||||
"en": "Search",
|
||||
"zh-CN": "搜索"
|
||||
},
|
||||
"gui.search.source": {
|
||||
"en": "Source",
|
||||
"zh-CN": "歌源"
|
||||
},
|
||||
"gui.search.title": {
|
||||
"en": "Title",
|
||||
"zh-CN": "歌名"
|
||||
},
|
||||
"gui.tab.config": {
|
||||
"en": "Config",
|
||||
"zh-CN": "设置"
|
||||
},
|
||||
"gui.tab.player": {
|
||||
"en": "Player",
|
||||
"zh-CN": "播放器"
|
||||
},
|
||||
"gui.tab.playlist": {
|
||||
"en": "Playlist",
|
||||
"zh-CN": "播放列表"
|
||||
},
|
||||
"gui.tab.room": {
|
||||
"en": "Room",
|
||||
"zh-CN": "直播间"
|
||||
},
|
||||
"gui.tab.search": {
|
||||
"en": "Search",
|
||||
"zh-CN": "搜索"
|
||||
},
|
||||
"plugin.diange.admin": {
|
||||
"en": "Admin",
|
||||
"zh-CN": "管理员"
|
||||
},
|
||||
"plugin.diange.cooldown": {
|
||||
"en": "Cooldown",
|
||||
"zh-CN": "点歌冷却"
|
||||
},
|
||||
"plugin.diange.custom_cmd": {
|
||||
"en": "Custom Command (Default one still works)",
|
||||
"zh-CN": "自定义命令 (默认的依然可用)"
|
||||
},
|
||||
"plugin.diange.description": {
|
||||
"en": "Basic Diange Configuration",
|
||||
"zh-CN": "点歌基本设置"
|
||||
},
|
||||
"plugin.diange.permission": {
|
||||
"en": "Permission",
|
||||
"zh-CN": "点歌权限"
|
||||
},
|
||||
"plugin.diange.privilege": {
|
||||
"en": "Privilege",
|
||||
"zh-CN": "舰长"
|
||||
},
|
||||
"plugin.diange.queue_max": {
|
||||
"en": "Max Queue",
|
||||
"zh-CN": "最大点歌数"
|
||||
},
|
||||
"plugin.diange.title": {
|
||||
"en": "Diange",
|
||||
"zh-CN": "点歌"
|
||||
},
|
||||
"plugin.diange.user": {
|
||||
"en": "User",
|
||||
"zh-CN": "普通用户"
|
||||
},
|
||||
"plugin.qiege.admin": {
|
||||
"en": "Admin",
|
||||
"zh-CN": "管理员"
|
||||
},
|
||||
"plugin.qiege.custom_cmd": {
|
||||
"en": "Custom Command (Default one still works)",
|
||||
"zh-CN": "自定义命令 (默认的依然可用)"
|
||||
},
|
||||
"plugin.qiege.description": {
|
||||
"en": "Basic Qiege configuration",
|
||||
"zh-CN": "基础切歌设置"
|
||||
},
|
||||
"plugin.qiege.permission": {
|
||||
"en": "Permission",
|
||||
"zh-CN": "切歌权限"
|
||||
},
|
||||
"plugin.qiege.privilege": {
|
||||
"en": "Privilege",
|
||||
"zh-CN": "舰长"
|
||||
},
|
||||
"plugin.qiege.title": {
|
||||
"en": "Qiege",
|
||||
"zh-CN": "切歌"
|
||||
},
|
||||
"plugin.qiege.user": {
|
||||
"en": "User",
|
||||
"zh-CN": "切自己"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"path"
|
||||
)
|
||||
|
||||
const VERSION = "alpha 0.6.3"
|
||||
const VERSION = "alpha 0.6.5"
|
||||
|
||||
const CONFIG_PATH = "./config.ini"
|
||||
const Assests_PATH = "./assets"
|
||||
@@ -38,7 +38,7 @@ func init() {
|
||||
fmt.Println("config not found, using default config")
|
||||
ConfigFile = ini.Empty()
|
||||
}
|
||||
for _, cfg := range []Config{Log, LiveRoom, Player, Provider} {
|
||||
for _, cfg := range []Config{Log, LiveRoom, Player, Provider, General} {
|
||||
LoadConfig(cfg)
|
||||
}
|
||||
}
|
||||
|
||||
13
config/config_general.go
Normal file
13
config/config_general.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package config
|
||||
|
||||
type _GeneralConfig struct {
|
||||
Language string
|
||||
}
|
||||
|
||||
func (c *_GeneralConfig) Name() string {
|
||||
return "General"
|
||||
}
|
||||
|
||||
var General = &_GeneralConfig{
|
||||
Language: "en",
|
||||
}
|
||||
11
gui/gui.go
11
gui/gui.go
@@ -2,6 +2,7 @@ package gui
|
||||
|
||||
import (
|
||||
"AynaLivePlayer/config"
|
||||
"AynaLivePlayer/i18n"
|
||||
"AynaLivePlayer/logger"
|
||||
"fmt"
|
||||
"fyne.io/fyne/v2"
|
||||
@@ -33,19 +34,19 @@ func Initialize() {
|
||||
MainWindow = App.NewWindow(fmt.Sprintf("AynaLivePlayer Ver.%s", config.VERSION))
|
||||
|
||||
tabs := container.NewAppTabs(
|
||||
container.NewTabItem("Player",
|
||||
container.NewTabItem(i18n.T("gui.tab.player"),
|
||||
newPaddedBoarder(nil, createPlayController(), nil, nil, createPlaylist()),
|
||||
),
|
||||
container.NewTabItem("Search",
|
||||
container.NewTabItem(i18n.T("gui.tab.search"),
|
||||
newPaddedBoarder(createSearchBar(), nil, nil, nil, createSearchList()),
|
||||
),
|
||||
container.NewTabItem("Room",
|
||||
container.NewTabItem(i18n.T("gui.tab.room"),
|
||||
newPaddedBoarder(createRoomController(), nil, nil, nil, createRoomLogger()),
|
||||
),
|
||||
container.NewTabItem("Playlist",
|
||||
container.NewTabItem(i18n.T("gui.tab.playlist"),
|
||||
newPaddedBoarder(nil, nil, createPlaylists(), nil, createPlaylistMedias()),
|
||||
),
|
||||
container.NewTabItem("Config",
|
||||
container.NewTabItem(i18n.T("gui.tab.config"),
|
||||
newPaddedBoarder(nil, nil, nil, nil, createConfigLayout()),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"AynaLivePlayer/config"
|
||||
"AynaLivePlayer/controller"
|
||||
"AynaLivePlayer/event"
|
||||
"AynaLivePlayer/i18n"
|
||||
"AynaLivePlayer/player"
|
||||
"AynaLivePlayer/util"
|
||||
"fyne.io/fyne/v2"
|
||||
@@ -64,7 +65,7 @@ func createPlayController() fyne.CanvasObject {
|
||||
|
||||
PlayController.Volume = widget.NewSlider(0, 100)
|
||||
volumeIcon := widget.NewIcon(theme.VolumeMuteIcon())
|
||||
PlayController.ButtonLrc = widget.NewButton("lrc", func() {})
|
||||
PlayController.ButtonLrc = widget.NewButton(i18n.T("gui.player.button.lrc"), func() {})
|
||||
|
||||
volumeControl := container.NewBorder(nil, nil, container.NewHBox(widget.NewLabel(" "), volumeIcon), nil,
|
||||
container.NewGridWithColumns(3, container.NewMax(PlayController.Volume), PlayController.ButtonLrc))
|
||||
|
||||
@@ -3,6 +3,7 @@ package gui
|
||||
import (
|
||||
"AynaLivePlayer/controller"
|
||||
"AynaLivePlayer/event"
|
||||
"AynaLivePlayer/i18n"
|
||||
"AynaLivePlayer/player"
|
||||
"fmt"
|
||||
"fyne.io/fyne/v2"
|
||||
@@ -23,10 +24,10 @@ func (b *playlistOperationButton) Tapped(e *fyne.PointEvent) {
|
||||
|
||||
func newPlaylistOperationButton() *playlistOperationButton {
|
||||
b := &playlistOperationButton{Index: 0}
|
||||
deleteItem := fyne.NewMenuItem("Delete", func() {
|
||||
deleteItem := fyne.NewMenuItem(i18n.T("gui.player.playlist.op.delete"), func() {
|
||||
fmt.Println("delete", b.Index)
|
||||
})
|
||||
topItem := fyne.NewMenuItem("Top", func() {
|
||||
topItem := fyne.NewMenuItem(i18n.T("gui.player.playlist.op.top"), func() {
|
||||
controller.UserPlaylist.Move(b.Index, 0)
|
||||
})
|
||||
m := fyne.NewMenu("", deleteItem, topItem)
|
||||
@@ -72,8 +73,11 @@ func createPlaylist() fyne.CanvasObject {
|
||||
registerPlaylistHandler()
|
||||
return container.NewBorder(
|
||||
container.NewBorder(nil, nil,
|
||||
widget.NewLabel("#"), widget.NewLabel("OPs"),
|
||||
container.NewGridWithColumns(3, widget.NewLabel("Title"), widget.NewLabel("Artist"), widget.NewLabel("User"))),
|
||||
widget.NewLabel("#"), widget.NewLabel(i18n.T("gui.player.playlist.ops")),
|
||||
container.NewGridWithColumns(3,
|
||||
widget.NewLabel(i18n.T("gui.player.playlist.title")),
|
||||
widget.NewLabel(i18n.T("gui.player.playlist.artist")),
|
||||
widget.NewLabel(i18n.T("gui.player.playlist.user")))),
|
||||
widget.NewSeparator(),
|
||||
nil, nil,
|
||||
UserPlaylist.List,
|
||||
|
||||
@@ -3,6 +3,7 @@ package gui
|
||||
import (
|
||||
"AynaLivePlayer/config"
|
||||
"AynaLivePlayer/controller"
|
||||
"AynaLivePlayer/i18n"
|
||||
"fmt"
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
@@ -25,9 +26,9 @@ type PlaylistManagerContainer struct {
|
||||
|
||||
func (p *PlaylistManagerContainer) UpdateCurrentSystemPlaylist() {
|
||||
if config.Player.PlaylistIndex >= len(controller.PlaylistManager) {
|
||||
p.CurrentSystemPlaylist.SetText("Current: None")
|
||||
p.CurrentSystemPlaylist.SetText(i18n.T("gui.playlist.current.none"))
|
||||
}
|
||||
p.CurrentSystemPlaylist.SetText("Current: " + controller.PlaylistManager[config.Player.PlaylistIndex].Name)
|
||||
p.CurrentSystemPlaylist.SetText(i18n.T("gui.playlist.current") + controller.PlaylistManager[config.Player.PlaylistIndex].Name)
|
||||
}
|
||||
|
||||
var PlaylistManager = &PlaylistManagerContainer{}
|
||||
@@ -44,22 +45,22 @@ func createPlaylists() fyne.CanvasObject {
|
||||
object.(*widget.Label).SetText(
|
||||
controller.PlaylistManager[id].Name)
|
||||
})
|
||||
PlaylistManager.AddBtn = widget.NewButton("Add", func() {
|
||||
PlaylistManager.AddBtn = widget.NewButton(i18n.T("gui.playlist.button.add"), func() {
|
||||
providerEntry := widget.NewSelect(config.Provider.Priority, nil)
|
||||
idEntry := widget.NewEntry()
|
||||
dia := dialog.NewCustomConfirm(
|
||||
"Add Playlist",
|
||||
"Add",
|
||||
"Cancel",
|
||||
i18n.T("gui.playlist.add.title"),
|
||||
i18n.T("gui.playlist.add.confirm"),
|
||||
i18n.T("gui.playlist.add.cancel"),
|
||||
container.NewVBox(
|
||||
container.New(
|
||||
layout.NewFormLayout(),
|
||||
widget.NewLabel("Provider"),
|
||||
widget.NewLabel(i18n.T("gui.playlist.add.confirm")),
|
||||
providerEntry,
|
||||
widget.NewLabel("ID/URL"),
|
||||
widget.NewLabel(i18n.T("gui.playlist.add.id_url")),
|
||||
idEntry,
|
||||
),
|
||||
widget.NewLabel("Please Enter playlist id or playlist url"),
|
||||
widget.NewLabel(i18n.T("gui.playlist.add.prompt")),
|
||||
),
|
||||
func(b bool) {
|
||||
if b && len(providerEntry.Selected) > 0 && len(idEntry.Text) > 0 {
|
||||
@@ -73,7 +74,7 @@ func createPlaylists() fyne.CanvasObject {
|
||||
dia.Resize(fyne.NewSize(512, 256))
|
||||
dia.Show()
|
||||
})
|
||||
PlaylistManager.RemoveBtn = widget.NewButton("Remove", func() {
|
||||
PlaylistManager.RemoveBtn = widget.NewButton(i18n.T("gui.playlist.button.remove"), func() {
|
||||
controller.RemovePlaylist(PlaylistManager.Index)
|
||||
//PlaylistManager.Index = 0
|
||||
PlaylistManager.Playlists.Select(0)
|
||||
@@ -95,13 +96,13 @@ func createPlaylists() fyne.CanvasObject {
|
||||
|
||||
func createPlaylistMedias() fyne.CanvasObject {
|
||||
PlaylistManager.RefreshBtn = createAsyncButton(
|
||||
widget.NewButtonWithIcon("Refresh", theme.ViewRefreshIcon(), nil),
|
||||
widget.NewButtonWithIcon(i18n.T("gui.playlist.button.refresh"), theme.ViewRefreshIcon(), nil),
|
||||
func() {
|
||||
controller.PreparePlaylistByIndex(PlaylistManager.Index)
|
||||
PlaylistManager.PlaylistMedia.Refresh()
|
||||
})
|
||||
PlaylistManager.SetAsSystemBtn = createAsyncButton(
|
||||
widget.NewButton("SetAsSystem", nil),
|
||||
widget.NewButton(i18n.T("gui.playlist.button.set_as_system"), nil),
|
||||
func() {
|
||||
controller.SetSystemPlaylist(PlaylistManager.Index)
|
||||
PlaylistManager.PlaylistMedia.Refresh()
|
||||
@@ -143,7 +144,7 @@ func createPlaylistMedias() fyne.CanvasObject {
|
||||
}
|
||||
})
|
||||
return container.NewBorder(
|
||||
container.NewHBox(PlaylistManager.RefreshBtn, PlaylistManager.SetAsSystemBtn), nil,
|
||||
container.NewHBox(PlaylistManager.RefreshBtn, PlaylistManager.SetAsSystemBtn, PlaylistManager.CurrentSystemPlaylist), nil,
|
||||
nil, nil,
|
||||
PlaylistManager.PlaylistMedia)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"AynaLivePlayer/config"
|
||||
"AynaLivePlayer/controller"
|
||||
"AynaLivePlayer/event"
|
||||
"AynaLivePlayer/i18n"
|
||||
"AynaLivePlayer/liveclient"
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
@@ -21,11 +22,11 @@ var RoomController = &RoomControllerContainer{}
|
||||
|
||||
func createRoomController() fyne.CanvasObject {
|
||||
RoomController.Input = widget.NewSelectEntry(config.LiveRoom.History)
|
||||
RoomController.ConnectBtn = widget.NewButton("Connect", func() {
|
||||
RoomController.ConnectBtn = widget.NewButton(i18n.T("gui.room.btn.connect"), func() {
|
||||
RoomController.ConnectBtn.Disable()
|
||||
controller.SetDanmuClient(RoomController.Input.Text)
|
||||
if controller.LiveClient == nil {
|
||||
RoomController.Status.SetText("Set Failed")
|
||||
RoomController.Status.SetText(i18n.T("gui.room.status.failed"))
|
||||
RoomController.ConnectBtn.Enable()
|
||||
RoomController.Status.Refresh()
|
||||
return
|
||||
@@ -34,9 +35,9 @@ func createRoomController() fyne.CanvasObject {
|
||||
controller.LiveClient.Handler().RegisterA(liveclient.EventStatusChange, "gui.liveclient.status", func(event *event.Event) {
|
||||
d := event.Data.(liveclient.StatusChangeEvent)
|
||||
if d.Connected {
|
||||
RoomController.Status.SetText("Connected")
|
||||
RoomController.Status.SetText(i18n.T("gui.room.status.connected"))
|
||||
} else {
|
||||
RoomController.Status.SetText("Disconnected")
|
||||
RoomController.Status.SetText(i18n.T("gui.room.status.disconnected"))
|
||||
}
|
||||
RoomController.Status.Refresh()
|
||||
})
|
||||
@@ -45,13 +46,13 @@ func createRoomController() fyne.CanvasObject {
|
||||
RoomController.ConnectBtn.Enable()
|
||||
}()
|
||||
})
|
||||
RoomController.DisConnectBtn = widget.NewButton("Disconnect", func() {
|
||||
RoomController.DisConnectBtn = widget.NewButton(i18n.T("gui.room.btn.disconnect"), func() {
|
||||
controller.ResetDanmuClient()
|
||||
})
|
||||
RoomController.Status = widget.NewLabel("Waiting")
|
||||
RoomController.Status = widget.NewLabel(i18n.T("gui.room.waiting"))
|
||||
return container.NewBorder(
|
||||
nil, nil,
|
||||
widget.NewLabel("Room ID:"), container.NewHBox(RoomController.ConnectBtn, RoomController.DisConnectBtn),
|
||||
widget.NewLabel(i18n.T("gui.room.id")), container.NewHBox(RoomController.ConnectBtn, RoomController.DisConnectBtn),
|
||||
container.NewBorder(nil, nil, nil, RoomController.Status, RoomController.Input),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package gui
|
||||
import (
|
||||
"AynaLivePlayer/config"
|
||||
"AynaLivePlayer/controller"
|
||||
"AynaLivePlayer/i18n"
|
||||
"AynaLivePlayer/player"
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
@@ -20,8 +21,8 @@ var SearchBar = &SearchBarContainer{}
|
||||
|
||||
func createSearchBar() fyne.CanvasObject {
|
||||
SearchBar.Input = widget.NewEntry()
|
||||
SearchBar.Input.SetPlaceHolder("Keyword")
|
||||
SearchBar.Button = widget.NewButton("Search", nil)
|
||||
SearchBar.Input.SetPlaceHolder(i18n.T("gui.search.placeholder"))
|
||||
SearchBar.Button = widget.NewButton(i18n.T("gui.search.search"), nil)
|
||||
SearchBar.Button.OnTapped = createAsyncOnTapped(SearchBar.Button, func() {
|
||||
keyword := SearchBar.Input.Text
|
||||
s := make([]string, len(SearchBar.UseSource.Selected))
|
||||
@@ -44,10 +45,10 @@ func createSearchBar() fyne.CanvasObject {
|
||||
SearchBar.UseSource.Horizontal = true
|
||||
SearchBar.UseSource.SetSelected(s)
|
||||
searchInput := container.NewBorder(
|
||||
nil, nil, widget.NewLabel("Search"), SearchBar.Button,
|
||||
nil, nil, widget.NewLabel(i18n.T("gui.search.search")), SearchBar.Button,
|
||||
SearchBar.Input)
|
||||
return container.NewVBox(
|
||||
searchInput,
|
||||
container.NewHBox(widget.NewLabel("Source filter: "), SearchBar.UseSource),
|
||||
container.NewHBox(widget.NewLabel(i18n.T("gui.search.filter")), SearchBar.UseSource),
|
||||
widget.NewSeparator())
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package gui
|
||||
|
||||
import (
|
||||
"AynaLivePlayer/controller"
|
||||
"AynaLivePlayer/i18n"
|
||||
"AynaLivePlayer/player"
|
||||
"AynaLivePlayer/provider"
|
||||
"fmt"
|
||||
@@ -53,11 +54,11 @@ func createSearchList() fyne.CanvasObject {
|
||||
})
|
||||
return container.NewBorder(
|
||||
container.NewBorder(nil, nil,
|
||||
widget.NewLabel("#"), widget.NewLabel("Operation"),
|
||||
widget.NewLabel("#"), widget.NewLabel(i18n.T("gui.search.operation")),
|
||||
container.NewGridWithColumns(3,
|
||||
widget.NewLabel("title"),
|
||||
widget.NewLabel("artist"),
|
||||
widget.NewLabel("source"))),
|
||||
widget.NewLabel(i18n.T("gui.search.title")),
|
||||
widget.NewLabel(i18n.T("gui.search.artist")),
|
||||
widget.NewLabel(i18n.T("gui.search.source")))),
|
||||
nil, nil, nil,
|
||||
SearchResult.List,
|
||||
)
|
||||
|
||||
63
i18n/i18n.go
Normal file
63
i18n/i18n.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"AynaLivePlayer/config"
|
||||
"AynaLivePlayer/util"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
const FILENAME = "translation.json"
|
||||
|
||||
type Translation struct {
|
||||
Languages []string
|
||||
Messages map[string]map[string]string
|
||||
}
|
||||
|
||||
func (t *Translation) HasLanguage(lang string) bool {
|
||||
for _, l := range t.Languages {
|
||||
if l == lang {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var TranslationMap Translation
|
||||
var CurrentLanguage string
|
||||
|
||||
func init() {
|
||||
TranslationMap = Translation{make([]string, 0), make(map[string]map[string]string)}
|
||||
file, err := ioutil.ReadFile(config.GetAssetPath(FILENAME))
|
||||
if err == nil {
|
||||
_ = json.Unmarshal([]byte(file), &TranslationMap)
|
||||
}
|
||||
LoadLanguage(config.General.Language)
|
||||
}
|
||||
|
||||
func LoadLanguage(lang string) {
|
||||
CurrentLanguage = lang
|
||||
if TranslationMap.HasLanguage(lang) {
|
||||
return
|
||||
}
|
||||
TranslationMap.Languages = append(TranslationMap.Languages, lang)
|
||||
for id, m := range TranslationMap.Messages {
|
||||
m[lang] = id
|
||||
}
|
||||
}
|
||||
|
||||
func T(id string) string {
|
||||
if x, ok := TranslationMap.Messages[id]; ok {
|
||||
return x[CurrentLanguage]
|
||||
}
|
||||
TranslationMap.Messages[id] = make(map[string]string)
|
||||
for _, l := range TranslationMap.Languages {
|
||||
TranslationMap.Messages[id][l] = id
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
func SaveTranslation() {
|
||||
content, _ := util.MarshalIndentUnescape(TranslationMap, "", " ")
|
||||
_ = ioutil.WriteFile(config.GetAssetPath(FILENAME), []byte(content), 0666)
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"AynaLivePlayer/config"
|
||||
"AynaLivePlayer/controller"
|
||||
"AynaLivePlayer/gui"
|
||||
"AynaLivePlayer/i18n"
|
||||
"AynaLivePlayer/liveclient"
|
||||
"AynaLivePlayer/logger"
|
||||
"fyne.io/fyne/v2"
|
||||
@@ -91,11 +92,11 @@ func (d *Diange) Execute(command string, args []string, danmu *liveclient.DanmuM
|
||||
}
|
||||
|
||||
func (d *Diange) Title() string {
|
||||
return "Diange"
|
||||
return i18n.T("plugin.diange.title")
|
||||
}
|
||||
|
||||
func (d *Diange) Description() string {
|
||||
return "Basic diange configuration"
|
||||
return i18n.T("plugin.diange.description")
|
||||
}
|
||||
|
||||
func (d *Diange) CreatePanel() fyne.CanvasObject {
|
||||
@@ -103,21 +104,21 @@ func (d *Diange) CreatePanel() fyne.CanvasObject {
|
||||
return d.panel
|
||||
}
|
||||
dgPerm := container.NewHBox(
|
||||
widget.NewLabel("点歌权限"),
|
||||
widget.NewCheckWithData("用户", binding.BindBool(&d.UserPermission)),
|
||||
widget.NewCheckWithData("舰长", binding.BindBool(&d.PrivilegePermission)),
|
||||
widget.NewCheckWithData("管理员", binding.BindBool(&d.AdminPermission)),
|
||||
widget.NewLabel(i18n.T("plugin.diange.permission")),
|
||||
widget.NewCheckWithData(i18n.T("plugin.diange.user"), binding.BindBool(&d.UserPermission)),
|
||||
widget.NewCheckWithData(i18n.T("plugin.diange.privilege"), binding.BindBool(&d.PrivilegePermission)),
|
||||
widget.NewCheckWithData(i18n.T("plugin.diange.admin"), binding.BindBool(&d.AdminPermission)),
|
||||
)
|
||||
dgQueue := container.NewBorder(nil, nil,
|
||||
widget.NewLabel("最大点歌数"), nil,
|
||||
widget.NewLabel(i18n.T("plugin.diange.queue_max")), nil,
|
||||
widget.NewEntryWithData(binding.IntToString(binding.BindInt(&d.QueueMax))),
|
||||
)
|
||||
dgCoolDown := container.NewBorder(nil, nil,
|
||||
widget.NewLabel("点歌冷却时间"), nil,
|
||||
widget.NewLabel(i18n.T("plugin.diange.cooldown")), nil,
|
||||
widget.NewEntryWithData(binding.IntToString(binding.BindInt(&d.UserCoolDown))),
|
||||
)
|
||||
dgShortCut := container.NewBorder(nil, nil,
|
||||
widget.NewLabel("自定义命令 (默认的依然可用)"), nil,
|
||||
widget.NewLabel(i18n.T("plugin.diange.custom_cmd")), nil,
|
||||
widget.NewEntryWithData(binding.BindString(&d.CustomCMD)),
|
||||
)
|
||||
d.panel = container.NewVBox(dgPerm, dgQueue, dgCoolDown, dgShortCut)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"AynaLivePlayer/config"
|
||||
"AynaLivePlayer/controller"
|
||||
"AynaLivePlayer/gui"
|
||||
"AynaLivePlayer/i18n"
|
||||
"AynaLivePlayer/liveclient"
|
||||
"AynaLivePlayer/logger"
|
||||
"fyne.io/fyne/v2"
|
||||
@@ -74,26 +75,25 @@ func (d *Qiege) Execute(command string, args []string, danmu *liveclient.DanmuMe
|
||||
}
|
||||
|
||||
func (d *Qiege) Title() string {
|
||||
return "Qiege"
|
||||
return i18n.T("plugin.qiege.title")
|
||||
}
|
||||
|
||||
func (d *Qiege) Description() string {
|
||||
return "Basic Qiege configuration"
|
||||
return i18n.T("plugin.qiege.description")
|
||||
}
|
||||
|
||||
func (d *Qiege) CreatePanel() fyne.CanvasObject {
|
||||
if d.panel != nil {
|
||||
return d.panel
|
||||
}
|
||||
|
||||
dgPerm := container.NewHBox(
|
||||
widget.NewLabel("切歌权限"),
|
||||
widget.NewCheckWithData("切自己", binding.BindBool(&d.UserPermission)),
|
||||
widget.NewCheckWithData("舰长", binding.BindBool(&d.PrivilegePermission)),
|
||||
widget.NewCheckWithData("管理员", binding.BindBool(&d.AdminPermission)),
|
||||
widget.NewLabel(i18n.T("plugin.qiege.permission")),
|
||||
widget.NewCheckWithData(i18n.T("plugin.qiege.user"), binding.BindBool(&d.UserPermission)),
|
||||
widget.NewCheckWithData(i18n.T("plugin.qiege.privilege"), binding.BindBool(&d.PrivilegePermission)),
|
||||
widget.NewCheckWithData(i18n.T("plugin.qiege.admin"), binding.BindBool(&d.AdminPermission)),
|
||||
)
|
||||
qgShortCut := container.NewBorder(nil, nil,
|
||||
widget.NewLabel("自定义命令 (默认的依然可用)"), nil,
|
||||
widget.NewLabel(i18n.T("plugin.qiege.custom_cmd")), nil,
|
||||
widget.NewEntryWithData(binding.BindString(&d.CustomCMD)),
|
||||
)
|
||||
d.panel = container.NewVBox(dgPerm, qgShortCut)
|
||||
|
||||
33
util/json.go
Normal file
33
util/json.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
func MarshalUnescape(v interface{}) (string, error) {
|
||||
bf := bytes.NewBuffer([]byte{})
|
||||
jsonEncoder := json.NewEncoder(bf)
|
||||
jsonEncoder.SetEscapeHTML(false)
|
||||
err := jsonEncoder.Encode(v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return bf.String(), nil
|
||||
}
|
||||
|
||||
func MarshalIndentUnescape(v interface{}, prefix, indent string) (string, error) {
|
||||
bf := bytes.NewBuffer([]byte{})
|
||||
jsonEncoder := json.NewEncoder(bf)
|
||||
jsonEncoder.SetEscapeHTML(false)
|
||||
err := jsonEncoder.Encode(v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
err = json.Indent(&buf, bf.Bytes(), prefix, indent)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
Reference in New Issue
Block a user