feat: add proxy targets support in site and stream #904

This commit is contained in:
Jacky
2025-05-26 02:59:44 +00:00
parent beccf9db85
commit 7580fa4572
43 changed files with 2492 additions and 671 deletions
+23 -24
View File
@@ -35,7 +35,7 @@ func GetAutoBackupList(c *gin.Context) {
// Request Body: AutoBackup model with required fields
// Response: Created auto backup configuration
func CreateAutoBackup(c *gin.Context) {
ctx := cosy.Core[model.AutoBackup](c).SetValidRules(gin.H{
cosy.Core[model.AutoBackup](c).SetValidRules(gin.H{
"name": "required",
"backup_type": "required",
"storage_type": "required",
@@ -54,16 +54,15 @@ func CreateAutoBackup(c *gin.Context) {
ctx.AbortWithError(err)
return
}
})
ctx.Create()
// Register cron job only if the backup is enabled
if ctx.Model.Enabled {
if err := cron.AddAutoBackupJob(ctx.Model.ID, ctx.Model.CronExpression); err != nil {
logger.Errorf("Failed to add auto backup job %d: %v", ctx.Model.ID, err)
}).ExecutedHook(func(ctx *cosy.Ctx[model.AutoBackup]) {
// Register cron job only if the backup is enabled
if ctx.Model.Enabled {
if err := cron.AddAutoBackupJob(ctx.Model.ID, ctx.Model.CronExpression); err != nil {
ctx.AbortWithError(err)
return
}
}
}
}).Create()
}
// GetAutoBackup retrieves a single auto backup configuration by ID.
@@ -85,7 +84,7 @@ func GetAutoBackup(c *gin.Context) {
// Request Body: Partial AutoBackup model with fields to update
// Response: Updated auto backup configuration
func ModifyAutoBackup(c *gin.Context) {
ctx := cosy.Core[model.AutoBackup](c).SetValidRules(gin.H{
cosy.Core[model.AutoBackup](c).SetValidRules(gin.H{
"name": "omitempty",
"backup_type": "omitempty",
"storage_type": "omitempty",
@@ -104,20 +103,20 @@ func ModifyAutoBackup(c *gin.Context) {
ctx.AbortWithError(err)
return
}
})
ctx.Modify()
// Update cron job based on enabled status
if ctx.Model.Enabled {
if err := cron.UpdateAutoBackupJob(ctx.Model.ID, ctx.Model.CronExpression); err != nil {
logger.Errorf("Failed to update auto backup job %d: %v", ctx.Model.ID, err)
}).ExecutedHook(func(ctx *cosy.Ctx[model.AutoBackup]) {
// Update cron job based on enabled status
if ctx.Model.Enabled {
if err := cron.UpdateAutoBackupJob(ctx.Model.ID, ctx.Model.CronExpression); err != nil {
ctx.AbortWithError(err)
return
}
} else {
if err := cron.RemoveAutoBackupJob(ctx.Model.ID); err != nil {
ctx.AbortWithError(err)
return
}
}
} else {
if err := cron.RemoveAutoBackupJob(ctx.Model.ID); err != nil {
logger.Errorf("Failed to remove auto backup job %d: %v", ctx.Model.ID, err)
}
}
}).Modify()
}
// DestroyAutoBackup deletes an auto backup configuration and removes its cron job.
+19 -8
View File
@@ -103,15 +103,26 @@ func GetSiteList(c *gin.Context) {
indexedSite := site.GetIndexedSite(file.Name())
// Convert site.ProxyTarget to config.ProxyTarget
var proxyTargets []config.ProxyTarget
for _, target := range indexedSite.ProxyTargets {
proxyTargets = append(proxyTargets, config.ProxyTarget{
Host: target.Host,
Port: target.Port,
Type: target.Type,
})
}
configs = append(configs, config.Config{
Name: file.Name(),
ModifiedAt: fileInfo.ModTime(),
Size: fileInfo.Size(),
IsDir: fileInfo.IsDir(),
Status: configStatusMap[file.Name()],
EnvGroupID: envGroupId,
EnvGroup: envGroup,
Urls: indexedSite.Urls,
Name: file.Name(),
ModifiedAt: fileInfo.ModTime(),
Size: fileInfo.Size(),
IsDir: fileInfo.IsDir(),
Status: configStatusMap[file.Name()],
EnvGroupID: envGroupId,
EnvGroup: envGroup,
Urls: indexedSite.Urls,
ProxyTargets: proxyTargets,
})
}
+27 -12
View File
@@ -23,7 +23,7 @@ import (
type Stream struct {
ModifiedAt time.Time `json:"modified_at"`
Advanced bool `json:"advanced"`
Enabled bool `json:"enabled"`
Status config.ConfigStatus `json:"status"`
Name string `json:"name"`
Config string `json:"config"`
ChatGPTMessages []openai.ChatCompletionMessage `json:"chatgpt_messages,omitempty"`
@@ -32,6 +32,7 @@ type Stream struct {
EnvGroupID uint64 `json:"env_group_id"`
EnvGroup *model.EnvGroup `json:"env_group,omitempty"`
SyncNodeIDs []uint64 `json:"sync_node_ids" gorm:"serializer:json"`
ProxyTargets []config.ProxyTarget `json:"proxy_targets,omitempty"`
}
func GetStreams(c *gin.Context) {
@@ -130,15 +131,29 @@ func GetStreams(c *gin.Context) {
continue
}
// Get indexed stream for proxy targets
indexedStream := stream.GetIndexedStream(file.Name())
// Convert stream.ProxyTarget to config.ProxyTarget
var proxyTargets []config.ProxyTarget
for _, target := range indexedStream.ProxyTargets {
proxyTargets = append(proxyTargets, config.ProxyTarget{
Host: target.Host,
Port: target.Port,
Type: target.Type,
})
}
// Add the config to the result list after passing all filters
configs = append(configs, config.Config{
Name: file.Name(),
ModifiedAt: fileInfo.ModTime(),
Size: fileInfo.Size(),
IsDir: fileInfo.IsDir(),
Status: enabledConfigMap[file.Name()],
EnvGroupID: envGroupId,
EnvGroup: envGroup,
Name: file.Name(),
ModifiedAt: fileInfo.ModTime(),
Size: fileInfo.Size(),
IsDir: fileInfo.IsDir(),
Status: enabledConfigMap[file.Name()],
EnvGroupID: envGroupId,
EnvGroup: envGroup,
ProxyTargets: proxyTargets,
})
}
@@ -164,9 +179,9 @@ func GetStream(c *gin.Context) {
}
// Check if the stream is enabled
enabled := true
status := config.StatusEnabled
if _, err := os.Stat(nginx.GetConfPath("streams-enabled", name)); os.IsNotExist(err) {
enabled = false
status = config.StatusDisabled
}
// Retrieve or create ChatGPT log for this stream
@@ -201,7 +216,7 @@ func GetStream(c *gin.Context) {
c.JSON(http.StatusOK, Stream{
ModifiedAt: file.ModTime(),
Advanced: streamModel.Advanced,
Enabled: enabled,
Status: status,
Name: name,
Config: string(origContent),
ChatGPTMessages: chatgpt.Content,
@@ -223,7 +238,7 @@ func GetStream(c *gin.Context) {
c.JSON(http.StatusOK, Stream{
ModifiedAt: file.ModTime(),
Advanced: streamModel.Advanced,
Enabled: enabled,
Status: status,
Name: name,
Config: nginxConfig.FmtCode(),
Tokenized: nginxConfig,
+150 -15
View File
@@ -1,15 +1,23 @@
package upstream
import (
"context"
"net/http"
"sync"
"time"
"github.com/0xJacky/Nginx-UI/internal/helper"
"github.com/0xJacky/Nginx-UI/internal/upstream"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"github.com/uozi-tech/cosy/logger"
"net/http"
"time"
)
type wsMessage struct {
data interface{}
done chan error
}
func AvailabilityTest(c *gin.Context) {
var upGrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
@@ -25,24 +33,151 @@ func AvailabilityTest(c *gin.Context) {
defer ws.Close()
var body []string
var currentTargets []string
var targetsMutex sync.RWMutex
err = ws.ReadJSON(&body)
// Use context to manage goroutine lifecycle
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
if err != nil {
logger.Error(err)
return
// Use channel to serialize WebSocket write operations, avoiding concurrent conflicts
writeChan := make(chan wsMessage, 10)
testChan := make(chan bool, 1) // Immediate test signal
// Create debouncer for test execution
testDebouncer := helper.NewDebouncer(300 * time.Millisecond)
// WebSocket writer goroutine - serialize all write operations
go func() {
defer logger.Debug("WebSocket writer goroutine stopped")
for {
select {
case <-ctx.Done():
return
case msg := <-writeChan:
err := ws.WriteJSON(msg.data)
if msg.done != nil {
msg.done <- err
close(msg.done)
}
if err != nil {
logger.Error("Failed to send WebSocket message:", err)
if helper.IsUnexpectedWebsocketError(err) {
cancel() // Cancel all goroutines
}
}
}
}
}()
// Safe WebSocket write function
writeJSON := func(data interface{}) error {
done := make(chan error, 1)
msg := wsMessage{data: data, done: done}
select {
case writeChan <- msg:
return <-done
case <-ctx.Done():
return ctx.Err()
case <-time.After(5 * time.Second): // Prevent write blocking
return context.DeadlineExceeded
}
}
// Function to perform availability test
performTest := func() {
targetsMutex.RLock()
targets := make([]string, len(currentTargets))
copy(targets, currentTargets)
targetsMutex.RUnlock()
logger.Debug("Performing availability test for targets:", targets)
if len(targets) > 0 {
logger.Debug("Starting upstream.AvailabilityTest...")
result := upstream.AvailabilityTest(targets)
logger.Debug("Test completed, results:", result)
logger.Debug("Sending results via WebSocket...")
if err := writeJSON(result); err != nil {
logger.Error("Failed to send WebSocket message:", err)
if helper.IsUnexpectedWebsocketError(err) {
cancel() // Cancel all goroutines
}
} else {
logger.Debug("Results sent successfully")
}
} else {
logger.Debug("No targets to test")
// Send empty result even if no targets
emptyResult := make(map[string]interface{})
if err := writeJSON(emptyResult); err != nil {
logger.Error("Failed to send empty result:", err)
} else {
logger.Debug("Empty result sent successfully")
}
}
}
// Goroutine to handle incoming messages (target updates)
go func() {
defer logger.Debug("WebSocket reader goroutine stopped")
for {
select {
case <-ctx.Done():
return
default:
}
var newTargets []string
// Set read timeout to avoid blocking
ws.SetReadDeadline(time.Now().Add(30 * time.Second))
err := ws.ReadJSON(&newTargets)
ws.SetReadDeadline(time.Time{}) // Clear deadline
if err != nil {
if helper.IsUnexpectedWebsocketError(err) {
logger.Error(err)
}
cancel() // Cancel all goroutines
return
}
logger.Debug("Received targets from frontend:", newTargets)
targetsMutex.Lock()
currentTargets = newTargets
targetsMutex.Unlock()
// Use debouncer to trigger test execution
testDebouncer.Trigger(func() {
select {
case testChan <- true:
default:
}
})
}
}()
// Main testing loop
ticker := time.NewTicker(10 * time.Second)
defer ticker.Stop()
logger.Debug("WebSocket connection established, waiting for messages...")
for {
err = ws.WriteJSON(upstream.AvailabilityTest(body))
if err != nil {
if helper.IsUnexpectedWebsocketError(err) {
logger.Error(err)
}
break
select {
case <-ctx.Done():
testDebouncer.Stop()
logger.Debug("WebSocket connection closed")
return
case <-testChan:
// Debounce triggered test or first test
go performTest() // Execute asynchronously to avoid blocking main loop
case <-ticker.C:
// Periodic test execution
go performTest() // Execute asynchronously to avoid blocking main loop
}
time.Sleep(10 * time.Second)
}
}
+2
View File
@@ -100,6 +100,8 @@ declare module 'vue' {
PortScannerPortScanner: typeof import('./src/components/PortScanner/PortScanner.vue')['default']
PortScannerPortScannerCompact: typeof import('./src/components/PortScanner/PortScannerCompact.vue')['default']
ProcessingStatusProcessingStatus: typeof import('./src/components/ProcessingStatus/ProcessingStatus.vue')['default']
ProxyTargets: typeof import('./src/components/ProxyTargets.vue')['default']
ProxyTargetsProxyTargets: typeof import('./src/components/ProxyTargets/ProxyTargets.vue')['default']
ReactiveFromNowReactiveFromNow: typeof import('./src/components/ReactiveFromNow/ReactiveFromNow.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
+7
View File
@@ -8,6 +8,12 @@ import { extendCurdApi, http, useCurdApi } from '@uozi-admin/request'
export type SiteStatus = ConfigStatus.Enabled | ConfigStatus.Disabled | ConfigStatus.Maintenance
export interface ProxyTarget {
host: string
port: string
type: string // "proxy_pass" or "upstream"
}
export interface Site extends ModelBase {
modified_at: string
path: string
@@ -23,6 +29,7 @@ export interface Site extends ModelBase {
env_group?: EnvGroup
sync_node_ids: number[]
urls?: string[]
proxy_targets?: ProxyTarget[]
status: SiteStatus
}
+3 -1
View File
@@ -1,12 +1,13 @@
import type { EnvGroup } from './env_group'
import type { NgxConfig } from '@/api/ngx'
import type { ChatComplicationMessage } from '@/api/openai'
import type { ProxyTarget, SiteStatus } from '@/api/site'
import { extendCurdApi, http, useCurdApi } from '@uozi-admin/request'
export interface Stream {
modified_at: string
advanced: boolean
enabled: boolean
status: SiteStatus
name: string
filepath: string
config: string
@@ -15,6 +16,7 @@ export interface Stream {
env_group_id: number
env_group?: EnvGroup
sync_node_ids: number[]
proxy_targets?: ProxyTarget[]
}
const baseUrl = '/streams'
@@ -0,0 +1,109 @@
<script setup lang="ts">
import type { ProxyTarget } from '@/api/site'
import { useProxyAvailabilityStore } from '@/pinia/moudule/proxyAvailability'
interface Props {
targets: ProxyTarget[]
}
const props = defineProps<Props>()
const proxyStore = useProxyAvailabilityStore()
let componentId = ''
// Register component and watch for target changes
watch(() => props.targets, newTargets => {
componentId = proxyStore.registerComponent(newTargets)
}, {
immediate: true,
deep: true,
})
// Cleanup when component unmounts
onBeforeUnmount(() => {
proxyStore.unregisterComponent(componentId)
})
function getTargetColor(target: ProxyTarget): string {
const result = proxyStore.getAvailabilityResult(target)
if (!result)
return 'default'
return result.online ? 'green' : 'red'
}
function getTargetText(target: ProxyTarget): string {
const result = proxyStore.getAvailabilityResult(target)
if (!result)
return `${target.host}:${target.port}`
if (result.online) {
return `${target.host}:${target.port} (${result.latency.toFixed(2)}ms)`
}
else {
return `${target.host}:${target.port} (${$gettext('Offline')})`
}
}
function getTargetTitle(target: ProxyTarget): string {
return `${$gettext('Type')}: ${target.type === 'upstream' ? $gettext('Upstream') : $gettext('Proxy Pass')}`
}
</script>
<template>
<div v-if="targets.length > 0" class="proxy-targets">
<ATag
v-for="target in targets"
:key="proxyStore.getTargetKey(target)"
:color="getTargetColor(target)"
class="proxy-target-tag"
:bordered="false"
>
<template #icon>
<ATooltip
:title="getTargetTitle(target)"
placement="bottom"
class="cursor-pointer"
>
<span v-if="target.type === 'upstream'" class="target-type-icon">U</span>
<span v-else class="target-type-icon">P</span>
</ATooltip>
</template>
{{ getTargetText(target) }}
</ATag>
</div>
</template>
<style scoped lang="less">
.proxy-targets {
display: flex;
flex-wrap: wrap;
gap: 4px;
max-width: 100%;
overflow: hidden;
}
.proxy-target-tag {
margin-right: 4px;
margin-bottom: 4px;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 12px;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.target-type-icon {
display: inline-block;
width: 12px;
height: 12px;
line-height: 12px;
text-align: center;
background: rgba(255, 255, 255, 0.2);
border-radius: 2px;
margin-right: 4px;
font-weight: bold;
font-size: 10px;
flex-shrink: 0;
}
}
</style>
+3
View File
@@ -0,0 +1,3 @@
import ProxyTargets from './ProxyTargets.vue'
export default ProxyTargets
+55 -35
View File
@@ -143,7 +143,7 @@ msgstr "إجراء"
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129 src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142 src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr "الإجراءات"
@@ -161,7 +161,7 @@ msgstr "النسبة الفعلية للعامل إلى المُهيأ"
#: src/components/NgxConfigEditor/NgxUpstream.vue:159 src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr "إضافة"
@@ -188,11 +188,11 @@ msgstr "أضف مكان"
msgid "Add Site"
msgstr "أضف موقع"
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr "أضف Stream"
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr "تمت الإضافة بنجاح"
@@ -276,7 +276,7 @@ msgid "Are you sure you want to delete permanently?"
msgstr "هل أنت متأكد أنك تريد الحذف نهائيًا؟"
#: src/language/curd.ts:25 src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr "هل أنت متأكد أنك تريد الحذف؟"
@@ -567,6 +567,7 @@ msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr "إلغاء"
@@ -1203,7 +1204,7 @@ msgstr "حدد اسم منطقة الذاكرة المشتركة والحجم،
#: src/components/NgxConfigEditor/NgxUpstream.vue:129 src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr "حذف"
@@ -1251,7 +1252,7 @@ msgstr "فشل حذف الدفق %{name} من %{node}"
msgid "Delete stream %{name} from %{node} successfully"
msgstr "تم حذف الدفق %{name} من %{node} بنجاح"
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr "حذف البث: %{stream_name}"
@@ -1325,13 +1326,10 @@ msgid "Directory path to store cache files"
msgstr "مسار الدليل لتخزين ملفات الذاكرة المؤقتة"
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr "تعطيل"
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr "تعطيل"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr "فشل تعطيل التجديد التلقائي لـ %{name}"
@@ -1392,15 +1390,16 @@ msgstr "تم تعطيل الدفق %{name} من %{node} بنجاح"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114 src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127 src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr "معطل"
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr "تم التعطيل بنجاح"
@@ -1430,6 +1429,10 @@ msgstr "لا تقم بتمكين هذا الخيار إلا إذا كنت متأ
msgid "Do you want to %{action} this site?"
msgstr "هل تريد %{action} هذا الموقع؟"
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr "هل تريد %{action} هذا البث؟"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr "هل تريد تعطيل التجديد التلقائي للشهادة؟"
@@ -1505,7 +1508,7 @@ msgstr ""
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr "مكرر"
@@ -1554,13 +1557,10 @@ msgid "Email (*)"
msgstr "البريد الإلكتروني (*)"
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr "تمكين"
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr "تفعيل"
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr "تم تفعيل المصادقة الثنائية بنجاح"
@@ -1659,9 +1659,10 @@ msgstr "تفعيل TOTP"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110 src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123 src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr "مفعل"
@@ -1669,7 +1670,7 @@ msgstr "مفعل"
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr "تم التفعيل بنجاح"
@@ -1906,7 +1907,7 @@ msgstr "فشل حذف الشهادة من قاعدة البيانات: %{error}"
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr "فشل في تعطيل %{msg}"
@@ -1916,7 +1917,7 @@ msgstr "فشل تعطيل وضع الصيانة %{msg}"
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr "فشل في التفعيل %{msg}"
@@ -2655,7 +2656,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr "صيانة"
@@ -2684,7 +2685,7 @@ msgstr "إدارة التكوينات"
msgid "Manage Sites"
msgstr "إدارة المواقع"
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:101
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr "إدارة التدفقات"
@@ -2858,12 +2859,12 @@ msgstr "توجيه متعدد الأسطر"
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr "اسم"
@@ -3124,7 +3125,7 @@ msgstr "يتضمن Nginx.conf دليل streams-enabled"
#: src/views/notification/Notification.vue:38
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:155
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:119
msgid "No"
msgstr "لا"
@@ -3146,7 +3147,7 @@ msgid "Node"
msgstr "العقدة"
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63 src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76 src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr "مجموعة العقد"
@@ -3259,6 +3260,7 @@ msgstr "إيقاف"
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3276,7 +3278,8 @@ msgstr "غير متصل"
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr "حسنًا"
@@ -3667,6 +3670,15 @@ msgstr "مزود"
msgid "Proxy"
msgstr "وكيل"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr "تمرير الوكيل"
#: src/views/site/site_list/columns.tsx:64
#: src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr "أهداف الوكيل"
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr "رقم الأمن العام"
@@ -4527,7 +4539,7 @@ msgstr "ثابت"
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88 src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101 src/views/stream/columns.tsx:69
msgid "Status"
msgstr "الحالة"
@@ -5099,6 +5111,7 @@ msgstr "الثلاثاء"
msgid "Two-factor authentication required"
msgstr "يتطلب المصادقة الثنائية"
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -5135,7 +5148,7 @@ msgstr "تم التحديث بنجاح"
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81 src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94 src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -5169,6 +5182,10 @@ msgstr "تحميل الملفات"
msgid "Upload Folders"
msgstr "تحميل المجلدات"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr "أعلى التيار"
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr "اسم المنبع"
@@ -5454,6 +5471,12 @@ msgstr "رموزك القديمة لن تعمل بعد الآن."
msgid "Your passkeys"
msgstr "مفاتيح المرور الخاصة بك"
#~ msgid "Disable"
#~ msgstr "تعطيل"
#~ msgid "Enable"
#~ msgstr "تفعيل"
#~ msgid "Last Backup Error"
#~ msgstr "خطأ آخر نسخة احتياطية"
@@ -5653,9 +5676,6 @@ msgstr "مفاتيح المرور الخاصة بك"
#~ msgid "Sync config %{config_name} to %{env_name} failed, response: %{resp}"
#~ msgstr "فشل مزامنة التكوين %{config_name} إلى %{env_name}، الاستجابة: %{resp}"
#~ msgid "Target"
#~ msgstr "الهدف"
#~ msgid ""
#~ "If you lose your mobile phone, you can use the recovery code to reset your "
#~ "2FA."
+55 -35
View File
@@ -143,7 +143,7 @@ msgstr "Aktion"
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129 src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142 src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr "Aktionen"
@@ -161,7 +161,7 @@ msgstr "Tatsächliches Verhältnis von Arbeitern zu konfigurierten"
#: src/components/NgxConfigEditor/NgxUpstream.vue:159 src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr "Hinzufügen"
@@ -188,11 +188,11 @@ msgstr "Ort hinzufügen"
msgid "Add Site"
msgstr "Seite hinzufügen"
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr "Stream hinzufügen"
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr "Erfolgreich hinzugefügt"
@@ -278,7 +278,7 @@ msgid "Are you sure you want to delete permanently?"
msgstr "Sind Sie sicher, dass Sie dauerhaft löschen möchten?"
#: src/language/curd.ts:25 src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr "Sind Sie sicher, dass Sie löschen möchten?"
@@ -579,6 +579,7 @@ msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr "Abbrechen"
@@ -1218,7 +1219,7 @@ msgstr ""
#: src/components/NgxConfigEditor/NgxUpstream.vue:129 src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr "Löschen"
@@ -1266,7 +1267,7 @@ msgstr "Löschen des Streams %{name} von %{node} fehlgeschlagen"
msgid "Delete stream %{name} from %{node} successfully"
msgstr "Stream %{name} wurde erfolgreich von %{node} gelöscht"
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr "Stream löschen: %{stream_name}"
@@ -1340,13 +1341,10 @@ msgid "Directory path to store cache files"
msgstr "Verzeichnispfad zum Speichern der Cache-Dateien"
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr "Deaktivieren"
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr "Deaktivieren"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr "Automatische Verlängerung für %{name} konnte nicht deaktiviert werden"
@@ -1407,15 +1405,16 @@ msgstr "Stream %{name} von %{node} erfolgreich deaktiviert"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114 src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127 src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr "Deaktiviert"
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr "Erfolgreich deaktiviert"
@@ -1447,6 +1446,10 @@ msgstr ""
msgid "Do you want to %{action} this site?"
msgstr "Möchten Sie diese Website %{action}?"
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr "Möchten Sie diesen Stream %{action}?"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr "Möchtest du die automatische Zertifikatsverlängerung deaktivieren?"
@@ -1525,7 +1528,7 @@ msgstr ""
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr "Duplizieren"
@@ -1574,13 +1577,10 @@ msgid "Email (*)"
msgstr "Email (*)"
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr "aktivieren"
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr "Aktivieren"
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr "2FA erfolgreich aktiviert"
@@ -1679,9 +1679,10 @@ msgstr "TOTP aktivieren"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110 src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123 src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr "Aktiviert"
@@ -1689,7 +1690,7 @@ msgstr "Aktiviert"
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr "Erfolgreich aktiviert"
@@ -1926,7 +1927,7 @@ msgstr "Löschen des Zertifikats aus der Datenbank fehlgeschlagen: %{error}"
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr "Deaktivierung von %{msg} fehlgeschlagen"
@@ -1936,7 +1937,7 @@ msgstr "Deaktivierung des Wartungsmodus fehlgeschlagen: %{msg}"
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr "Aktiviern von %{msg} fehlgeschlagen"
@@ -2682,7 +2683,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr "Wartung"
@@ -2712,7 +2713,7 @@ msgstr "Verwalte Konfigurationen"
msgid "Manage Sites"
msgstr "Verwalte Seiten"
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:101
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr "Streams verwalten"
@@ -2886,12 +2887,12 @@ msgstr "Mehrzeilige Direktive"
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr "Name"
@@ -3154,7 +3155,7 @@ msgstr "Nginx.conf enthält das streams-enabled-Verzeichnis"
#: src/views/notification/Notification.vue:38
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:155
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:119
msgid "No"
msgstr "Nein"
@@ -3176,7 +3177,7 @@ msgid "Node"
msgstr "Node"
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63 src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76 src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr "Node-Gruppe"
@@ -3292,6 +3293,7 @@ msgstr "Aus"
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3309,7 +3311,8 @@ msgstr "Offline"
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr "OK"
@@ -3715,6 +3718,15 @@ msgstr "Anbieter"
msgid "Proxy"
msgstr "Proxy"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr "Proxy-Weiterleitung"
#: src/views/site/site_list/columns.tsx:64
#: src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr "Proxy-Ziele"
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr "Öffentliche Sicherheitsnummer"
@@ -4589,7 +4601,7 @@ msgstr "Statisch"
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88 src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101 src/views/stream/columns.tsx:69
msgid "Status"
msgstr "Status"
@@ -5174,6 +5186,7 @@ msgstr "Dienstag"
msgid "Two-factor authentication required"
msgstr "Zwei-Faktor-Authentifizierung erforderlich"
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -5210,7 +5223,7 @@ msgstr "Erfolgreich aktualisiert"
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81 src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94 src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -5244,6 +5257,10 @@ msgstr "Dateien hochladen"
msgid "Upload Folders"
msgstr "Ordner hochladen"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr "Upstream"
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr "Upstream-Name"
@@ -5543,6 +5560,12 @@ msgstr "Ihre alten Codes funktionieren nicht mehr."
msgid "Your passkeys"
msgstr "Deine Passkeys"
#~ msgid "Disable"
#~ msgstr "Deaktivieren"
#~ msgid "Enable"
#~ msgstr "Aktivieren"
#~ msgid "Last Backup Error"
#~ msgstr "Letzter Sicherungsfehler"
@@ -5749,9 +5772,6 @@ msgstr "Deine Passkeys"
#~ msgid "Sync config %{config_name} to %{env_name} failed, response: %{resp}"
#~ msgstr "Speichern erfolgreich"
#~ msgid "Target"
#~ msgstr "Ziel"
#~ msgid "Bist du sicher, dass du diese Richtlinie löschen möchtest?"
#~ msgstr "Bist du sicher, dass du diese Richtlinie löschen möchtest?"
+48 -32
View File
@@ -127,7 +127,7 @@ msgstr ""
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129 src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142 src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr ""
@@ -145,7 +145,7 @@ msgstr ""
#: src/components/NgxConfigEditor/NgxUpstream.vue:159 src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr ""
@@ -172,11 +172,11 @@ msgstr ""
msgid "Add Site"
msgstr ""
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr ""
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr ""
@@ -260,7 +260,7 @@ msgid "Are you sure you want to delete permanently?"
msgstr ""
#: src/language/curd.ts:25 src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr ""
@@ -549,6 +549,7 @@ msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr ""
@@ -1144,7 +1145,7 @@ msgstr ""
#: src/components/NgxConfigEditor/NgxUpstream.vue:129 src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr ""
@@ -1192,7 +1193,7 @@ msgstr ""
msgid "Delete stream %{name} from %{node} successfully"
msgstr ""
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr ""
@@ -1266,13 +1267,10 @@ msgid "Directory path to store cache files"
msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr ""
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr ""
@@ -1333,15 +1331,16 @@ msgstr ""
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114 src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127 src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr ""
@@ -1371,6 +1370,10 @@ msgstr ""
msgid "Do you want to %{action} this site?"
msgstr ""
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr ""
@@ -1445,7 +1448,7 @@ msgstr ""
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr ""
@@ -1494,13 +1497,10 @@ msgid "Email (*)"
msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr ""
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr ""
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr ""
@@ -1599,9 +1599,10 @@ msgstr ""
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110 src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123 src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr ""
@@ -1609,7 +1610,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr ""
@@ -1846,7 +1847,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr ""
@@ -1856,7 +1857,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr ""
@@ -2576,7 +2577,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr ""
@@ -2603,7 +2604,7 @@ msgstr ""
msgid "Manage Sites"
msgstr ""
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:101
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr ""
@@ -2777,12 +2778,12 @@ msgstr ""
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr ""
@@ -3043,7 +3044,7 @@ msgstr ""
#: src/views/notification/Notification.vue:38
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:155
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:119
msgid "No"
msgstr ""
@@ -3065,7 +3066,7 @@ msgid "Node"
msgstr ""
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63 src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76 src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr ""
@@ -3174,6 +3175,7 @@ msgstr ""
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3191,7 +3193,8 @@ msgstr ""
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr ""
@@ -3576,6 +3579,14 @@ msgstr ""
msgid "Proxy"
msgstr ""
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr ""
#: src/views/site/site_list/columns.tsx:64 src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr ""
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr ""
@@ -4424,7 +4435,7 @@ msgstr ""
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88 src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101 src/views/stream/columns.tsx:69
msgid "Status"
msgstr ""
@@ -4947,6 +4958,7 @@ msgstr ""
msgid "Two-factor authentication required"
msgstr ""
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -4983,7 +4995,7 @@ msgstr ""
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81 src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94 src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -5017,6 +5029,10 @@ msgstr ""
msgid "Upload Folders"
msgstr ""
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr ""
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr ""
+55 -35
View File
@@ -150,7 +150,7 @@ msgstr "Acción"
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129 src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142 src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr "Acciones"
@@ -168,7 +168,7 @@ msgstr "Proporción real de trabajadores a configurados"
#: src/components/NgxConfigEditor/NgxUpstream.vue:159 src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr "Agregar"
@@ -195,11 +195,11 @@ msgstr "Agregar Ubicación"
msgid "Add Site"
msgstr "Agregar Sitio"
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr "Agregar Stream"
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr "Agregado exitoso"
@@ -285,7 +285,7 @@ msgid "Are you sure you want to delete permanently?"
msgstr "¿Estás seguro de que quieres eliminar permanentemente?"
#: src/language/curd.ts:25 src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr "¿Está seguro de que quiere borrar?"
@@ -588,6 +588,7 @@ msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr "Cancelar"
@@ -1229,7 +1230,7 @@ msgstr ""
#: src/components/NgxConfigEditor/NgxUpstream.vue:129 src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr "Eliminar"
@@ -1277,7 +1278,7 @@ msgstr "Error al eliminar el flujo %{name} de %{node}"
msgid "Delete stream %{name} from %{node} successfully"
msgstr "Se eliminó el flujo %{name} de %{node} correctamente"
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr "Eliminar stream: %{site_name}"
@@ -1351,13 +1352,10 @@ msgid "Directory path to store cache files"
msgstr "Ruta del directorio para almacenar archivos de caché"
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr "Desactivar"
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr "Desactivar"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr "Error al desactivar la renovación automática para %{name}"
@@ -1418,15 +1416,16 @@ msgstr "Deshabilitar el flujo %{name} desde %{node} con éxito"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114 src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127 src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr "Desactivado"
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr "Desactivado con éxito"
@@ -1456,6 +1455,10 @@ msgstr "No habilite esta opción a menos que esté seguro de que la necesita."
msgid "Do you want to %{action} this site?"
msgstr "¿Desea %{action} este sitio?"
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr "¿Quieres %{action} este flujo?"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr "¿Desea deshabilitar la renovación automática de certificado?"
@@ -1534,7 +1537,7 @@ msgstr ""
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr "Duplicar"
@@ -1583,13 +1586,10 @@ msgid "Email (*)"
msgstr "Correo (*)"
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr "habilitar"
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr "Habilitar"
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr "Habilitar 2FA exitoso"
@@ -1688,9 +1688,10 @@ msgstr "Habilitar TOTP"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110 src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123 src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr "Habilitado"
@@ -1698,7 +1699,7 @@ msgstr "Habilitado"
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr "Habilitado con éxito"
@@ -1937,7 +1938,7 @@ msgstr "Error al eliminar el certificado de la base de datos: %{error}"
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr "Error al deshabilitar %{msg}"
@@ -1947,7 +1948,7 @@ msgstr "Error al desactivar el modo de mantenimiento: %{msg}"
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr "Error al habilitar %{msg}"
@@ -2691,7 +2692,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr "Mantenimiento"
@@ -2720,7 +2721,7 @@ msgstr "Administrar configuraciones"
msgid "Manage Sites"
msgstr "Administrar sitios"
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:101
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr "Administrar Transmisiones"
@@ -2894,12 +2895,12 @@ msgstr "Directiva multilínea"
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr "Nombre"
@@ -3162,7 +3163,7 @@ msgstr "Nginx.conf incluye el directorio streams-enabled"
#: src/views/notification/Notification.vue:38
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:155
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:119
msgid "No"
msgstr "No"
@@ -3184,7 +3185,7 @@ msgid "Node"
msgstr "Nodo"
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63 src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76 src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr "Grupo de nodos"
@@ -3300,6 +3301,7 @@ msgstr "Apagado"
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3317,7 +3319,8 @@ msgstr "Desconectado"
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr "OK"
@@ -3726,6 +3729,15 @@ msgstr "Proveedor"
msgid "Proxy"
msgstr "Proxy"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr "Pase de Proxy"
#: src/views/site/site_list/columns.tsx:64
#: src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr "Objetivos del proxy"
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr "Número de Seguridad Pública"
@@ -4598,7 +4610,7 @@ msgstr "Estático"
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88 src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101 src/views/stream/columns.tsx:69
msgid "Status"
msgstr "Estado"
@@ -5182,6 +5194,7 @@ msgstr "Martes"
msgid "Two-factor authentication required"
msgstr "Se requiere autenticación de dos factores"
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -5218,7 +5231,7 @@ msgstr "Actualización exitosa"
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81 src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94 src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -5252,6 +5265,10 @@ msgstr "Subir archivos"
msgid "Upload Folders"
msgstr "Subir carpetas"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr "Aguas arriba"
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr "Nombre de la Transmisión"
@@ -5546,6 +5563,12 @@ msgstr "Tus códigos antiguos ya no funcionarán."
msgid "Your passkeys"
msgstr "Sus llaves de acceso"
#~ msgid "Disable"
#~ msgstr "Desactivar"
#~ msgid "Enable"
#~ msgstr "Habilitar"
#~ msgid "Last Backup Error"
#~ msgstr "Último error de copia de seguridad"
@@ -5743,9 +5766,6 @@ msgstr "Sus llaves de acceso"
#~ "Sincronización de la configuración %{config_name} a %{env_name} fallida, "
#~ "respuesta: %{resp}"
#~ msgid "Target"
#~ msgstr "Objetivo"
#~ msgid "Can't scan? Use text key binding"
#~ msgstr "¿No puede escanear? Utilice la vinculación con una llave de texto"
+55 -32
View File
@@ -148,7 +148,7 @@ msgstr "Action"
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129 src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142 src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr "Actions"
@@ -166,7 +166,7 @@ msgstr "Ratio réel des travailleurs par rapport à la configuration"
#: src/components/NgxConfigEditor/NgxUpstream.vue:159 src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr "Ajouter"
@@ -193,11 +193,11 @@ msgstr "Ajouter une localisation"
msgid "Add Site"
msgstr "Ajouter un site"
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr "Ajouter un flux"
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr "Ajouté avec succès"
@@ -283,7 +283,7 @@ msgid "Are you sure you want to delete permanently?"
msgstr "Êtes-vous sûr de vouloir supprimer définitivement ?"
#: src/language/curd.ts:25 src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr "Etes-vous sûr que vous voulez supprimer ?"
@@ -583,6 +583,7 @@ msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr "Annuler"
@@ -1225,7 +1226,7 @@ msgstr ""
#: src/components/NgxConfigEditor/NgxUpstream.vue:129 src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr "Supprimer"
@@ -1273,7 +1274,7 @@ msgstr "Échec de la suppression du flux %{name} de %{node}"
msgid "Delete stream %{name} from %{node} successfully"
msgstr "Le flux %{name} a été supprimé de %{node} avec succès"
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr "Supprimer le flux : %{stream_name}"
@@ -1347,13 +1348,10 @@ msgid "Directory path to store cache files"
msgstr "Chemin du répertoire pour stocker les fichiers de cache"
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr "Désactiver"
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr "Désactiver"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr "Échec de la désactivation du renouvellement automatique pour %{name}"
@@ -1414,15 +1412,16 @@ msgstr "Désactivation du flux %{name} depuis %{node} réussie"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114 src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127 src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr "Désactivé"
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr "Désactivé avec succès"
@@ -1452,6 +1451,10 @@ msgstr "N'activez pas cette option sauf si vous êtes sûr d'en avoir avez besoi
msgid "Do you want to %{action} this site?"
msgstr "Voulez-vous %{action} ce site ?"
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr "Voulez-vous %{action} ce flux ?"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr "Voulez-vous désactiver le renouvellement automatique des certificats ?"
@@ -1528,7 +1531,7 @@ msgstr ""
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr "Dupliquer"
@@ -1577,13 +1580,10 @@ msgid "Email (*)"
msgstr "Email (*)"
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr "activer"
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr "Activer"
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr "2FA activé avec succès"
@@ -1682,9 +1682,10 @@ msgstr "Activer TOTP"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110 src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123 src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr "Activé"
@@ -1692,7 +1693,7 @@ msgstr "Activé"
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr "Activé avec succès"
@@ -1929,7 +1930,7 @@ msgstr "Échec de la suppression du certificat de la base de données : %{error}
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr "Impossible de désactiver %{msg}"
@@ -1939,7 +1940,7 @@ msgstr "Échec de la désactivation du mode maintenance : %{msg}"
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr "Impossible d'activer %{msg}"
@@ -2689,7 +2690,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr "Maintenance"
@@ -2718,7 +2719,7 @@ msgstr "Gérer les configurations"
msgid "Manage Sites"
msgstr "Gérer les sites"
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:101
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr "Gérer les flux"
@@ -2892,12 +2893,12 @@ msgstr "Directive multiligne"
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr "Nom"
@@ -3160,7 +3161,7 @@ msgstr "Nginx.conf inclut le répertoire streams-enabled"
#: src/views/notification/Notification.vue:38
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:155
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:119
msgid "No"
msgstr "Non"
@@ -3182,7 +3183,7 @@ msgid "Node"
msgstr "Nœud"
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63 src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76 src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr "Groupe de nœuds"
@@ -3297,6 +3298,7 @@ msgstr "Désactivé"
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3314,7 +3316,8 @@ msgstr "Hors ligne"
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr "OK"
@@ -3723,6 +3726,15 @@ msgstr "Fournisseur"
msgid "Proxy"
msgstr "Proxy"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr "Passe de Proxy"
#: src/views/site/site_list/columns.tsx:64
#: src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr "Cibles du proxy"
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr "Numéro de sécurité publique"
@@ -4597,7 +4609,7 @@ msgstr "Statique"
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88 src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101 src/views/stream/columns.tsx:69
msgid "Status"
msgstr "Statut"
@@ -5190,6 +5202,7 @@ msgstr "Mardi"
msgid "Two-factor authentication required"
msgstr "Authentification à deux facteurs requise"
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -5226,7 +5239,7 @@ msgstr "Mise à jour réussie"
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81 src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94 src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -5260,6 +5273,10 @@ msgstr "Téléverser des fichiers"
msgid "Upload Folders"
msgstr "Télécharger des dossiers"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr "Amont"
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr "Nom de l'amont"
@@ -5557,6 +5574,12 @@ msgstr "Vos anciens codes ne fonctionneront plus."
msgid "Your passkeys"
msgstr "Vos clés d'accès"
#~ msgid "Disable"
#~ msgstr "Désactiver"
#~ msgid "Enable"
#~ msgstr "Activer"
#~ msgid "Last Backup Error"
#~ msgstr "Dernière erreur de sauvegarde"
+55 -32
View File
@@ -144,7 +144,7 @@ msgstr "操作"
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129 src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142 src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr "操作"
@@ -162,7 +162,7 @@ msgstr "実際のワーカー数と設定値の比率"
#: src/components/NgxConfigEditor/NgxUpstream.vue:159 src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr "追加"
@@ -189,11 +189,11 @@ msgstr "Locationを追加"
msgid "Add Site"
msgstr "サイトを追加"
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr "Streamを追加"
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr "正常に追加されました"
@@ -277,7 +277,7 @@ msgid "Are you sure you want to delete permanently?"
msgstr "完全に削除してもよろしいですか?"
#: src/language/curd.ts:25 src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr "削除してもよろしいですか?"
@@ -568,6 +568,7 @@ msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr "キャンセル"
@@ -1183,7 +1184,7 @@ msgstr "共有メモリゾーンの名前とサイズを定義します(例: p
#: src/components/NgxConfigEditor/NgxUpstream.vue:129 src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr "削除"
@@ -1231,7 +1232,7 @@ msgstr "%{node} からのストリーム %{name} の削除に失敗しました"
msgid "Delete stream %{name} from %{node} successfully"
msgstr "ストリーム %{name} を %{node} から削除しました"
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr "ストリームを削除: %{stream_name}"
@@ -1305,13 +1306,10 @@ msgid "Directory path to store cache files"
msgstr "キャッシュファイルを保存するディレクトリパス"
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr "無効化"
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr "無効化"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr "%{name} の自動更新の無効化に失敗しました"
@@ -1372,15 +1370,16 @@ msgstr "ストリーム %{name} を %{node} から無効化しました"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114 src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127 src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr "無効"
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr "無効化に成功しました"
@@ -1410,6 +1409,10 @@ msgstr "このオプションは必要な場合以外は有効にしないでく
msgid "Do you want to %{action} this site?"
msgstr "このサイトを%{action}しますか?"
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr "このストリームを%{action}しますか?"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr "自動証明書更新を無効にしますか?"
@@ -1483,7 +1486,7 @@ msgstr "一部のブラウザのセキュリティポリシーのため、localh
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr "複製"
@@ -1532,13 +1535,10 @@ msgid "Email (*)"
msgstr "メールアドレス (*)"
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr "有効にする"
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr "有効にする"
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr "2FAが有効化されました"
@@ -1637,9 +1637,10 @@ msgstr "TOTP を有効にする"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110 src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123 src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr "有効"
@@ -1647,7 +1648,7 @@ msgstr "有効"
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr "有効化に成功しました"
@@ -1884,7 +1885,7 @@ msgstr "データベースから証明書の削除に失敗しました: %{error
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr "%{msg}の無効化に失敗しました"
@@ -1894,7 +1895,7 @@ msgstr "メンテナンスモードの無効化に失敗しました: %{msg}"
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr "有効化に失敗しました %{msg}"
@@ -2620,7 +2621,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr "メンテナンス"
@@ -2649,7 +2650,7 @@ msgstr "設定管理"
msgid "Manage Sites"
msgstr "サイト管理"
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:101
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr "ストリームの管理"
@@ -2823,12 +2824,12 @@ msgstr "複数行ディレクティブ"
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr "名前"
@@ -3089,7 +3090,7 @@ msgstr "Nginx.conf には streams-enabled ディレクトリが含まれてい
#: src/views/notification/Notification.vue:38
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:155
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:119
msgid "No"
msgstr "いいえ"
@@ -3111,7 +3112,7 @@ msgid "Node"
msgstr "ノード"
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63 src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76 src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr "ノードグループ"
@@ -3220,6 +3221,7 @@ msgstr "オフ"
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3237,7 +3239,8 @@ msgstr "オフライン"
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr "OK"
@@ -3625,6 +3628,15 @@ msgstr "プロバイダー"
msgid "Proxy"
msgstr "プロキシ"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr "プロキシパス"
#: src/views/site/site_list/columns.tsx:64
#: src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr "プロキシターゲット"
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr "公安番号"
@@ -4477,7 +4489,7 @@ msgstr "静的"
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88 src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101 src/views/stream/columns.tsx:69
msgid "Status"
msgstr "ステータス"
@@ -5016,6 +5028,7 @@ msgstr "火曜日"
msgid "Two-factor authentication required"
msgstr "二要素認証が必要です"
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -5052,7 +5065,7 @@ msgstr "更新に成功しました"
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81 src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94 src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -5086,6 +5099,10 @@ msgstr "ファイルをアップロード"
msgid "Upload Folders"
msgstr "フォルダをアップロード"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr "アップストリーム"
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr "アップストリーム名"
@@ -5358,6 +5375,12 @@ msgstr "以前のコードはもう使えません。"
msgid "Your passkeys"
msgstr "あなたのパスキー"
#~ msgid "Disable"
#~ msgstr "無効化"
#~ msgid "Enable"
#~ msgstr "有効にする"
#~ msgid "Last Backup Error"
#~ msgstr "最後のバックアップエラー"
+55 -35
View File
@@ -142,7 +142,7 @@ msgstr "작업"
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129 src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142 src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr "작업"
@@ -160,7 +160,7 @@ msgstr "실제 작업자 대 구성 비율"
#: src/components/NgxConfigEditor/NgxUpstream.vue:159 src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr "추가"
@@ -187,11 +187,11 @@ msgstr "위치 추가"
msgid "Add Site"
msgstr "사이트 추가"
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr "스트림 추가"
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr "성공적으로 추가됨"
@@ -275,7 +275,7 @@ msgid "Are you sure you want to delete permanently?"
msgstr "정말 영구적으로 삭제하시겠습니까?"
#: src/language/curd.ts:25 src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr "정말 삭제하시겠습니까?"
@@ -566,6 +566,7 @@ msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr "취소"
@@ -1179,7 +1180,7 @@ msgstr "공유 메모리 영역 이름과 크기를 정의합니다(예: proxy_c
#: src/components/NgxConfigEditor/NgxUpstream.vue:129 src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr "삭제"
@@ -1227,7 +1228,7 @@ msgstr "%{node}에서 스트림 %{name} 삭제 실패"
msgid "Delete stream %{name} from %{node} successfully"
msgstr "스트림 %{name}을(를) %{node}에서 성공적으로 삭제했습니다"
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr "스트림 삭제: %{stream_name}"
@@ -1301,13 +1302,10 @@ msgid "Directory path to store cache files"
msgstr "캐시 파일을 저장할 디렉터리 경로"
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr "비활성화"
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr "비활성화"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr "%{name}의 자동 갱신 비활성화 실패"
@@ -1368,15 +1366,16 @@ msgstr "스트림 %{name}을(를) %{node}에서 비활성화했습니다"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114 src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127 src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr "비활성화됨"
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr "성공적으로 비활성화됨"
@@ -1406,6 +1405,10 @@ msgstr "이 옵션은 필요한 경우가 아니라면 활성화하지 마세요
msgid "Do you want to %{action} this site?"
msgstr "이 사이트를 %{action}하시겠습니까?"
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr "이 스트림을 %{action}하시겠습니까?"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr "자동 인증서 갱신을 비활성화하시겠습니까?"
@@ -1481,7 +1484,7 @@ msgstr ""
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr "복제"
@@ -1530,13 +1533,10 @@ msgid "Email (*)"
msgstr "이메일 (*)"
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr "활성화"
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr "활성화"
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr "2FA가 성공적으로 활성화되었습니다"
@@ -1635,9 +1635,10 @@ msgstr "TOTP 활성화"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110 src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123 src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr "활성화됨"
@@ -1645,7 +1646,7 @@ msgstr "활성화됨"
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr "성공적으로 활성화됨"
@@ -1882,7 +1883,7 @@ msgstr "데이터베이스에서 인증서 삭제 실패: %{error}"
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr "%{msg} 비활성화 실패"
@@ -1892,7 +1893,7 @@ msgstr "점검 모드 비활성화 실패: %{msg}"
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr "%{msg} 활성화 실패"
@@ -2617,7 +2618,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr "유지보수"
@@ -2644,7 +2645,7 @@ msgstr "구성 관리"
msgid "Manage Sites"
msgstr "사이트 관리"
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:101
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr "스트림 관리"
@@ -2818,12 +2819,12 @@ msgstr "여러 줄 지시문"
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr "이름"
@@ -3084,7 +3085,7 @@ msgstr "Nginx.conf에는 streams-enabled 디렉토리가 포함됩니다"
#: src/views/notification/Notification.vue:38
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:155
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:119
msgid "No"
msgstr "아니요"
@@ -3106,7 +3107,7 @@ msgid "Node"
msgstr "노드"
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63 src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76 src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr "노드 그룹"
@@ -3215,6 +3216,7 @@ msgstr "끔"
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3232,7 +3234,8 @@ msgstr "오프라인"
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr "확인"
@@ -3618,6 +3621,15 @@ msgstr "제공자"
msgid "Proxy"
msgstr "프록시"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr "프록시 패스"
#: src/views/site/site_list/columns.tsx:64
#: src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr "프록시 대상"
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr "공공 보안 번호"
@@ -4472,7 +4484,7 @@ msgstr "정적"
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88 src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101 src/views/stream/columns.tsx:69
msgid "Status"
msgstr "상태"
@@ -5009,6 +5021,7 @@ msgstr "화요일"
msgid "Two-factor authentication required"
msgstr "2단계 인증이 필요합니다"
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -5045,7 +5058,7 @@ msgstr "성공적으로 업데이트되었습니다"
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81 src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94 src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -5079,6 +5092,10 @@ msgstr "파일 업로드"
msgid "Upload Folders"
msgstr "폴더 업로드"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr "업스트림"
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr "업스트림 이름"
@@ -5353,6 +5370,12 @@ msgstr "이전 코드는 더 이상 작동하지 않습니다."
msgid "Your passkeys"
msgstr "귀하의 패스키"
#~ msgid "Disable"
#~ msgstr "비활성화"
#~ msgid "Enable"
#~ msgstr "활성화"
#~ msgid "Last Backup Error"
#~ msgstr "마지막 백업 오류"
@@ -5528,9 +5551,6 @@ msgstr "귀하의 패스키"
#~ msgid "Sync config %{config_name} to %{env_name} failed, response: %{resp}"
#~ msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
#~ msgid "Target"
#~ msgstr "대상"
#~ msgid "File"
#~ msgstr "파일"
+55 -38
View File
@@ -131,8 +131,8 @@ msgstr ""
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129
#: src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142
#: src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr ""
@@ -151,7 +151,7 @@ msgstr ""
#: src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr ""
@@ -180,11 +180,11 @@ msgstr ""
msgid "Add Site"
msgstr ""
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr ""
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr ""
@@ -269,7 +269,7 @@ msgstr ""
#: src/language/curd.ts:25
#: src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr ""
@@ -559,6 +559,7 @@ msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr ""
@@ -1125,7 +1126,7 @@ msgstr ""
#: src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr ""
@@ -1175,7 +1176,7 @@ msgstr ""
msgid "Delete stream %{name} from %{node} successfully"
msgstr ""
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr ""
@@ -1250,13 +1251,10 @@ msgid "Directory path to store cache files"
msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr ""
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr ""
@@ -1319,16 +1317,17 @@ msgstr ""
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114
#: src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127
#: src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr ""
@@ -1358,6 +1357,10 @@ msgstr ""
msgid "Do you want to %{action} this site?"
msgstr ""
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr ""
@@ -1430,7 +1433,7 @@ msgstr ""
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr ""
@@ -1480,13 +1483,10 @@ msgid "Email (*)"
msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr ""
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr ""
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr ""
@@ -1587,10 +1587,11 @@ msgstr ""
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110
#: src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123
#: src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr ""
@@ -1598,7 +1599,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr ""
@@ -1836,7 +1837,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr ""
@@ -1846,7 +1847,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr ""
@@ -2548,7 +2549,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr ""
@@ -2577,7 +2578,7 @@ msgid "Manage Sites"
msgstr ""
#: src/routes/modules/streams.ts:10
#: src/views/stream/StreamList.vue:101
#: src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr ""
@@ -2754,12 +2755,12 @@ msgstr ""
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr ""
@@ -3024,7 +3025,7 @@ msgstr ""
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98
#: src/views/stream/StreamList.vue:155
#: src/views/stream/StreamList.vue:119
msgid "No"
msgstr ""
@@ -3046,8 +3047,8 @@ msgid "Node"
msgstr ""
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63
#: src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76
#: src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr ""
@@ -3152,6 +3153,7 @@ msgstr ""
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3170,7 +3172,8 @@ msgstr ""
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr ""
@@ -3545,6 +3548,15 @@ msgstr ""
msgid "Proxy"
msgstr ""
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr ""
#: src/views/site/site_list/columns.tsx:64
#: src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr ""
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr ""
@@ -4389,8 +4401,8 @@ msgstr ""
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88
#: src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101
#: src/views/stream/columns.tsx:69
msgid "Status"
msgstr ""
@@ -4866,6 +4878,7 @@ msgstr ""
msgid "Two-factor authentication required"
msgstr ""
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -4903,8 +4916,8 @@ msgstr ""
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81
#: src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94
#: src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -4939,6 +4952,10 @@ msgstr ""
msgid "Upload Folders"
msgstr ""
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr ""
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr ""
+55 -35
View File
@@ -144,7 +144,7 @@ msgstr "Acção"
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129 src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142 src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr "Ações"
@@ -162,7 +162,7 @@ msgstr "Rácio real de workers para configurado"
#: src/components/NgxConfigEditor/NgxUpstream.vue:159 src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr "Adicionar"
@@ -189,11 +189,11 @@ msgstr "Adicionar Local"
msgid "Add Site"
msgstr "Adicionar Site"
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr "Adicionar Stream"
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr "Adicionado com sucesso"
@@ -279,7 +279,7 @@ msgid "Are you sure you want to delete permanently?"
msgstr "Tem a certeza de que pretende eliminar permanentemente?"
#: src/language/curd.ts:25 src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr "Tem certeza que pretende eliminar?"
@@ -576,6 +576,7 @@ msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr "Cancelar"
@@ -1216,7 +1217,7 @@ msgstr ""
#: src/components/NgxConfigEditor/NgxUpstream.vue:129 src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr "Eliminar"
@@ -1264,7 +1265,7 @@ msgstr "Falha ao eliminar o fluxo %{name} de %{node}"
msgid "Delete stream %{name} from %{node} successfully"
msgstr "O fluxo %{name} foi eliminado de %{node} com sucesso"
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr "Eliminar stream: %{stream_name}"
@@ -1338,13 +1339,10 @@ msgid "Directory path to store cache files"
msgstr "Caminho do diretório para armazenar ficheiros de cache"
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr "Desativar"
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr "Desativar"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr "Falha ao desativar a renovação automática para %{name}"
@@ -1405,15 +1403,16 @@ msgstr "Desativar o fluxo %{name} de %{node} com sucesso"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114 src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127 src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr "Desativado"
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr "Desactivado com sucesso"
@@ -1443,6 +1442,10 @@ msgstr "Não ative esta opção a menos que tenha a certeza de que precisa dela.
msgid "Do you want to %{action} this site?"
msgstr "Deseja %{action} este site?"
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr "Deseja %{action} este fluxo?"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr "Desactivar a renovação automática do certificado?"
@@ -1519,7 +1522,7 @@ msgstr ""
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr "Duplicado"
@@ -1568,13 +1571,10 @@ msgid "Email (*)"
msgstr "E-mail (*)"
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr "ativar"
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr "Activar"
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr "2FA Activado com Sucesso"
@@ -1673,9 +1673,10 @@ msgstr "Ativar TOTP"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110 src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123 src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr "Activado"
@@ -1683,7 +1684,7 @@ msgstr "Activado"
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr "Activado com sucesso"
@@ -1920,7 +1921,7 @@ msgstr "Falha ao eliminar o certificado da base de dados: %{error}"
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr "Falha ao desactivar %{msg}"
@@ -1930,7 +1931,7 @@ msgstr "Falha ao desativar o modo de manutenção: %{msg}"
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr "Falha ao Activar %{msg}"
@@ -2675,7 +2676,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr "Manutenção"
@@ -2704,7 +2705,7 @@ msgstr "Gerir Configurações"
msgid "Manage Sites"
msgstr "Gerir Sites"
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:101
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr "Gerir Streams"
@@ -2878,12 +2879,12 @@ msgstr "Diretiva Multilinha"
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr "Nome"
@@ -3146,7 +3147,7 @@ msgstr "Nginx.conf inclui o diretório streams-enabled"
#: src/views/notification/Notification.vue:38
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:155
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:119
msgid "No"
msgstr "Não"
@@ -3168,7 +3169,7 @@ msgid "Node"
msgstr "Nó"
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63 src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76 src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr "Grupo de nós"
@@ -3283,6 +3284,7 @@ msgstr "Desligado"
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3300,7 +3302,8 @@ msgstr "Off-line"
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr "OK"
@@ -3704,6 +3707,15 @@ msgstr "Provedor"
msgid "Proxy"
msgstr "Proxy"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr "Passe de Proxy"
#: src/views/site/site_list/columns.tsx:64
#: src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr "Destinos do proxy"
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr "Número de Segurança Pública"
@@ -4577,7 +4589,7 @@ msgstr "Estático"
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88 src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101 src/views/stream/columns.tsx:69
msgid "Status"
msgstr "Estado"
@@ -5157,6 +5169,7 @@ msgstr "Terça-feira"
msgid "Two-factor authentication required"
msgstr "Autenticação de dois fatores necessária"
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -5193,7 +5206,7 @@ msgstr "Atualização bem-sucedida"
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81 src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94 src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -5227,6 +5240,10 @@ msgstr "Carregar ficheiros"
msgid "Upload Folders"
msgstr "Carregar pastas"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr "A montante"
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr "Nome do Upstream"
@@ -5520,6 +5537,12 @@ msgstr "Os seus códigos antigos não funcionarão mais."
msgid "Your passkeys"
msgstr "As suas chaves de acesso"
#~ msgid "Disable"
#~ msgstr "Desativar"
#~ msgid "Enable"
#~ msgstr "Activar"
#~ msgid "Last Backup Error"
#~ msgstr "Último erro de backup"
@@ -5683,9 +5706,6 @@ msgstr "As suas chaves de acesso"
#~ "Sincronização de configuração %{config_name} para %{env_name} falhou, "
#~ "resposta: %{resp}"
#~ msgid "Target"
#~ msgstr "Destino"
#~ msgid "The recovery code is only displayed once, please save it in a safe place."
#~ msgstr ""
#~ "O código de recuperação é apresentado apenas uma vez, guarde-o num local "
+55 -35
View File
@@ -148,7 +148,7 @@ msgstr "Действие"
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129 src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142 src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr "Действия"
@@ -166,7 +166,7 @@ msgstr "Фактическое соотношение рабочих к наст
#: src/components/NgxConfigEditor/NgxUpstream.vue:159 src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr "Добавить"
@@ -193,11 +193,11 @@ msgstr "Добавить Location"
msgid "Add Site"
msgstr "Добавить Сайт"
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr "Добавить поток"
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr "Добавлено успешно"
@@ -281,7 +281,7 @@ msgid "Are you sure you want to delete permanently?"
msgstr "Вы уверены, что хотите удалить безвозвратно?"
#: src/language/curd.ts:25 src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr "Вы уверены, что хотите удалить?"
@@ -582,6 +582,7 @@ msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr "Отмена"
@@ -1217,7 +1218,7 @@ msgstr "Определите имя и размер зоны общей памя
#: src/components/NgxConfigEditor/NgxUpstream.vue:129 src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr "Удалить"
@@ -1265,7 +1266,7 @@ msgstr "Не удалось удалить поток %{name} с %{node}"
msgid "Delete stream %{name} from %{node} successfully"
msgstr "Поток %{name} успешно удален с %{node}"
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr "Удалить поток: %{stream_name}"
@@ -1339,13 +1340,10 @@ msgid "Directory path to store cache files"
msgstr "Путь к каталогу для хранения кэшированных файлов"
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr "Отключить"
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr "Отключить"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr "Не удалось отключить автоматическое продление для %{name}"
@@ -1406,15 +1404,16 @@ msgstr "Поток %{name} отключен от %{node} успешно"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114 src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127 src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr "Отключено"
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr "Отключено успешно"
@@ -1444,6 +1443,10 @@ msgstr "Не включайте эту опцию, если не уверены,
msgid "Do you want to %{action} this site?"
msgstr "Вы хотите %{action} этот сайт?"
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr "Вы хотите %{action} этот поток?"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr "Вы хотите отключить автоматическое обновление сертификата?"
@@ -1520,7 +1523,7 @@ msgstr ""
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr "Дублировать"
@@ -1569,13 +1572,10 @@ msgid "Email (*)"
msgstr "Email (*)"
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr "включить"
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr "Включить"
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr "Двухфакторная аутентификация успешно включена"
@@ -1674,9 +1674,10 @@ msgstr "Включить TOTP"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110 src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123 src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr "Включено"
@@ -1684,7 +1685,7 @@ msgstr "Включено"
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr "Активировано успешно"
@@ -1921,7 +1922,7 @@ msgstr "Не удалось удалить сертификат из базы д
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr "Не удалось отключить %{msg}"
@@ -1931,7 +1932,7 @@ msgstr "Не удалось отключить режим обслуживани
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr "Не удалось включить %{msg}"
@@ -2674,7 +2675,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr "Техническое обслуживание"
@@ -2703,7 +2704,7 @@ msgstr "Конфигурации"
msgid "Manage Sites"
msgstr "Сайты"
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:101
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr "Управление потоками"
@@ -2877,12 +2878,12 @@ msgstr "Многострочная директива"
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr "Имя"
@@ -3145,7 +3146,7 @@ msgstr "Nginx.conf включает каталог streams-enabled"
#: src/views/notification/Notification.vue:38
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:155
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:119
msgid "No"
msgstr "Нет"
@@ -3167,7 +3168,7 @@ msgid "Node"
msgstr "Узел"
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63 src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76 src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr "Группа узлов"
@@ -3282,6 +3283,7 @@ msgstr "Выкл"
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3299,7 +3301,8 @@ msgstr "Оффлайн"
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr "ОК"
@@ -3708,6 +3711,15 @@ msgstr "Провайдер"
msgid "Proxy"
msgstr "Прокси"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr "Прокси-передача"
#: src/views/site/site_list/columns.tsx:64
#: src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr "Цели прокси"
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr "Номер в органах общественной безопасности"
@@ -4573,7 +4585,7 @@ msgstr "Статический"
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88 src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101 src/views/stream/columns.tsx:69
msgid "Status"
msgstr "Статус"
@@ -5154,6 +5166,7 @@ msgstr "Вторник"
msgid "Two-factor authentication required"
msgstr "Требуется двухфакторная аутентификация"
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -5190,7 +5203,7 @@ msgstr "Успешно обновлено"
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81 src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94 src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -5224,6 +5237,10 @@ msgstr "Загрузить файлы"
msgid "Upload Folders"
msgstr "Загрузить папки"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr "Восходящий поток"
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr "Имя Upstream"
@@ -5516,6 +5533,12 @@ msgstr "Ваши старые коды больше не будут работа
msgid "Your passkeys"
msgstr "Ваши ключи доступа"
#~ msgid "Disable"
#~ msgstr "Отключить"
#~ msgid "Enable"
#~ msgstr "Включить"
#~ msgid "Last Backup Error"
#~ msgstr "Ошибка последнего резервного копирования"
@@ -5703,9 +5726,6 @@ msgstr "Ваши ключи доступа"
#~ "Синхронизация конфигурации %{config_name} с %{env_name} не удалась, ответ: "
#~ "%{resp}"
#~ msgid "Target"
#~ msgstr "Цель"
#~ msgid "File"
#~ msgstr "Файл"
+55 -36
View File
@@ -144,7 +144,7 @@ msgstr "Eylem"
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129 src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142 src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr "İşlemler"
@@ -162,7 +162,7 @@ msgstr "Gerçek çalışanın yapılandırılmışa oranı"
#: src/components/NgxConfigEditor/NgxUpstream.vue:159 src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr "Ekle"
@@ -189,11 +189,11 @@ msgstr "Konum ekle"
msgid "Add Site"
msgstr "Site Ekle"
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr "Akış Ekle"
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr "Başarıyla eklendi"
@@ -277,7 +277,7 @@ msgid "Are you sure you want to delete permanently?"
msgstr "Kalıcı olarak silmek istediğinizden emin misiniz?"
#: src/language/curd.ts:25 src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr "Silmek istediğine emin misin?"
@@ -572,6 +572,7 @@ msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr "İptal"
@@ -1211,7 +1212,7 @@ msgstr ""
#: src/components/NgxConfigEditor/NgxUpstream.vue:129 src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr "Sil"
@@ -1259,7 +1260,7 @@ msgstr "%{node} üzerindeki %{name} akışı silinemedi"
msgid "Delete stream %{name} from %{node} successfully"
msgstr "%{name} akışı %{node} üzerinden başarıyla silindi"
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr "Akışı sil: %{stream_name}"
@@ -1333,13 +1334,10 @@ msgid "Directory path to store cache files"
msgstr "Önbellek dosyalarını depolamak için dizin yolu"
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr "Devre dışı bırak"
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr "Devre Dışı Bırak"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr "%{name} için otomatik yenileme devre dışı bırakılamadı"
@@ -1400,15 +1398,16 @@ msgstr "Akış %{name}, %{node} üzerinden başarıyla devre dışı bırakıld
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114 src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127 src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr "Devre dışı"
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr "Başarıyla devre dışı bırakıldı"
@@ -1438,6 +1437,10 @@ msgstr "Bu seçeneği, ihtiyacınız olduğundan emin olmadıkça etkinleştirme
msgid "Do you want to %{action} this site?"
msgstr "Bu siteyi %{action} etmek istiyor musunuz?"
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr "Bu akışı %{action} etmek istiyor musunuz?"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr "Otomatik sertifika yenilemeyi devre dışı bırakmak istiyor musunuz?"
@@ -1516,7 +1519,7 @@ msgstr ""
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr "Kopyala"
@@ -1565,13 +1568,10 @@ msgid "Email (*)"
msgstr "E-posta(*)"
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr "etkinleştir"
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr "Etkinleştir"
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr "2FA'yı başarıyla etkinleştirildi"
@@ -1670,9 +1670,10 @@ msgstr "TOTP'yi Etkinleştir"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110 src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123 src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr "Etkin"
@@ -1680,7 +1681,7 @@ msgstr "Etkin"
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr "Başarıyla etkinleştirildi"
@@ -1917,7 +1918,7 @@ msgstr "Sertifika veritabanından silinemedi: %{error}"
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr "Devre dışı bırakılamadı %{msg}"
@@ -1927,7 +1928,7 @@ msgstr "Bakım modu devre dışı bırakılamadı: %{msg}"
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr "Etkinleştirilemedi %{msg}"
@@ -2673,7 +2674,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr "Bakım"
@@ -2702,7 +2703,7 @@ msgstr "Yapılandırmaları Yönet"
msgid "Manage Sites"
msgstr "Siteleri Yönet"
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:101
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr "Akışları Yönet"
@@ -2876,12 +2877,12 @@ msgstr "Çok Satırlı Yönergeler"
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr "İsim"
@@ -3144,7 +3145,7 @@ msgstr "Nginx.conf, streams-enabled dizinini içerir"
#: src/views/notification/Notification.vue:38
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:155
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:119
msgid "No"
msgstr "Hayır"
@@ -3166,7 +3167,7 @@ msgid "Node"
msgstr "Düğüm"
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63 src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76 src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr "Düğüm Grubu"
@@ -3281,6 +3282,7 @@ msgstr "Kapalı"
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3298,7 +3300,8 @@ msgstr "Çevrimdışı"
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr "Tamam"
@@ -3702,6 +3705,15 @@ msgstr "Sağlayıcı"
msgid "Proxy"
msgstr "Proxy"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr "Proxy Geçişi"
#: src/views/site/site_list/columns.tsx:64
#: src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr "Proxy Hedefleri"
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr "Kamu Güvenlik Numarası"
@@ -4574,7 +4586,7 @@ msgstr "Statik"
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88 src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101 src/views/stream/columns.tsx:69
msgid "Status"
msgstr "Durum"
@@ -5156,6 +5168,7 @@ msgstr "Salı"
msgid "Two-factor authentication required"
msgstr "İki faktörlü kimlik doğrulama gerekiyor"
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -5192,7 +5205,7 @@ msgstr "Başarıyla güncellendi"
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81 src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94 src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -5226,6 +5239,10 @@ msgstr "Dosyaları Yükle"
msgid "Upload Folders"
msgstr "Klasörleri Yükle"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr "Yukarı Akış"
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr "Yukarı Akış Adı"
@@ -5520,6 +5537,12 @@ msgstr "Eski kodlarınız artık çalışmayacak."
msgid "Your passkeys"
msgstr "Geçiş Anahtarlarınız"
#~ msgid "Disable"
#~ msgstr "Devre Dışı Bırak"
#~ msgid "Enable"
#~ msgstr "Etkinleştir"
#~ msgid "Last Backup Error"
#~ msgstr "Son Yedekleme Hatası"
@@ -5710,10 +5733,6 @@ msgstr "Geçiş Anahtarlarınız"
#~ "Yapılandırma %{config_name} ile %{env_name} arasında eşitleme başarısız "
#~ "oldu, yanıt: %{resp}"
#, fuzzy
#~ msgid "Target"
#~ msgstr "Hedef"
#~ msgid "Can't scan? Use text key binding"
#~ msgstr "Tarayamıyor musunuz? Metin anahtar bağlamasını kullanın"
+55 -32
View File
@@ -148,7 +148,7 @@ msgstr "Дія"
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129 src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142 src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr "Дії"
@@ -166,7 +166,7 @@ msgstr "Фактичне співвідношення робочих до нал
#: src/components/NgxConfigEditor/NgxUpstream.vue:159 src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr "Додати"
@@ -193,11 +193,11 @@ msgstr "Додати локацію"
msgid "Add Site"
msgstr "Додати сайт"
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr "Додати стрім"
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr "Успішно додано"
@@ -281,7 +281,7 @@ msgid "Are you sure you want to delete permanently?"
msgstr "Ви впевнені, що хочете видалити назавжди?"
#: src/language/curd.ts:25 src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr "Ви впевнені, що хочете видалити?"
@@ -579,6 +579,7 @@ msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr "Скасувати"
@@ -1247,7 +1248,7 @@ msgstr "Вкажіть назву та розмір зони спільної п
#: src/components/NgxConfigEditor/NgxUpstream.vue:129 src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr "Видалити"
@@ -1295,7 +1296,7 @@ msgstr "Не вдалося видалити потік %{name} з %{node}"
msgid "Delete stream %{name} from %{node} successfully"
msgstr "Потік %{name} успішно видалено з %{node}"
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr "Видалити потік: %{stream_name}"
@@ -1405,13 +1406,10 @@ msgid "Directory path to store cache files"
msgstr "Шлях до каталогу для зберігання файлів кешу"
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr "Вимкнути"
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr "Вимкнути"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr "Не вдалося вимкнути автоматичне поновлення для %{name}"
@@ -1472,15 +1470,16 @@ msgstr "Потік %{name} успішно вимкнено з %{node}"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114 src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127 src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr "Вимкнено"
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr "Успішно вимкнено"
@@ -1510,6 +1509,10 @@ msgstr "Не вмикайте цю опцію, якщо ви не впевнен
msgid "Do you want to %{action} this site?"
msgstr "Ви хочете %{action} цей сайт?"
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr "Ви хочете %{action} цей потік?"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr "Ви хочете вимкнути автоматичне оновлення сертифіката?"
@@ -1586,7 +1589,7 @@ msgstr ""
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr "Дублювати"
@@ -1635,13 +1638,10 @@ msgid "Email (*)"
msgstr "Електронна пошта (*)"
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr "увімкнути"
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr "Увімкнути"
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr "2FA успішно ввімкнено"
@@ -1740,9 +1740,10 @@ msgstr "Увімкнути TOTP"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110 src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123 src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr "Увімкнено"
@@ -1750,7 +1751,7 @@ msgstr "Увімкнено"
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr "Успішно ввімкнено"
@@ -1987,7 +1988,7 @@ msgstr "Не вдалося видалити сертифікат з бази д
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr "Не вдалося вимкнути %{msg}"
@@ -1997,7 +1998,7 @@ msgstr "Не вдалося вимкнути режим обслуговуван
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr "Не вдалося увімкнути %{msg}"
@@ -2740,7 +2741,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr "Технічне обслуговування"
@@ -2769,7 +2770,7 @@ msgstr "Керування конфігураціями"
msgid "Manage Sites"
msgstr "Керування сайтами"
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:101
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr "Керування потоками"
@@ -2943,12 +2944,12 @@ msgstr "Багаторядкова директива"
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr "Ім'я"
@@ -3211,7 +3212,7 @@ msgstr "Nginx.conf включає каталог streams-enabled"
#: src/views/notification/Notification.vue:38
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:155
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:119
msgid "No"
msgstr "Ні"
@@ -3233,7 +3234,7 @@ msgid "Node"
msgstr "Вузол"
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63 src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76 src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr "Група вузлів"
@@ -3348,6 +3349,7 @@ msgstr "Вимкнено"
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3365,7 +3367,8 @@ msgstr "Офлайн"
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr "Гаразд"
@@ -3770,6 +3773,15 @@ msgstr "Провайдер"
msgid "Proxy"
msgstr "Проксі"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr "Проксі-передача"
#: src/views/site/site_list/columns.tsx:64
#: src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr "Цілі проксі"
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr "Номер громадської безпеки"
@@ -4642,7 +4654,7 @@ msgstr "Статичний"
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88 src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101 src/views/stream/columns.tsx:69
msgid "Status"
msgstr "Статус"
@@ -5222,6 +5234,7 @@ msgstr "Вівторок"
msgid "Two-factor authentication required"
msgstr "Потрібна двофакторна аутентифікація"
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -5258,7 +5271,7 @@ msgstr "Успішно оновлено"
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81 src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94 src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -5292,6 +5305,10 @@ msgstr "Завантажити файли"
msgid "Upload Folders"
msgstr "Завантажити папки"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr "Вгору за течією"
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr "Назва апстріму"
@@ -5583,6 +5600,12 @@ msgstr "Ваші старі коди більше не працюватимут
msgid "Your passkeys"
msgstr "Ваші ключі доступу"
#~ msgid "Disable"
#~ msgstr "Вимкнути"
#~ msgid "Enable"
#~ msgstr "Увімкнути"
#~ msgid "Last Backup Error"
#~ msgstr "Помилка останнього резервного копіювання"
+55 -35
View File
@@ -139,7 +139,7 @@ msgstr "Hành động"
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129 src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142 src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr "Hành động"
@@ -157,7 +157,7 @@ msgstr "Tỷ lệ công nhân thực tế so với cấu hình"
#: src/components/NgxConfigEditor/NgxUpstream.vue:159 src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr "Thêm"
@@ -184,11 +184,11 @@ msgstr "Thêm Location"
msgid "Add Site"
msgstr "Thêm Website"
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr "Thêm luồng"
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr "Đã thêm thành công"
@@ -272,7 +272,7 @@ msgid "Are you sure you want to delete permanently?"
msgstr "Bạn có chắc chắn muốn xóa vĩnh viễn không?"
#: src/language/curd.ts:25 src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr "Bạn có chắc chắn muốn xóa không?"
@@ -563,6 +563,7 @@ msgstr ""
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr "Huỷ"
@@ -1191,7 +1192,7 @@ msgstr "Xác định tên và kích thước vùng bộ nhớ dùng chung, ví d
#: src/components/NgxConfigEditor/NgxUpstream.vue:129 src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr "Xoá"
@@ -1239,7 +1240,7 @@ msgstr "Xóa luồng %{name} từ %{node} thất bại"
msgid "Delete stream %{name} from %{node} successfully"
msgstr "Đã xóa luồng %{name} từ %{node} thành công"
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr "Xóa luồng: %{stream_name}"
@@ -1313,13 +1314,10 @@ msgid "Directory path to store cache files"
msgstr "Đường dẫn thư mục để lưu trữ các tệp bộ nhớ đệm"
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr "Vô hiệu hóa"
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr "Vô hiệu hóa"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr "Vô hiệu hóa gia hạn tự động thất bại cho %{name}"
@@ -1380,15 +1378,16 @@ msgstr "Đã vô hiệu hóa luồng %{name} từ %{node} thành công"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114 src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127 src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr "Đã tắt"
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr "Đã tắt thành công"
@@ -1418,6 +1417,10 @@ msgstr "Không bật tùy chọn này trừ khi bạn chắc chắn cần đến
msgid "Do you want to %{action} this site?"
msgstr "Bạn có muốn %{action} trang web này không?"
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr "Bạn có muốn %{action} luồng này không?"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr "Bạn muốn tắt tự động gia hạn chứng chỉ SSL ?"
@@ -1495,7 +1498,7 @@ msgstr ""
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr "Nhân bản"
@@ -1544,13 +1547,10 @@ msgid "Email (*)"
msgstr "Email (*)"
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr "bật"
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr "Bật"
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr "Bật 2FA thành công"
@@ -1649,9 +1649,10 @@ msgstr "Bật TOTP"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110 src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123 src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr "Đã bật"
@@ -1659,7 +1660,7 @@ msgstr "Đã bật"
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr "Đã bật"
@@ -1896,7 +1897,7 @@ msgstr "Xóa chứng chỉ từ cơ sở dữ liệu thất bại: %{error}"
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr "Không thể tắt %{msg}"
@@ -1906,7 +1907,7 @@ msgstr "Không thể tắt chế độ bảo trì %{msg}"
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr "Không thể bật %{msg}"
@@ -2648,7 +2649,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr "Bảo trì"
@@ -2677,7 +2678,7 @@ msgstr "Quản lý cấu hình"
msgid "Manage Sites"
msgstr "Quản lý Website"
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:101
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr "Quản lý luồng"
@@ -2851,12 +2852,12 @@ msgstr "Chỉ thị nhiều dòng"
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr "Tên"
@@ -3119,7 +3120,7 @@ msgstr "Nginx.conf bao gồm thư mục streams-enabled"
#: src/views/notification/Notification.vue:38
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:155
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:119
msgid "No"
msgstr "Không"
@@ -3141,7 +3142,7 @@ msgid "Node"
msgstr "Nút"
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63 src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76 src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr "Nhóm nút"
@@ -3254,6 +3255,7 @@ msgstr "Tắt"
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3271,7 +3273,8 @@ msgstr "Ngoại tuyến"
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr "Đồng ý"
@@ -3667,6 +3670,15 @@ msgstr "Nhà cung cấp"
msgid "Proxy"
msgstr "Proxy"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr "Chuyển tiếp Proxy"
#: src/views/site/site_list/columns.tsx:64
#: src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr "Mục tiêu proxy"
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr "Số An ninh Công cộng"
@@ -4530,7 +4542,7 @@ msgstr "Tĩnh"
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88 src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101 src/views/stream/columns.tsx:69
msgid "Status"
msgstr "Trạng thái"
@@ -5110,6 +5122,7 @@ msgstr "Thứ Ba"
msgid "Two-factor authentication required"
msgstr "Yêu cầu xác thực hai yếu tố"
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -5146,7 +5159,7 @@ msgstr "Cập nhật thành công"
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81 src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94 src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -5180,6 +5193,10 @@ msgstr "Tải lên tệp"
msgid "Upload Folders"
msgstr "Tải lên thư mục"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr "Ngược dòng"
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr "Tên Upstream"
@@ -5469,6 +5486,12 @@ msgstr "Mã cũ của bạn sẽ không còn hoạt động nữa."
msgid "Your passkeys"
msgstr "Khóa truy cập của bạn"
#~ msgid "Disable"
#~ msgstr "Vô hiệu hóa"
#~ msgid "Enable"
#~ msgstr "Bật"
#~ msgid "Last Backup Error"
#~ msgstr "Lỗi sao lưu cuối cùng"
@@ -5642,9 +5665,6 @@ msgstr "Khóa truy cập của bạn"
#~ msgid "Sync config %{config_name} to %{env_name} failed, response: %{resp}"
#~ msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
#~ msgid "Target"
#~ msgstr "Mục tiêu"
#~ msgid "File"
#~ msgstr "Tệp tin"
+55 -35
View File
@@ -143,7 +143,7 @@ msgstr "操作"
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129 src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142 src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr "操作"
@@ -161,7 +161,7 @@ msgstr "实际工作进程与配置比例"
#: src/components/NgxConfigEditor/NgxUpstream.vue:159 src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr "添加"
@@ -188,11 +188,11 @@ msgstr "添加 Location"
msgid "Add Site"
msgstr "添加站点"
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr "添加 Stream"
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr "添加成功"
@@ -276,7 +276,7 @@ msgid "Are you sure you want to delete permanently?"
msgstr "确定要永久删除吗?"
#: src/language/curd.ts:25 src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr "您确定要删除吗?"
@@ -565,6 +565,7 @@ msgstr "基于 worker_processes * worker_connections 计算得出。实际性能
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr "取消"
@@ -1173,7 +1174,7 @@ msgstr "定义共享内存区名称和大小,例如 proxy_cache:10m"
#: src/components/NgxConfigEditor/NgxUpstream.vue:129 src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr "删除"
@@ -1221,7 +1222,7 @@ msgstr "从 %{node} 删除 Stream %{name} 失败"
msgid "Delete stream %{name} from %{node} successfully"
msgstr "已成功从 %{node} 删除 Stream %{name}"
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr "删除 Stream: %{stream_name}"
@@ -1295,13 +1296,10 @@ msgid "Directory path to store cache files"
msgstr "存储缓存文件的目录路径"
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr "禁用"
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr "禁用"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr "禁用 %{name} 的自动续期失败"
@@ -1362,15 +1360,16 @@ msgstr "在 %{node} 上禁用 %{name} 成功"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114 src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127 src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr "禁用"
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr "禁用成功"
@@ -1400,6 +1399,10 @@ msgstr "除非确定需要,否则不要启用该选项。"
msgid "Do you want to %{action} this site?"
msgstr "您想将这个网站%{action}吗?"
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr "您要%{action}此流吗?"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr "你想禁用自动更新证书吗?"
@@ -1473,7 +1476,7 @@ msgstr "由于某些浏览器的安全策略,除非在 localhost 上使用,
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr "复制"
@@ -1522,13 +1525,10 @@ msgid "Email (*)"
msgstr "邮箱 (*)"
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr "启用"
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr "启用"
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr "二步验证启用成功"
@@ -1627,9 +1627,10 @@ msgstr "启用 TOTP"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110 src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123 src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr "启用"
@@ -1637,7 +1638,7 @@ msgstr "启用"
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr "启用成功"
@@ -1874,7 +1875,7 @@ msgstr "从数据库中删除证书失败:%{error}"
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr "禁用失败 %{msg}"
@@ -1884,7 +1885,7 @@ msgstr "停用维护模式失败 %{msg}"
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr "启用失败 %{msg}"
@@ -2609,7 +2610,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr "维护模式"
@@ -2636,7 +2637,7 @@ msgstr "配置管理"
msgid "Manage Sites"
msgstr "网站管理"
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:101
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr "管理 Stream"
@@ -2810,12 +2811,12 @@ msgstr "多行指令"
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr "名称"
@@ -3076,7 +3077,7 @@ msgstr "检查 nginx.conf 是否包含 streams-enabled 的目录"
#: src/views/notification/Notification.vue:38
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:155
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:119
msgid "No"
msgstr "取消"
@@ -3098,7 +3099,7 @@ msgid "Node"
msgstr "节点"
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63 src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76 src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr "节点组"
@@ -3207,6 +3208,7 @@ msgstr "关闭"
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3224,7 +3226,8 @@ msgstr "离线"
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr "确定"
@@ -3608,6 +3611,15 @@ msgstr "提供商"
msgid "Proxy"
msgstr "代理"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr "代理传递"
#: src/views/site/site_list/columns.tsx:64
#: src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr "代理目标"
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr "公安备案号"
@@ -4460,7 +4472,7 @@ msgstr "静态"
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88 src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101 src/views/stream/columns.tsx:69
msgid "Status"
msgstr "状态"
@@ -4989,6 +5001,7 @@ msgstr "星期二"
msgid "Two-factor authentication required"
msgstr "需要两步验证"
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -5025,7 +5038,7 @@ msgstr "更新成功"
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81 src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94 src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -5059,6 +5072,10 @@ msgstr "上传文件"
msgid "Upload Folders"
msgstr "上传文件夹"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr "上游"
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr "Upstream 名称"
@@ -5329,6 +5346,12 @@ msgstr "您的旧代码将不再有效。"
msgid "Your passkeys"
msgstr "你的 Passkeys"
#~ msgid "Disable"
#~ msgstr "禁用"
#~ msgid "Enable"
#~ msgstr "启用"
#~ msgid "Last Backup Error"
#~ msgstr "最后一次备份错误"
@@ -5546,9 +5569,6 @@ msgstr "你的 Passkeys"
#~ msgid "Sync config %{config_name} to %{env_name} failed, response: %{resp}"
#~ msgstr "同步配置 %{config_name} 到 %{env_name} 失败,响应:%{resp}"
#~ msgid "Target"
#~ msgstr "目标"
#~ msgid ""
#~ "If you lose your mobile phone, you can use the recovery code to reset your "
#~ "2FA."
+55 -35
View File
@@ -147,7 +147,7 @@ msgstr "操作"
#: src/views/nginx_log/NginxLogList.vue:52
#: src/views/notification/notificationColumns.tsx:72
#: src/views/preference/components/ExternalNotify/columns.tsx:76
#: src/views/site/site_list/columns.tsx:129 src/views/stream/columns.tsx:64
#: src/views/site/site_list/columns.tsx:142 src/views/stream/columns.tsx:105
#: src/views/user/userColumns.tsx:58
msgid "Actions"
msgstr "操作"
@@ -165,7 +165,7 @@ msgstr "實際工作進程與配置比例"
#: src/components/NgxConfigEditor/NgxUpstream.vue:159 src/language/curd.ts:19
#: src/views/preference/tabs/CertSettings.vue:45
#: src/views/site/site_edit/components/ConfigTemplate/ConfigTemplate.vue:94
#: src/views/stream/StreamList.vue:121
#: src/views/stream/StreamList.vue:101
msgid "Add"
msgstr "新增"
@@ -192,11 +192,11 @@ msgstr "新增 Location"
msgid "Add Site"
msgstr "新增網站"
#: src/views/stream/StreamList.vue:174
#: src/views/stream/StreamList.vue:138
msgid "Add Stream"
msgstr "新增 Stream"
#: src/views/stream/StreamList.vue:92
#: src/views/stream/StreamList.vue:72
msgid "Added successfully"
msgstr "新增成功"
@@ -280,7 +280,7 @@ msgid "Are you sure you want to delete permanently?"
msgstr "確定要永久刪除嗎?"
#: src/language/curd.ts:25 src/views/site/site_list/SiteList.vue:100
#: src/views/stream/StreamList.vue:157
#: src/views/stream/StreamList.vue:121
msgid "Are you sure you want to delete?"
msgstr "您確定要刪除嗎?"
@@ -569,6 +569,7 @@ msgstr "基於 worker_processes * worker_connections 計算得出。實際效能
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:143
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:21
#: src/views/stream/components/RightPanel/Basic.vue:47
#: src/views/stream/components/StreamStatusSelect.vue:65
msgid "Cancel"
msgstr "取消"
@@ -1177,7 +1178,7 @@ msgstr "定義共享記憶體區域名稱和大小,例如 proxy_cache:10m"
#: src/components/NgxConfigEditor/NgxUpstream.vue:129 src/language/curd.ts:9
#: src/views/certificate/components/RemoveCert.vue:88
#: src/views/site/site_list/SiteList.vue:109
#: src/views/stream/StreamList.vue:166
#: src/views/stream/StreamList.vue:130
msgid "Delete"
msgstr "刪除"
@@ -1225,7 +1226,7 @@ msgstr "從 %{node} 刪除串流 %{name} 失敗"
msgid "Delete stream %{name} from %{node} successfully"
msgstr "已成功從 %{node} 刪除串流 %{name}"
#: src/views/stream/StreamList.vue:67
#: src/views/stream/StreamList.vue:47
msgid "Delete stream: %{stream_name}"
msgstr "刪除 Stream%{stream_name}"
@@ -1299,13 +1300,10 @@ msgid "Directory path to store cache files"
msgstr "儲存快取檔案的目錄路徑"
#: src/views/site/components/SiteStatusSelect.vue:115
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "disable"
msgstr "禁用"
#: src/views/stream/StreamList.vue:137
msgid "Disable"
msgstr "停用"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:80
msgid "Disable auto-renewal failed for %{name}"
msgstr "停用 %{name} 的自動續期失敗"
@@ -1366,15 +1364,16 @@ msgstr "已成功從 %{node} 停用串流 %{name}"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:162
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:62
#: src/views/site/site_list/columns.tsx:114 src/views/stream/columns.tsx:48
#: src/views/site/site_list/columns.tsx:127 src/views/stream/columns.tsx:94
#: src/views/stream/components/StreamEditor.vue:30
#: src/views/stream/components/StreamStatusSelect.vue:89
#: src/views/user/userColumns.tsx:39
msgid "Disabled"
msgstr "停用"
#: src/views/site/components/SiteStatusSelect.vue:67
#: src/views/stream/components/RightPanel/Basic.vue:34
#: src/views/stream/StreamList.vue:56
#: src/views/stream/components/StreamStatusSelect.vue:39
msgid "Disabled successfully"
msgstr "成功停用"
@@ -1404,6 +1403,10 @@ msgstr "除非您確定需要,否則不要啟用此選項。"
msgid "Do you want to %{action} this site?"
msgstr "您想要%{action}這個網站嗎?"
#: src/views/stream/components/StreamStatusSelect.vue:61
msgid "Do you want to %{action} this stream?"
msgstr "您要%{action}此串流嗎?"
#: src/views/site/site_edit/components/Cert/ObtainCert.vue:139
msgid "Do you want to disable auto-cert renewal?"
msgstr "您要停用自動憑證續訂嗎?"
@@ -1477,7 +1480,7 @@ msgstr "基於部分瀏覽器的安全政策,您無法在未啟用 HTTPS 網
#: src/views/site/site_list/SiteDuplicate.vue:72
#: src/views/site/site_list/SiteList.vue:95
#: src/views/stream/components/StreamDuplicate.vue:64
#: src/views/stream/StreamList.vue:152
#: src/views/stream/StreamList.vue:116
msgid "Duplicate"
msgstr "複製"
@@ -1526,13 +1529,10 @@ msgid "Email (*)"
msgstr "電子郵件 (*)"
#: src/views/site/components/SiteStatusSelect.vue:114
#: src/views/stream/components/StreamStatusSelect.vue:58
msgid "enable"
msgstr "啟用"
#: src/views/stream/StreamList.vue:145
msgid "Enable"
msgstr "啟用"
#: src/views/preference/components/AuthSettings/TOTP.vue:45
msgid "Enable 2FA successfully"
msgstr "啟用多因素身份驗證成功"
@@ -1631,9 +1631,10 @@ msgstr "啟用 TOTP"
#: src/views/preference/tabs/NodeSettings.vue:30
#: src/views/site/components/SiteStatusSelect.vue:159
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:56
#: src/views/site/site_list/columns.tsx:110 src/views/stream/columns.tsx:44
#: src/views/site/site_list/columns.tsx:123 src/views/stream/columns.tsx:90
#: src/views/stream/components/RightPanel/Basic.vue:62
#: src/views/stream/components/StreamEditor.vue:24
#: src/views/stream/components/StreamStatusSelect.vue:88
#: src/views/user/userColumns.tsx:36
msgid "Enabled"
msgstr "已啟用"
@@ -1641,7 +1642,7 @@ msgstr "已啟用"
#: src/views/site/components/SiteStatusSelect.vue:54
#: src/views/site/site_add/SiteAdd.vue:32
#: src/views/stream/components/RightPanel/Basic.vue:25
#: src/views/stream/StreamList.vue:46
#: src/views/stream/components/StreamStatusSelect.vue:26
msgid "Enabled successfully"
msgstr "成功啟用"
@@ -1878,7 +1879,7 @@ msgstr "從資料庫刪除憑證失敗: %{error}"
#: src/views/site/components/SiteStatusSelect.vue:73
#: src/views/stream/components/RightPanel/Basic.vue:37
#: src/views/stream/StreamList.vue:60
#: src/views/stream/components/StreamStatusSelect.vue:45
msgid "Failed to disable %{msg}"
msgstr "停用 %{msg} 失敗"
@@ -1888,7 +1889,7 @@ msgstr "無法停用維護模式 %{msg}"
#: src/views/site/components/SiteStatusSelect.vue:60
#: src/views/stream/components/RightPanel/Basic.vue:28
#: src/views/stream/StreamList.vue:50
#: src/views/stream/components/StreamStatusSelect.vue:32
msgid "Failed to enable %{msg}"
msgstr "啟用 %{msg} 失敗"
@@ -2613,7 +2614,7 @@ msgstr ""
#: src/views/site/components/SiteStatusSelect.vue:165
#: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:68
#: src/views/site/site_list/columns.tsx:118
#: src/views/site/site_list/columns.tsx:131
msgid "Maintenance"
msgstr "維護"
@@ -2640,7 +2641,7 @@ msgstr "管理設定"
msgid "Manage Sites"
msgstr "管理網站"
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:101
#: src/routes/modules/streams.ts:10 src/views/stream/StreamList.vue:81
msgid "Manage Streams"
msgstr "管理 Stream"
@@ -2814,12 +2815,12 @@ msgstr "多行指令"
#: src/views/nginx_log/NginxLogList.vue:36
#: src/views/preference/components/AuthSettings/AddPasskey.vue:75
#: src/views/site/site_edit/components/RightPanel/Basic.vue:35
#: src/views/site/site_list/columns.tsx:15
#: src/views/site/site_list/columns.tsx:16
#: src/views/site/site_list/SiteDuplicate.vue:79
#: src/views/stream/columns.tsx:10
#: src/views/stream/columns.tsx:12
#: src/views/stream/components/RightPanel/Basic.vue:69
#: src/views/stream/components/StreamDuplicate.vue:71
#: src/views/stream/StreamList.vue:179
#: src/views/stream/StreamList.vue:143
msgid "Name"
msgstr "名稱"
@@ -3080,7 +3081,7 @@ msgstr "Nginx.conf 包含 streams-enabled 目錄"
#: src/views/notification/Notification.vue:38
#: src/views/preference/tabs/AuthSettings.vue:132
#: src/views/preference/tabs/CertSettings.vue:73
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:155
#: src/views/site/site_list/SiteList.vue:98 src/views/stream/StreamList.vue:119
msgid "No"
msgstr "取消"
@@ -3102,7 +3103,7 @@ msgid "Node"
msgstr "節點"
#: src/views/site/site_edit/components/RightPanel/Basic.vue:41
#: src/views/site/site_list/columns.tsx:63 src/views/stream/columns.tsx:20
#: src/views/site/site_list/columns.tsx:76 src/views/stream/columns.tsx:44
#: src/views/stream/components/RightPanel/Basic.vue:77
msgid "Node Group"
msgstr "節點群組"
@@ -3211,6 +3212,7 @@ msgstr "關"
#: src/components/EnvGroupTabs/EnvGroupTabs.vue:159
#: src/components/NgxConfigEditor/NgxUpstream.vue:145
#: src/components/NodeSelector/NodeSelector.vue:109
#: src/components/ProxyTargets/ProxyTargets.vue:43
#: src/views/dashboard/Environments.vue:107
#: src/views/environments/list/envColumns.tsx:55
msgid "Offline"
@@ -3228,7 +3230,8 @@ msgstr "離線"
#: src/views/site/site_edit/components/EnableTLS/EnableTLS.vue:20
#: src/views/site/site_list/SiteList.vue:99
#: src/views/stream/components/RightPanel/Basic.vue:46
#: src/views/stream/StreamList.vue:156
#: src/views/stream/components/StreamStatusSelect.vue:64
#: src/views/stream/StreamList.vue:120
msgid "OK"
msgstr "確定"
@@ -3614,6 +3617,15 @@ msgstr "供應商"
msgid "Proxy"
msgstr "代理伺服器"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Proxy Pass"
msgstr "代理傳遞"
#: src/views/site/site_list/columns.tsx:64
#: src/views/stream/columns.tsx:32
msgid "Proxy Targets"
msgstr "代理目標"
#: src/views/preference/tabs/NodeSettings.vue:46
msgid "Public Security Number"
msgstr "公安編號"
@@ -4466,7 +4478,7 @@ msgstr "靜態"
#: src/views/dashboard/components/ModulesTable.vue:96
#: src/views/environments/list/envColumns.tsx:43
#: src/views/site/site_edit/components/RightPanel/Basic.vue:28
#: src/views/site/site_list/columns.tsx:88 src/views/stream/columns.tsx:37
#: src/views/site/site_list/columns.tsx:101 src/views/stream/columns.tsx:69
msgid "Status"
msgstr "狀態"
@@ -4995,6 +5007,7 @@ msgstr "星期二"
msgid "Two-factor authentication required"
msgstr "需要多重因素驗證"
#: src/components/ProxyTargets/ProxyTargets.vue:48
#: src/views/certificate/CertificateList/certColumns.tsx:24
#: src/views/dashboard/components/ModulesTable.vue:83
#: src/views/nginx_log/NginxLogList.vue:12
@@ -5031,7 +5044,7 @@ msgstr "更新成功"
#: src/views/environments/group/columns.ts:35
#: src/views/environments/list/envColumns.tsx:89
#: src/views/site/site_edit/components/RightPanel/Basic.vue:38
#: src/views/site/site_list/columns.tsx:81 src/views/stream/columns.tsx:57
#: src/views/site/site_list/columns.tsx:94 src/views/stream/columns.tsx:62
#: src/views/stream/components/RightPanel/Basic.vue:73
#: src/views/user/userColumns.tsx:52
msgid "Updated at"
@@ -5065,6 +5078,10 @@ msgstr "上傳檔案"
msgid "Upload Folders"
msgstr "上傳資料夾"
#: src/components/ProxyTargets/ProxyTargets.vue:48
msgid "Upstream"
msgstr "上游"
#: src/components/NgxConfigEditor/NgxUpstream.vue:177
msgid "Upstream Name"
msgstr "Upstream 名稱"
@@ -5335,6 +5352,12 @@ msgstr "您的舊代碼將不再有效。"
msgid "Your passkeys"
msgstr "您的通行金鑰"
#~ msgid "Disable"
#~ msgstr "停用"
#~ msgid "Enable"
#~ msgstr "啟用"
#~ msgid "Last Backup Error"
#~ msgstr "最後一次備份錯誤"
@@ -5524,9 +5547,6 @@ msgstr "您的通行金鑰"
#~ msgid "Sync config %{config_name} to %{env_name} failed, response: %{resp}"
#~ msgstr "同步設定 %{config_name} 到 %{env_name} 失敗,回應:%{resp}"
#~ msgid "Target"
#~ msgstr "目標"
#~ msgid ""
#~ "If you lose your mobile phone, you can use the recovery code to reset your "
#~ "2FA."
+2
View File
@@ -1,9 +1,11 @@
import { useGlobalStore } from './moudule/global'
import { useProxyAvailabilityStore } from './moudule/proxyAvailability'
import { useSettingsStore } from './moudule/settings'
import { useUserStore } from './moudule/user'
export {
useGlobalStore,
useProxyAvailabilityStore,
useSettingsStore,
useUserStore,
}
+142
View File
@@ -0,0 +1,142 @@
import type ReconnectingWebSocket from 'reconnecting-websocket'
import type { ProxyTarget } from '@/api/site'
import { debounce } from 'lodash'
import { defineStore } from 'pinia'
import upstream from '@/api/upstream'
export interface ProxyAvailabilityResult {
online: boolean
latency: number
}
export const useProxyAvailabilityStore = defineStore('proxyAvailability', () => {
const availabilityResults = ref<Record<string, ProxyAvailabilityResult>>({})
const websocket = shallowRef<ReconnectingWebSocket | WebSocket>()
const isConnected = ref(false)
// Map to store targets for each component instance
const componentTargets = ref<Map<string, string[]>>(new Map())
// Computed property to get unique targets from all components
const allTargets = computed(() => {
const allTargetsList: string[] = []
componentTargets.value.forEach(targets => {
allTargetsList.push(...targets)
})
return [...new Set(allTargetsList)]
})
function getTargetKey(target: ProxyTarget): string {
return `${target.host}:${target.port}`
}
// Debounced function to update targets on server
const debouncedUpdateTargets = debounce(() => {
if (websocket.value && isConnected.value) {
websocket.value.send(JSON.stringify(allTargets.value))
}
}, 300)
function ensureWebSocketConnection() {
if (websocket.value && isConnected.value) {
return
}
// Close existing connection if any
if (websocket.value) {
websocket.value.close()
}
// Create new WebSocket connection
websocket.value = upstream.availability_test()
websocket.value.onopen = () => {
isConnected.value = true
// Send current targets immediately after connection
debouncedUpdateTargets()
}
websocket.value.onmessage = (e: MessageEvent) => {
const results = JSON.parse(e.data) as Record<string, ProxyAvailabilityResult>
// Update availability results
Object.assign(availabilityResults.value, results)
}
websocket.value.onclose = () => {
isConnected.value = false
}
websocket.value.onerror = error => {
console.error('WebSocket error:', error)
isConnected.value = false
}
}
function registerComponent(targets: ProxyTarget[]): string {
const componentId = useId()
const targetKeys = targets.map(getTargetKey)
componentTargets.value.set(componentId, targetKeys)
// Ensure WebSocket connection exists
ensureWebSocketConnection()
// Update targets on server (debounced)
debouncedUpdateTargets()
return componentId
}
function updateComponentTargets(componentId: string, targets: ProxyTarget[]) {
const targetKeys = targets.map(getTargetKey)
componentTargets.value.set(componentId, targetKeys)
// Update targets on server (debounced)
debouncedUpdateTargets()
}
function unregisterComponent(componentId: string) {
componentTargets.value.delete(componentId)
// Update targets on server (debounced)
debouncedUpdateTargets()
// Close WebSocket if no components are registered
if (componentTargets.value.size === 0) {
// Cancel pending debounced calls
debouncedUpdateTargets.cancel()
if (websocket.value) {
websocket.value.close()
websocket.value = undefined
isConnected.value = false
}
}
}
function getAvailabilityResult(target: ProxyTarget): ProxyAvailabilityResult | undefined {
const key = getTargetKey(target)
return availabilityResults.value[key]
}
function isTargetTesting(target: ProxyTarget): boolean {
const key = getTargetKey(target)
return allTargets.value.includes(key)
}
// Watch for changes in allTargets and update server (debounced)
watch(allTargets, () => {
debouncedUpdateTargets()
})
return {
availabilityResults: readonly(availabilityResults),
isConnected: readonly(isConnected),
registerComponent,
updateComponentTargets,
unregisterComponent,
getAvailabilityResult,
isTargetTesting,
getTargetKey,
}
})
+15 -2
View File
@@ -7,6 +7,7 @@ import type { JSXElements } from '@/types'
import { actualFieldRender, datetimeRender } from '@uozi-admin/curd'
import { Tag } from 'ant-design-vue'
import env_group from '@/api/env_group'
import ProxyTargets from '@/components/ProxyTargets'
import { ConfigStatus } from '@/constants'
import envGroupColumns from '@/views/environments/group/columns'
import SiteStatusSelect from '@/views/site/components/SiteStatusSelect.vue'
@@ -53,12 +54,24 @@ const columns: StdTableColumn[] = [{
}
template.push(
<div style="display: flex; flex-wrap: wrap;">{urlsContainer}</div>,
<div style="display: flex; flex-wrap: wrap; margin-bottom: 4px;">{urlsContainer}</div>,
)
}
return h('div', {}, template)
},
}, {
title: () => $gettext('Proxy Targets'),
dataIndex: 'proxy_targets',
width: 200,
customRender: ({ record }: CustomRenderArgs) => {
if (record.proxy_targets && record.proxy_targets.length > 0) {
return h(ProxyTargets, {
targets: record.proxy_targets,
})
}
return h('span', '-')
},
}, {
title: () => $gettext('Node Group'),
dataIndex: 'env_group_id',
@@ -123,7 +136,7 @@ const columns: StdTableColumn[] = [{
},
sorter: true,
pure: true,
width: 50,
width: 100,
fixed: 'right',
}, {
title: () => $gettext('Actions'),
-36
View File
@@ -41,26 +41,6 @@ watch(route, () => {
inspect_config.value?.test()
})
function enable(name: string) {
stream.enable(name).then(() => {
message.success($gettext('Enabled successfully'))
curd.value?.refresh()
inspect_config.value?.test()
}).catch(r => {
message.error($gettext('Failed to enable %{msg}', { msg: r.message ?? '' }), 10)
})
}
function disable(name: string) {
stream.disable(name).then(() => {
message.success($gettext('Disabled successfully'))
curd.value?.refresh()
inspect_config.value?.test()
}).catch(r => {
message.error($gettext('Failed to disable %{msg}', { msg: r.message ?? '' }))
})
}
function destroy(stream_name: string) {
stream.deleteItem(stream_name).then(() => {
curd.value.refresh()
@@ -128,22 +108,6 @@ function handleAddStream() {
</template>
<template #afterActions="{ record }">
<AButton
v-if="record.enabled"
type="link"
size="small"
@click="disable(record.name)"
>
{{ $gettext('Disable') }}
</AButton>
<AButton
v-else
type="link"
size="small"
@click="enable(record.name)"
>
{{ $gettext('Enable') }}
</AButton>
<AButton
type="link"
size="small"
+66 -25
View File
@@ -1,10 +1,12 @@
import type { CustomRenderArgs, StdTableColumn } from '@uozi-admin/curd'
import type { SiteStatus } from '@/api/site'
import type { Stream } from '@/api/stream'
import type { JSXElements } from '@/types'
import { actualFieldRender, datetimeRender } from '@uozi-admin/curd'
import { Badge } from 'ant-design-vue'
import env_group from '@/api/env_group'
import { ConfigStatus } from '@/constants'
import ProxyTargets from '@/components/ProxyTargets'
import envGroupColumns from '@/views/environments/group/columns'
import StreamStatusSelect from '@/views/stream/components/StreamStatusSelect.vue'
const columns: StdTableColumn[] = [{
title: () => $gettext('Name'),
@@ -16,6 +18,28 @@ const columns: StdTableColumn[] = [{
},
search: true,
width: 150,
customRender: ({ text }: CustomRenderArgs<Stream>) => {
const template: JSXElements = []
// Add stream name
template.push(
<div style="margin-bottom: 8px;">{text}</div>,
)
return h('div', {}, template)
},
}, {
title: () => $gettext('Proxy Targets'),
dataIndex: 'proxy_targets',
width: 200,
customRender: ({ record }: CustomRenderArgs<Stream>) => {
if (record.proxy_targets && record.proxy_targets.length > 0) {
return h(ProxyTargets, {
targets: record.proxy_targets,
})
}
return h('span', '-')
},
}, {
title: () => $gettext('Node Group'),
dataIndex: 'env_group_id',
@@ -30,40 +54,57 @@ const columns: StdTableColumn[] = [{
selectionType: 'radio',
},
},
batchEdit: true,
sorter: true,
pure: true,
width: 150,
}, {
title: () => $gettext('Status'),
dataIndex: 'status',
customRender: (args: CustomRenderArgs) => {
const template: JSXElements = []
const { text } = args
if (text === ConfigStatus.Enabled) {
template.push(<Badge status="success" />)
template.push(h('span', $gettext('Enabled')))
}
else if (text === ConfigStatus.Disabled) {
template.push(<Badge status="warning" />)
template.push(h('span', $gettext('Disabled')))
}
return h('div', template)
},
sorter: true,
pure: true,
width: 200,
width: 100,
}, {
title: () => $gettext('Updated at'),
dataIndex: 'modified_at',
customRender: datetimeRender,
sorter: true,
pure: true,
width: 200,
width: 150,
}, {
title: () => $gettext('Status'),
dataIndex: 'status',
customRender: (args: CustomRenderArgs<Stream>) => {
const { record } = args
return h(StreamStatusSelect, {
'status': record.status,
'streamName': record.name,
'onStatusChanged': ({ status }: { status: SiteStatus }) => {
record.status = status
},
'onUpdate:status': (val?: SiteStatus) => {
// This will be handled by the component internal events
record.status = val!
},
})
},
search: {
type: 'select',
select: {
options: [
{
label: $gettext('Enabled'),
value: 'enabled',
},
{
label: $gettext('Disabled'),
value: 'disabled',
},
],
},
},
sorter: true,
pure: true,
width: 100,
fixed: 'right',
}, {
title: () => $gettext('Actions'),
dataIndex: 'actions',
width: 250,
width: 80,
fixed: 'right',
}]
@@ -1,5 +1,5 @@
<script setup lang="ts">
import type { CheckedType } from '@/types'
import type { SiteStatus } from '@/api/site'
import { InfoCircleOutlined } from '@ant-design/icons-vue'
import { StdSelector } from '@uozi-admin/curd'
import { message, Modal } from 'ant-design-vue'
@@ -7,15 +7,17 @@ import { storeToRefs } from 'pinia'
import envGroup from '@/api/env_group'
import stream from '@/api/stream'
import NodeSelector from '@/components/NodeSelector'
import { ConfigStatus } from '@/constants'
import { formatDateTime } from '@/lib/helper'
import { useSettingsStore } from '@/pinia'
import envGroupColumns from '@/views/environments/group/columns'
import { useStreamEditorStore } from '../../store'
import ConfigName from '../ConfigName.vue'
import StreamStatusSelect from '../StreamStatusSelect.vue'
const settings = useSettingsStore()
const store = useStreamEditorStore()
const { name, enabled, data } = storeToRefs(store)
const { name, status, data } = storeToRefs(store)
const [modal, ContextHolder] = Modal.useModal()
const showSync = computed(() => !settings.is_remote)
@@ -23,7 +25,7 @@ const showSync = computed(() => !settings.is_remote)
function enable() {
stream.enable(name.value).then(() => {
message.success($gettext('Enabled successfully'))
enabled.value = true
status.value = ConfigStatus.Enabled
}).catch(r => {
message.error($gettext('Failed to enable %{msg}', { msg: r.message ?? '' }), 10)
})
@@ -32,21 +34,21 @@ function enable() {
function disable() {
stream.disable(name.value).then(() => {
message.success($gettext('Disabled successfully'))
enabled.value = false
status.value = ConfigStatus.Disabled
}).catch(r => {
message.error($gettext('Failed to disable %{msg}', { msg: r.message ?? '' }))
})
}
function onChangeEnabled(checked: CheckedType) {
function onChangeEnabled({ status }: { status: SiteStatus }) {
modal.confirm({
title: checked ? $gettext('Do you want to enable this stream?') : $gettext('Do you want to disable this stream?'),
title: status === ConfigStatus.Enabled ? $gettext('Do you want to enable this stream?') : $gettext('Do you want to disable this stream?'),
mask: false,
centered: true,
okText: $gettext('OK'),
cancelText: $gettext('Cancel'),
async onOk() {
if (checked)
if (status === ConfigStatus.Enabled)
enable()
else
disable()
@@ -60,9 +62,10 @@ function onChangeEnabled(checked: CheckedType) {
<ContextHolder />
<AFormItem :label="$gettext('Enabled')">
<ASwitch
:checked="enabled"
@change="onChangeEnabled"
<StreamStatusSelect
v-model:status="status"
:stream-name="name"
@status-changed="onChangeEnabled"
/>
</AFormItem>
@@ -4,12 +4,13 @@ import CodeEditor from '@/components/CodeEditor'
import ConfigHistory from '@/components/ConfigHistory'
import FooterToolBar from '@/components/FooterToolbar'
import NgxConfigEditor from '@/components/NgxConfigEditor'
import { ConfigStatus } from '@/constants'
import { useStreamEditorStore } from '../store'
const router = useRouter()
const store = useStreamEditorStore()
const { name, enabled, configText, filepath, saving, parseErrorStatus, parseErrorMessage, advanceMode } = storeToRefs(store)
const { name, status, configText, filepath, saving, parseErrorStatus, parseErrorMessage, advanceMode } = storeToRefs(store)
const showHistory = ref(false)
</script>
@@ -18,7 +19,7 @@ const showHistory = ref(false)
<template #title>
<span style="margin-right: 10px">{{ $gettext('Edit %{n}', { n: name }) }}</span>
<ATag
v-if="enabled"
v-if="status === ConfigStatus.Enabled"
color="blue"
>
{{ $gettext('Enabled') }}
@@ -88,7 +89,7 @@ const showHistory = ref(false)
class="domain-edit-container"
>
<NgxConfigEditor
:enabled="enabled"
:enabled="status === ConfigStatus.Enabled"
context="stream"
/>
</div>
@@ -0,0 +1,103 @@
<script setup lang="ts">
import type { SiteStatus } from '@/api/site'
import type { CheckedType } from '@/types'
import { message, Modal } from 'ant-design-vue'
import stream from '@/api/stream'
import { ConfigStatus } from '@/constants'
// Define props with TypeScript
const props = defineProps<{
streamName: string
}>()
// Define event for status change notification
const emit = defineEmits<{
statusChanged: [{ status: SiteStatus }]
}>()
// Use defineModel for v-model binding
const status = defineModel<SiteStatus>('status')
const [modal, ContextHolder] = Modal.useModal()
// Enable the stream
function enable() {
stream.enable(props.streamName).then(() => {
message.success($gettext('Enabled successfully'))
status.value = ConfigStatus.Enabled
emit('statusChanged', {
status: ConfigStatus.Enabled,
})
}).catch(r => {
message.error($gettext('Failed to enable %{msg}', { msg: r.message ?? '' }), 10)
})
}
// Disable the stream
function disable() {
stream.disable(props.streamName).then(() => {
message.success($gettext('Disabled successfully'))
status.value = ConfigStatus.Disabled
emit('statusChanged', {
status: ConfigStatus.Disabled,
})
}).catch(r => {
message.error($gettext('Failed to disable %{msg}', { msg: r.message ?? '' }))
})
}
function onChangeStatus(checked: CheckedType) {
const isChecked = checked === true || checked === 'true'
// Save original status to restore if user cancels
const originalStatus = status.value
const action = isChecked ? $gettext('enable') : $gettext('disable')
modal.confirm({
title: $gettext('Do you want to %{action} this stream?', { action }),
mask: false,
centered: true,
okText: $gettext('OK'),
cancelText: $gettext('Cancel'),
async onOk() {
if (isChecked) {
enable()
}
else {
disable()
}
},
onCancel() {
// Restore original status if user cancels
status.value = originalStatus
},
})
}
</script>
<template>
<div class="stream-status-select">
<ContextHolder />
<div class="status-display">
<ASwitch
:checked="status === 'enabled'"
:checked-children="$gettext('Enabled')"
:un-checked-children="$gettext('Disabled')"
@change="onChangeStatus"
/>
</div>
</div>
</template>
<style scoped>
.stream-status-select {
display: flex;
align-items: center;
justify-content: flex-start;
}
.status-display {
display: flex;
align-items: center;
}
</style>
+4 -3
View File
@@ -6,6 +6,7 @@ import config from '@/api/config'
import ngx from '@/api/ngx'
import stream from '@/api/stream'
import { useNgxConfigStore } from '@/components/NgxConfigEditor'
import { ConfigStatus } from '@/constants'
export const useStreamEditorStore = defineStore('streamEditor', () => {
const name = ref('')
@@ -20,7 +21,7 @@ export const useStreamEditorStore = defineStore('streamEditor', () => {
const certInfoMap = ref({}) as Ref<Record<number, CertificateInfo[]>>
const filename = ref('')
const filepath = ref('')
const enabled = ref(false)
const status = ref(ConfigStatus.Disabled)
const ngxConfigStore = useNgxConfigStore()
const { ngxConfig, configText, curServerIdx, curServer, curServerDirectives, curDirectivesMap } = storeToRefs(ngxConfigStore)
@@ -90,7 +91,7 @@ export const useStreamEditorStore = defineStore('streamEditor', () => {
if (r.advanced)
advanceMode.value = true
enabled.value = r.enabled
status.value = r.status
parseErrorStatus.value = false
parseErrorMessage.value = ''
filename.value = r.name
@@ -152,7 +153,7 @@ export const useStreamEditorStore = defineStore('streamEditor', () => {
filename,
filepath,
configText,
enabled,
status,
init,
save,
handleModeChange,
+7 -7
View File
@@ -160,8 +160,8 @@ func (s *Scanner) Initialize(ctx context.Context) error {
configDir := filepath.Dir(nginx.GetConfPath())
availableDir := nginx.GetConfPath("sites-available")
enabledDir := nginx.GetConfPath("sites-enabled")
streamAvailableDir := nginx.GetConfPath("stream-available")
streamEnabledDir := nginx.GetConfPath("stream-enabled")
streamAvailableDir := nginx.GetConfPath("streams-available")
streamEnabledDir := nginx.GetConfPath("streams-enabled")
// Watch the main directories
err = s.watcher.Add(configDir)
@@ -184,18 +184,18 @@ func (s *Scanner) Initialize(ctx context.Context) error {
}
}
// Watch stream-available and stream-enabled if they exist
// Watch streams-available and streams-enabled if they exist
if _, err := os.Stat(streamAvailableDir); err == nil {
err = s.watcher.Add(streamAvailableDir)
if err != nil {
logger.Error("Failed to watch stream-available directory:", err)
logger.Error("Failed to watch streams-available directory:", err)
}
}
if _, err := os.Stat(streamEnabledDir); err == nil {
err = s.watcher.Add(streamEnabledDir)
if err != nil {
logger.Error("Failed to watch stream-enabled directory:", err)
logger.Error("Failed to watch streams-enabled directory:", err)
}
}
@@ -434,8 +434,8 @@ func (s *Scanner) ScanAllConfigs() error {
}
}
// Scan stream-available directory if it exists
streamAvailablePath := nginx.GetConfPath("stream-available", "")
// Scan streams-available directory if it exists
streamAvailablePath := nginx.GetConfPath("streams-available", "")
streamAvailableFiles, err := os.ReadDir(streamAvailablePath)
if err == nil {
for _, file := range streamAvailableFiles {
+5
View File
@@ -3,6 +3,7 @@ package config
import (
"time"
"github.com/0xJacky/Nginx-UI/internal/upstream"
"github.com/0xJacky/Nginx-UI/model"
"github.com/sashabaranov/go-openai"
)
@@ -15,6 +16,9 @@ const (
StatusMaintenance ConfigStatus = "maintenance"
)
// ProxyTarget is an alias for upstream.ProxyTarget
type ProxyTarget = upstream.ProxyTarget
type Config struct {
Name string `json:"name"`
Content string `json:"content"`
@@ -28,6 +32,7 @@ type Config struct {
Status ConfigStatus `json:"status"`
Dir string `json:"dir"`
Urls []string `json:"urls,omitempty"`
ProxyTargets []ProxyTarget `json:"proxy_targets,omitempty"`
SyncNodeIds []uint64 `json:"sync_node_ids,omitempty"`
SyncOverwrite bool `json:"sync_overwrite"`
}
+57
View File
@@ -0,0 +1,57 @@
package helper
import (
"sync"
"time"
)
// Debouncer handles debounced execution of functions
type Debouncer struct {
timer *time.Timer
mutex sync.Mutex
duration time.Duration
isFirst bool
}
// NewDebouncer creates a new debouncer with the specified duration
func NewDebouncer(duration time.Duration) *Debouncer {
return &Debouncer{
duration: duration,
isFirst: true,
}
}
// Trigger executes the callback function with debouncing logic
// For the first call, it executes immediately
// For subsequent calls, it debounces with the configured duration
func (d *Debouncer) Trigger(callback func()) {
d.mutex.Lock()
defer d.mutex.Unlock()
if d.isFirst {
d.isFirst = false
go callback() // Execute immediately for first call
return
}
// Stop existing timer if any
if d.timer != nil {
d.timer.Stop()
}
// Set new timer for debounced execution
d.timer = time.AfterFunc(d.duration, func() {
go callback()
})
}
// Stop cancels any pending debounced execution
func (d *Debouncer) Stop() {
d.mutex.Lock()
defer d.mutex.Unlock()
if d.timer != nil {
d.timer.Stop()
d.timer = nil
}
}
+101
View File
@@ -0,0 +1,101 @@
package helper
import (
"sync"
"testing"
"time"
)
func TestDebouncer_FirstCallImmediate(t *testing.T) {
debouncer := NewDebouncer(100 * time.Millisecond)
var called bool
var mu sync.Mutex
callback := func() {
mu.Lock()
called = true
mu.Unlock()
}
debouncer.Trigger(callback)
// Wait a short time for the goroutine to execute
time.Sleep(10 * time.Millisecond)
mu.Lock()
if !called {
t.Error("First call should execute immediately")
}
mu.Unlock()
debouncer.Stop()
}
func TestDebouncer_SubsequentCallsDebounced(t *testing.T) {
debouncer := NewDebouncer(50 * time.Millisecond)
var callCount int
var mu sync.Mutex
callback := func() {
mu.Lock()
callCount++
mu.Unlock()
}
// First call - should execute immediately
debouncer.Trigger(callback)
time.Sleep(10 * time.Millisecond)
// Multiple rapid calls - should be debounced
debouncer.Trigger(callback)
debouncer.Trigger(callback)
debouncer.Trigger(callback)
// Wait for debounce period
time.Sleep(70 * time.Millisecond)
mu.Lock()
if callCount != 2 { // First immediate + one debounced
t.Errorf("Expected 2 calls, got %d", callCount)
}
mu.Unlock()
debouncer.Stop()
}
func TestDebouncer_Stop(t *testing.T) {
debouncer := NewDebouncer(100 * time.Millisecond)
var called bool
var mu sync.Mutex
callback := func() {
mu.Lock()
called = true
mu.Unlock()
}
// First call to set isFirst to false
debouncer.Trigger(callback)
time.Sleep(10 * time.Millisecond)
// Reset called flag
mu.Lock()
called = false
mu.Unlock()
// Trigger and immediately stop
debouncer.Trigger(callback)
debouncer.Stop()
// Wait longer than debounce period
time.Sleep(150 * time.Millisecond)
mu.Lock()
if called {
t.Error("Callback should not be called after Stop()")
}
mu.Unlock()
}
+14 -8
View File
@@ -8,12 +8,14 @@ import (
"strings"
"github.com/0xJacky/Nginx-UI/internal/cache"
"github.com/0xJacky/Nginx-UI/internal/upstream"
)
type SiteIndex struct {
Path string
Content string
Urls []string
Path string
Content string
Urls []string
ProxyTargets []ProxyTarget
}
var (
@@ -41,9 +43,10 @@ func scanForSite(configPath string, content []byte) error {
serverBlocks := serverBlockRegex.FindAllSubmatch(content, -1)
siteIndex := SiteIndex{
Path: configPath,
Content: string(content),
Urls: []string{},
Path: configPath,
Content: string(content),
Urls: []string{},
ProxyTargets: []ProxyTarget{},
}
// Map to track hosts, their SSL status and port
@@ -153,8 +156,11 @@ func scanForSite(configPath string, content []byte) error {
siteIndex.Urls = append(siteIndex.Urls, url)
}
// Only store if we found valid URLs
if len(siteIndex.Urls) > 0 {
// Parse proxy targets from the configuration content
siteIndex.ProxyTargets = upstream.ParseProxyTargetsFromRawContent(string(content))
// Only store if we found valid URLs or proxy targets
if len(siteIndex.Urls) > 0 || len(siteIndex.ProxyTargets) > 0 {
IndexedSites[filepath.Base(configPath)] = &siteIndex
}
+5
View File
@@ -5,6 +5,7 @@ import (
"github.com/0xJacky/Nginx-UI/internal/cert"
"github.com/0xJacky/Nginx-UI/internal/nginx"
"github.com/0xJacky/Nginx-UI/internal/upstream"
"github.com/0xJacky/Nginx-UI/model"
"github.com/sashabaranov/go-openai"
)
@@ -17,6 +18,9 @@ const (
SiteStatusMaintenance SiteStatus = "maintenance"
)
// ProxyTarget is an alias for upstream.ProxyTarget
type ProxyTarget = upstream.ProxyTarget
type Site struct {
*model.Site
Name string `json:"name"`
@@ -28,4 +32,5 @@ type Site struct {
Tokenized *nginx.NgxConfig `json:"tokenized,omitempty"`
CertInfo map[int][]*cert.Info `json:"cert_info,omitempty"`
Filepath string `json:"filepath"`
ProxyTargets []ProxyTarget `json:"proxy_targets,omitempty"`
}
+58
View File
@@ -0,0 +1,58 @@
package stream
import (
"path/filepath"
"strings"
"github.com/0xJacky/Nginx-UI/internal/cache"
"github.com/0xJacky/Nginx-UI/internal/upstream"
)
type StreamIndex struct {
Path string
Content string
ProxyTargets []upstream.ProxyTarget
}
var (
IndexedStreams = make(map[string]*StreamIndex)
)
func GetIndexedStream(path string) *StreamIndex {
if stream, ok := IndexedStreams[path]; ok {
return stream
}
return &StreamIndex{}
}
func init() {
cache.RegisterCallback(scanForStream)
}
func scanForStream(configPath string, content []byte) error {
// Only process stream configuration files
if !isStreamConfig(configPath) {
return nil
}
streamIndex := StreamIndex{
Path: configPath,
Content: string(content),
ProxyTargets: []upstream.ProxyTarget{},
}
// Parse proxy targets from the configuration content
streamIndex.ProxyTargets = upstream.ParseProxyTargetsFromRawContent(string(content))
// Only store if we found proxy targets
if len(streamIndex.ProxyTargets) > 0 {
IndexedStreams[filepath.Base(configPath)] = &streamIndex
}
return nil
}
// isStreamConfig checks if the config path is a stream configuration
func isStreamConfig(configPath string) bool {
return strings.Contains(configPath, "streams-available") ||
strings.Contains(configPath, "streams-enabled")
}
+79
View File
@@ -0,0 +1,79 @@
package stream
import (
"testing"
)
func TestIsStreamConfig(t *testing.T) {
tests := []struct {
path string
expected bool
}{
{"streams-available/test.conf", true},
{"streams-enabled/test.conf", true},
{"/etc/nginx/streams-available/test.conf", true},
{"/etc/nginx/streams-enabled/test.conf", true},
{"/var/lib/nginx/streams-available/my-stream.conf", true},
{"/home/user/nginx/streams-enabled/tcp-proxy.conf", true},
{"sites-available/test.conf", false},
{"sites-enabled/test.conf", false},
{"/etc/nginx/conf.d/test.conf", false},
{"test.conf", false},
}
for _, test := range tests {
result := isStreamConfig(test.path)
if result != test.expected {
t.Errorf("isStreamConfig(%q) = %v, expected %v", test.path, result, test.expected)
}
}
}
func TestScanForStream(t *testing.T) {
// Clear the IndexedStreams map
IndexedStreams = make(map[string]*StreamIndex)
config := `upstream my-tcp {
server 127.0.0.1:9000;
}
server {
listen 1234-1236;
resolver 8.8.8.8 valid=1s;
proxy_pass example.com:$server_port;
}`
// Test with a valid stream config path
err := scanForStream("streams-available/test.conf", []byte(config))
if err != nil {
t.Errorf("scanForStream failed: %v", err)
}
// Check if the stream was indexed
if len(IndexedStreams) != 1 {
t.Errorf("Expected 1 indexed stream, got %d", len(IndexedStreams))
}
stream := IndexedStreams["test.conf"]
if stream == nil {
t.Fatal("Stream not found in index")
}
if len(stream.ProxyTargets) != 2 {
t.Errorf("Expected 2 proxy targets, got %d", len(stream.ProxyTargets))
for i, target := range stream.ProxyTargets {
t.Logf("Target %d: %+v", i, target)
}
}
// Test with a non-stream config path
IndexedStreams = make(map[string]*StreamIndex)
err = scanForStream("sites-available/test.conf", []byte(config))
if err != nil {
t.Errorf("scanForStream failed: %v", err)
}
// Should not be indexed
if len(IndexedStreams) != 0 {
t.Errorf("Expected 0 indexed streams for non-stream config, got %d", len(IndexedStreams))
}
}
+275
View File
@@ -0,0 +1,275 @@
package upstream
import (
"net/url"
"regexp"
"strings"
"github.com/0xJacky/Nginx-UI/internal/nginx"
)
// ProxyTarget represents a proxy destination
type ProxyTarget struct {
Host string `json:"host"`
Port string `json:"port"`
Type string `json:"type"` // "proxy_pass" or "upstream"
}
// ParseProxyTargets extracts proxy targets from nginx configuration
func ParseProxyTargets(config *nginx.NgxConfig) []ProxyTarget {
var targets []ProxyTarget
if config == nil {
return targets
}
// Parse upstream servers
for _, upstream := range config.Upstreams {
upstreamTargets := parseUpstreamServers(upstream)
targets = append(targets, upstreamTargets...)
}
// Parse proxy_pass directives in servers
for _, server := range config.Servers {
proxyTargets := parseServerProxyPass(server)
targets = append(targets, proxyTargets...)
}
return deduplicateTargets(targets)
}
// ParseProxyTargetsFromRawContent parses proxy targets from raw nginx configuration content
func ParseProxyTargetsFromRawContent(content string) []ProxyTarget {
var targets []ProxyTarget
// First, collect all upstream names
upstreamNames := make(map[string]bool)
upstreamRegex := regexp.MustCompile(`(?s)upstream\s+([^\s]+)\s*\{([^}]+)\}`)
upstreamMatches := upstreamRegex.FindAllStringSubmatch(content, -1)
// Parse upstream blocks and collect upstream names
for _, match := range upstreamMatches {
if len(match) >= 3 {
upstreamName := match[1]
upstreamNames[upstreamName] = true
upstreamContent := match[2]
serverRegex := regexp.MustCompile(`(?m)^\s*server\s+([^;]+);`)
serverMatches := serverRegex.FindAllStringSubmatch(upstreamContent, -1)
for _, serverMatch := range serverMatches {
if len(serverMatch) >= 2 {
target := parseServerAddress(strings.TrimSpace(serverMatch[1]), "upstream")
if target.Host != "" {
targets = append(targets, target)
}
}
}
}
}
// Parse proxy_pass directives, but skip upstream references
proxyPassRegex := regexp.MustCompile(`(?m)^\s*proxy_pass\s+([^;]+);`)
proxyMatches := proxyPassRegex.FindAllStringSubmatch(content, -1)
for _, match := range proxyMatches {
if len(match) >= 2 {
proxyPassURL := strings.TrimSpace(match[1])
// Skip if this proxy_pass references an upstream
if !isUpstreamReference(proxyPassURL, upstreamNames) {
target := parseProxyPassURL(proxyPassURL)
if target.Host != "" {
targets = append(targets, target)
}
}
}
}
return deduplicateTargets(targets)
}
// parseUpstreamServers extracts server addresses from upstream blocks
func parseUpstreamServers(upstream *nginx.NgxUpstream) []ProxyTarget {
var targets []ProxyTarget
for _, directive := range upstream.Directives {
if directive.Directive == "server" {
target := parseServerAddress(directive.Params, "upstream")
if target.Host != "" {
targets = append(targets, target)
}
}
}
return targets
}
// parseServerProxyPass extracts proxy_pass targets from server blocks
func parseServerProxyPass(server *nginx.NgxServer) []ProxyTarget {
var targets []ProxyTarget
// Check directives in server block
for _, directive := range server.Directives {
if directive.Directive == "proxy_pass" {
target := parseProxyPassURL(directive.Params)
if target.Host != "" {
targets = append(targets, target)
}
}
}
// Check directives in location blocks
for _, location := range server.Locations {
locationTargets := parseLocationProxyPass(location.Content)
targets = append(targets, locationTargets...)
}
return targets
}
// parseLocationProxyPass extracts proxy_pass from location content
func parseLocationProxyPass(content string) []ProxyTarget {
var targets []ProxyTarget
// Use regex to find proxy_pass directives
proxyPassRegex := regexp.MustCompile(`(?m)^\s*proxy_pass\s+([^;]+);`)
matches := proxyPassRegex.FindAllStringSubmatch(content, -1)
for _, match := range matches {
if len(match) >= 2 {
target := parseProxyPassURL(strings.TrimSpace(match[1]))
if target.Host != "" {
targets = append(targets, target)
}
}
}
return targets
}
// parseProxyPassURL parses a proxy_pass URL and extracts host and port
func parseProxyPassURL(proxyPass string) ProxyTarget {
proxyPass = strings.TrimSpace(proxyPass)
// Handle HTTP/HTTPS URLs (e.g., "http://backend")
if strings.HasPrefix(proxyPass, "http://") || strings.HasPrefix(proxyPass, "https://") {
if parsedURL, err := url.Parse(proxyPass); err == nil {
host := parsedURL.Hostname()
port := parsedURL.Port()
// Set default ports if not specified
if port == "" {
if parsedURL.Scheme == "https" {
port = "443"
} else {
port = "80"
}
}
return ProxyTarget{
Host: host,
Port: port,
Type: "proxy_pass",
}
}
}
// Handle direct address format for stream module (e.g., "127.0.0.1:8080", "backend.example.com:12345")
// This is used in stream configurations where proxy_pass doesn't require a protocol
if !strings.Contains(proxyPass, "://") {
return parseServerAddress(proxyPass, "proxy_pass")
}
return ProxyTarget{}
}
// parseServerAddress parses upstream server address
func parseServerAddress(serverAddr string, targetType string) ProxyTarget {
serverAddr = strings.TrimSpace(serverAddr)
// Remove additional parameters (weight, max_fails, etc.)
parts := strings.Fields(serverAddr)
if len(parts) == 0 {
return ProxyTarget{}
}
addr := parts[0]
// Handle IPv6 addresses
if strings.HasPrefix(addr, "[") {
// IPv6 format: [::1]:8080
if idx := strings.LastIndex(addr, "]:"); idx != -1 {
host := addr[1:idx]
port := addr[idx+2:]
return ProxyTarget{
Host: host,
Port: port,
Type: targetType,
}
}
// IPv6 without port: [::1]
host := strings.Trim(addr, "[]")
return ProxyTarget{
Host: host,
Port: "80",
Type: targetType,
}
}
// Handle IPv4 addresses and hostnames
if strings.Contains(addr, ":") {
parts := strings.Split(addr, ":")
if len(parts) == 2 {
return ProxyTarget{
Host: parts[0],
Port: parts[1],
Type: targetType,
}
}
}
// No port specified, use default
return ProxyTarget{
Host: addr,
Port: "80",
Type: targetType,
}
}
// deduplicateTargets removes duplicate proxy targets
func deduplicateTargets(targets []ProxyTarget) []ProxyTarget {
seen := make(map[string]bool)
var result []ProxyTarget
for _, target := range targets {
key := target.Host + ":" + target.Port + ":" + target.Type
if !seen[key] {
seen[key] = true
result = append(result, target)
}
}
return result
}
// isUpstreamReference checks if a proxy_pass URL references an upstream block
func isUpstreamReference(proxyPass string, upstreamNames map[string]bool) bool {
proxyPass = strings.TrimSpace(proxyPass)
// For HTTP/HTTPS URLs, parse the URL to extract the hostname
if strings.HasPrefix(proxyPass, "http://") || strings.HasPrefix(proxyPass, "https://") {
if parsedURL, err := url.Parse(proxyPass); err == nil {
hostname := parsedURL.Hostname()
// Check if the hostname matches any upstream name
return upstreamNames[hostname]
}
}
// For stream module, proxy_pass can directly reference upstream name without protocol
// Check if the proxy_pass value directly matches an upstream name
if !strings.Contains(proxyPass, "://") && !strings.Contains(proxyPass, ":") {
return upstreamNames[proxyPass]
}
return false
}
+381
View File
@@ -0,0 +1,381 @@
package upstream
import (
"testing"
)
func TestParseProxyTargetsFromRawContent(t *testing.T) {
config := `map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream api-1 {
server 127.0.0.1:9000;
server 127.0.0.1:443;
}
upstream api-2 {
server 127.0.0.1:9003;
server 127.0.0.1:9005;
}
server {
listen 80;
listen [::]:80;
server_name test.jackyu.cn;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
index index.html;
try_files $uri $uri/ /index.html;
}
location /admin {
index admin.html;
try_files $uri $uri/ /admin.html;
}
location /user {
index user.html;
try_files $uri $uri/ /user.html;
}
location /api/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://api-1/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 1000m;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name test.jackyu.cn;
ssl_certificate /etc/nginx/ssl/test.jackyu.cn_P256/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/test.jackyu.cn_P256/private.key;
root /var/www/ibeta/html;
index index.html;
http2 on;
access_log /var/log/nginx/test.jackyu.cn.log main;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
index index.html;
try_files $uri $uri/ /index.html;
}
location /admin {
index admin.html;
try_files $uri $uri/ /admin.html;
}
location /user {
index user.html;
try_files $uri $uri/ /user.html;
}
location /api/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://api-1/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 100m;
}
}`
targets := ParseProxyTargetsFromRawContent(config)
// Expected targets: 4 upstream servers (2 from api-1, 2 from api-2)
// proxy_pass http://api-1/ should be ignored since it references an upstream
expectedTargets := []ProxyTarget{
{Host: "127.0.0.1", Port: "9000", Type: "upstream"},
{Host: "127.0.0.1", Port: "443", Type: "upstream"},
{Host: "127.0.0.1", Port: "9003", Type: "upstream"},
{Host: "127.0.0.1", Port: "9005", Type: "upstream"},
}
if len(targets) != len(expectedTargets) {
t.Errorf("Expected %d targets, got %d", len(expectedTargets), len(targets))
for i, target := range targets {
t.Logf("Target %d: %+v", i, target)
}
return
}
// Create a map for easier comparison
targetMap := make(map[string]ProxyTarget)
for _, target := range targets {
key := target.Host + ":" + target.Port + ":" + target.Type
targetMap[key] = target
}
for _, expected := range expectedTargets {
key := expected.Host + ":" + expected.Port + ":" + expected.Type
if _, found := targetMap[key]; !found {
t.Errorf("Expected target not found: %+v", expected)
}
}
}
func TestIsUpstreamReference(t *testing.T) {
upstreamNames := map[string]bool{
"api-1": true,
"api-2": true,
"backend": true,
}
tests := []struct {
proxyPass string
expected bool
}{
{"http://api-1/", true},
{"http://api-1", true},
{"https://api-2/path", true},
{"http://backend", true},
{"http://127.0.0.1:8080", false},
{"https://example.com", false},
{"http://unknown-upstream", false},
}
for _, test := range tests {
result := isUpstreamReference(test.proxyPass, upstreamNames)
if result != test.expected {
t.Errorf("isUpstreamReference(%q) = %v, expected %v", test.proxyPass, result, test.expected)
}
}
}
func TestParseProxyTargetsWithDirectProxyPass(t *testing.T) {
config := `upstream api-1 {
server 127.0.0.1:9000;
server 127.0.0.1:443;
}
server {
listen 80;
server_name test.jackyu.cn;
location /api/ {
proxy_pass http://api-1/;
}
location /external/ {
proxy_pass http://external.example.com:8080/;
}
location /another/ {
proxy_pass https://another.example.com/;
}
}`
targets := ParseProxyTargetsFromRawContent(config)
// Expected targets:
// - 2 upstream servers from api-1
// - 2 direct proxy_pass targets (external.example.com:8080, another.example.com:443)
// - proxy_pass http://api-1/ should be ignored since it references an upstream
expectedTargets := []ProxyTarget{
{Host: "127.0.0.1", Port: "9000", Type: "upstream"},
{Host: "127.0.0.1", Port: "443", Type: "upstream"},
{Host: "external.example.com", Port: "8080", Type: "proxy_pass"},
{Host: "another.example.com", Port: "443", Type: "proxy_pass"},
}
if len(targets) != len(expectedTargets) {
t.Errorf("Expected %d targets, got %d", len(expectedTargets), len(targets))
for i, target := range targets {
t.Logf("Target %d: %+v", i, target)
}
return
}
// Create a map for easier comparison
targetMap := make(map[string]ProxyTarget)
for _, target := range targets {
key := target.Host + ":" + target.Port + ":" + target.Type
targetMap[key] = target
}
for _, expected := range expectedTargets {
key := expected.Host + ":" + expected.Port + ":" + expected.Type
if _, found := targetMap[key]; !found {
t.Errorf("Expected target not found: %+v", expected)
}
}
}
func TestParseProxyTargetsFromStreamConfig(t *testing.T) {
config := `upstream backend {
server 127.0.0.1:9000;
server 127.0.0.1:9001;
}
server {
listen 12345;
proxy_pass backend;
}
server {
listen 12346;
proxy_pass 192.168.1.100:8080;
}
server {
listen 12347;
proxy_pass example.com:3306;
}`
targets := ParseProxyTargetsFromRawContent(config)
// Expected targets:
// - 2 upstream servers from backend
// - 2 direct proxy_pass targets (192.168.1.100:8080, example.com:3306)
// - proxy_pass backend should be ignored since it references an upstream
expectedTargets := []ProxyTarget{
{Host: "127.0.0.1", Port: "9000", Type: "upstream"},
{Host: "127.0.0.1", Port: "9001", Type: "upstream"},
{Host: "192.168.1.100", Port: "8080", Type: "proxy_pass"},
{Host: "example.com", Port: "3306", Type: "proxy_pass"},
}
if len(targets) != len(expectedTargets) {
t.Errorf("Expected %d targets, got %d", len(expectedTargets), len(targets))
for i, target := range targets {
t.Logf("Target %d: %+v", i, target)
}
return
}
// Create a map for easier comparison
targetMap := make(map[string]ProxyTarget)
for _, target := range targets {
key := target.Host + ":" + target.Port + ":" + target.Type
targetMap[key] = target
}
for _, expected := range expectedTargets {
key := expected.Host + ":" + expected.Port + ":" + expected.Type
if _, found := targetMap[key]; !found {
t.Errorf("Expected target not found: %+v", expected)
}
}
}
func TestParseProxyTargetsFromMixedConfig(t *testing.T) {
config := `upstream web_backend {
server web1.example.com:80;
server web2.example.com:80;
}
upstream stream_backend {
server stream1.example.com:12345;
server stream2.example.com:12345;
}
# HTTP server block
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://web_backend/;
}
location /api {
proxy_pass http://api.example.com:8080/;
}
}
# Stream server blocks
server {
listen 12345;
proxy_pass stream_backend;
}
server {
listen 3306;
proxy_pass mysql.example.com:3306;
}`
targets := ParseProxyTargetsFromRawContent(config)
// Expected targets:
// - 2 upstream servers from web_backend
// - 2 upstream servers from stream_backend
// - 1 direct HTTP proxy_pass (api.example.com:8080)
// - 1 direct stream proxy_pass (mysql.example.com:3306)
// - proxy_pass http://web_backend/ and proxy_pass stream_backend should be ignored
expectedTargets := []ProxyTarget{
{Host: "web1.example.com", Port: "80", Type: "upstream"},
{Host: "web2.example.com", Port: "80", Type: "upstream"},
{Host: "stream1.example.com", Port: "12345", Type: "upstream"},
{Host: "stream2.example.com", Port: "12345", Type: "upstream"},
{Host: "api.example.com", Port: "8080", Type: "proxy_pass"},
{Host: "mysql.example.com", Port: "3306", Type: "proxy_pass"},
}
if len(targets) != len(expectedTargets) {
t.Errorf("Expected %d targets, got %d", len(expectedTargets), len(targets))
for i, target := range targets {
t.Logf("Target %d: %+v", i, target)
}
return
}
// Create a map for easier comparison
targetMap := make(map[string]ProxyTarget)
for _, target := range targets {
key := target.Host + ":" + target.Port + ":" + target.Type
targetMap[key] = target
}
for _, expected := range expectedTargets {
key := expected.Host + ":" + expected.Port + ":" + expected.Type
if _, found := targetMap[key]; !found {
t.Errorf("Expected target not found: %+v", expected)
}
}
}
func TestParseProxyTargetsFromUserConfig(t *testing.T) {
config := `upstream my-tcp {
server 127.0.0.1:9000;
}
server {
listen 1234-1236;
resolver 8.8.8.8 valid=1s;
proxy_pass example.com:$server_port;
}`
targets := ParseProxyTargetsFromRawContent(config)
// Print actual results for debugging
t.Logf("Found %d targets:", len(targets))
for i, target := range targets {
t.Logf("Target %d: Host=%s, Port=%s, Type=%s", i+1, target.Host, target.Port, target.Type)
}
// Expected targets:
// - 1 upstream server from my-tcp
// - 1 proxy_pass target (example.com with variable port should still be parsed)
expectedTargets := []ProxyTarget{
{Host: "127.0.0.1", Port: "9000", Type: "upstream"},
{Host: "example.com", Port: "$server_port", Type: "proxy_pass"},
}
if len(targets) != len(expectedTargets) {
t.Errorf("Expected %d targets, got %d", len(expectedTargets), len(targets))
return
}
// Create a map for easier comparison
targetMap := make(map[string]ProxyTarget)
for _, target := range targets {
key := target.Host + ":" + target.Port + ":" + target.Type
targetMap[key] = target
}
for _, expected := range expectedTargets {
key := expected.Host + ":" + expected.Port + ":" + expected.Type
if _, found := targetMap[key]; !found {
t.Errorf("Expected target not found: %+v", expected)
}
}
}