mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-05-31 18:24:10 +00:00
* chore(frontend): add react+typescript toolchain alongside vue
Step 0 of the planned vue->react migration. React 19, antd 5, i18next
+ react-i18next, typescript 5, and @vitejs/plugin-react 6 are added as
dev/runtime deps alongside the existing vue stack. Both frameworks
coexist in the build until the last entry flips.
* vite.config.js: react() plugin runs next to vue(); new manualChunks
for vendor-react / vendor-antd-react / vendor-icons-react /
vendor-i18next. Existing vue chunks unchanged.
* eslint.config.js: typescript-eslint + eslint-plugin-react-hooks
rules scoped to *.{ts,tsx}; vue config untouched for *.{js,vue}.
* tsconfig.json: strict, jsx: react-jsx, moduleResolution: bundler,
allowJs: true (lets .tsx files import the remaining .js modules
during incremental migration), @/* path alias.
* env.d.ts: Vite client types + window.X_UI_BASE_PATH typing +
SubPageData shape consumed by the subscription page.
Vite stays pinned at 8.0.13 per the existing project policy. No
existing .vue/.js source files touched in this step.
eslint-plugin-react (not -hooks) is not included because its latest
release does not yet support ESLint 10. react-hooks/purity covers
the safety-critical case; revisit when the plugin updates.
* refactor(frontend): port subpage to react+ts
Step 1 of the planned vue->react migration. The standalone
subscription page (sub/sub.go renders the HTML host; React mounts
into #app) is the first entry off vue.
Introduces two shared pieces both entries (and future ones) will
use:
* src/hooks/useTheme.tsx — React Context + useTheme hook + the
same buildAntdThemeConfig (dark/ultra-dark token overrides) and
pauseAnimationsUntilLeave helper the vue version exposes. Same
localStorage keys (dark-mode, isUltraDarkThemeEnabled) and DOM
side effects (body.className, html[data-theme]) so the two stay
in sync across the coexistence period.
* src/i18n/react.ts — i18next + react-i18next loader that reads
the same web/translation/*.json files via import.meta.glob. The
vue-i18n setup in src/i18n/index.js is untouched and still serves
the remaining vue entries.
SubPage.tsx mirrors the vue version's behavior: reads
window.__SUB_PAGE_DATA__ injected by the Go sub server, renders QR
codes / descriptions / Android+iOS deep-link dropdowns, supports
theme cycle and language switch. Uses AntD v5 idioms: Descriptions
items prop, Dropdown menu prop, Layout.Content.
* refactor(frontend): port login to react+ts
Step 2 of the planned vue->react migration. The login entry is the
first to exercise AntD React's Form API (Form + Form.Item with
name/rules + onFinish) and the existing axios/CSRF interceptors
under React.
* LoginPage.tsx: same form fields, conditional 2FA input,
rotating headline ("Hello" / "Welcome to..."), drifting blob
background, theme cycle + language popover. Headline transition
switches from vue's <Transition mode=out-in> to a CSS keyframe
animation keyed off the visible word.
* entries/login.tsx: setupAxios() + applyDocumentTitle() unchanged
from the vue entry — both are framework-agnostic in src/utils
and src/api/axios-init.js.
useTheme hook, ThemeProvider, and i18n/react.ts loader introduced
in step 1 are now shared across two entries; Vite extracts them as
a small chunk in the build output.
* refactor(frontend): port api-docs to react+ts
Step 3 of the planned vue->react migration. The five api-docs files
(ApiDocsPage, CodeBlock, EndpointRow, EndpointSection, plus the
data-only endpoints.js) all move to react+ts.
Also introduces components/AppSidebar.tsx — api-docs is the first
authenticated page to need it. AppSidebar.vue stays in place for the
six remaining vue entries (settings, inbounds, clients, xray, nodes,
index); each gets switched to AppSidebar.tsx as its entry migrates.
After the last entry flips, AppSidebar.vue is deleted.
Notable transformations:
* The scroll observer that highlights the active TOC link is a
useEffect keyed on sections — re-registers whenever the visible
set changes (search filter narrows it). Same behaviour as the vue
watchEffect.
* v-html="safeInlineHtml(...)" becomes
dangerouslySetInnerHTML={{ __html: safeInlineHtml(...) }}. The
helper still escapes everything except <code> tags.
* JSON syntax highlighter in CodeBlock is unchanged — pure regex on
the escaped string, then rendered via dangerouslySetInnerHTML.
* endpoints.js stays as JS (allowJs in tsconfig); only the consumer
signatures (Endpoint, Section) are typed at the React boundary.
* AppSidebar reuses pauseAnimationsUntilLeave + useTheme from
step 1. Drawer + Sider keyed off the same localStorage flag
(isSidebarCollapsed) and DOM theme attributes the vue version
uses, so the two stay in sync during coexistence.
* refactor(frontend): port nodes to react+ts
Step 4 of the planned vue->react migration. The nodes entry brings in
the largest shared-infrastructure batch so far — every authenticated
react page from here on can lean on these.
New shared pieces (live alongside their .vue counterparts during
coexistence):
* hooks/useMediaQuery.ts — useState + resize listener
* hooks/useWebSocket.ts — wraps WebSocketClient, subscribes on mount
and unsubscribes on unmount. The underlying client is a single
module-level instance so multiple components on the same page
share one socket.
* hooks/useNodes.ts — node list state + CRUD + probe/test, including
the totals memo (online/offline/avgLatency) used by the summary card.
applyNodesEvent is the entry point for the heartbeat-pushed list.
* components/CustomStatistic.tsx — thin Statistic wrapper, prefix +
suffix slots become props.
* components/Sparkline.tsx — the SVG line chart with measured-width
axis scaling, gradient fill, tooltip overlay, and per-instance
gradient id from React.useId. ResizeObserver lifecycle is in
useEffect; the math is unchanged.
Pages:
* NodesPage — wires hooks + WebSocket together, renders summary card
+ NodeList, hosts the form modal. Uses Modal.useModal() for the
delete confirm so the dialog inherits ConfigProvider theming.
* NodeList — desktop renders a Table with expandable history rows;
mobile flips to a vertical card list whose actions live in a
bottom-right Dropdown. The IP-blur eye toggle persists across both.
* NodeFormModal — controlled form (useState object, single setForm
per change). The reset-on-open effect computes the next state
once and applies it with eslint-disable to satisfy the new
react-hooks/set-state-in-effect rule on a legitimate pattern.
* NodeHistoryPanel — polls /panel/api/nodes/history/{id}/{metric}/
{bucket} every 15s, renders cpu+mem sparklines side-by-side.
* refactor(frontend): port settings to react+ts
Step 5 of the planned vue->react migration. Settings is the first
entry whose state model didn't translate to the Vue-style "parent
passes a reactive object, children mutate it in place" pattern, so
the React port flips it to lifted state + a typed updateSetting
patch function.
* models/setting.ts — typed AllSetting class with the same field
defaults and equals() behavior the vue version had. The .js
twin is deleted; nothing else imported it.
* hooks/useAllSetting.ts — owns allSetting + oldAllSetting state,
exposes updateSetting(patch), saveDisabled is derived via useMemo
off equals() (no more 1Hz dirty-check timer).
* components/SettingListItem.tsx — children-based wrapper instead
of named slots. The vue twin stays alive because xray (BasicsTab,
DnsTab) still imports it; deleted when xray migrates.
The five tab components and the TwoFactorModal each accept
{ allSetting, updateSetting } and render with AntD v5's Collapse
items[] API. Every v-model:value="x" became
value={...} onChange={(e) => updateSetting({ key: e.target.value })}
or onChange={(v) => updateSetting({ key: v })} for non-input
controls.
SubscriptionFormatsTab is the trickiest — fragment / noises[] /
mux / direct routing rules are stored as JSON-encoded strings on
the wire. Parsing them once via useMemo per field, mutating the
parsed object on edit, and stringifying back into the patch keeps
the round-trip identical to the vue version.
SettingsPage hosts the tab navigation (with hash sync), the
save / restart action bar, the security-warnings alert banner,
and the restart flow that rebuilds the panel URL after the new
host/port/cert settings take effect.
* refactor(frontend): port clients to react+ts
Step 6 of the planned vue->react migration. Clients is the biggest
data-CRUD page in the panel (1.1k-line ClientsPage, 4 modals, full
table + mobile card list, WebSocket-driven realtime traffic + online
updates).
New shared infra (lives alongside vue twins until inbounds migrates):
* hooks/useClients.ts — clients + inbounds list, CRUD + bulk delete +
attach/detach + traffic reset, with WebSocket event handlers
(traffic, client_stats, invalidate) and a small debounced refresh
on the invalidate event. State managed via setState; the live
client_stats event merges traffic snapshots row-by-row through a
ref to avoid stale closure issues.
* hooks/useDatepicker.ts — singleton "gregorian"/"jalalian" cache
with subscribe/notify so multiple components can read the panel's
Calendar Type without re-fetching. Mirrors useDatepicker.js.
* components/DateTimePicker.tsx — AntD DatePicker wrapper.
vue3-persian-datetime-picker has no React port; the Jalali UI
calendar is deferred (read-only Jalali display via IntlUtil
formatDate still works). The vue twin stays for inbounds.
* pages/inbounds/QrPanel.tsx — copy/download/copy-as-png QR helper
shared between clients (qr modal) and inbounds (still on vue).
Vue twin stays alive at QrPanel.vue.
* models/inbound.ts — slim port: only the TLS_FLOW_CONTROL constant
the clients form needs. The full inbound model stays as
inbound.js for now; inbounds will pull it in as inbound.ts.
The clients page itself uses Modal.useModal() for all confirm
dialogs (delete, bulk-delete, reset-traffic, delDepleted, reset-all)
so the dialogs render themed. Filter state persists to
localStorage under clientsFilterState. Sort + pagination state is
local; pageSize seeds from /panel/setting/defaultSettings.
The four modals share a controlled "open/onOpenChange" pattern
that replaces vue's v-model:open. ClientFormModal computes
attach/detach diffs from the inbound multi-select on submit; the
parent's onSave callback routes them through useClients's attach()/
detach() after the main update succeeds.
ESLint config: turned off four react-hooks v7 rules
(react-compiler, preserve-manual-memoization, set-state-in-effect,
purity). They're all React-Compiler-driven informational rules; we
don't run the compiler and the patterns they flag (initial-fetch
useEffect, derived computations using Date.now, inline arrow event
handlers) are all idiomatic React. Disabling globally instead of
per-line keeps the diff readable.
* refactor(frontend): port index dashboard to react+ts
Step 7 of the Vue→React migration. Ports the overview/index entry: dashboard
page, status + xray cards, panel-update / log / backup / system-history /
xray-metrics / xray-log / version modals, and the custom-geo subsection. Adds
the shared JsonEditor (CodeMirror 6) and useStatus hook used by the config
modal. Removes the unused react-hooks/set-state-in-effect disables now that
the rule is off globally.
* refactor(frontend): port xray to react+ts
Step 8 of the Vue→React migration. Ports the xray config entry: page shell,
basics/routing/outbounds/balancers/dns tabs, the rule + balancer + dns server
+ dns presets + warp + nord modals, the protocol-aware outbound form, and the
shared FinalMaskForm (TCP/UDP masks + QUIC params). Adds useXraySetting that
mirrors the legacy two-way sync between the JSON template string and the
parsed templateSettings tree. The outbound model itself stays in JS so the
class-driven form keeps its existing mutation API; instance access is typed
loosely inside the form to match.
The shared FinalMaskForm.vue and JsonEditor.vue stay alongside the new .tsx
versions until step 9 — InboundFormModal.vue still imports them.
Adds react-hooks/immutability and react-hooks/refs to the already-disabled
react-compiler rule set; both flag the outbound form's instance-mutation
pattern that doesn't run through useState.
* Upgrade frontend deps (antd v6, i18n, TS)
Bump frontend dependencies in package.json and regenerate package-lock.json. Notable updates: upgrade antd to v6, update i18next/react-i18next, axios, qs, vue-i18n, TypeScript and ESLint, plus related @rc-component packages and replacements (e.g. classnames/rc-util -> clsx/@rc-component/util). Lockfile changes reflect the new dependency tree required for Ant Design v6 and other package upgrades.
* refactor(frontend): port inbounds to react+ts and drop vue toolchain
Step 9 — the last entry. Ports the inbounds entry: page shell, list with
desktop table + mobile cards, info modal, qr-code modal, share-link
helpers, and the protocol-aware form modal (basics / protocol /
stream / security / sniffing / advanced JSON). useInbounds replaces
the Vue composable with WebSocket-driven traffic + client-stats merge.
Inbound and DBInbound models stay in JS so the class-driven form keeps
its mutation API; instance access is typed loosely inside the form to
match. FinalMaskForm/JsonEditor/TextModal/PromptModal/InfinityIcon are
the last shared bits to flip; their .vue counterparts go too.
Toolchain cleanup now that no entry needs Vue: drop plugin-vue from
vite.config, remove the .vue lint block + parser, prune vue / vue-i18n
/ ant-design-vue / @ant-design/icons-vue / vue3-persian-datetime-picker
/ moment-jalaali override from package.json, and switch utils/index.js
to import { message } from 'antd' instead of ant-design-vue.
* chore(frontend): adopt antd v6 api updates
Sweep deprecated props across the React tree:
- Modal: destroyOnClose -> destroyOnHidden, maskClosable -> mask.closable
- Space: direction -> orientation (or removed when redundant)
- Input.Group compact -> Space.Compact block
- Drawer: width -> size
- Spin: tip -> description
- Progress: trailColor -> railColor
- Alert: message -> title
- Popover: overlayClassName -> rootClassName
- BackTop -> FloatButton.BackTop
Also refresh dashboard theming for v6: rename dark/ultra Layout and Menu
tokens (siderBg, darkItemBg, darkSubMenuItemBg, darkPopupBg), tweak gauge
size/stroke, add font-size overrides for Statistic and Progress so the
overview numbers stay legible under v6 defaults.
* chore(frontend): antd v6 polish, theme + modal fixes
- adopt message.useMessage hook + messageBus bridge so HttpUtil messages
inherit ConfigProvider theme tokens
- replace deprecated antd APIs (List, Input addonBefore/After, Empty
imageStyle); introduce InputAddon helper + SettingListItem custom rows
- fix dark/ultra selectors in portaled modals (body.dark,
html[data-theme='ultra-dark']) instead of nonexistent .is-dark/.is-ultra
- add horizontal scroll to clients table; reorder node columns so
actions+enable sit at the left
- swap raw button for antd Button in NodeFormModal test connection
- fix FinalMaskForm nested-form by hoisting it outside OutboundFormModal's
parent Form
- fix advanced "all" JSON tab in InboundFormModal — useMemo on a mutated
ref was stale; compute on every render
- fix chart-on-open for SystemHistory + XrayMetrics modals by adding open
to effect deps (useRef.current doesn't trigger re-runs)
- switch i18next interpolation to single-brace {var} to match locale files
- drop residual Vue mentions in CI workflows and Go comments
* fix(frontend): qr code collapse — open only first panel, allow toggle
ClientQrModal and QrCodeModal both used activeKey without onChange,
forcing every panel open and blocking user toggle. Switch to controlled
state initialized to the first item's key on open, with onChange so
clicks update state.
Also remove unused AppBridge.tsx (superseded by per-page message.useMessage
hook).
* fix(frontend): hover cards, balancer load, routing dnd, modal a11y, outbound crash
- ClientsPage/SettingsPage/XrayPage: add hoverable to bottom card/tabs so
hover affordance matches the top card
- BalancerFormModal: lazy-init useState from props + destroyOnHidden so
the form mounts with saved values instead of relying on a useEffect
sync that could miss the first open
- RoutingTab: rewrite pointer drag — handlers are now defined inside the
pointerdown closure so addEventListener/removeEventListener match;
drag state lives on a ref (from/to/moved) so onUp reads the real
indices, not stale closure values. Adds setPointerCapture so Windows
and touch keep delivering events when the cursor leaves the handle.
- OutboundFormModal/InboundFormModal: blur the focused input before
switching tabs to silence the aria-hidden-on-focused-element warning
- utils.isArrEmpty: return true for undefined/null arrays — the old form
treated undefined as "not empty" which crashed VLESSSettings.fromJson
when json.vnext was missing
* fix(frontend): clipboard reliability + restyle login page
- ClipboardManager.copyText: prefer navigator.clipboard on secure
contexts, fall back to a focused on-screen textarea + execCommand.
Old path used left:-9999px which failed selection in some browsers
and swallowed execCommand's return value, so the "copied" toast
appeared even when nothing made it to the clipboard.
- LoginPage: richer gradient backdrop — five animated colour blobs,
glassmorphic card (backdrop-filter blur + saturate), gradient brand
text/accent, masked grid texture for depth, and a thin gradient
border on the card. Light/dark/ultra each get their own palette.
* Memoize compactAdvancedJson and update deps
Wrap compactAdvancedJson in useCallback (dependent on messageApi) and add it to the dependency array of applyAdvancedJsonToBasic. This ensures a stable function reference for correct dependency tracking and avoids stale closures/unnecessary re-renders in InboundFormModal.tsx.
* style(frontend): prettier charts, drop redundant frame, format net rates
- Sparkline: multi-stop gradient fill, soft drop-shadow under the line,
dashed grid, glowing pulse on the latest-point marker, pill-shaped
tooltip with dashed crosshair
- XrayMetricsModal: glow + pulse on the observatory alive dot,
monospace stamps/listen text
- SystemHistoryModal: keep just the modal's frame around the chart (the
inner wrapper I'd added stacked a second border on top); strip the
decimal from Net Up/Down (25.63 KB/s → 25 KB/s) only on this chart's
formatter
* style(frontend): refined dark/ultra palette + shared pro card frame
- Dark tokens shifted to a cooler, Linear-style palette: page #1a1b1f,
sidebar/header #15161a (recessed nav, darker than cards), card
#23252b, elevated #2d2f37
- Ultra dark: page pure #000 for OLED, sidebar #050507 disappears into
the frame, card #101013 with a clear step, elevated #1a1a1e
- New styles/page-cards.css holds the card border/shadow/hover rules so
all seven content pages (index, clients, inbounds, xray, settings,
nodes, api-docs) share one definition instead of duplicating in each
page CSS
- Dashboard typography: uppercase card titles with letter-spacing,
larger 17px stat values, subtle gradient divider between stat columns,
ellipsis on action labels so "Backup & Restore" doesn't break the
card height at mid widths
- Light --bg-page stays at #e6e8ec for the contrast against white cards
* fix(frontend): wireguard info alignment, blue login dark, embed gitkeep
- align WireGuard info-modal fields with Protocol/Address/Port by wrapping
values in Tag (matches the rest of the dl.info-list rows)
- swap login dark palette from purple to pure blue blobs/accent/brand
- pin web/dist/.gitkeep through gitignore so //go:embed all:dist never
fails on a fresh clone with an empty dist directory
* docs: refresh frontend docs for the React + TS + AntD 6 stack
Update CONTRIBUTING.md and frontend/README.md to describe the migrated
frontend accurately:
- replace Vue 3 / Ant Design Vue 4 references with React 19 / AntD 6 / TS
- swap composables -> hooks, vue-i18n -> react-i18next, createApp -> createRoot
- mention the typecheck step (tsc --noEmit) in the PR checklist
- document the Vite 8.0.13 pin and TypeScript strict mode in conventions
- list the nodes and api-docs entries that were missing from the layout
* style(frontend): improve readability and mobile polish
- bump statistic title/value contrast in dark and ultra-dark so totals
on the inbounds summary card stay legible
- give index card actions explicit colors per theme so links like Stop,
Logs, System History no longer fade into the card background
- show the panel version as a tag next to "3X-UI" on mobile, mirroring
the Xray version tag pattern, and turn it orange when an update is
available
- make the login settings button a proper circle by adding size="large"
+ an explicit border-radius fallback on .toolbar-btn
* feat: jalali calendar support and date formatting fixes
- Wire useDatepicker into IntlUtil and switch jalalian display locale
to fa-IR for clean "1405/07/03 12:00:00" output (drops the awkward
"AP" era suffix that "<lang>-u-ca-persian" produced)
- Drop in persian-calendar-suite for the jalali date picker, with a
light/dark/ultra theme map and CSS overrides so the inline-styled
input stays readable and bg matches the surrounding container
- Force LTR on the picker input so "1405/03/07 00:00" reads naturally
- Pass calendar setting through ClientInfoModal, ClientsPage Duration
tooltip, and ClientFormModal's expiry picker
- Heuristic toMs() in ClientInfoModal so GORM's autoUpdateTime seconds
render as a real date instead of "1348/11/01"
- Persist UpdatedAt on the ClientRecord row in client_service.Update;
previously only the inbound settings JSON was bumped, so the panel
never saw a fresh updated_at after editing a client
* feat(frontend): donate link, panel version label, login lang menu
- Sidebar: add heart donate link to https://donate.sanaei.dev and small panel version under 3X-UI brand
- Login: swap settings-cog for translation icon, drop title, render languages as a direct list
- Vite dev: inject window.X_UI_CUR_VER from config/version so dev mode matches prod
- Translations: add menu.donate across all locales
* fix(xray-update): respect XUI_BIN_FOLDER on Windows
The Windows update path hardcoded "bin/xray-windows-amd64.exe", ignoring
the configured XUI_BIN_FOLDER. In dev mode (folder set to x-ui) this
created a stray bin/ folder while the running binary stayed un-updated.
* Bump Xray to v26.5.9 and minor cleanup
Update Xray release URLs to v26.5.9 in the GitHub Actions workflow and DockerInit.sh. Remove the hardcoded skip for tagVersion "26.5.3" so it will be considered when collecting Xray versions. Apply small formatting fixes: remove an extra blank line in database/db.go, normalize spacing/alignment of Protocol constants in database/model/model.go, and trim a trailing blank line in web/controller/inbound.go.
* fix(frontend): route remaining copy buttons through ClipboardManager
Direct navigator.clipboard calls fail in non-secure contexts (HTTP on a
LAN IP), making the API-docs code copy and security-tab token copy
silently broken. Both now go through ClipboardManager which falls back
to document.execCommand('copy') when navigator.clipboard is unavailable.
* fix(db): store CreatedAt/UpdatedAt in milliseconds
GORM's autoCreateTime/autoUpdateTime tags default to Unix seconds on
int64 fields and overwrite the service-supplied UnixMilli value on
save. The frontend interprets these timestamps as JS Date inputs
(milliseconds), so created/updated columns rendered ~1970 dates. Adding
the :milli qualifier makes GORM match what the service code and UI
expect.
* Improve legacy clipboard copy handling
Refactor ClipboardManager._legacyCopy to better handle focus and selection when copying. The textarea is now appended to the active element's parent (or body) and placed off-screen with aria-hidden and readonly attributes. The code preserves and restores the previous document selection and active element, uses focus({preventScroll: true}) to avoid scrolling, and returns the execCommand('copy') result. This makes legacy copy behavior more robust and less disruptive to the page state.
* fix(lint): drop redundant ok=false in clipboard fallback catch
* chore(deps): bump golang.org/x/net to v0.55.0 for GO-2026-5026
1093 lines
No EOL
57 KiB
JSON
1093 lines
No EOL
57 KiB
JSON
{
|
||
"username": "Nome de Usuário",
|
||
"password": "Senha",
|
||
"login": "Entrar",
|
||
"confirm": "Confirmar",
|
||
"cancel": "Cancelar",
|
||
"close": "Fechar",
|
||
"save": "Salvar",
|
||
"logout": "Sair",
|
||
"create": "Criar",
|
||
"update": "Atualizar",
|
||
"copy": "Copiar",
|
||
"copied": "Copiado",
|
||
"download": "Baixar",
|
||
"remark": "Observação",
|
||
"enable": "Ativado",
|
||
"protocol": "Protocolo",
|
||
"search": "Pesquisar",
|
||
"filter": "Filtrar",
|
||
"loading": "Carregando...",
|
||
"refresh": "Atualizar",
|
||
"clear": "Limpar",
|
||
"second": "Segundo",
|
||
"minute": "Minuto",
|
||
"hour": "Hora",
|
||
"day": "Dia",
|
||
"check": "Verificar",
|
||
"indefinite": "Indeterminado",
|
||
"unlimited": "Ilimitado",
|
||
"none": "Nada",
|
||
"qrCode": "Código QR",
|
||
"info": "Mais Informações",
|
||
"edit": "Editar",
|
||
"delete": "Excluir",
|
||
"reset": "Redefinir",
|
||
"noData": "Sem dados.",
|
||
"copySuccess": "Copiado com Sucesso",
|
||
"sure": "Certo",
|
||
"encryption": "Criptografia",
|
||
"useIPv4ForHost": "Usar IPv4 para o host",
|
||
"transmission": "Transmissão",
|
||
"host": "Servidor",
|
||
"path": "Caminho",
|
||
"camouflage": "Ofuscação",
|
||
"status": "Status",
|
||
"enabled": "Ativado",
|
||
"disabled": "Desativado",
|
||
"depleted": "Encerrado",
|
||
"depletingSoon": "Esgotando",
|
||
"offline": "Offline",
|
||
"online": "Online",
|
||
"domainName": "Nome de Domínio",
|
||
"monitor": "IP de Escuta",
|
||
"certificate": "Certificado Digital",
|
||
"fail": "Falhou",
|
||
"comment": "Comentário",
|
||
"success": "Com Sucesso",
|
||
"lastOnline": "Última vez online",
|
||
"getVersion": "Obter Versão",
|
||
"install": "Instalar",
|
||
"clients": "Clientes",
|
||
"usage": "Uso",
|
||
"twoFactorCode": "Código",
|
||
"remained": "Restante",
|
||
"security": "Segurança",
|
||
"secAlertTitle": "Alerta de Segurança",
|
||
"secAlertSsl": "Esta conexão não é segura. Evite inserir informações confidenciais até que o TLS seja ativado para proteção de dados.",
|
||
"secAlertConf": "Algumas configurações estão vulneráveis a ataques. Recomenda-se reforçar os protocolos de segurança para evitar possíveis violações.",
|
||
"secAlertSSL": "O painel não possui uma conexão segura. Instale o certificado TLS para proteção de dados.",
|
||
"secAlertPanelPort": "A porta padrão do painel é vulnerável. Configure uma porta aleatória ou específica.",
|
||
"secAlertPanelURI": "O caminho URI padrão do painel não é seguro. Configure um caminho URI complexo.",
|
||
"secAlertSubURI": "O caminho URI padrão de inscrição não é seguro. Configure um caminho URI complexo.",
|
||
"secAlertSubJsonURI": "O caminho URI JSON de inscrição padrão não é seguro. Configure um caminho URI complexo.",
|
||
"emptyDnsDesc": "Nenhum servidor DNS adicionado.",
|
||
"emptyFakeDnsDesc": "Nenhum servidor Fake DNS adicionado.",
|
||
"emptyBalancersDesc": "Nenhum balanceador adicionado.",
|
||
"emptyReverseDesc": "Nenhum proxy reverso adicionado.",
|
||
"somethingWentWrong": "Algo deu errado",
|
||
"subscription": {
|
||
"title": "Informações da assinatura",
|
||
"subId": "ID da assinatura",
|
||
"status": "Status",
|
||
"downloaded": "Baixado",
|
||
"uploaded": "Enviado",
|
||
"expiry": "Validade",
|
||
"totalQuota": "Cota total",
|
||
"individualLinks": "Links individuais",
|
||
"active": "Ativo",
|
||
"inactive": "Inativo",
|
||
"unlimited": "Ilimitado",
|
||
"noExpiry": "Sem validade"
|
||
},
|
||
"menu": {
|
||
"theme": "Tema",
|
||
"dark": "Escuro",
|
||
"ultraDark": "Ultra Escuro",
|
||
"dashboard": "Visão Geral",
|
||
"inbounds": "Inbounds",
|
||
"clients": "Clientes",
|
||
"nodes": "Nós",
|
||
"settings": "Panel Settings",
|
||
"xray": "Xray Configs",
|
||
"apiDocs": "Documentação da API",
|
||
"logout": "Sair",
|
||
"link": "Gerenciar",
|
||
"donate": "Doar"
|
||
},
|
||
"pages": {
|
||
"login": {
|
||
"hello": "Olá",
|
||
"title": "Bem-vindo",
|
||
"loginAgain": "Sua sessão expirou, faça login novamente",
|
||
"toasts": {
|
||
"invalidFormData": "O formato dos dados de entrada é inválido.",
|
||
"emptyUsername": "Nome de usuário é obrigatório",
|
||
"emptyPassword": "Senha é obrigatória",
|
||
"wrongUsernameOrPassword": "Nome de usuário, senha ou código de dois fatores inválido.",
|
||
"successLogin": "Você entrou na sua conta com sucesso."
|
||
}
|
||
},
|
||
"index": {
|
||
"title": "Visão Geral",
|
||
"cpu": "CPU",
|
||
"logicalProcessors": "Processadores lógicos",
|
||
"frequency": "Frequência",
|
||
"swap": "Swap",
|
||
"storage": "Armazenamento",
|
||
"memory": "RAM",
|
||
"threads": "Threads",
|
||
"xrayStatus": "Xray",
|
||
"stopXray": "Parar",
|
||
"restartXray": "Reiniciar",
|
||
"xraySwitch": "Versão",
|
||
"xrayUpdates": "Atualizações do Xray",
|
||
"xraySwitchClick": "Escolha a versão para a qual deseja alternar.",
|
||
"xraySwitchClickDesk": "Escolha com cuidado, pois versões mais antigas podem não ser compatíveis com as configurações atuais.",
|
||
"updatePanel": "Atualizar painel",
|
||
"panelUpdateDesc": "Isso atualizará o 3X-UI para a versão mais recente e reiniciará o serviço do painel.",
|
||
"currentPanelVersion": "Versão atual do painel",
|
||
"latestPanelVersion": "Última versão do painel",
|
||
"panelUpToDate": "O painel está atualizado",
|
||
"upToDate": "Atualizado",
|
||
"xrayStatusUnknown": "Desconhecido",
|
||
"xrayStatusRunning": "Em execução",
|
||
"xrayStatusStop": "Parado",
|
||
"xrayStatusError": "Erro",
|
||
"xrayErrorPopoverTitle": "Ocorreu um erro ao executar o Xray",
|
||
"operationHours": "Tempo de Atividade",
|
||
"systemHistoryTitle": "Histórico do Sistema",
|
||
"charts": "Gráficos",
|
||
"xrayMetricsTitle": "Métricas do Xray",
|
||
"xrayMetricsDisabled": "Endpoint de métricas do Xray não configurado",
|
||
"xrayMetricsHint": "Adicione um bloco metrics de nível superior à configuração do xray com tag metrics_out e listen 127.0.0.1:11111, depois reinicie o xray.",
|
||
"xrayObservatoryEmpty": "Ainda não há dados do Observatory",
|
||
"xrayObservatoryHint": "Adicione um bloco observatory à configuração do xray listando as tags de outbound a sondar, depois reinicie o xray.",
|
||
"xrayObservatoryTagPlaceholder": "Selecionar outbound",
|
||
"xrayObservatoryAlive": "Ativo",
|
||
"xrayObservatoryDead": "Inativo",
|
||
"xrayObservatoryLastSeen": "Visto pela última vez",
|
||
"xrayObservatoryLastTry": "Última tentativa",
|
||
"trendLast2Min": "Últimos 2 minutos",
|
||
"systemLoad": "Carga do Sistema",
|
||
"systemLoadDesc": "Média de carga do sistema nos últimos 1, 5 e 15 minutos",
|
||
"connectionCount": "Estatísticas de Conexão",
|
||
"ipAddresses": "Endereços IP",
|
||
"toggleIpVisibility": "Alternar visibilidade do IP",
|
||
"overallSpeed": "Velocidade geral",
|
||
"upload": "Upload",
|
||
"download": "Download",
|
||
"totalData": "Dados totais",
|
||
"sent": "Enviado",
|
||
"received": "Recebido",
|
||
"documentation": "Documentação",
|
||
"xraySwitchVersionDialog": "Você realmente deseja alterar a versão do Xray?",
|
||
"xraySwitchVersionDialogDesc": "Isso mudará a versão do Xray para #version#.",
|
||
"xraySwitchVersionPopover": "Xray atualizado com sucesso",
|
||
"panelUpdateDialog": "Deseja realmente atualizar o painel?",
|
||
"panelUpdateDialogDesc": "Isso atualizará o 3X-UI para #version# e reiniciará o serviço do painel.",
|
||
"panelUpdateCheckPopover": "Falha na verificação de atualização do painel",
|
||
"panelUpdateStartedPopover": "Atualização do painel iniciada",
|
||
"geofileUpdateDialog": "Você realmente deseja atualizar o geofile?",
|
||
"geofileUpdateDialogDesc": "Isso atualizará o arquivo #filename#.",
|
||
"geofilesUpdateDialogDesc": "Isso atualizará todos os arquivos.",
|
||
"geofilesUpdateAll": "Atualizar tudo",
|
||
"geofileUpdatePopover": "Geofile atualizado com sucesso",
|
||
"customGeoTitle": "GeoSite / GeoIP personalizados",
|
||
"customGeoAdd": "Adicionar",
|
||
"customGeoType": "Tipo",
|
||
"customGeoAlias": "Alias",
|
||
"customGeoUrl": "URL",
|
||
"customGeoEnabled": "Ativado",
|
||
"customGeoLastUpdated": "Última atualização",
|
||
"customGeoExtColumn": "Roteamento (ext:…)",
|
||
"customGeoToastUpdateAll": "Todas as fontes personalizadas foram atualizadas",
|
||
"customGeoActions": "Ações",
|
||
"customGeoEdit": "Editar",
|
||
"customGeoDelete": "Excluir",
|
||
"customGeoDownload": "Atualizar agora",
|
||
"customGeoModalAdd": "Adicionar geo personalizado",
|
||
"customGeoModalEdit": "Editar geo personalizado",
|
||
"customGeoModalSave": "Salvar",
|
||
"customGeoDeleteConfirm": "Excluir esta fonte geo personalizada?",
|
||
"customGeoRoutingHint": "Nas regras de roteamento use a coluna de valor como ext:arquivo.dat:tag (substitua a tag).",
|
||
"customGeoInvalidId": "ID de recurso inválido",
|
||
"customGeoAliasesError": "Falha ao carregar aliases geo personalizados",
|
||
"customGeoValidationAlias": "O alias só pode conter letras minúsculas, dígitos, - e _",
|
||
"customGeoValidationUrl": "A URL deve começar com http:// ou https://",
|
||
"customGeoAliasPlaceholder": "a-z 0-9 _ -",
|
||
"customGeoAliasLabelSuffix": " (personalizado)",
|
||
"customGeoToastList": "Lista de geo personalizado",
|
||
"customGeoToastAdd": "Adicionar geo personalizado",
|
||
"customGeoToastUpdate": "Atualizar geo personalizado",
|
||
"customGeoToastDelete": "Geofile personalizado “{{ .fileName }}” excluído",
|
||
"customGeoToastDownload": "Geofile “{{ .fileName }}” atualizado",
|
||
"customGeoErrInvalidType": "O tipo deve ser geosite ou geoip",
|
||
"customGeoErrAliasRequired": "Alias é obrigatório",
|
||
"customGeoErrAliasPattern": "O alias contém caracteres não permitidos",
|
||
"customGeoErrAliasReserved": "Este alias é reservado",
|
||
"customGeoErrUrlRequired": "URL é obrigatória",
|
||
"customGeoErrInvalidUrl": "URL inválida",
|
||
"customGeoErrUrlScheme": "A URL deve usar http ou https",
|
||
"customGeoErrUrlHost": "Host da URL inválido",
|
||
"customGeoErrDuplicateAlias": "Este alias já está em uso para este tipo",
|
||
"customGeoErrNotFound": "Fonte geo personalizada não encontrada",
|
||
"customGeoErrDownload": "Falha no download",
|
||
"customGeoErrUpdateAllIncomplete": "Falha ao atualizar uma ou mais fontes geo personalizadas",
|
||
"customGeoEmpty": "Ainda não há fontes geo personalizadas — clique em Adicionar para criar uma",
|
||
"dontRefresh": "Instalação em andamento, por favor não atualize a página",
|
||
"logs": "Logs",
|
||
"config": "Configuração",
|
||
"backup": "Backup",
|
||
"backupTitle": "Backup & Restauração",
|
||
"exportDatabase": "Backup",
|
||
"exportDatabaseDesc": "Clique para baixar um arquivo .db contendo um backup do seu banco de dados atual para o seu dispositivo.",
|
||
"importDatabase": "Restaurar",
|
||
"importDatabaseDesc": "Clique para selecionar e enviar um arquivo .db do seu dispositivo para restaurar seu banco de dados a partir de um backup.",
|
||
"importDatabaseSuccess": "O banco de dados foi importado com sucesso",
|
||
"importDatabaseError": "Ocorreu um erro ao importar o banco de dados",
|
||
"readDatabaseError": "Ocorreu um erro ao ler o banco de dados",
|
||
"getDatabaseError": "Ocorreu um erro ao recuperar o banco de dados",
|
||
"getConfigError": "Ocorreu um erro ao recuperar o arquivo de configuração"
|
||
},
|
||
"inbounds": {
|
||
"title": "Inbounds",
|
||
"totalDownUp": "Total Enviado/Recebido",
|
||
"totalUsage": "Uso Total",
|
||
"inboundCount": "Total de Inbounds",
|
||
"operate": "Menu",
|
||
"enable": "Ativado",
|
||
"remark": "Observação",
|
||
"node": "Nó",
|
||
"deployTo": "Implantar em",
|
||
"localPanel": "Painel local",
|
||
"fallbacks": {
|
||
"title": "Fallbacks",
|
||
"help": "Quando uma conexão neste inbound não corresponde a nenhum cliente, redirecione-a para outro inbound. Escolha um filho abaixo e os campos de roteamento (SNI / ALPN / Path / xver) são preenchidos automaticamente a partir do transporte dele — a maioria das configurações não precisa de mais ajustes. Cada filho deve escutar em 127.0.0.1 com security=none.",
|
||
"empty": "Ainda sem fallbacks",
|
||
"add": "Adicionar fallback",
|
||
"pickInbound": "Escolha um inbound",
|
||
"matchAny": "qualquer",
|
||
"rederive": "Preencher a partir do filho",
|
||
"rederived": "Preenchido a partir do filho",
|
||
"editAdvanced": "Editar campos de roteamento",
|
||
"hideAdvanced": "Ocultar avançado",
|
||
"quickAddAll": "Adicionar todos os elegíveis",
|
||
"quickAdded": "{n} fallback(s) adicionado(s)",
|
||
"quickAddedNone": "Nenhum inbound novo elegível para adicionar",
|
||
"routesWhen": "Roteia quando",
|
||
"defaultCatchAll": "Padrão — captura qualquer outra coisa"
|
||
},
|
||
"protocol": "Protocolo",
|
||
"port": "Porta",
|
||
"portMap": "Porta Mapeada",
|
||
"traffic": "Tráfego",
|
||
"details": "Detalhes",
|
||
"transportConfig": "Transporte",
|
||
"expireDate": "Duração",
|
||
"createdAt": "Criado",
|
||
"updatedAt": "Atualizado",
|
||
"resetTraffic": "Redefinir Tráfego",
|
||
"addInbound": "Adicionar Inbound",
|
||
"generalActions": "Ações Gerais",
|
||
"modifyInbound": "Modificar Inbound",
|
||
"deleteInbound": "Excluir Inbound",
|
||
"deleteInboundContent": "Tem certeza de que deseja excluir o inbound?",
|
||
"deleteClient": "Excluir Cliente",
|
||
"deleteClientContent": "Tem certeza de que deseja excluir o cliente?",
|
||
"resetTrafficContent": "Tem certeza de que deseja redefinir o tráfego?",
|
||
"copyLink": "Copiar URL",
|
||
"address": "Endereço",
|
||
"network": "Rede",
|
||
"destinationPort": "Porta de Destino",
|
||
"targetAddress": "Endereço de Destino",
|
||
"monitorDesc": "Deixe em branco para ouvir todos os IPs",
|
||
"meansNoLimit": "= Ilimitado. (unidade: GB)",
|
||
"totalFlow": "Fluxo Total",
|
||
"leaveBlankToNeverExpire": "Deixe em branco para nunca expirar",
|
||
"noRecommendKeepDefault": "Recomenda-se manter o padrão",
|
||
"certificatePath": "Caminho",
|
||
"certificateContent": "Conteúdo",
|
||
"publicKey": "Chave Pública",
|
||
"privatekey": "Chave Privada",
|
||
"clickOnQRcode": "Clique no Código QR para Copiar",
|
||
"client": "Cliente",
|
||
"export": "Exportar Todos os URLs",
|
||
"clone": "Clonar",
|
||
"cloneInbound": "Clonar",
|
||
"cloneInboundContent": "Todas as configurações deste inbound, exceto Porta, IP de Escuta e Clientes, serão aplicadas ao clone.",
|
||
"cloneInboundOk": "Clonar",
|
||
"resetAllTraffic": "Redefinir Tráfego de Todos os Inbounds",
|
||
"resetAllTrafficTitle": "Redefinir Tráfego de Todos os Inbounds",
|
||
"resetAllTrafficContent": "Tem certeza de que deseja redefinir o tráfego de todos os inbounds?",
|
||
"resetInboundClientTraffics": "Redefinir Tráfego dos Clientes",
|
||
"resetInboundClientTrafficTitle": "Redefinir Tráfego dos Clientes",
|
||
"resetInboundClientTrafficContent": "Tem certeza de que deseja redefinir o tráfego dos clientes deste inbound?",
|
||
"resetAllClientTraffics": "Redefinir Tráfego de Todos os Clientes",
|
||
"resetAllClientTrafficTitle": "Redefinir Tráfego de Todos os Clientes",
|
||
"resetAllClientTrafficContent": "Tem certeza de que deseja redefinir o tráfego de todos os clientes?",
|
||
"delDepletedClients": "Excluir Clientes Esgotados",
|
||
"delDepletedClientsTitle": "Excluir Clientes Esgotados",
|
||
"delDepletedClientsContent": "Tem certeza de que deseja excluir todos os clientes esgotados?",
|
||
"email": "Email",
|
||
"emailDesc": "Por favor, forneça um endereço de e-mail único.",
|
||
"IPLimit": "Limite de IP",
|
||
"IPLimitDesc": "Desativa o inbound se o número ultrapassar o valor definido. (0 = desativar)",
|
||
"IPLimitlog": "Log de IP",
|
||
"IPLimitlogDesc": "O histórico de IPs. (para ativar o inbound após a desativação, limpe o log)",
|
||
"IPLimitlogclear": "Limpar o Log",
|
||
"setDefaultCert": "Definir Certificado pelo Painel",
|
||
"streamTab": "Stream",
|
||
"securityTab": "Segurança",
|
||
"sniffingTab": "Sniffing",
|
||
"sniffingMetadataOnly": "Apenas metadados",
|
||
"sniffingRouteOnly": "Apenas roteamento",
|
||
"sniffingIpsExcluded": "IPs excluídos",
|
||
"sniffingDomainsExcluded": "Domínios excluídos",
|
||
"decryption": "Descriptografia",
|
||
"encryption": "Criptografia",
|
||
"vlessAuthX25519": "Autenticação X25519",
|
||
"vlessAuthMlkem768": "Autenticação ML-KEM-768",
|
||
"vlessAuthCustom": "Personalizado",
|
||
"vlessAuthSelected": "Selecionado: {auth}",
|
||
"advanced": {
|
||
"title": "Seções JSON do inbound",
|
||
"subtitle": "JSON completo do inbound e editores específicos para settings, sniffing e streamSettings.",
|
||
"all": "Tudo",
|
||
"allHelp": "Objeto inbound completo com todos os campos em um único editor.",
|
||
"settings": "Configurações",
|
||
"settingsHelp": "Wrapper do bloco settings do Xray:",
|
||
"sniffing": "Sniffing",
|
||
"sniffingHelp": "Wrapper do bloco sniffing do Xray:",
|
||
"stream": "Stream",
|
||
"streamHelp": "Wrapper do bloco stream do Xray:",
|
||
"jsonErrorPrefix": "JSON avançado"
|
||
},
|
||
"telegramDesc": "Por favor, forneça o ID do Chat do Telegram. (use o comando '/id' no bot) ou ({'@'}userinfobot)",
|
||
"subscriptionDesc": "Para encontrar seu URL de assinatura, navegue até 'Detalhes'. Além disso, você pode usar o mesmo nome para vários clientes.",
|
||
"info": "Informações",
|
||
"same": "Igual",
|
||
"inboundData": "Dados do Inbound",
|
||
"exportInbound": "Exportar Inbound",
|
||
"import": "Importar",
|
||
"importInbound": "Importar um Inbound",
|
||
"periodicTrafficResetTitle": "Reset de Tráfego",
|
||
"periodicTrafficResetDesc": "Reinicia automaticamente o contador de tráfego em intervalos especificados",
|
||
"lastReset": "Último Reset",
|
||
"periodicTrafficReset": {
|
||
"never": "Nunca",
|
||
"daily": "Diariamente",
|
||
"weekly": "Semanalmente",
|
||
"monthly": "Mensalmente",
|
||
"hourly": "A cada hora"
|
||
},
|
||
"toasts": {
|
||
"obtain": "Obter",
|
||
"updateSuccess": "A atualização foi bem-sucedida",
|
||
"logCleanSuccess": "O log foi limpo",
|
||
"inboundsUpdateSuccess": "Entradas atualizadas com sucesso",
|
||
"inboundUpdateSuccess": "Entrada atualizada com sucesso",
|
||
"inboundCreateSuccess": "Entrada criada com sucesso",
|
||
"inboundDeleteSuccess": "Entrada excluída com sucesso",
|
||
"inboundClientAddSuccess": "Cliente(s) de entrada adicionado(s)",
|
||
"inboundClientDeleteSuccess": "Cliente de entrada excluído",
|
||
"inboundClientUpdateSuccess": "Cliente de entrada atualizado",
|
||
"delDepletedClientsSuccess": "Todos os clientes esgotados foram excluídos",
|
||
"resetAllClientTrafficSuccess": "Todo o tráfego do cliente foi reiniciado",
|
||
"resetAllTrafficSuccess": "Todo o tráfego foi reiniciado",
|
||
"resetInboundClientTrafficSuccess": "O tráfego foi reiniciado",
|
||
"resetInboundTrafficSuccess": "O tráfego de entrada foi reiniciado",
|
||
"trafficGetError": "Erro ao obter tráfegos",
|
||
"getNewX25519CertError": "Erro ao obter o certificado X25519.",
|
||
"getNewmldsa65Error": "Erro ao obter o certificado mldsa65.",
|
||
"getNewVlessEncError": "Erro ao obter o certificado VlessEnc."
|
||
},
|
||
"stream": {
|
||
"general": {
|
||
"request": "Requisição",
|
||
"response": "Resposta",
|
||
"name": "Nome",
|
||
"value": "Valor"
|
||
},
|
||
"tcp": {
|
||
"version": "Versão",
|
||
"method": "Método",
|
||
"path": "Caminho",
|
||
"status": "Status",
|
||
"statusDescription": "Descrição do Status",
|
||
"requestHeader": "Cabeçalho da Requisição",
|
||
"responseHeader": "Cabeçalho da Resposta"
|
||
}
|
||
}
|
||
},
|
||
"clients": {
|
||
"add": "Adicionar cliente",
|
||
"edit": "Editar cliente",
|
||
"submitAdd": "Adicionar cliente",
|
||
"submitEdit": "Salvar alterações",
|
||
"clientCount": "Número de clientes",
|
||
"bulk": "Adicionar em lote",
|
||
"copyFromInbound": "Copiar clientes do inbound",
|
||
"copyToInbound": "Copiar clientes para",
|
||
"copySelected": "Copiar selecionados",
|
||
"copySource": "Origem",
|
||
"copyEmailPreview": "Prévia do e-mail resultante",
|
||
"copySelectSourceFirst": "Selecione primeiro um inbound de origem.",
|
||
"copyResult": "Resultado da cópia",
|
||
"copyResultSuccess": "Copiado com sucesso",
|
||
"copyResultNone": "Nada a copiar: nenhum cliente selecionado ou a origem está vazia",
|
||
"copyResultErrors": "Erros de cópia",
|
||
"copyFlowLabel": "Flow para os novos clientes (VLESS)",
|
||
"copyFlowHint": "Aplicado a todos os clientes copiados. Deixe em branco para ignorar.",
|
||
"selectAll": "Selecionar tudo",
|
||
"clearAll": "Limpar tudo",
|
||
"method": "Método",
|
||
"first": "Primeiro",
|
||
"last": "Último",
|
||
"ipLog": "Registro de IP",
|
||
"prefix": "Prefixo",
|
||
"postfix": "Sufixo",
|
||
"delayedStart": "Iniciar após o primeiro uso",
|
||
"expireDays": "Duração",
|
||
"days": "Dia(s)",
|
||
"renew": "Renovação automática",
|
||
"renewDesc": "Renovação automática após a expiração. (0 = desativar) (unidade: dia)",
|
||
"title": "Clientes",
|
||
"actions": "Ações",
|
||
"totalGB": "Total enviado/recebido (GB)",
|
||
"expiryTime": "Expiração",
|
||
"addClients": "Adicionar clientes",
|
||
"limitIp": "Limite de IP",
|
||
"password": "Senha",
|
||
"subId": "ID da assinatura",
|
||
"online": "Online",
|
||
"email": "E-mail",
|
||
"comment": "Comentário",
|
||
"traffic": "Tráfego",
|
||
"offline": "Offline",
|
||
"addTitle": "Adicionar cliente",
|
||
"qrCode": "Código QR",
|
||
"moreInformation": "Mais informações",
|
||
"delete": "Excluir",
|
||
"reset": "Redefinir tráfego",
|
||
"editTitle": "Editar cliente",
|
||
"client": "Cliente",
|
||
"enabled": "Habilitado",
|
||
"remaining": "Restante",
|
||
"duration": "Duração",
|
||
"attachedInbounds": "Inbounds associados",
|
||
"selectInbound": "Selecione um ou mais inbounds",
|
||
"noSubId": "Este cliente não tem subId, sem link compartilhável.",
|
||
"noLinks": "Sem links compartilháveis — associe primeiro este cliente a um inbound compatível com o protocolo.",
|
||
"link": "Link",
|
||
"resetNotPossible": "Associe primeiro este cliente a um inbound.",
|
||
"general": "Geral",
|
||
"resetAllTraffics": "Redefinir o tráfego de todos os clientes",
|
||
"resetAllTrafficsTitle": "Redefinir o tráfego de todos os clientes?",
|
||
"resetAllTrafficsContent": "Os contadores de envio/recebimento de cada cliente vão a zero. Cota e expiração não são afetadas. Não é possível desfazer.",
|
||
"empty": "Ainda não há clientes — adicione um para começar.",
|
||
"deleteConfirmTitle": "Excluir o cliente {email}?",
|
||
"deleteConfirmContent": "Isto remove o cliente de cada inbound associado e descarta o registro de tráfego. Não é possível desfazer.",
|
||
"deleteSelected": "Excluir ({count})",
|
||
"bulkDeleteConfirmTitle": "Excluir {count} clientes?",
|
||
"bulkDeleteConfirmContent": "Cada cliente selecionado é removido dos inbounds associados e o registro de tráfego é descartado. Não é possível desfazer.",
|
||
"delDepleted": "Excluir esgotados",
|
||
"delDepletedConfirmTitle": "Excluir clientes esgotados?",
|
||
"delDepletedConfirmContent": "Remove todos os clientes cuja cota de tráfego foi esgotada ou cuja expiração já passou. Não é possível desfazer.",
|
||
"auth": "Auth",
|
||
"hysteriaAuth": "Auth do Hysteria",
|
||
"uuid": "UUID",
|
||
"flow": "Flow",
|
||
"reverseTag": "Reverse tag",
|
||
"reverseTagPlaceholder": "Reverse tag opcional",
|
||
"telegramId": "ID de usuário do Telegram",
|
||
"telegramIdPlaceholder": "ID numérico de usuário do Telegram (0 = nenhum)",
|
||
"created": "Criado",
|
||
"updated": "Atualizado",
|
||
"ipLimit": "Limite de IP",
|
||
"toasts": {
|
||
"deleted": "Cliente excluído",
|
||
"trafficReset": "Tráfego redefinido",
|
||
"allTrafficsReset": "Tráfego de todos os clientes redefinido",
|
||
"bulkDeleted": "{count} clientes excluídos",
|
||
"bulkDeletedMixed": "{ok} excluídos, {failed} com falha",
|
||
"bulkCreated": "{count} clientes criados",
|
||
"bulkCreatedMixed": "{ok} criados, {failed} com falha",
|
||
"delDepleted": "{count} clientes esgotados excluídos"
|
||
}
|
||
},
|
||
"nodes": {
|
||
"title": "Nós",
|
||
"addNode": "Adicionar nó",
|
||
"editNode": "Editar nó",
|
||
"totalNodes": "Total de nós",
|
||
"onlineNodes": "Online",
|
||
"offlineNodes": "Offline",
|
||
"avgLatency": "Latência média",
|
||
"name": "Nome",
|
||
"namePlaceholder": "ex.: de-frankfurt-1",
|
||
"addressPlaceholder": "panel.example.com ou 1.2.3.4",
|
||
"remark": "Observação",
|
||
"scheme": "Esquema",
|
||
"address": "Endereço",
|
||
"port": "Porta",
|
||
"basePath": "Caminho base",
|
||
"apiToken": "Token da API",
|
||
"apiTokenPlaceholder": "Token da página de Configurações do painel remoto",
|
||
"apiTokenHint": "O painel remoto exibe o token da API em Configurações → Token da API.",
|
||
"regenerate": "Regenerar token",
|
||
"regenerateConfirm": "Regenerar invalida o token atual. Qualquer painel central que o utilize perderá acesso até ser atualizado. Continuar?",
|
||
"allowPrivateAddress": "Permitir endereço privado",
|
||
"allowPrivateAddressHint": "Ativar apenas para nós em uma rede privada ou VPN.",
|
||
"enable": "Ativado",
|
||
"status": "Status",
|
||
"cpu": "CPU",
|
||
"mem": "Memória",
|
||
"uptime": "Tempo ativo",
|
||
"latency": "Latência",
|
||
"lastHeartbeat": "Último heartbeat",
|
||
"xrayVersion": "Versão do Xray",
|
||
"panelVersion": "Versão do painel",
|
||
"actions": "Ações",
|
||
"probe": "Sondar agora",
|
||
"testConnection": "Testar conexão",
|
||
"connectionOk": "Conexão OK ({ms} ms)",
|
||
"connectionFailed": "Falha na conexão",
|
||
"never": "nunca",
|
||
"justNow": "agora mesmo",
|
||
"deleteConfirmTitle": "Excluir o nó \"{name}\"?",
|
||
"deleteConfirmContent": "Isso interrompe o monitoramento do nó. O painel remoto em si não é afetado.",
|
||
"statusValues": {
|
||
"online": "Online",
|
||
"offline": "Offline",
|
||
"unknown": "Desconhecido"
|
||
},
|
||
"toasts": {
|
||
"list": "Falha ao carregar os nós",
|
||
"obtain": "Falha ao carregar o nó",
|
||
"add": "Adicionar nó",
|
||
"update": "Atualizar nó",
|
||
"delete": "Excluir nó",
|
||
"deleted": "Nó excluído",
|
||
"test": "Testar conexão",
|
||
"fillRequired": "Nome, endereço, porta e token da API são obrigatórios",
|
||
"probeFailed": "Falha na sondagem"
|
||
}
|
||
},
|
||
"settings": {
|
||
"title": "Configurações do Painel",
|
||
"save": "Salvar",
|
||
"infoDesc": "Toda alteração feita aqui precisa ser salva. Reinicie o painel para aplicar as alterações.",
|
||
"restartPanel": "Reiniciar Painel",
|
||
"restartPanelDesc": "Tem certeza de que deseja reiniciar o painel? Se não conseguir acessar o painel após reiniciar, consulte os logs do painel no servidor.",
|
||
"restartPanelSuccess": "O painel foi reiniciado com sucesso",
|
||
"actions": "Ações",
|
||
"resetDefaultConfig": "Redefinir para Padrão",
|
||
"panelSettings": "Geral",
|
||
"securitySettings": "Autenticação",
|
||
"TGBotSettings": "Bot do Telegram",
|
||
"panelListeningIP": "IP de Escuta",
|
||
"panelListeningIPDesc": "O endereço IP para o painel web. (deixe em branco para escutar em todos os IPs)",
|
||
"panelListeningDomain": "Domínio de Escuta",
|
||
"panelListeningDomainDesc": "O nome de domínio para o painel web. (deixe em branco para escutar em todos os domínios e IPs)",
|
||
"panelPort": "Porta de Escuta",
|
||
"panelPortDesc": "O número da porta para o painel web. (deve ser uma porta não usada)",
|
||
"publicKeyPath": "Caminho da Chave Pública",
|
||
"publicKeyPathDesc": "O caminho do arquivo de chave pública para o painel web. (começa com ‘/‘)",
|
||
"privateKeyPath": "Caminho da Chave Privada",
|
||
"privateKeyPathDesc": "O caminho do arquivo de chave privada para o painel web. (começa com ‘/‘)",
|
||
"panelUrlPath": "Caminho URI",
|
||
"panelUrlPathDesc": "O caminho URI para o painel web. (começa com ‘/‘ e termina com ‘/‘)",
|
||
"pageSize": "Tamanho da Paginação",
|
||
"pageSizeDesc": "Definir o tamanho da página para a tabela de entradas. (0 = desativado)",
|
||
"remarkModel": "Modelo de Observação & Caractere de Separação",
|
||
"datepicker": "Tipo de Calendário",
|
||
"datepickerPlaceholder": "Selecionar data",
|
||
"datepickerDescription": "Tarefas agendadas serão executadas com base neste calendário.",
|
||
"sampleRemark": "Exemplo de Observação",
|
||
"oldUsername": "Nome de Usuário Atual",
|
||
"currentPassword": "Senha Atual",
|
||
"newUsername": "Novo Nome de Usuário",
|
||
"newPassword": "Nova Senha",
|
||
"telegramBotEnable": "Ativar Bot do Telegram",
|
||
"telegramBotEnableDesc": "Ativa o bot do Telegram.",
|
||
"telegramToken": "Token do Telegram",
|
||
"telegramTokenDesc": "O token do bot do Telegram obtido de '{'@'}BotFather'.",
|
||
"telegramProxy": "Proxy SOCKS",
|
||
"telegramProxyDesc": "Ativa o proxy SOCKS5 para conectar ao Telegram. (ajuste as configurações conforme o guia)",
|
||
"telegramAPIServer": "API Server do Telegram",
|
||
"telegramAPIServerDesc": "O servidor API do Telegram a ser usado. Deixe em branco para usar o servidor padrão.",
|
||
"telegramChatId": "ID de Chat do Administrador",
|
||
"telegramChatIdDesc": "O(s) ID(s) de Chat do Administrador no Telegram. (separado por vírgulas)(obtenha aqui {'@'}userinfobot) ou (use o comando '/id' no bot)",
|
||
"telegramNotifyTime": "Hora da Notificação",
|
||
"telegramNotifyTimeDesc": "O horário de notificação do bot do Telegram configurado para relatórios periódicos. (use o formato de tempo do crontab)",
|
||
"tgNotifyBackup": "Backup do Banco de Dados",
|
||
"tgNotifyBackupDesc": "Enviar arquivo de backup do banco de dados junto com o relatório.",
|
||
"tgNotifyLogin": "Notificação de Login",
|
||
"tgNotifyLoginDesc": "Receba notificações sobre o nome de usuário, endereço IP e horário sempre que alguém tentar fazer login no seu painel web.",
|
||
"sessionMaxAge": "Duração da Sessão",
|
||
"sessionMaxAgeDesc": "A duração pela qual você pode permanecer logado. (unidade: minuto)",
|
||
"expireTimeDiff": "Notificação de Expiração",
|
||
"expireTimeDiffDesc": "Receba notificações sobre a data de expiração ao atingir esse limite. (unidade: dia)",
|
||
"trafficDiff": "Notificação de Limite de Tráfego",
|
||
"trafficDiffDesc": "Receba notificações sobre o limite de tráfego ao atingir esse limite. (unidade: GB)",
|
||
"tgNotifyCpu": "Notificação de Carga da CPU",
|
||
"tgNotifyCpuDesc": "Receba notificações se a carga da CPU ultrapassar esse limite. (unidade: %)",
|
||
"timeZone": "Fuso Horário",
|
||
"timeZoneDesc": "As tarefas agendadas serão executadas com base nesse fuso horário.",
|
||
"subSettings": "Assinatura",
|
||
"subEnable": "Ativar Serviço de Assinatura",
|
||
"subEnableDesc": "Ativa o serviço de assinatura.",
|
||
"subJsonEnable": "Ativar/Desativar o endpoint de assinatura JSON de forma independente.",
|
||
"subTitle": "Título da Assinatura",
|
||
"subTitleDesc": "Título exibido no cliente VPN",
|
||
"subSupportUrl": "URL de Suporte",
|
||
"subSupportUrlDesc": "Link de suporte técnico exibido no cliente VPN",
|
||
"subProfileUrl": "URL de Perfil",
|
||
"subProfileUrlDesc": "Um link para o seu site exibido no cliente VPN",
|
||
"subAnnounce": "Anúncio",
|
||
"subAnnounceDesc": "O texto do anúncio exibido no cliente VPN",
|
||
"subEnableRouting": "Ativar roteamento",
|
||
"subEnableRoutingDesc": "Configuração global para habilitar o roteamento no cliente VPN. (Apenas para Happ)",
|
||
"subRoutingRules": "Regras de roteamento",
|
||
"subRoutingRulesDesc": "Regras de roteamento globais para o cliente VPN. (Apenas para Happ)",
|
||
"subListen": "IP de Escuta",
|
||
"subListenDesc": "O endereço IP para o serviço de assinatura. (deixe em branco para escutar em todos os IPs)",
|
||
"subPort": "Porta de Escuta",
|
||
"subPortDesc": "O número da porta para o serviço de assinatura. (deve ser uma porta não usada)",
|
||
"subCertPath": "Caminho da Chave Pública",
|
||
"subCertPathDesc": "O caminho do arquivo de chave pública para o serviço de assinatura. (começa com ‘/‘)",
|
||
"subKeyPath": "Caminho da Chave Privada",
|
||
"subKeyPathDesc": "O caminho do arquivo de chave privada para o serviço de assinatura. (começa com ‘/‘)",
|
||
"subPath": "Caminho URI",
|
||
"subPathDesc": "O caminho URI para o serviço de assinatura. (começa com ‘/‘ e termina com ‘/‘)",
|
||
"subDomain": "Domínio de Escuta",
|
||
"subDomainDesc": "O nome de domínio para o serviço de assinatura. (deixe em branco para escutar em todos os domínios e IPs)",
|
||
"subUpdates": "Intervalos de Atualização",
|
||
"subUpdatesDesc": "Os intervalos de atualização da URL de assinatura nos aplicativos de cliente. (unidade: hora)",
|
||
"subEncrypt": "Codificar",
|
||
"subEncryptDesc": "O conteúdo retornado pelo serviço de assinatura será codificado em Base64.",
|
||
"subShowInfo": "Mostrar Informações de Uso",
|
||
"subShowInfoDesc": "O tráfego restante e a data serão exibidos nos aplicativos de cliente.",
|
||
"subEmailInRemark": "Incluir Email no nome",
|
||
"subEmailInRemarkDesc": "Incluir o email do cliente no nome do perfil de assinatura.",
|
||
"subURI": "URI de Proxy Reverso",
|
||
"subURIDesc": "O caminho URI da URL de assinatura para uso por trás de proxies.",
|
||
"externalTrafficInformEnable": "Informações de tráfego externo",
|
||
"externalTrafficInformEnableDesc": "Informar a API externa sobre cada atualização de tráfego.",
|
||
"externalTrafficInformURI": "URI de informação de tráfego externo",
|
||
"externalTrafficInformURIDesc": "As atualizações de tráfego são enviadas para este URI.",
|
||
"restartXrayOnClientDisable": "Reiniciar Xray Após Desativação Automática",
|
||
"restartXrayOnClientDisableDesc": "Quando um cliente for desativado automaticamente por expiração ou limite de tráfego, reinicie o Xray.",
|
||
"fragment": "Fragmentação",
|
||
"fragmentDesc": "Ativa a fragmentação para o pacote TLS hello.",
|
||
"fragmentSett": "Configurações de Fragmentação",
|
||
"noisesDesc": "Ativar Noises.",
|
||
"noisesSett": "Configurações de Noises",
|
||
"mux": "Mux",
|
||
"muxDesc": "Transmitir múltiplos fluxos de dados independentes dentro de um fluxo de dados estabelecido.",
|
||
"muxSett": "Configurações de Mux",
|
||
"direct": "Conexão Direta",
|
||
"directDesc": "Estabelece conexões diretamente com domínios ou intervalos de IP de um país específico.",
|
||
"notifications": "Notificações",
|
||
"certs": "Certificados",
|
||
"externalTraffic": "Tráfego Externo",
|
||
"dateAndTime": "Data e Hora",
|
||
"proxyAndServer": "Proxy e Servidor",
|
||
"intervals": "Intervalos",
|
||
"information": "Informação",
|
||
"language": "Idioma",
|
||
"telegramBotLanguage": "Idioma do Bot do Telegram",
|
||
"security": {
|
||
"admin": "Credenciais de administrador",
|
||
"twoFactor": "Autenticação de dois fatores",
|
||
"twoFactorEnable": "Ativar 2FA",
|
||
"twoFactorEnableDesc": "Adiciona uma camada extra de autenticação para mais segurança.",
|
||
"twoFactorModalSetTitle": "Ativar autenticação de dois fatores",
|
||
"twoFactorModalDeleteTitle": "Desativar autenticação de dois fatores",
|
||
"twoFactorModalSteps": "Para configurar a autenticação de dois fatores, siga alguns passos:",
|
||
"twoFactorModalFirstStep": "1. Escaneie este QR code no aplicativo de autenticação ou copie o token próximo ao QR code e cole no aplicativo",
|
||
"twoFactorModalSecondStep": "2. Digite o código do aplicativo",
|
||
"twoFactorModalRemoveStep": "Digite o código do aplicativo para remover a autenticação de dois fatores.",
|
||
"twoFactorModalChangeCredentialsTitle": "Alterar credenciais",
|
||
"twoFactorModalChangeCredentialsStep": "Insira o código do aplicativo para alterar as credenciais do administrador.",
|
||
"twoFactorModalSetSuccess": "A autenticação de dois fatores foi estabelecida com sucesso",
|
||
"twoFactorModalDeleteSuccess": "A autenticação de dois fatores foi excluída com sucesso",
|
||
"twoFactorModalError": "Código incorreto",
|
||
"show": "Mostrar",
|
||
"hide": "Ocultar",
|
||
"apiTokenNew": "Novo token",
|
||
"apiTokenName": "Nome",
|
||
"apiTokenNamePlaceholder": "ex.: central-panel-a",
|
||
"apiTokenNameRequired": "O nome é obrigatório",
|
||
"apiTokenEmpty": "Nenhum token ainda — crie um para autenticar bots ou painéis remotos.",
|
||
"apiTokenDeleteWarning": "Qualquer cliente usando este token deixará de se autenticar imediatamente."
|
||
},
|
||
"toasts": {
|
||
"modifySettings": "Os parâmetros foram alterados.",
|
||
"getSettings": "Ocorreu um erro ao recuperar os parâmetros.",
|
||
"modifyUserError": "Ocorreu um erro ao alterar as credenciais do administrador.",
|
||
"modifyUser": "Você alterou com sucesso as credenciais do administrador.",
|
||
"originalUserPassIncorrect": "O nome de usuário ou senha atual é inválido",
|
||
"userPassMustBeNotEmpty": "O novo nome de usuário e senha não podem estar vazios",
|
||
"getOutboundTrafficError": "Erro ao obter tráfego de saída",
|
||
"resetOutboundTrafficError": "Erro ao redefinir tráfego de saída"
|
||
}
|
||
},
|
||
"xray": {
|
||
"title": "Configurações Xray",
|
||
"save": "Salvar",
|
||
"restart": "Reiniciar Xray",
|
||
"restartSuccess": "Xray foi reiniciado com sucesso",
|
||
"stopSuccess": "Xray foi interrompido com sucesso",
|
||
"restartError": "Ocorreu um erro ao reiniciar o Xray.",
|
||
"stopError": "Ocorreu um erro ao parar o Xray.",
|
||
"basicTemplate": "Básico",
|
||
"advancedTemplate": "Avançado",
|
||
"generalConfigs": "Geral",
|
||
"generalConfigsDesc": "Essas opções determinam ajustes gerais.",
|
||
"logConfigs": "Log",
|
||
"logConfigsDesc": "Os logs podem afetar a eficiência do servidor. É recomendável habilitá-los com sabedoria apenas se necessário.",
|
||
"blockConfigsDesc": "Essas opções bloqueiam tráfego com base em protocolos e sites específicos solicitados.",
|
||
"basicRouting": "Roteamento Básico",
|
||
"blockConnectionsConfigsDesc": "Essas opções bloquearão o tráfego com base no país solicitado.",
|
||
"directConnectionsConfigsDesc": "Uma conexão direta garante que o tráfego específico não seja roteado por outro servidor.",
|
||
"blockips": "Bloquear IPs",
|
||
"blockdomains": "Bloquear Domínios",
|
||
"directips": "IPs Diretos",
|
||
"directdomains": "Domínios Diretos",
|
||
"ipv4Routing": "Roteamento IPv4",
|
||
"ipv4RoutingDesc": "Essas opções roteam o tráfego para um destino específico via IPv4.",
|
||
"warpRouting": "Roteamento WARP",
|
||
"warpRoutingDesc": "Essas opções roteam o tráfego para um destino específico via WARP.",
|
||
"nordRouting": "Roteamento NordVPN",
|
||
"nordRoutingDesc": "Essas opções roteiam o tráfego para um destino específico via NordVPN.",
|
||
"Template": "Modelo de Configuração Avançada do Xray",
|
||
"TemplateDesc": "O arquivo final de configuração do Xray será gerado com base neste modelo.",
|
||
"FreedomStrategy": "Estratégia do Protocolo Freedom",
|
||
"FreedomStrategyDesc": "Definir a estratégia de saída para a rede no Protocolo Freedom.",
|
||
"RoutingStrategy": "Estratégia Geral de Roteamento",
|
||
"RoutingStrategyDesc": "Definir a estratégia geral de roteamento de tráfego para resolver todas as solicitações.",
|
||
"outboundTestUrl": "URL de teste de outbound",
|
||
"outboundTestUrlDesc": "URL usada ao testar conectividade do outbound",
|
||
"Torrent": "Bloquear Protocolo BitTorrent",
|
||
"Inbounds": "Inbounds",
|
||
"InboundsDesc": "Aceitar clientes específicos.",
|
||
"Outbounds": "Outbounds",
|
||
"Balancers": "Balanceadores",
|
||
"OutboundsDesc": "Definir o caminho de saída do tráfego.",
|
||
"Routings": "Regras de Roteamento",
|
||
"RoutingsDesc": "A prioridade de cada regra é importante!",
|
||
"completeTemplate": "Todos",
|
||
"logLevel": "Nível de Log",
|
||
"logLevelDesc": "O nível de log para erros, indicando a informação que precisa ser registrada.",
|
||
"accessLog": "Log de Acesso",
|
||
"accessLogDesc": "O caminho do arquivo para o log de acesso. O valor especial 'none' desativa os logs de acesso.",
|
||
"errorLog": "Log de Erros",
|
||
"errorLogDesc": "O caminho do arquivo para o log de erros. O valor especial 'none' desativa os logs de erro.",
|
||
"dnsLog": "Log DNS",
|
||
"dnsLogDesc": "Se ativar logs de consulta DNS",
|
||
"maskAddress": "Mascarar Endereço",
|
||
"maskAddressDesc": "Máscara de endereço IP, quando ativado, substitui automaticamente o endereço IP que aparece no log.",
|
||
"statistics": "Estatísticas",
|
||
"statsInboundUplink": "Estatísticas de Upload de Entrada",
|
||
"statsInboundUplinkDesc": "Habilita a coleta de estatísticas para o tráfego de upload de todos os proxies de entrada.",
|
||
"statsInboundDownlink": "Estatísticas de Download de Entrada",
|
||
"statsInboundDownlinkDesc": "Habilita a coleta de estatísticas para o tráfego de download de todos os proxies de entrada.",
|
||
"statsOutboundUplink": "Estatísticas de Upload de Saída",
|
||
"statsOutboundUplinkDesc": "Habilita a coleta de estatísticas para o tráfego de upload de todos os proxies de saída.",
|
||
"statsOutboundDownlink": "Estatísticas de Download de Saída",
|
||
"statsOutboundDownlinkDesc": "Habilita a coleta de estatísticas para o tráfego de download de todos os proxies de saída.",
|
||
"rules": {
|
||
"first": "Primeiro",
|
||
"last": "Último",
|
||
"up": "Cima",
|
||
"down": "Baixo",
|
||
"source": "Fonte",
|
||
"dest": "Destino",
|
||
"inbound": "Entrada",
|
||
"outbound": "Saída",
|
||
"balancer": "Balanceador",
|
||
"info": "Info",
|
||
"add": "Adicionar Regra",
|
||
"edit": "Editar Regra",
|
||
"useComma": "Itens separados por vírgula"
|
||
},
|
||
"outbound": {
|
||
"addOutbound": "Adicionar Saída",
|
||
"addReverse": "Adicionar Reverso",
|
||
"editOutbound": "Editar Saída",
|
||
"editReverse": "Editar Reverso",
|
||
"reverseTag": "Tag de Reverso",
|
||
"reverseTagDesc": "Tag de saída do proxy reverso simples VLESS. Deixe vazio para desabilitar.",
|
||
"reverseTagPlaceholder": "tag de saída (vazio para desabilitar)",
|
||
"tag": "Tag",
|
||
"tagDesc": "Tag Única",
|
||
"address": "Endereço",
|
||
"reverse": "Reverso",
|
||
"domain": "Domínio",
|
||
"type": "Tipo",
|
||
"bridge": "Ponte",
|
||
"portal": "Portal",
|
||
"link": "Link",
|
||
"intercon": "Interconexão",
|
||
"settings": "Configurações",
|
||
"accountInfo": "Informações da Conta",
|
||
"outboundStatus": "Status de Saída",
|
||
"sendThrough": "Enviar Através de",
|
||
"test": "Testar",
|
||
"testResult": "Resultado do teste",
|
||
"testing": "Testando conexão...",
|
||
"testSuccess": "Teste bem-sucedido",
|
||
"testFailed": "Teste falhou",
|
||
"testError": "Falha ao testar saída",
|
||
"nordvpn": "NordVPN",
|
||
"accessToken": "Token de Acesso",
|
||
"country": "País",
|
||
"server": "Servidor",
|
||
"city": "Cidade",
|
||
"allCities": "Todas as Cidades",
|
||
"privateKey": "Chave Privada",
|
||
"load": "Carga"
|
||
},
|
||
"balancer": {
|
||
"addBalancer": "Adicionar Balanceador",
|
||
"editBalancer": "Editar Balanceador",
|
||
"balancerStrategy": "Estratégia",
|
||
"balancerSelectors": "Seletores",
|
||
"tag": "Tag",
|
||
"tagDesc": "Tag Única",
|
||
"balancerDesc": "Não é possível usar balancerTag e outboundTag ao mesmo tempo. Se usados simultaneamente, apenas outboundTag funcionará."
|
||
},
|
||
"wireguard": {
|
||
"secretKey": "Chave Secreta",
|
||
"publicKey": "Chave Pública",
|
||
"allowedIPs": "IPs Permitidos",
|
||
"endpoint": "Ponto Final",
|
||
"psk": "Chave Pré-Compartilhada",
|
||
"domainStrategy": "Estratégia de Domínio"
|
||
},
|
||
"tun": {
|
||
"nameDesc": "O nome da interface TUN. O padrão é 'xray0'",
|
||
"mtuDesc": "Unidade Máxima de Transmissão. O tamanho máximo dos pacotes de dados. O padrão é 1500",
|
||
"userLevel": "Nível do Usuário",
|
||
"userLevelDesc": "Todas as conexões feitas através deste inbound usarão este nível de usuário. O padrão é 0"
|
||
},
|
||
"dns": {
|
||
"enable": "Ativar DNS",
|
||
"enableDesc": "Ativar o servidor DNS integrado",
|
||
"tag": "Tag de Entrada DNS",
|
||
"tagDesc": "Esta tag estará disponível como uma tag de Entrada nas regras de roteamento.",
|
||
"clientIp": "IP do Cliente",
|
||
"clientIpDesc": "Usado para notificar o servidor sobre a localização IP especificada durante consultas DNS",
|
||
"disableCache": "Desativar cache",
|
||
"disableCacheDesc": "Desativa o cache de DNS",
|
||
"disableFallback": "Desativar Fallback",
|
||
"disableFallbackDesc": "Desativa consultas DNS de fallback",
|
||
"disableFallbackIfMatch": "Desativar Fallback Se Corresponder",
|
||
"disableFallbackIfMatchDesc": "Desativa consultas DNS de fallback quando a lista de domínios correspondentes do servidor DNS é atingida",
|
||
"enableParallelQuery": "Habilitar Consulta Paralela",
|
||
"enableParallelQueryDesc": "Habilitar consultas DNS paralelas para múltiplos servidores para resolução mais rápida",
|
||
"strategy": "Estratégia de Consulta",
|
||
"strategyDesc": "Estratégia geral para resolver nomes de domínio",
|
||
"add": "Adicionar Servidor",
|
||
"edit": "Editar Servidor",
|
||
"domains": "Domínios",
|
||
"expectIPs": "IPs Esperadas",
|
||
"unexpectIPs": "IPs inesperados",
|
||
"useSystemHosts": "Usar Hosts do sistema",
|
||
"useSystemHostsDesc": "Usar o arquivo hosts de um sistema instalado",
|
||
"serveStale": "Servir Expirados",
|
||
"serveStaleDesc": "Retornar resultados expirados do cache enquanto atualiza em segundo plano",
|
||
"serveExpiredTTL": "TTL de Expirados",
|
||
"serveExpiredTTLDesc": "Validade (segundos) das entradas expiradas no cache; 0 = nunca expira",
|
||
"timeoutMs": "Tempo limite (ms)",
|
||
"skipFallback": "Ignorar Fallback",
|
||
"finalQuery": "Consulta Final",
|
||
"hosts": "Hosts",
|
||
"hostsAdd": "Adicionar Host",
|
||
"hostsEmpty": "Nenhum Host definido",
|
||
"hostsDomain": "Domínio (ex. domain:example.com)",
|
||
"hostsValues": "IP ou domínio — digite e pressione Enter",
|
||
"usePreset": "Usar modelo",
|
||
"dnsPresetTitle": "Modelos DNS",
|
||
"dnsPresetFamily": "Familiar",
|
||
"clearAll": "Remover Todos",
|
||
"clearAllTitle": "Remover todos os servidores DNS?",
|
||
"clearAllConfirm": "Isso remove todos os servidores DNS da lista. Não pode ser desfeito."
|
||
},
|
||
"fakedns": {
|
||
"add": "Adicionar Fake DNS",
|
||
"edit": "Editar Fake DNS",
|
||
"ipPool": "Sub-rede do Pool de IP",
|
||
"poolSize": "Tamanho do Pool"
|
||
}
|
||
}
|
||
},
|
||
"tgbot": {
|
||
"keyboardClosed": "❌ Teclado fechado!",
|
||
"noResult": "❗ Nenhum resultado!",
|
||
"noQuery": "❌ Consulta não encontrada! Por favor, use o comando novamente!",
|
||
"wentWrong": "❌ Algo deu errado!",
|
||
"noIpRecord": "❗ Nenhum registro de IP!",
|
||
"noInbounds": "❗ Nenhum inbound encontrado!",
|
||
"unlimited": "♾ Ilimitado (Reset)",
|
||
"add": "Adicionar",
|
||
"month": "Mês",
|
||
"months": "Meses",
|
||
"day": "Dia",
|
||
"days": "Dias",
|
||
"hours": "Horas",
|
||
"minutes": "Minutos",
|
||
"unknown": "Desconhecido",
|
||
"inbounds": "Inbounds",
|
||
"clients": "Clientes",
|
||
"offline": "🔴 Offline",
|
||
"online": "🟢 Online",
|
||
"commands": {
|
||
"unknown": "❗ Comando desconhecido.",
|
||
"pleaseChoose": "👇 Escolha:\r\n",
|
||
"help": "🤖 Bem-vindo a este bot! Ele foi projetado para oferecer dados específicos do painel da web e permite que você faça as modificações necessárias.\r\n\r\n",
|
||
"start": "👋 Olá <i>{{ .Firstname }}</i>.\r\n",
|
||
"welcome": "🤖 Bem-vindo ao bot de gerenciamento do <b>{{ .Hostname }}</b>.\r\n",
|
||
"status": "✅ Bot está OK!",
|
||
"usage": "❗ Por favor, forneça um texto para pesquisar!",
|
||
"getID": "🆔 Seu ID: <code>{{ .ID }}</code>",
|
||
"helpAdminCommands": "Para reiniciar o Xray Core:\r\n<code>/restart</code>\r\n\r\nPara pesquisar por um email de cliente:\r\n<code>/usage [Email]</code>\r\n\r\nPara pesquisar por inbounds (com estatísticas do cliente):\r\n<code>/inbound [Remark]</code>\r\n\r\nTelegram Chat ID:\r\n<code>/id</code>",
|
||
"helpClientCommands": "Para pesquisar por estatísticas, use o seguinte comando:\r\n\r\n<code>/usage [Email]</code>\r\n\r\nTelegram Chat ID:\r\n<code>/id</code>",
|
||
"restartUsage": "\r\n\r\n<code>/restart</code>",
|
||
"restartSuccess": "✅ Operação bem-sucedida!",
|
||
"restartFailed": "❗ Erro na operação.\r\n\r\n<code>Erro: {{ .Error }}</code>.",
|
||
"xrayNotRunning": "❗ Xray Core não está em execução.",
|
||
"startDesc": "Mostrar menu principal",
|
||
"helpDesc": "Ajuda do bot",
|
||
"statusDesc": "Verificar status do bot",
|
||
"idDesc": "Mostrar seu ID do Telegram"
|
||
},
|
||
"messages": {
|
||
"cpuThreshold": "🔴 A carga da CPU {{ .Percent }}% excede o limite de {{ .Threshold }}%",
|
||
"selectUserFailed": "❌ Erro na seleção do usuário!",
|
||
"userSaved": "✅ Usuário do Telegram salvo.",
|
||
"loginSuccess": "✅ Conectado ao painel com sucesso.\r\n",
|
||
"loginFailed": "❗️Tentativa de login no painel falhou.\r\n",
|
||
"2faFailed": "Falha no 2FA",
|
||
"report": "🕰 Relatórios agendados: {{ .RunTime }}\r\n",
|
||
"datetime": "⏰ Data&Hora: {{ .DateTime }}\r\n",
|
||
"hostname": "💻 Host: {{ .Hostname }}\r\n",
|
||
"version": "🚀 Versão 3X-UI: {{ .Version }}\r\n",
|
||
"xrayVersion": "📡 Versão Xray: {{ .XrayVersion }}\r\n",
|
||
"ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
|
||
"ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
|
||
"ip": "🌐 IP: {{ .IP }}\r\n",
|
||
"ips": "🔢 IPs:\r\n{{ .IPs }}\r\n",
|
||
"serverUpTime": "⏳ Tempo de atividade: {{ .UpTime }} {{ .Unit }}\r\n",
|
||
"serverLoad": "📈 Carga do sistema: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
|
||
"serverMemory": "📋 RAM: {{ .Current }}/{{ .Total }}\r\n",
|
||
"tcpCount": "🔹 TCP: {{ .Count }}\r\n",
|
||
"udpCount": "🔸 UDP: {{ .Count }}\r\n",
|
||
"traffic": "🚦 Tráfego: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
|
||
"xrayStatus": "ℹ️ Status: {{ .State }}\r\n",
|
||
"username": "👤 Nome de usuário: {{ .Username }}\r\n",
|
||
"reason": "❗️ Motivo: {{ .Reason }}\r\n",
|
||
"time": "⏰ Hora: {{ .Time }}\r\n",
|
||
"inbound": "📍 Inbound: {{ .Remark }}\r\n",
|
||
"port": "🔌 Porta: {{ .Port }}\r\n",
|
||
"expire": "📅 Data de expiração: {{ .Time }}\r\n",
|
||
"expireIn": "📅 Expira em: {{ .Time }}\r\n",
|
||
"active": "💡 Ativo: {{ .Enable }}\r\n",
|
||
"enabled": "🚨 Ativado: {{ .Enable }}\r\n",
|
||
"online": "🌐 Status da conexão: {{ .Status }}\r\n",
|
||
"lastOnline": "🔙 Última vez online: {{ .Time }}\r\n",
|
||
"email": "📧 Email: {{ .Email }}\r\n",
|
||
"upload": "🔼 Upload: ↑{{ .Upload }}\r\n",
|
||
"download": "🔽 Download: ↓{{ .Download }}\r\n",
|
||
"total": "📊 Total: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
|
||
"TGUser": "👤 Usuário do Telegram: {{ .TelegramID }}\r\n",
|
||
"exhaustedMsg": "🚨 {{ .Type }} esgotado:\r\n",
|
||
"exhaustedCount": "🚨 Contagem de {{ .Type }} esgotado:\r\n",
|
||
"onlinesCount": "🌐 Clientes online: {{ .Count }}\r\n",
|
||
"disabled": "🛑 Desativado: {{ .Disabled }}\r\n",
|
||
"depleteSoon": "🔜 Esgotar em breve: {{ .Deplete }}\r\n\r\n",
|
||
"backupTime": "🗄 Hora do backup: {{ .Time }}\r\n",
|
||
"refreshedOn": "\r\n📋🔄 Atualizado em: {{ .Time }}\r\n\r\n",
|
||
"yes": "✅ Sim",
|
||
"no": "❌ Não",
|
||
"received_id": "🔑📥 ID atualizado.",
|
||
"received_password": "🔑📥 Senha atualizada.",
|
||
"received_email": "📧📥 E-mail atualizado.",
|
||
"received_comment": "💬📥 Comentário atualizado.",
|
||
"id_prompt": "🔑 ID Padrão: {{ .ClientId }}\n\nDigite seu ID.",
|
||
"pass_prompt": "🔑 Senha Padrão: {{ .ClientPassword }}\n\nDigite sua senha.",
|
||
"email_prompt": "📧 E-mail Padrão: {{ .ClientEmail }}\n\nDigite seu e-mail.",
|
||
"comment_prompt": "💬 Comentário Padrão: {{ .ClientComment }}\n\nDigite seu comentário.",
|
||
"inbound_client_data_id": "🔄 Entrada: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Tráfego: {{ .ClientTraffic }}\n📅 Data de expiração: {{ .ClientExp }}\n🌐 Limite de IP: {{ .IpLimit }}\n💬 Comentário: {{ .ClientComment }}\n\nAgora você pode adicionar o cliente à entrada!",
|
||
"inbound_client_data_pass": "🔄 Entrada: {{ .InboundRemark }}\n\n🔑 Senha: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Tráfego: {{ .ClientTraffic }}\n📅 Data de expiração: {{ .ClientExp }}\n🌐 Limite de IP: {{ .IpLimit }}\n💬 Comentário: {{ .ClientComment }}\n\nAgora você pode adicionar o cliente à entrada!",
|
||
"cancel": "❌ Processo Cancelado! \n\nVocê pode iniciar novamente a qualquer momento com /start. 🔄",
|
||
"error_add_client": "⚠️ Erro:\n\n {{ .error }}",
|
||
"using_default_value": "Tudo bem, vou manter o valor padrão. 😊",
|
||
"incorrect_input": "Sua entrada não é válida.\nAs frases devem ser contínuas, sem espaços.\nExemplo correto: aaaaaa\nExemplo incorreto: aaa aaa 🚫",
|
||
"AreYouSure": "Você tem certeza? 🤔",
|
||
"SuccessResetTraffic": "📧 Email: {{ .ClientEmail }}\n🏁 Resultado: ✅ Sucesso",
|
||
"FailedResetTraffic": "📧 Email: {{ .ClientEmail }}\n🏁 Resultado: ❌ Falhou \n\n🛠️ Erro: [ {{ .ErrorMessage }} ]",
|
||
"FinishProcess": "🔚 Processo de redefinição de tráfego concluído para todos os clientes."
|
||
},
|
||
"buttons": {
|
||
"closeKeyboard": "❌ Fechar teclado",
|
||
"cancel": "❌ Cancelar",
|
||
"cancelReset": "❌ Cancelar redefinição",
|
||
"cancelIpLimit": "❌ Cancelar limite de IP",
|
||
"confirmResetTraffic": "✅ Confirmar redefinição de tráfego?",
|
||
"confirmClearIps": "✅ Confirmar limpar IPs?",
|
||
"confirmRemoveTGUser": "✅ Confirmar remover usuário do Telegram?",
|
||
"confirmToggle": "✅ Confirmar ativar/desativar usuário?",
|
||
"dbBackup": "Obter backup do DB",
|
||
"serverUsage": "Uso do servidor",
|
||
"getInbounds": "Obter Inbounds",
|
||
"depleteSoon": "Esgotar em breve",
|
||
"clientUsage": "Obter uso",
|
||
"onlines": "Clientes online",
|
||
"commands": "Comandos",
|
||
"refresh": "🔄 Atualizar",
|
||
"clearIPs": "❌ Limpar IPs",
|
||
"removeTGUser": "❌ Remover usuário do Telegram",
|
||
"selectTGUser": "👤 Selecionar usuário do Telegram",
|
||
"selectOneTGUser": "👤 Selecione um usuário do Telegram:",
|
||
"resetTraffic": "📈 Redefinir tráfego",
|
||
"resetExpire": "📅 Alterar data de expiração",
|
||
"ipLog": "🔢 Log de IP",
|
||
"ipLimit": "🔢 Limite de IP",
|
||
"setTGUser": "👤 Definir usuário do Telegram",
|
||
"toggle": "🔘 Ativar / Desativar",
|
||
"custom": "🔢 Personalizado",
|
||
"confirmNumber": "✅ Confirmar: {{ .Num }}",
|
||
"confirmNumberAdd": "✅ Confirmar adicionar: {{ .Num }}",
|
||
"limitTraffic": "🚧 Limite de tráfego",
|
||
"getBanLogs": "Obter logs de banimento",
|
||
"allClients": "Todos os clientes",
|
||
"addClient": "Adicionar Cliente",
|
||
"submitDisable": "Enviar como Desativado ☑️",
|
||
"submitEnable": "Enviar como Ativado ✅",
|
||
"use_default": "🏷️ Usar padrão",
|
||
"change_id": "⚙️🔑 ID",
|
||
"change_password": "⚙️🔑 Senha",
|
||
"change_email": "⚙️📧 E-mail",
|
||
"change_comment": "⚙️💬 Comentário",
|
||
"change_flow": "⚙️🚦 Fluxo",
|
||
"ResetAllTraffics": "Redefinir Todo o Tráfego",
|
||
"SortedTrafficUsageReport": "Relatório de Uso de Tráfego Ordenado"
|
||
},
|
||
"answers": {
|
||
"successfulOperation": "✅ Operação bem-sucedida!",
|
||
"errorOperation": "❗ Erro na operação.",
|
||
"getInboundsFailed": "❌ Falha ao obter inbounds.",
|
||
"getClientsFailed": "❌ Falha ao obter clientes.",
|
||
"canceled": "❌ {{ .Email }}: Operação cancelada.",
|
||
"clientRefreshSuccess": "✅ {{ .Email }}: Cliente atualizado com sucesso.",
|
||
"IpRefreshSuccess": "✅ {{ .Email }}: IPs atualizados com sucesso.",
|
||
"TGIdRefreshSuccess": "✅ {{ .Email }}: Usuário do Telegram do cliente atualizado com sucesso.",
|
||
"resetTrafficSuccess": "✅ {{ .Email }}: Tráfego redefinido com sucesso.",
|
||
"setTrafficLimitSuccess": "✅ {{ .Email }}: Limite de tráfego salvo com sucesso.",
|
||
"expireResetSuccess": "✅ {{ .Email }}: Dias de expiração redefinidos com sucesso.",
|
||
"resetIpSuccess": "✅ {{ .Email }}: Limite de IP {{ .Count }} salvo com sucesso.",
|
||
"clearIpSuccess": "✅ {{ .Email }}: IPs limpos com sucesso.",
|
||
"getIpLog": "✅ {{ .Email }}: Obter log de IP.",
|
||
"getUserInfo": "✅ {{ .Email }}: Obter informações do usuário do Telegram.",
|
||
"removedTGUserSuccess": "✅ {{ .Email }}: Usuário do Telegram removido com sucesso.",
|
||
"enableSuccess": "✅ {{ .Email }}: Ativado com sucesso.",
|
||
"disableSuccess": "✅ {{ .Email }}: Desativado com sucesso.",
|
||
"askToAddUserId": "Sua configuração não foi encontrada!\r\nPeça ao seu administrador para usar seu Telegram ChatID em suas configurações.\r\n\r\nSeu ChatID: <code>{{ .TgUserID }}</code>",
|
||
"chooseClient": "Escolha um cliente para Inbound {{ .Inbound }}",
|
||
"chooseInbound": "Escolha um Inbound"
|
||
}
|
||
}
|
||
} |