The interface is fully Russified
This commit is contained in:
@@ -196,7 +196,7 @@ func (u *ui) handleClicks(gtx layout.Context) {
|
||||
u.refresh()
|
||||
}
|
||||
for u.disconnectBtn.Clicked(gtx) {
|
||||
u.runAction("Disconnecting...", func() error {
|
||||
u.runAction("Отключение...", func() error {
|
||||
return vpn.Disconnect(config.LogsDir)
|
||||
})
|
||||
}
|
||||
@@ -223,7 +223,7 @@ func (u *ui) handleClicks(gtx layout.Context) {
|
||||
for u.vlessConnectBtns[i].Clicked(gtx) {
|
||||
if i < len(u.configs.VLESS) {
|
||||
name := u.configs.VLESS[i].Name
|
||||
u.runAction("Connecting to "+name+"...", func() error {
|
||||
u.runAction("Подключение к "+name+"...", func() error {
|
||||
return vless.Connect(name, config.LogsDir, config.XrayDir)
|
||||
})
|
||||
}
|
||||
@@ -237,15 +237,15 @@ func (u *ui) handleClicks(gtx layout.Context) {
|
||||
for u.vlessPingBtns[i].Clicked(gtx) {
|
||||
if i < len(u.configs.VLESS) {
|
||||
cfg := u.configs.VLESS[i]
|
||||
u.runAction("Testing "+cfg.Name+"...", func() error {
|
||||
u.runAction("Тестирование "+cfg.Name+"...", func() error {
|
||||
ok, latency, err := vless.PingServer(cfg.URL, 4*time.Second)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf("server is unreachable")
|
||||
return fmt.Errorf("сервер не найден")
|
||||
}
|
||||
return fmt.Errorf("latency %.0f ms", latency)
|
||||
return fmt.Errorf("пинг %.0f мс", latency)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -255,7 +255,7 @@ func (u *ui) handleClicks(gtx layout.Context) {
|
||||
for u.wgConnectBtns[i].Clicked(gtx) {
|
||||
if i < len(u.configs.WireGuard) {
|
||||
name := u.configs.WireGuard[i].Name
|
||||
u.runAction("Connecting WireGuard "+name+"...", func() error {
|
||||
u.runAction("Подключение WireGuard "+name+"...", func() error {
|
||||
return wireguard.Connect(name, config.LogsDir)
|
||||
})
|
||||
}
|
||||
@@ -272,7 +272,7 @@ func (u *ui) handleClicks(gtx layout.Context) {
|
||||
for u.subUpdateBtns[i].Clicked(gtx) {
|
||||
if i < len(u.subs.Subscriptions) {
|
||||
name := u.subs.Subscriptions[i].Name
|
||||
u.runAction("Updating "+name+"...", func() error {
|
||||
u.runAction("Обновление "+name+"...", func() error {
|
||||
return subscription.UpdateSubscription(name, config.LogsDir)
|
||||
})
|
||||
}
|
||||
@@ -286,7 +286,7 @@ func (u *ui) handleClicks(gtx layout.Context) {
|
||||
for u.subTestBtns[i].Clicked(gtx) {
|
||||
if i < len(u.subs.Subscriptions) {
|
||||
name := u.subs.Subscriptions[i].Name
|
||||
u.runAction("Testing configs from "+name+"...", func() error {
|
||||
u.runAction("Тестирование конфигов из "+name+"...", func() error {
|
||||
return u.testSubscriptionConfigs(name)
|
||||
})
|
||||
}
|
||||
@@ -309,7 +309,7 @@ func (u *ui) runAction(progress string, fn func() error) {
|
||||
u.async <- func() {
|
||||
u.busy = false
|
||||
if err != nil {
|
||||
if strings.HasPrefix(err.Error(), "latency ") {
|
||||
if strings.HasPrefix(err.Error(), "задержка ") {
|
||||
u.message = err.Error()
|
||||
u.messageColor = successColor
|
||||
} else {
|
||||
@@ -317,7 +317,7 @@ func (u *ui) runAction(progress string, fn func() error) {
|
||||
u.messageColor = dangerColor
|
||||
}
|
||||
} else {
|
||||
u.message = "Action completed."
|
||||
u.message = "Действие выполнено."
|
||||
u.messageColor = successColor
|
||||
}
|
||||
u.refresh()
|
||||
@@ -365,12 +365,12 @@ func (u *ui) addVLESSConfig() {
|
||||
name := strings.TrimSpace(u.configNameEditor.Text())
|
||||
rawURL := strings.TrimSpace(u.configURLEditor.Text())
|
||||
if name == "" || rawURL == "" {
|
||||
u.message = "Name and VLESS URL are required."
|
||||
u.message = "Имя и URL VLESS не заполнены."
|
||||
u.messageColor = dangerColor
|
||||
return
|
||||
}
|
||||
if _, err := url.Parse(rawURL); err != nil {
|
||||
u.message = "The VLESS URL is not valid."
|
||||
u.message = "VLESS URL не действителен."
|
||||
u.messageColor = dangerColor
|
||||
return
|
||||
}
|
||||
@@ -384,7 +384,7 @@ func (u *ui) addVLESSConfig() {
|
||||
|
||||
for _, item := range cfgs.VLESS {
|
||||
if item.Name == name {
|
||||
u.message = "A config with this name already exists."
|
||||
u.message = "Конфиг с таким именем уже существует"
|
||||
u.messageColor = dangerColor
|
||||
return
|
||||
}
|
||||
@@ -403,7 +403,7 @@ func (u *ui) addVLESSConfig() {
|
||||
|
||||
u.configNameEditor.SetText("")
|
||||
u.configURLEditor.SetText("vless://")
|
||||
u.message = "VLESS config added."
|
||||
u.message = "VLESS конфиг добавлен."
|
||||
u.messageColor = successColor
|
||||
u.refresh()
|
||||
}
|
||||
@@ -427,7 +427,7 @@ func (u *ui) deleteVLESSConfig(name string) {
|
||||
}
|
||||
cfgs.VLESS = filtered
|
||||
if !found {
|
||||
u.message = "Config was already removed."
|
||||
u.message = "Конфиг уже удалён."
|
||||
u.messageColor = warningColor
|
||||
return
|
||||
}
|
||||
@@ -437,7 +437,7 @@ func (u *ui) deleteVLESSConfig(name string) {
|
||||
return
|
||||
}
|
||||
|
||||
u.message = "Config removed."
|
||||
u.message = "Конфиг удалён."
|
||||
u.messageColor = successColor
|
||||
u.refresh()
|
||||
}
|
||||
@@ -446,12 +446,12 @@ func (u *ui) addSubscription() {
|
||||
name := strings.TrimSpace(u.subNameEditor.Text())
|
||||
rawURL := strings.TrimSpace(u.subURLEditor.Text())
|
||||
if name == "" || rawURL == "" {
|
||||
u.message = "Subscription name and URL are required."
|
||||
u.message = "Имя и URL подписки не заполнены."
|
||||
u.messageColor = dangerColor
|
||||
return
|
||||
}
|
||||
if _, err := url.Parse(rawURL); err != nil {
|
||||
u.message = "The subscription URL is not valid."
|
||||
u.message = "URL подписки не действителен."
|
||||
u.messageColor = dangerColor
|
||||
return
|
||||
}
|
||||
@@ -465,7 +465,7 @@ func (u *ui) addSubscription() {
|
||||
|
||||
for _, item := range subs.Subscriptions {
|
||||
if item.Name == name {
|
||||
u.message = "A subscription with this name already exists."
|
||||
u.message = "Подписка с таким именем уже существует."
|
||||
u.messageColor = dangerColor
|
||||
return
|
||||
}
|
||||
@@ -483,7 +483,7 @@ func (u *ui) addSubscription() {
|
||||
|
||||
u.subNameEditor.SetText("")
|
||||
u.subURLEditor.SetText("")
|
||||
u.message = "Subscription added."
|
||||
u.message = "Подписка добавлена."
|
||||
u.messageColor = successColor
|
||||
u.refresh()
|
||||
}
|
||||
@@ -507,7 +507,7 @@ func (u *ui) deleteSubscription(name string) {
|
||||
}
|
||||
subs.Subscriptions = filtered
|
||||
if !found {
|
||||
u.message = "Subscription was already removed."
|
||||
u.message = "Подписка уже удалена."
|
||||
u.messageColor = warningColor
|
||||
return
|
||||
}
|
||||
@@ -517,7 +517,7 @@ func (u *ui) deleteSubscription(name string) {
|
||||
return
|
||||
}
|
||||
|
||||
u.message = "Subscription removed."
|
||||
u.message = "Подписка удалена."
|
||||
u.messageColor = successColor
|
||||
u.refresh()
|
||||
}
|
||||
@@ -525,20 +525,20 @@ func (u *ui) deleteSubscription(name string) {
|
||||
func (u *ui) testURL() {
|
||||
rawURL := strings.TrimSpace(u.testURLEditor.Text())
|
||||
if rawURL == "" {
|
||||
u.message = "Paste a VLESS URL to test."
|
||||
u.message = "Вставьте VLESS ссылку для проверки."
|
||||
u.messageColor = dangerColor
|
||||
return
|
||||
}
|
||||
|
||||
u.runAction("Testing custom URL...", func() error {
|
||||
u.runAction("Пингуем кастомный URL...", func() error {
|
||||
ok, latency, err := vless.PingServer(rawURL, 4*time.Second)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf("server is unreachable")
|
||||
return fmt.Errorf("сервер не найден")
|
||||
}
|
||||
return fmt.Errorf("latency %.0f ms", latency)
|
||||
return fmt.Errorf("пинг %.0f мс", latency)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -588,7 +588,7 @@ func (u *ui) layoutHeader(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(
|
||||
gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(15), "GIO DESKTOP")
|
||||
lbl := material.Label(u.theme, unit.Sp(15), "POWERED BY NEVETIME")
|
||||
lbl.Color = accentColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
@@ -598,7 +598,7 @@ func (u *ui) layoutHeader(gtx layout.Context) layout.Dimensions {
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Body1(u.theme, "A modern control surface for VLESS, subscriptions, and live connection state.")
|
||||
lbl := material.Body1(u.theme, "Современный клиент на Go для особой производительности и удобства")
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
@@ -608,11 +608,11 @@ func (u *ui) layoutHeader(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{Alignment: layout.Middle}.Layout(
|
||||
gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return u.layoutButton(gtx, &u.refreshBtn, "Refresh", accentSoftColor)
|
||||
return u.layoutButton(gtx, &u.refreshBtn, "Обновить", accentSoftColor)
|
||||
}),
|
||||
layout.Rigid(spacerW(10)),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return u.layoutButton(gtx, &u.openLogsBtn, "Logs", panelAltColor)
|
||||
return u.layoutButton(gtx, &u.openLogsBtn, "Логи", panelAltColor)
|
||||
}),
|
||||
)
|
||||
}),
|
||||
@@ -624,12 +624,12 @@ func (u *ui) layoutStatusBanner(gtx layout.Context) layout.Dimensions {
|
||||
inset := layout.UniformInset(unit.Dp(18))
|
||||
return inset.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
connected := u.statusState != nil && u.statusState.Connected
|
||||
statusText := "Offline"
|
||||
statusText := "Оффлайн"
|
||||
statusColor := warningColor
|
||||
details := "No active tunnel. Open the VLESS or WireGuard tab and press Connect on a saved config."
|
||||
details := "Нет активных туннелей. Откройте VLESS или WireGuard и подключитесь к одному из сохранённых конфигов."
|
||||
|
||||
if connected {
|
||||
statusText = "Connected"
|
||||
statusText = "Подключен"
|
||||
statusColor = successColor
|
||||
details = fmt.Sprintf("%s via %s", u.statusState.ConfigName, strings.ToUpper(u.statusState.ConfigType))
|
||||
}
|
||||
@@ -657,7 +657,7 @@ func (u *ui) layoutStatusBanner(gtx layout.Context) layout.Dimensions {
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
msg := u.message
|
||||
if msg == "" {
|
||||
msg = "Ready."
|
||||
msg = "Готов."
|
||||
}
|
||||
lbl := material.Body2(u.theme, msg)
|
||||
lbl.Color = u.messageColor
|
||||
@@ -669,7 +669,7 @@ func (u *ui) layoutStatusBanner(gtx layout.Context) layout.Dimensions {
|
||||
)
|
||||
}),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return u.layoutButton(gtx, &u.disconnectBtn, "Disconnect", dangerColor)
|
||||
return u.layoutButton(gtx, &u.disconnectBtn, "Отключиться", dangerColor)
|
||||
}),
|
||||
)
|
||||
})
|
||||
@@ -700,7 +700,7 @@ func (u *ui) layoutTabs(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{}.Layout(
|
||||
gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return u.layoutTab(gtx, tabDashboard, "Overview")
|
||||
return u.layoutTab(gtx, tabDashboard, "Главная")
|
||||
}),
|
||||
layout.Rigid(spacerW(10)),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
@@ -712,7 +712,7 @@ func (u *ui) layoutTabs(gtx layout.Context) layout.Dimensions {
|
||||
}),
|
||||
layout.Rigid(spacerW(10)),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return u.layoutTab(gtx, tabSubscriptions, "Subscriptions")
|
||||
return u.layoutTab(gtx, tabSubscriptions, "Подписки")
|
||||
}),
|
||||
)
|
||||
}
|
||||
@@ -734,15 +734,15 @@ func (u *ui) layoutDashboard(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{Spacing: layout.SpaceBetween}.Layout(
|
||||
gtx,
|
||||
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
|
||||
return u.metricCard(gtx, "VLESS configs", fmt.Sprintf("%d", len(u.configs.VLESS)), accentColor)
|
||||
return u.metricCard(gtx, "VLESS конфиги", fmt.Sprintf("%d", len(u.configs.VLESS)), accentColor)
|
||||
}),
|
||||
layout.Rigid(spacerW(12)),
|
||||
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
|
||||
return u.metricCard(gtx, "WireGuard configs", fmt.Sprintf("%d", len(u.configs.WireGuard)), accentSoftColor)
|
||||
return u.metricCard(gtx, "WireGuard конфиги", fmt.Sprintf("%d", len(u.configs.WireGuard)), accentSoftColor)
|
||||
}),
|
||||
layout.Rigid(spacerW(12)),
|
||||
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
|
||||
return u.metricCard(gtx, "Subscriptions", fmt.Sprintf("%d", len(u.subs.Subscriptions)), successColor)
|
||||
return u.metricCard(gtx, "Подписки", fmt.Sprintf("%d", len(u.subs.Subscriptions)), successColor)
|
||||
}),
|
||||
)
|
||||
}),
|
||||
@@ -753,17 +753,17 @@ func (u *ui) layoutDashboard(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(
|
||||
gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.H5(u.theme, "Quick latency probe")
|
||||
lbl := material.H5(u.theme, "Быстрый пинг")
|
||||
lbl.Color = textColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(spacerH(10)),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return u.layoutEditor(gtx, &u.testURLEditor, "Paste a VLESS URL")
|
||||
return u.layoutEditor(gtx, &u.testURLEditor, "Вставьте VLESS ссылку")
|
||||
}),
|
||||
layout.Rigid(spacerH(12)),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return u.layoutButton(gtx, &u.testURLBtn, "Test URL", accentColor)
|
||||
return u.layoutButton(gtx, &u.testURLBtn, "Протестировать подключение", accentColor)
|
||||
}),
|
||||
)
|
||||
})
|
||||
@@ -833,15 +833,15 @@ func (u *ui) layoutVLESS(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{}.Layout(
|
||||
gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return u.layoutButton(gtx, &u.vlessConnectBtns[i], "Connect", accentColor)
|
||||
return u.layoutButton(gtx, &u.vlessConnectBtns[i], "Подключение", accentColor)
|
||||
}),
|
||||
layout.Rigid(spacerW(8)),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return u.layoutButton(gtx, &u.vlessPingBtns[i], "Ping", accentSoftColor)
|
||||
return u.layoutButton(gtx, &u.vlessPingBtns[i], "Пинг", accentSoftColor)
|
||||
}),
|
||||
layout.Rigid(spacerW(8)),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return u.layoutButton(gtx, &u.vlessDeleteBtns[i], "Delete", dangerColor)
|
||||
return u.layoutButton(gtx, &u.vlessDeleteBtns[i], "Удалить", dangerColor)
|
||||
}),
|
||||
)
|
||||
}),
|
||||
@@ -911,11 +911,11 @@ func (u *ui) layoutSubscriptions(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{}.Layout(
|
||||
gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return u.layoutButton(gtx, &u.subUpdateBtns[i], "Update configs", accentColor)
|
||||
return u.layoutButton(gtx, &u.subUpdateBtns[i], "Обновить конфиги", accentColor)
|
||||
}),
|
||||
layout.Rigid(spacerW(8)),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return u.layoutButton(gtx, &u.subDeleteBtns[i], "Delete", dangerColor)
|
||||
return u.layoutButton(gtx, &u.subDeleteBtns[i], "Удалить", dangerColor)
|
||||
}),
|
||||
)
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user